1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "src/v8.h"
33
34 #include "src/compiler.h"
35 #include "src/execution.h"
36 #include "src/isolate.h"
37 #include "src/objects.h"
38 #include "src/parser.h"
39 #include "src/preparser.h"
40 #include "src/scanner-character-streams.h"
41 #include "src/token.h"
42 #include "src/utils.h"
43 #include "test/cctest/cctest.h"
44
TEST(ScanKeywords)45 TEST(ScanKeywords) {
46 struct KeywordToken {
47 const char* keyword;
48 i::Token::Value token;
49 };
50
51 static const KeywordToken keywords[] = {
52 #define KEYWORD(t, s, d) { s, i::Token::t },
53 TOKEN_LIST(IGNORE_TOKEN, KEYWORD)
54 #undef KEYWORD
55 { NULL, i::Token::IDENTIFIER }
56 };
57
58 KeywordToken key_token;
59 i::UnicodeCache unicode_cache;
60 i::byte buffer[32];
61 for (int i = 0; (key_token = keywords[i]).keyword != NULL; i++) {
62 const i::byte* keyword =
63 reinterpret_cast<const i::byte*>(key_token.keyword);
64 int length = i::StrLength(key_token.keyword);
65 CHECK(static_cast<int>(sizeof(buffer)) >= length);
66 {
67 i::Utf8ToUtf16CharacterStream stream(keyword, length);
68 i::Scanner scanner(&unicode_cache);
69 // The scanner should parse Harmony keywords for this test.
70 scanner.SetHarmonyScoping(true);
71 scanner.SetHarmonyModules(true);
72 scanner.Initialize(&stream);
73 CHECK_EQ(key_token.token, scanner.Next());
74 CHECK_EQ(i::Token::EOS, scanner.Next());
75 }
76 // Removing characters will make keyword matching fail.
77 {
78 i::Utf8ToUtf16CharacterStream stream(keyword, length - 1);
79 i::Scanner scanner(&unicode_cache);
80 scanner.Initialize(&stream);
81 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
82 CHECK_EQ(i::Token::EOS, scanner.Next());
83 }
84 // Adding characters will make keyword matching fail.
85 static const char chars_to_append[] = { 'z', '0', '_' };
86 for (int j = 0; j < static_cast<int>(ARRAY_SIZE(chars_to_append)); ++j) {
87 i::MemMove(buffer, keyword, length);
88 buffer[length] = chars_to_append[j];
89 i::Utf8ToUtf16CharacterStream stream(buffer, length + 1);
90 i::Scanner scanner(&unicode_cache);
91 scanner.Initialize(&stream);
92 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
93 CHECK_EQ(i::Token::EOS, scanner.Next());
94 }
95 // Replacing characters will make keyword matching fail.
96 {
97 i::MemMove(buffer, keyword, length);
98 buffer[length - 1] = '_';
99 i::Utf8ToUtf16CharacterStream stream(buffer, length);
100 i::Scanner scanner(&unicode_cache);
101 scanner.Initialize(&stream);
102 CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
103 CHECK_EQ(i::Token::EOS, scanner.Next());
104 }
105 }
106 }
107
108
TEST(ScanHTMLEndComments)109 TEST(ScanHTMLEndComments) {
110 v8::V8::Initialize();
111 v8::Isolate* isolate = CcTest::isolate();
112 v8::HandleScope handles(isolate);
113
114 // Regression test. See:
115 // http://code.google.com/p/chromium/issues/detail?id=53548
116 // Tests that --> is correctly interpreted as comment-to-end-of-line if there
117 // is only whitespace before it on the line (with comments considered as
118 // whitespace, even a multiline-comment containing a newline).
119 // This was not the case if it occurred before the first real token
120 // in the input.
121 const char* tests[] = {
122 // Before first real token.
123 "--> is eol-comment\nvar y = 37;\n",
124 "\n --> is eol-comment\nvar y = 37;\n",
125 "/* precomment */ --> is eol-comment\nvar y = 37;\n",
126 "\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
127 // After first real token.
128 "var x = 42;\n--> is eol-comment\nvar y = 37;\n",
129 "var x = 42;\n/* precomment */ --> is eol-comment\nvar y = 37;\n",
130 NULL
131 };
132
133 const char* fail_tests[] = {
134 "x --> is eol-comment\nvar y = 37;\n",
135 "\"\\n\" --> is eol-comment\nvar y = 37;\n",
136 "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
137 "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
138 "var x = 42; --> is eol-comment\nvar y = 37;\n",
139 "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
140 NULL
141 };
142
143 // Parser/Scanner needs a stack limit.
144 int marker;
145 CcTest::i_isolate()->stack_guard()->SetStackLimit(
146 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
147 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
148 for (int i = 0; tests[i]; i++) {
149 const i::byte* source =
150 reinterpret_cast<const i::byte*>(tests[i]);
151 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i]));
152 i::CompleteParserRecorder log;
153 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
154 scanner.Initialize(&stream);
155 i::PreParser preparser(&scanner, &log, stack_limit);
156 preparser.set_allow_lazy(true);
157 i::PreParser::PreParseResult result = preparser.PreParseProgram();
158 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
159 i::ScriptData data(log.ExtractData());
160 CHECK(!data.has_error());
161 }
162
163 for (int i = 0; fail_tests[i]; i++) {
164 const i::byte* source =
165 reinterpret_cast<const i::byte*>(fail_tests[i]);
166 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i]));
167 i::CompleteParserRecorder log;
168 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
169 scanner.Initialize(&stream);
170 i::PreParser preparser(&scanner, &log, stack_limit);
171 preparser.set_allow_lazy(true);
172 i::PreParser::PreParseResult result = preparser.PreParseProgram();
173 // Even in the case of a syntax error, kPreParseSuccess is returned.
174 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
175 i::ScriptData data(log.ExtractData());
176 CHECK(data.has_error());
177 }
178 }
179
180
181 class ScriptResource : public v8::String::ExternalAsciiStringResource {
182 public:
ScriptResource(const char * data,size_t length)183 ScriptResource(const char* data, size_t length)
184 : data_(data), length_(length) { }
185
data() const186 const char* data() const { return data_; }
length() const187 size_t length() const { return length_; }
188
189 private:
190 const char* data_;
191 size_t length_;
192 };
193
194
TEST(UsingCachedData)195 TEST(UsingCachedData) {
196 v8::Isolate* isolate = CcTest::isolate();
197 v8::HandleScope handles(isolate);
198 v8::Local<v8::Context> context = v8::Context::New(isolate);
199 v8::Context::Scope context_scope(context);
200 int marker;
201 CcTest::i_isolate()->stack_guard()->SetStackLimit(
202 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
203
204 // Source containing functions that might be lazily compiled and all types
205 // of symbols (string, propertyName, regexp).
206 const char* source =
207 "var x = 42;"
208 "function foo(a) { return function nolazy(b) { return a + b; } }"
209 "function bar(a) { if (a) return function lazy(b) { return b; } }"
210 "var z = {'string': 'string literal', bareword: 'propertyName', "
211 " 42: 'number literal', for: 'keyword as propertyName', "
212 " f\\u006fr: 'keyword propertyname with escape'};"
213 "var v = /RegExp Literal/;"
214 "var w = /RegExp Literal\\u0020With Escape/gin;"
215 "var y = { get getter() { return 42; }, "
216 " set setter(v) { this.value = v; }};";
217 int source_length = i::StrLength(source);
218
219 // ScriptResource will be deleted when the corresponding String is GCd.
220 v8::ScriptCompiler::Source script_source(v8::String::NewExternal(
221 isolate, new ScriptResource(source, source_length)));
222 i::FLAG_min_preparse_length = 0;
223 v8::ScriptCompiler::Compile(isolate, &script_source,
224 v8::ScriptCompiler::kProduceDataToCache);
225 CHECK(script_source.GetCachedData());
226
227 // Compile the script again, using the cached data.
228 bool lazy_flag = i::FLAG_lazy;
229 i::FLAG_lazy = true;
230 v8::ScriptCompiler::Compile(isolate, &script_source);
231 i::FLAG_lazy = false;
232 v8::ScriptCompiler::CompileUnbound(isolate, &script_source);
233 i::FLAG_lazy = lazy_flag;
234 }
235
236
TEST(PreparseFunctionDataIsUsed)237 TEST(PreparseFunctionDataIsUsed) {
238 // This tests that we actually do use the function data generated by the
239 // preparser.
240
241 // Make preparsing work for short scripts.
242 i::FLAG_min_preparse_length = 0;
243
244 v8::Isolate* isolate = CcTest::isolate();
245 v8::HandleScope handles(isolate);
246 v8::Local<v8::Context> context = v8::Context::New(isolate);
247 v8::Context::Scope context_scope(context);
248 int marker;
249 CcTest::i_isolate()->stack_guard()->SetStackLimit(
250 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
251
252 const char* good_code =
253 "function this_is_lazy() { var a; } function foo() { return 25; } foo();";
254
255 // Insert a syntax error inside the lazy function.
256 const char* bad_code =
257 "function this_is_lazy() { if ( } function foo() { return 25; } foo();";
258
259 v8::ScriptCompiler::Source good_source(v8_str(good_code));
260 v8::ScriptCompiler::Compile(isolate, &good_source,
261 v8::ScriptCompiler::kProduceDataToCache);
262
263 const v8::ScriptCompiler::CachedData* cached_data =
264 good_source.GetCachedData();
265 CHECK(cached_data->data != NULL);
266 CHECK_GT(cached_data->length, 0);
267
268 // Now compile the erroneous code with the good preparse data. If the preparse
269 // data is used, the lazy function is skipped and it should compile fine.
270 v8::ScriptCompiler::Source bad_source(
271 v8_str(bad_code), new v8::ScriptCompiler::CachedData(
272 cached_data->data, cached_data->length));
273 v8::Local<v8::Value> result =
274 v8::ScriptCompiler::Compile(isolate, &bad_source)->Run();
275 CHECK(result->IsInt32());
276 CHECK_EQ(25, result->Int32Value());
277 }
278
279
TEST(StandAlonePreParser)280 TEST(StandAlonePreParser) {
281 v8::V8::Initialize();
282
283 int marker;
284 CcTest::i_isolate()->stack_guard()->SetStackLimit(
285 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
286
287 const char* programs[] = {
288 "{label: 42}",
289 "var x = 42;",
290 "function foo(x, y) { return x + y; }",
291 "%ArgleBargle(glop);",
292 "var x = new new Function('this.x = 42');",
293 NULL
294 };
295
296 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
297 for (int i = 0; programs[i]; i++) {
298 const char* program = programs[i];
299 i::Utf8ToUtf16CharacterStream stream(
300 reinterpret_cast<const i::byte*>(program),
301 static_cast<unsigned>(strlen(program)));
302 i::CompleteParserRecorder log;
303 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
304 scanner.Initialize(&stream);
305
306 i::PreParser preparser(&scanner, &log, stack_limit);
307 preparser.set_allow_lazy(true);
308 preparser.set_allow_natives_syntax(true);
309 i::PreParser::PreParseResult result = preparser.PreParseProgram();
310 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
311 i::ScriptData data(log.ExtractData());
312 CHECK(!data.has_error());
313 }
314 }
315
316
TEST(StandAlonePreParserNoNatives)317 TEST(StandAlonePreParserNoNatives) {
318 v8::V8::Initialize();
319
320 int marker;
321 CcTest::i_isolate()->stack_guard()->SetStackLimit(
322 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
323
324 const char* programs[] = {
325 "%ArgleBargle(glop);",
326 "var x = %_IsSmi(42);",
327 NULL
328 };
329
330 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
331 for (int i = 0; programs[i]; i++) {
332 const char* program = programs[i];
333 i::Utf8ToUtf16CharacterStream stream(
334 reinterpret_cast<const i::byte*>(program),
335 static_cast<unsigned>(strlen(program)));
336 i::CompleteParserRecorder log;
337 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
338 scanner.Initialize(&stream);
339
340 // Preparser defaults to disallowing natives syntax.
341 i::PreParser preparser(&scanner, &log, stack_limit);
342 preparser.set_allow_lazy(true);
343 i::PreParser::PreParseResult result = preparser.PreParseProgram();
344 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
345 i::ScriptData data(log.ExtractData());
346 // Data contains syntax error.
347 CHECK(data.has_error());
348 }
349 }
350
351
TEST(PreparsingObjectLiterals)352 TEST(PreparsingObjectLiterals) {
353 // Regression test for a bug where the symbol stream produced by PreParser
354 // didn't match what Parser wanted to consume.
355 v8::Isolate* isolate = CcTest::isolate();
356 v8::HandleScope handles(isolate);
357 v8::Local<v8::Context> context = v8::Context::New(isolate);
358 v8::Context::Scope context_scope(context);
359 int marker;
360 CcTest::i_isolate()->stack_guard()->SetStackLimit(
361 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
362
363 {
364 const char* source = "var myo = {if: \"foo\"}; myo.if;";
365 v8::Local<v8::Value> result = PreCompileCompileRun(source);
366 CHECK(result->IsString());
367 v8::String::Utf8Value utf8(result);
368 CHECK_EQ("foo", *utf8);
369 }
370
371 {
372 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
373 v8::Local<v8::Value> result = PreCompileCompileRun(source);
374 CHECK(result->IsString());
375 v8::String::Utf8Value utf8(result);
376 CHECK_EQ("foo", *utf8);
377 }
378
379 {
380 const char* source = "var myo = {1: \"foo\"}; myo[1];";
381 v8::Local<v8::Value> result = PreCompileCompileRun(source);
382 CHECK(result->IsString());
383 v8::String::Utf8Value utf8(result);
384 CHECK_EQ("foo", *utf8);
385 }
386 }
387
388
TEST(RegressChromium62639)389 TEST(RegressChromium62639) {
390 v8::V8::Initialize();
391 i::Isolate* isolate = CcTest::i_isolate();
392
393 int marker;
394 isolate->stack_guard()->SetStackLimit(
395 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
396
397 const char* program = "var x = 'something';\n"
398 "escape: function() {}";
399 // Fails parsing expecting an identifier after "function".
400 // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
401 // and then used the invalid currently scanned literal. This always
402 // failed in debug mode, and sometimes crashed in release mode.
403
404 i::Utf8ToUtf16CharacterStream stream(
405 reinterpret_cast<const i::byte*>(program),
406 static_cast<unsigned>(strlen(program)));
407 i::CompleteParserRecorder log;
408 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
409 scanner.Initialize(&stream);
410 i::PreParser preparser(&scanner, &log,
411 CcTest::i_isolate()->stack_guard()->real_climit());
412 preparser.set_allow_lazy(true);
413 i::PreParser::PreParseResult result = preparser.PreParseProgram();
414 // Even in the case of a syntax error, kPreParseSuccess is returned.
415 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
416 i::ScriptData data(log.ExtractData());
417 CHECK(data.has_error());
418 }
419
420
TEST(Regress928)421 TEST(Regress928) {
422 v8::V8::Initialize();
423 i::Isolate* isolate = CcTest::i_isolate();
424 i::Factory* factory = isolate->factory();
425
426 // Preparsing didn't consider the catch clause of a try statement
427 // as with-content, which made it assume that a function inside
428 // the block could be lazily compiled, and an extra, unexpected,
429 // entry was added to the data.
430 int marker;
431 isolate->stack_guard()->SetStackLimit(
432 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
433
434 const char* program =
435 "try { } catch (e) { var foo = function () { /* first */ } }"
436 "var bar = function () { /* second */ }";
437
438 v8::HandleScope handles(CcTest::isolate());
439 i::Handle<i::String> source = factory->NewStringFromAsciiChecked(program);
440 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
441 i::CompleteParserRecorder log;
442 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
443 scanner.Initialize(&stream);
444 i::PreParser preparser(&scanner, &log,
445 CcTest::i_isolate()->stack_guard()->real_climit());
446 preparser.set_allow_lazy(true);
447 i::PreParser::PreParseResult result = preparser.PreParseProgram();
448 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
449 i::ScriptData data(log.ExtractData());
450 CHECK(!data.has_error());
451 data.Initialize();
452
453 int first_function =
454 static_cast<int>(strstr(program, "function") - program);
455 int first_lbrace = first_function + i::StrLength("function () ");
456 CHECK_EQ('{', program[first_lbrace]);
457 i::FunctionEntry entry1 = data.GetFunctionEntry(first_lbrace);
458 CHECK(!entry1.is_valid());
459
460 int second_function =
461 static_cast<int>(strstr(program + first_lbrace, "function") - program);
462 int second_lbrace =
463 second_function + i::StrLength("function () ");
464 CHECK_EQ('{', program[second_lbrace]);
465 i::FunctionEntry entry2 = data.GetFunctionEntry(second_lbrace);
466 CHECK(entry2.is_valid());
467 CHECK_EQ('}', program[entry2.end_pos() - 1]);
468 }
469
470
TEST(PreParseOverflow)471 TEST(PreParseOverflow) {
472 v8::V8::Initialize();
473
474 int marker;
475 CcTest::i_isolate()->stack_guard()->SetStackLimit(
476 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
477
478 size_t kProgramSize = 1024 * 1024;
479 i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
480 memset(program.get(), '(', kProgramSize);
481 program[kProgramSize] = '\0';
482
483 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
484
485 i::Utf8ToUtf16CharacterStream stream(
486 reinterpret_cast<const i::byte*>(program.get()),
487 static_cast<unsigned>(kProgramSize));
488 i::CompleteParserRecorder log;
489 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
490 scanner.Initialize(&stream);
491
492 i::PreParser preparser(&scanner, &log, stack_limit);
493 preparser.set_allow_lazy(true);
494 i::PreParser::PreParseResult result = preparser.PreParseProgram();
495 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
496 }
497
498
499 class TestExternalResource: public v8::String::ExternalStringResource {
500 public:
TestExternalResource(uint16_t * data,int length)501 explicit TestExternalResource(uint16_t* data, int length)
502 : data_(data), length_(static_cast<size_t>(length)) { }
503
~TestExternalResource()504 ~TestExternalResource() { }
505
data() const506 const uint16_t* data() const {
507 return data_;
508 }
509
length() const510 size_t length() const {
511 return length_;
512 }
513 private:
514 uint16_t* data_;
515 size_t length_;
516 };
517
518
519 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
520
TestCharacterStream(const char * ascii_source,unsigned length,unsigned start=0,unsigned end=0)521 void TestCharacterStream(const char* ascii_source,
522 unsigned length,
523 unsigned start = 0,
524 unsigned end = 0) {
525 if (end == 0) end = length;
526 unsigned sub_length = end - start;
527 i::Isolate* isolate = CcTest::i_isolate();
528 i::Factory* factory = isolate->factory();
529 i::HandleScope test_scope(isolate);
530 i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
531 for (unsigned i = 0; i < length; i++) {
532 uc16_buffer[i] = static_cast<i::uc16>(ascii_source[i]);
533 }
534 i::Vector<const char> ascii_vector(ascii_source, static_cast<int>(length));
535 i::Handle<i::String> ascii_string =
536 factory->NewStringFromAscii(ascii_vector).ToHandleChecked();
537 TestExternalResource resource(uc16_buffer.get(), length);
538 i::Handle<i::String> uc16_string(
539 factory->NewExternalStringFromTwoByte(&resource).ToHandleChecked());
540
541 i::ExternalTwoByteStringUtf16CharacterStream uc16_stream(
542 i::Handle<i::ExternalTwoByteString>::cast(uc16_string), start, end);
543 i::GenericStringUtf16CharacterStream string_stream(ascii_string, start, end);
544 i::Utf8ToUtf16CharacterStream utf8_stream(
545 reinterpret_cast<const i::byte*>(ascii_source), end);
546 utf8_stream.SeekForward(start);
547
548 unsigned i = start;
549 while (i < end) {
550 // Read streams one char at a time
551 CHECK_EQU(i, uc16_stream.pos());
552 CHECK_EQU(i, string_stream.pos());
553 CHECK_EQU(i, utf8_stream.pos());
554 int32_t c0 = ascii_source[i];
555 int32_t c1 = uc16_stream.Advance();
556 int32_t c2 = string_stream.Advance();
557 int32_t c3 = utf8_stream.Advance();
558 i++;
559 CHECK_EQ(c0, c1);
560 CHECK_EQ(c0, c2);
561 CHECK_EQ(c0, c3);
562 CHECK_EQU(i, uc16_stream.pos());
563 CHECK_EQU(i, string_stream.pos());
564 CHECK_EQU(i, utf8_stream.pos());
565 }
566 while (i > start + sub_length / 4) {
567 // Pushback, re-read, pushback again.
568 int32_t c0 = ascii_source[i - 1];
569 CHECK_EQU(i, uc16_stream.pos());
570 CHECK_EQU(i, string_stream.pos());
571 CHECK_EQU(i, utf8_stream.pos());
572 uc16_stream.PushBack(c0);
573 string_stream.PushBack(c0);
574 utf8_stream.PushBack(c0);
575 i--;
576 CHECK_EQU(i, uc16_stream.pos());
577 CHECK_EQU(i, string_stream.pos());
578 CHECK_EQU(i, utf8_stream.pos());
579 int32_t c1 = uc16_stream.Advance();
580 int32_t c2 = string_stream.Advance();
581 int32_t c3 = utf8_stream.Advance();
582 i++;
583 CHECK_EQU(i, uc16_stream.pos());
584 CHECK_EQU(i, string_stream.pos());
585 CHECK_EQU(i, utf8_stream.pos());
586 CHECK_EQ(c0, c1);
587 CHECK_EQ(c0, c2);
588 CHECK_EQ(c0, c3);
589 uc16_stream.PushBack(c0);
590 string_stream.PushBack(c0);
591 utf8_stream.PushBack(c0);
592 i--;
593 CHECK_EQU(i, uc16_stream.pos());
594 CHECK_EQU(i, string_stream.pos());
595 CHECK_EQU(i, utf8_stream.pos());
596 }
597 unsigned halfway = start + sub_length / 2;
598 uc16_stream.SeekForward(halfway - i);
599 string_stream.SeekForward(halfway - i);
600 utf8_stream.SeekForward(halfway - i);
601 i = halfway;
602 CHECK_EQU(i, uc16_stream.pos());
603 CHECK_EQU(i, string_stream.pos());
604 CHECK_EQU(i, utf8_stream.pos());
605
606 while (i < end) {
607 // Read streams one char at a time
608 CHECK_EQU(i, uc16_stream.pos());
609 CHECK_EQU(i, string_stream.pos());
610 CHECK_EQU(i, utf8_stream.pos());
611 int32_t c0 = ascii_source[i];
612 int32_t c1 = uc16_stream.Advance();
613 int32_t c2 = string_stream.Advance();
614 int32_t c3 = utf8_stream.Advance();
615 i++;
616 CHECK_EQ(c0, c1);
617 CHECK_EQ(c0, c2);
618 CHECK_EQ(c0, c3);
619 CHECK_EQU(i, uc16_stream.pos());
620 CHECK_EQU(i, string_stream.pos());
621 CHECK_EQU(i, utf8_stream.pos());
622 }
623
624 int32_t c1 = uc16_stream.Advance();
625 int32_t c2 = string_stream.Advance();
626 int32_t c3 = utf8_stream.Advance();
627 CHECK_LT(c1, 0);
628 CHECK_LT(c2, 0);
629 CHECK_LT(c3, 0);
630 }
631
632
TEST(CharacterStreams)633 TEST(CharacterStreams) {
634 v8::Isolate* isolate = CcTest::isolate();
635 v8::HandleScope handles(isolate);
636 v8::Local<v8::Context> context = v8::Context::New(isolate);
637 v8::Context::Scope context_scope(context);
638
639 TestCharacterStream("abc\0\n\r\x7f", 7);
640 static const unsigned kBigStringSize = 4096;
641 char buffer[kBigStringSize + 1];
642 for (unsigned i = 0; i < kBigStringSize; i++) {
643 buffer[i] = static_cast<char>(i & 0x7f);
644 }
645 TestCharacterStream(buffer, kBigStringSize);
646
647 TestCharacterStream(buffer, kBigStringSize, 576, 3298);
648
649 TestCharacterStream("\0", 1);
650 TestCharacterStream("", 0);
651 }
652
653
TEST(Utf8CharacterStream)654 TEST(Utf8CharacterStream) {
655 static const unsigned kMaxUC16CharU = unibrow::Utf8::kMaxThreeByteChar;
656 static const int kMaxUC16Char = static_cast<int>(kMaxUC16CharU);
657
658 static const int kAllUtf8CharsSize =
659 (unibrow::Utf8::kMaxOneByteChar + 1) +
660 (unibrow::Utf8::kMaxTwoByteChar - unibrow::Utf8::kMaxOneByteChar) * 2 +
661 (unibrow::Utf8::kMaxThreeByteChar - unibrow::Utf8::kMaxTwoByteChar) * 3;
662 static const unsigned kAllUtf8CharsSizeU =
663 static_cast<unsigned>(kAllUtf8CharsSize);
664
665 char buffer[kAllUtf8CharsSizeU];
666 unsigned cursor = 0;
667 for (int i = 0; i <= kMaxUC16Char; i++) {
668 cursor += unibrow::Utf8::Encode(buffer + cursor,
669 i,
670 unibrow::Utf16::kNoPreviousCharacter);
671 }
672 ASSERT(cursor == kAllUtf8CharsSizeU);
673
674 i::Utf8ToUtf16CharacterStream stream(reinterpret_cast<const i::byte*>(buffer),
675 kAllUtf8CharsSizeU);
676 for (int i = 0; i <= kMaxUC16Char; i++) {
677 CHECK_EQU(i, stream.pos());
678 int32_t c = stream.Advance();
679 CHECK_EQ(i, c);
680 CHECK_EQU(i + 1, stream.pos());
681 }
682 for (int i = kMaxUC16Char; i >= 0; i--) {
683 CHECK_EQU(i + 1, stream.pos());
684 stream.PushBack(i);
685 CHECK_EQU(i, stream.pos());
686 }
687 int i = 0;
688 while (stream.pos() < kMaxUC16CharU) {
689 CHECK_EQU(i, stream.pos());
690 unsigned progress = stream.SeekForward(12);
691 i += progress;
692 int32_t c = stream.Advance();
693 if (i <= kMaxUC16Char) {
694 CHECK_EQ(i, c);
695 } else {
696 CHECK_EQ(-1, c);
697 }
698 i += 1;
699 CHECK_EQU(i, stream.pos());
700 }
701 }
702
703 #undef CHECK_EQU
704
TestStreamScanner(i::Utf16CharacterStream * stream,i::Token::Value * expected_tokens,int skip_pos=0,int skip_to=0)705 void TestStreamScanner(i::Utf16CharacterStream* stream,
706 i::Token::Value* expected_tokens,
707 int skip_pos = 0, // Zero means not skipping.
708 int skip_to = 0) {
709 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
710 scanner.Initialize(stream);
711
712 int i = 0;
713 do {
714 i::Token::Value expected = expected_tokens[i];
715 i::Token::Value actual = scanner.Next();
716 CHECK_EQ(i::Token::String(expected), i::Token::String(actual));
717 if (scanner.location().end_pos == skip_pos) {
718 scanner.SeekForward(skip_to);
719 }
720 i++;
721 } while (expected_tokens[i] != i::Token::ILLEGAL);
722 }
723
724
TEST(StreamScanner)725 TEST(StreamScanner) {
726 v8::V8::Initialize();
727
728 const char* str1 = "{ foo get for : */ <- \n\n /*foo*/ bib";
729 i::Utf8ToUtf16CharacterStream stream1(reinterpret_cast<const i::byte*>(str1),
730 static_cast<unsigned>(strlen(str1)));
731 i::Token::Value expectations1[] = {
732 i::Token::LBRACE,
733 i::Token::IDENTIFIER,
734 i::Token::IDENTIFIER,
735 i::Token::FOR,
736 i::Token::COLON,
737 i::Token::MUL,
738 i::Token::DIV,
739 i::Token::LT,
740 i::Token::SUB,
741 i::Token::IDENTIFIER,
742 i::Token::EOS,
743 i::Token::ILLEGAL
744 };
745 TestStreamScanner(&stream1, expectations1, 0, 0);
746
747 const char* str2 = "case default const {THIS\nPART\nSKIPPED} do";
748 i::Utf8ToUtf16CharacterStream stream2(reinterpret_cast<const i::byte*>(str2),
749 static_cast<unsigned>(strlen(str2)));
750 i::Token::Value expectations2[] = {
751 i::Token::CASE,
752 i::Token::DEFAULT,
753 i::Token::CONST,
754 i::Token::LBRACE,
755 // Skipped part here
756 i::Token::RBRACE,
757 i::Token::DO,
758 i::Token::EOS,
759 i::Token::ILLEGAL
760 };
761 ASSERT_EQ('{', str2[19]);
762 ASSERT_EQ('}', str2[37]);
763 TestStreamScanner(&stream2, expectations2, 20, 37);
764
765 const char* str3 = "{}}}}";
766 i::Token::Value expectations3[] = {
767 i::Token::LBRACE,
768 i::Token::RBRACE,
769 i::Token::RBRACE,
770 i::Token::RBRACE,
771 i::Token::RBRACE,
772 i::Token::EOS,
773 i::Token::ILLEGAL
774 };
775 // Skip zero-four RBRACEs.
776 for (int i = 0; i <= 4; i++) {
777 expectations3[6 - i] = i::Token::ILLEGAL;
778 expectations3[5 - i] = i::Token::EOS;
779 i::Utf8ToUtf16CharacterStream stream3(
780 reinterpret_cast<const i::byte*>(str3),
781 static_cast<unsigned>(strlen(str3)));
782 TestStreamScanner(&stream3, expectations3, 1, 1 + i);
783 }
784 }
785
786
TestScanRegExp(const char * re_source,const char * expected)787 void TestScanRegExp(const char* re_source, const char* expected) {
788 i::Utf8ToUtf16CharacterStream stream(
789 reinterpret_cast<const i::byte*>(re_source),
790 static_cast<unsigned>(strlen(re_source)));
791 i::HandleScope scope(CcTest::i_isolate());
792 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
793 scanner.Initialize(&stream);
794
795 i::Token::Value start = scanner.peek();
796 CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
797 CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
798 scanner.Next(); // Current token is now the regexp literal.
799 i::Handle<i::String> val =
800 scanner.AllocateInternalizedString(CcTest::i_isolate());
801 i::DisallowHeapAllocation no_alloc;
802 i::String::FlatContent content = val->GetFlatContent();
803 CHECK(content.IsAscii());
804 i::Vector<const uint8_t> actual = content.ToOneByteVector();
805 for (int i = 0; i < actual.length(); i++) {
806 CHECK_NE('\0', expected[i]);
807 CHECK_EQ(expected[i], actual[i]);
808 }
809 }
810
811
TEST(RegExpScanning)812 TEST(RegExpScanning) {
813 v8::V8::Initialize();
814
815 // RegExp token with added garbage at the end. The scanner should only
816 // scan the RegExp until the terminating slash just before "flipperwald".
817 TestScanRegExp("/b/flipperwald", "b");
818 // Incomplete escape sequences doesn't hide the terminating slash.
819 TestScanRegExp("/\\x/flipperwald", "\\x");
820 TestScanRegExp("/\\u/flipperwald", "\\u");
821 TestScanRegExp("/\\u1/flipperwald", "\\u1");
822 TestScanRegExp("/\\u12/flipperwald", "\\u12");
823 TestScanRegExp("/\\u123/flipperwald", "\\u123");
824 TestScanRegExp("/\\c/flipperwald", "\\c");
825 TestScanRegExp("/\\c//flipperwald", "\\c");
826 // Slashes inside character classes are not terminating.
827 TestScanRegExp("/[/]/flipperwald", "[/]");
828 TestScanRegExp("/[\\s-/]/flipperwald", "[\\s-/]");
829 // Incomplete escape sequences inside a character class doesn't hide
830 // the end of the character class.
831 TestScanRegExp("/[\\c/]/flipperwald", "[\\c/]");
832 TestScanRegExp("/[\\c]/flipperwald", "[\\c]");
833 TestScanRegExp("/[\\x]/flipperwald", "[\\x]");
834 TestScanRegExp("/[\\x1]/flipperwald", "[\\x1]");
835 TestScanRegExp("/[\\u]/flipperwald", "[\\u]");
836 TestScanRegExp("/[\\u1]/flipperwald", "[\\u1]");
837 TestScanRegExp("/[\\u12]/flipperwald", "[\\u12]");
838 TestScanRegExp("/[\\u123]/flipperwald", "[\\u123]");
839 // Escaped ']'s wont end the character class.
840 TestScanRegExp("/[\\]/]/flipperwald", "[\\]/]");
841 // Escaped slashes are not terminating.
842 TestScanRegExp("/\\//flipperwald", "\\/");
843 // Starting with '=' works too.
844 TestScanRegExp("/=/", "=");
845 TestScanRegExp("/=?/", "=?");
846 }
847
848
Utf8LengthHelper(const char * s)849 static int Utf8LengthHelper(const char* s) {
850 int len = i::StrLength(s);
851 int character_length = len;
852 for (int i = 0; i < len; i++) {
853 unsigned char c = s[i];
854 int input_offset = 0;
855 int output_adjust = 0;
856 if (c > 0x7f) {
857 if (c < 0xc0) continue;
858 if (c >= 0xf0) {
859 if (c >= 0xf8) {
860 // 5 and 6 byte UTF-8 sequences turn into a kBadChar for each UTF-8
861 // byte.
862 continue; // Handle first UTF-8 byte.
863 }
864 if ((c & 7) == 0 && ((s[i + 1] & 0x30) == 0)) {
865 // This 4 byte sequence could have been coded as a 3 byte sequence.
866 // Record a single kBadChar for the first byte and continue.
867 continue;
868 }
869 input_offset = 3;
870 // 4 bytes of UTF-8 turn into 2 UTF-16 code units.
871 character_length -= 2;
872 } else if (c >= 0xe0) {
873 if ((c & 0xf) == 0 && ((s[i + 1] & 0x20) == 0)) {
874 // This 3 byte sequence could have been coded as a 2 byte sequence.
875 // Record a single kBadChar for the first byte and continue.
876 continue;
877 }
878 input_offset = 2;
879 // 3 bytes of UTF-8 turn into 1 UTF-16 code unit.
880 output_adjust = 2;
881 } else {
882 if ((c & 0x1e) == 0) {
883 // This 2 byte sequence could have been coded as a 1 byte sequence.
884 // Record a single kBadChar for the first byte and continue.
885 continue;
886 }
887 input_offset = 1;
888 // 2 bytes of UTF-8 turn into 1 UTF-16 code unit.
889 output_adjust = 1;
890 }
891 bool bad = false;
892 for (int j = 1; j <= input_offset; j++) {
893 if ((s[i + j] & 0xc0) != 0x80) {
894 // Bad UTF-8 sequence turns the first in the sequence into kBadChar,
895 // which is a single UTF-16 code unit.
896 bad = true;
897 break;
898 }
899 }
900 if (!bad) {
901 i += input_offset;
902 character_length -= output_adjust;
903 }
904 }
905 }
906 return character_length;
907 }
908
909
TEST(ScopePositions)910 TEST(ScopePositions) {
911 v8::internal::FLAG_harmony_scoping = true;
912
913 // Test the parser for correctly setting the start and end positions
914 // of a scope. We check the scope positions of exactly one scope
915 // nested in the global scope of a program. 'inner source' is the
916 // source code that determines the part of the source belonging
917 // to the nested scope. 'outer_prefix' and 'outer_suffix' are
918 // parts of the source that belong to the global scope.
919 struct SourceData {
920 const char* outer_prefix;
921 const char* inner_source;
922 const char* outer_suffix;
923 i::ScopeType scope_type;
924 i::StrictMode strict_mode;
925 };
926
927 const SourceData source_data[] = {
928 { " with ({}) ", "{ block; }", " more;", i::WITH_SCOPE, i::SLOPPY },
929 { " with ({}) ", "{ block; }", "; more;", i::WITH_SCOPE, i::SLOPPY },
930 { " with ({}) ", "{\n"
931 " block;\n"
932 " }", "\n"
933 " more;", i::WITH_SCOPE, i::SLOPPY },
934 { " with ({}) ", "statement;", " more;", i::WITH_SCOPE, i::SLOPPY },
935 { " with ({}) ", "statement", "\n"
936 " more;", i::WITH_SCOPE, i::SLOPPY },
937 { " with ({})\n"
938 " ", "statement;", "\n"
939 " more;", i::WITH_SCOPE, i::SLOPPY },
940 { " try {} catch ", "(e) { block; }", " more;",
941 i::CATCH_SCOPE, i::SLOPPY },
942 { " try {} catch ", "(e) { block; }", "; more;",
943 i::CATCH_SCOPE, i::SLOPPY },
944 { " try {} catch ", "(e) {\n"
945 " block;\n"
946 " }", "\n"
947 " more;", i::CATCH_SCOPE, i::SLOPPY },
948 { " try {} catch ", "(e) { block; }", " finally { block; } more;",
949 i::CATCH_SCOPE, i::SLOPPY },
950 { " start;\n"
951 " ", "{ let block; }", " more;", i::BLOCK_SCOPE, i::STRICT },
952 { " start;\n"
953 " ", "{ let block; }", "; more;", i::BLOCK_SCOPE, i::STRICT },
954 { " start;\n"
955 " ", "{\n"
956 " let block;\n"
957 " }", "\n"
958 " more;", i::BLOCK_SCOPE, i::STRICT },
959 { " start;\n"
960 " function fun", "(a,b) { infunction; }", " more;",
961 i::FUNCTION_SCOPE, i::SLOPPY },
962 { " start;\n"
963 " function fun", "(a,b) {\n"
964 " infunction;\n"
965 " }", "\n"
966 " more;", i::FUNCTION_SCOPE, i::SLOPPY },
967 { " (function fun", "(a,b) { infunction; }", ")();",
968 i::FUNCTION_SCOPE, i::SLOPPY },
969 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;",
970 i::BLOCK_SCOPE, i::STRICT },
971 { " for ", "(let x = 1 ; x < 10; ++ x) { block; }", "; more;",
972 i::BLOCK_SCOPE, i::STRICT },
973 { " for ", "(let x = 1 ; x < 10; ++ x) {\n"
974 " block;\n"
975 " }", "\n"
976 " more;", i::BLOCK_SCOPE, i::STRICT },
977 { " for ", "(let x = 1 ; x < 10; ++ x) statement;", " more;",
978 i::BLOCK_SCOPE, i::STRICT },
979 { " for ", "(let x = 1 ; x < 10; ++ x) statement", "\n"
980 " more;", i::BLOCK_SCOPE, i::STRICT },
981 { " for ", "(let x = 1 ; x < 10; ++ x)\n"
982 " statement;", "\n"
983 " more;", i::BLOCK_SCOPE, i::STRICT },
984 { " for ", "(let x in {}) { block; }", " more;",
985 i::BLOCK_SCOPE, i::STRICT },
986 { " for ", "(let x in {}) { block; }", "; more;",
987 i::BLOCK_SCOPE, i::STRICT },
988 { " for ", "(let x in {}) {\n"
989 " block;\n"
990 " }", "\n"
991 " more;", i::BLOCK_SCOPE, i::STRICT },
992 { " for ", "(let x in {}) statement;", " more;",
993 i::BLOCK_SCOPE, i::STRICT },
994 { " for ", "(let x in {}) statement", "\n"
995 " more;", i::BLOCK_SCOPE, i::STRICT },
996 { " for ", "(let x in {})\n"
997 " statement;", "\n"
998 " more;", i::BLOCK_SCOPE, i::STRICT },
999 // Check that 6-byte and 4-byte encodings of UTF-8 strings do not throw
1000 // the preparser off in terms of byte offsets.
1001 // 6 byte encoding.
1002 { " 'foo\355\240\201\355\260\211';\n"
1003 " (function fun", "(a,b) { infunction; }", ")();",
1004 i::FUNCTION_SCOPE, i::SLOPPY },
1005 // 4 byte encoding.
1006 { " 'foo\360\220\220\212';\n"
1007 " (function fun", "(a,b) { infunction; }", ")();",
1008 i::FUNCTION_SCOPE, i::SLOPPY },
1009 // 3 byte encoding of \u0fff.
1010 { " 'foo\340\277\277';\n"
1011 " (function fun", "(a,b) { infunction; }", ")();",
1012 i::FUNCTION_SCOPE, i::SLOPPY },
1013 // Broken 6 byte encoding with missing last byte.
1014 { " 'foo\355\240\201\355\211';\n"
1015 " (function fun", "(a,b) { infunction; }", ")();",
1016 i::FUNCTION_SCOPE, i::SLOPPY },
1017 // Broken 3 byte encoding of \u0fff with missing last byte.
1018 { " 'foo\340\277';\n"
1019 " (function fun", "(a,b) { infunction; }", ")();",
1020 i::FUNCTION_SCOPE, i::SLOPPY },
1021 // Broken 3 byte encoding of \u0fff with missing 2 last bytes.
1022 { " 'foo\340';\n"
1023 " (function fun", "(a,b) { infunction; }", ")();",
1024 i::FUNCTION_SCOPE, i::SLOPPY },
1025 // Broken 3 byte encoding of \u00ff should be a 2 byte encoding.
1026 { " 'foo\340\203\277';\n"
1027 " (function fun", "(a,b) { infunction; }", ")();",
1028 i::FUNCTION_SCOPE, i::SLOPPY },
1029 // Broken 3 byte encoding of \u007f should be a 2 byte encoding.
1030 { " 'foo\340\201\277';\n"
1031 " (function fun", "(a,b) { infunction; }", ")();",
1032 i::FUNCTION_SCOPE, i::SLOPPY },
1033 // Unpaired lead surrogate.
1034 { " 'foo\355\240\201';\n"
1035 " (function fun", "(a,b) { infunction; }", ")();",
1036 i::FUNCTION_SCOPE, i::SLOPPY },
1037 // Unpaired lead surrogate where following code point is a 3 byte sequence.
1038 { " 'foo\355\240\201\340\277\277';\n"
1039 " (function fun", "(a,b) { infunction; }", ")();",
1040 i::FUNCTION_SCOPE, i::SLOPPY },
1041 // Unpaired lead surrogate where following code point is a 4 byte encoding
1042 // of a trail surrogate.
1043 { " 'foo\355\240\201\360\215\260\211';\n"
1044 " (function fun", "(a,b) { infunction; }", ")();",
1045 i::FUNCTION_SCOPE, i::SLOPPY },
1046 // Unpaired trail surrogate.
1047 { " 'foo\355\260\211';\n"
1048 " (function fun", "(a,b) { infunction; }", ")();",
1049 i::FUNCTION_SCOPE, i::SLOPPY },
1050 // 2 byte encoding of \u00ff.
1051 { " 'foo\303\277';\n"
1052 " (function fun", "(a,b) { infunction; }", ")();",
1053 i::FUNCTION_SCOPE, i::SLOPPY },
1054 // Broken 2 byte encoding of \u00ff with missing last byte.
1055 { " 'foo\303';\n"
1056 " (function fun", "(a,b) { infunction; }", ")();",
1057 i::FUNCTION_SCOPE, i::SLOPPY },
1058 // Broken 2 byte encoding of \u007f should be a 1 byte encoding.
1059 { " 'foo\301\277';\n"
1060 " (function fun", "(a,b) { infunction; }", ")();",
1061 i::FUNCTION_SCOPE, i::SLOPPY },
1062 // Illegal 5 byte encoding.
1063 { " 'foo\370\277\277\277\277';\n"
1064 " (function fun", "(a,b) { infunction; }", ")();",
1065 i::FUNCTION_SCOPE, i::SLOPPY },
1066 // Illegal 6 byte encoding.
1067 { " 'foo\374\277\277\277\277\277';\n"
1068 " (function fun", "(a,b) { infunction; }", ")();",
1069 i::FUNCTION_SCOPE, i::SLOPPY },
1070 // Illegal 0xfe byte
1071 { " 'foo\376\277\277\277\277\277\277';\n"
1072 " (function fun", "(a,b) { infunction; }", ")();",
1073 i::FUNCTION_SCOPE, i::SLOPPY },
1074 // Illegal 0xff byte
1075 { " 'foo\377\277\277\277\277\277\277\277';\n"
1076 " (function fun", "(a,b) { infunction; }", ")();",
1077 i::FUNCTION_SCOPE, i::SLOPPY },
1078 { " 'foo';\n"
1079 " (function fun", "(a,b) { 'bar\355\240\201\355\260\213'; }", ")();",
1080 i::FUNCTION_SCOPE, i::SLOPPY },
1081 { " 'foo';\n"
1082 " (function fun", "(a,b) { 'bar\360\220\220\214'; }", ")();",
1083 i::FUNCTION_SCOPE, i::SLOPPY },
1084 { NULL, NULL, NULL, i::EVAL_SCOPE, i::SLOPPY }
1085 };
1086
1087 i::Isolate* isolate = CcTest::i_isolate();
1088 i::Factory* factory = isolate->factory();
1089
1090 v8::HandleScope handles(CcTest::isolate());
1091 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1092 v8::Context::Scope context_scope(context);
1093
1094 int marker;
1095 isolate->stack_guard()->SetStackLimit(
1096 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1097
1098 for (int i = 0; source_data[i].outer_prefix; i++) {
1099 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1100 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1101 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1102 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1103 int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1104 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1105 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1106 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1107 i::ScopedVector<char> program(kProgramByteSize + 1);
1108 i::SNPrintF(program, "%s%s%s",
1109 source_data[i].outer_prefix,
1110 source_data[i].inner_source,
1111 source_data[i].outer_suffix);
1112
1113 // Parse program source.
1114 i::Handle<i::String> source = factory->NewStringFromUtf8(
1115 i::CStrVector(program.start())).ToHandleChecked();
1116 CHECK_EQ(source->length(), kProgramSize);
1117 i::Handle<i::Script> script = factory->NewScript(source);
1118 i::CompilationInfoWithZone info(script);
1119 i::Parser parser(&info);
1120 parser.set_allow_lazy(true);
1121 parser.set_allow_harmony_scoping(true);
1122 info.MarkAsGlobal();
1123 info.SetStrictMode(source_data[i].strict_mode);
1124 parser.Parse();
1125 CHECK(info.function() != NULL);
1126
1127 // Check scope types and positions.
1128 i::Scope* scope = info.function()->scope();
1129 CHECK(scope->is_global_scope());
1130 CHECK_EQ(scope->start_position(), 0);
1131 CHECK_EQ(scope->end_position(), kProgramSize);
1132 CHECK_EQ(scope->inner_scopes()->length(), 1);
1133
1134 i::Scope* inner_scope = scope->inner_scopes()->at(0);
1135 CHECK_EQ(inner_scope->scope_type(), source_data[i].scope_type);
1136 CHECK_EQ(inner_scope->start_position(), kPrefixLen);
1137 // The end position of a token is one position after the last
1138 // character belonging to that token.
1139 CHECK_EQ(inner_scope->end_position(), kPrefixLen + kInnerLen);
1140 }
1141 }
1142
1143
FormatMessage(i::ScriptData * data)1144 i::Handle<i::String> FormatMessage(i::ScriptData* data) {
1145 i::Isolate* isolate = CcTest::i_isolate();
1146 i::Factory* factory = isolate->factory();
1147 const char* message = data->BuildMessage();
1148 i::Handle<i::String> format = v8::Utils::OpenHandle(
1149 *v8::String::NewFromUtf8(CcTest::isolate(), message));
1150 const char* arg = data->BuildArg();
1151 i::Handle<i::JSArray> args_array = factory->NewJSArray(arg == NULL ? 0 : 1);
1152 if (arg != NULL) {
1153 i::JSArray::SetElement(
1154 args_array, 0, v8::Utils::OpenHandle(*v8::String::NewFromUtf8(
1155 CcTest::isolate(), arg)),
1156 NONE, i::SLOPPY).Check();
1157 }
1158 i::Handle<i::JSObject> builtins(isolate->js_builtins_object());
1159 i::Handle<i::Object> format_fun = i::Object::GetProperty(
1160 isolate, builtins, "FormatMessage").ToHandleChecked();
1161 i::Handle<i::Object> arg_handles[] = { format, args_array };
1162 i::Handle<i::Object> result = i::Execution::Call(
1163 isolate, format_fun, builtins, 2, arg_handles).ToHandleChecked();
1164 CHECK(result->IsString());
1165 i::DeleteArray(message);
1166 i::DeleteArray(arg);
1167 return i::Handle<i::String>::cast(result);
1168 }
1169
1170
1171 enum ParserFlag {
1172 kAllowLazy,
1173 kAllowNativesSyntax,
1174 kAllowHarmonyScoping,
1175 kAllowModules,
1176 kAllowGenerators,
1177 kAllowForOf,
1178 kAllowHarmonyNumericLiterals
1179 };
1180
1181
1182 enum ParserSyncTestResult {
1183 kSuccessOrError,
1184 kSuccess,
1185 kError
1186 };
1187
1188 template <typename Traits>
SetParserFlags(i::ParserBase<Traits> * parser,i::EnumSet<ParserFlag> flags)1189 void SetParserFlags(i::ParserBase<Traits>* parser,
1190 i::EnumSet<ParserFlag> flags) {
1191 parser->set_allow_lazy(flags.Contains(kAllowLazy));
1192 parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
1193 parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
1194 parser->set_allow_modules(flags.Contains(kAllowModules));
1195 parser->set_allow_generators(flags.Contains(kAllowGenerators));
1196 parser->set_allow_for_of(flags.Contains(kAllowForOf));
1197 parser->set_allow_harmony_numeric_literals(
1198 flags.Contains(kAllowHarmonyNumericLiterals));
1199 }
1200
1201
TestParserSyncWithFlags(i::Handle<i::String> source,i::EnumSet<ParserFlag> flags,ParserSyncTestResult result)1202 void TestParserSyncWithFlags(i::Handle<i::String> source,
1203 i::EnumSet<ParserFlag> flags,
1204 ParserSyncTestResult result) {
1205 i::Isolate* isolate = CcTest::i_isolate();
1206 i::Factory* factory = isolate->factory();
1207
1208 uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1209
1210 // Preparse the data.
1211 i::CompleteParserRecorder log;
1212 {
1213 i::Scanner scanner(isolate->unicode_cache());
1214 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
1215 i::PreParser preparser(&scanner, &log, stack_limit);
1216 SetParserFlags(&preparser, flags);
1217 scanner.Initialize(&stream);
1218 i::PreParser::PreParseResult result = preparser.PreParseProgram();
1219 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1220 }
1221 i::ScriptData data(log.ExtractData());
1222
1223 // Parse the data
1224 i::FunctionLiteral* function;
1225 {
1226 i::Handle<i::Script> script = factory->NewScript(source);
1227 i::CompilationInfoWithZone info(script);
1228 i::Parser parser(&info);
1229 SetParserFlags(&parser, flags);
1230 info.MarkAsGlobal();
1231 parser.Parse();
1232 function = info.function();
1233 }
1234
1235 // Check that preparsing fails iff parsing fails.
1236 if (function == NULL) {
1237 // Extract exception from the parser.
1238 CHECK(isolate->has_pending_exception());
1239 i::Handle<i::JSObject> exception_handle(
1240 i::JSObject::cast(isolate->pending_exception()));
1241 i::Handle<i::String> message_string =
1242 i::Handle<i::String>::cast(i::Object::GetProperty(
1243 isolate, exception_handle, "message").ToHandleChecked());
1244
1245 if (result == kSuccess) {
1246 i::OS::Print(
1247 "Parser failed on:\n"
1248 "\t%s\n"
1249 "with error:\n"
1250 "\t%s\n"
1251 "However, we expected no error.",
1252 source->ToCString().get(), message_string->ToCString().get());
1253 CHECK(false);
1254 }
1255
1256 if (!data.has_error()) {
1257 i::OS::Print(
1258 "Parser failed on:\n"
1259 "\t%s\n"
1260 "with error:\n"
1261 "\t%s\n"
1262 "However, the preparser succeeded",
1263 source->ToCString().get(), message_string->ToCString().get());
1264 CHECK(false);
1265 }
1266 // Check that preparser and parser produce the same error.
1267 i::Handle<i::String> preparser_message = FormatMessage(&data);
1268 if (!i::String::Equals(message_string, preparser_message)) {
1269 i::OS::Print(
1270 "Expected parser and preparser to produce the same error on:\n"
1271 "\t%s\n"
1272 "However, found the following error messages\n"
1273 "\tparser: %s\n"
1274 "\tpreparser: %s\n",
1275 source->ToCString().get(),
1276 message_string->ToCString().get(),
1277 preparser_message->ToCString().get());
1278 CHECK(false);
1279 }
1280 } else if (data.has_error()) {
1281 i::OS::Print(
1282 "Preparser failed on:\n"
1283 "\t%s\n"
1284 "with error:\n"
1285 "\t%s\n"
1286 "However, the parser succeeded",
1287 source->ToCString().get(), FormatMessage(&data)->ToCString().get());
1288 CHECK(false);
1289 } else if (result == kError) {
1290 i::OS::Print(
1291 "Expected error on:\n"
1292 "\t%s\n"
1293 "However, parser and preparser succeeded",
1294 source->ToCString().get());
1295 CHECK(false);
1296 }
1297 }
1298
1299
TestParserSync(const char * source,const ParserFlag * flag_list,size_t flag_list_length,ParserSyncTestResult result=kSuccessOrError)1300 void TestParserSync(const char* source,
1301 const ParserFlag* flag_list,
1302 size_t flag_list_length,
1303 ParserSyncTestResult result = kSuccessOrError) {
1304 i::Handle<i::String> str =
1305 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source);
1306 for (int bits = 0; bits < (1 << flag_list_length); bits++) {
1307 i::EnumSet<ParserFlag> flags;
1308 for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) {
1309 if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]);
1310 }
1311 TestParserSyncWithFlags(str, flags, result);
1312 }
1313 }
1314
1315
TEST(ParserSync)1316 TEST(ParserSync) {
1317 const char* context_data[][2] = {
1318 { "", "" },
1319 { "{", "}" },
1320 { "if (true) ", " else {}" },
1321 { "if (true) {} else ", "" },
1322 { "if (true) ", "" },
1323 { "do ", " while (false)" },
1324 { "while (false) ", "" },
1325 { "for (;;) ", "" },
1326 { "with ({})", "" },
1327 { "switch (12) { case 12: ", "}" },
1328 { "switch (12) { default: ", "}" },
1329 { "switch (12) { ", "case 12: }" },
1330 { "label2: ", "" },
1331 { NULL, NULL }
1332 };
1333
1334 const char* statement_data[] = {
1335 "{}",
1336 "var x",
1337 "var x = 1",
1338 "const x",
1339 "const x = 1",
1340 ";",
1341 "12",
1342 "if (false) {} else ;",
1343 "if (false) {} else {}",
1344 "if (false) {} else 12",
1345 "if (false) ;"
1346 "if (false) {}",
1347 "if (false) 12",
1348 "do {} while (false)",
1349 "for (;;) ;",
1350 "for (;;) {}",
1351 "for (;;) 12",
1352 "continue",
1353 "continue label",
1354 "continue\nlabel",
1355 "break",
1356 "break label",
1357 "break\nlabel",
1358 // TODO(marja): activate once parsing 'return' is merged into ParserBase.
1359 // "return",
1360 // "return 12",
1361 // "return\n12",
1362 "with ({}) ;",
1363 "with ({}) {}",
1364 "with ({}) 12",
1365 "switch ({}) { default: }"
1366 "label3: "
1367 "throw",
1368 "throw 12",
1369 "throw\n12",
1370 "try {} catch(e) {}",
1371 "try {} finally {}",
1372 "try {} catch(e) {} finally {}",
1373 "debugger",
1374 NULL
1375 };
1376
1377 const char* termination_data[] = {
1378 "",
1379 ";",
1380 "\n",
1381 ";\n",
1382 "\n;",
1383 NULL
1384 };
1385
1386 v8::HandleScope handles(CcTest::isolate());
1387 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1388 v8::Context::Scope context_scope(context);
1389
1390 int marker;
1391 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1392 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1393
1394 static const ParserFlag flags1[] = {
1395 kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
1396 kAllowForOf
1397 };
1398 for (int i = 0; context_data[i][0] != NULL; ++i) {
1399 for (int j = 0; statement_data[j] != NULL; ++j) {
1400 for (int k = 0; termination_data[k] != NULL; ++k) {
1401 int kPrefixLen = i::StrLength(context_data[i][0]);
1402 int kStatementLen = i::StrLength(statement_data[j]);
1403 int kTerminationLen = i::StrLength(termination_data[k]);
1404 int kSuffixLen = i::StrLength(context_data[i][1]);
1405 int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
1406 + kSuffixLen + i::StrLength("label: for (;;) { }");
1407
1408 // Plug the source code pieces together.
1409 i::ScopedVector<char> program(kProgramSize + 1);
1410 int length = i::SNPrintF(program,
1411 "label: for (;;) { %s%s%s%s }",
1412 context_data[i][0],
1413 statement_data[j],
1414 termination_data[k],
1415 context_data[i][1]);
1416 CHECK(length == kProgramSize);
1417 TestParserSync(program.start(), flags1, ARRAY_SIZE(flags1));
1418 }
1419 }
1420 }
1421
1422 // Neither Harmony numeric literals nor our natives syntax have any
1423 // interaction with the flags above, so test these separately to reduce
1424 // the combinatorial explosion.
1425 static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals };
1426 TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2));
1427 TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2));
1428
1429 static const ParserFlag flags3[] = { kAllowNativesSyntax };
1430 TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3));
1431 }
1432
1433
TEST(StrictOctal)1434 TEST(StrictOctal) {
1435 // Test that syntax error caused by octal literal is reported correctly as
1436 // such (issue 2220).
1437 v8::V8::Initialize();
1438 v8::HandleScope scope(CcTest::isolate());
1439 v8::Context::Scope context_scope(
1440 v8::Context::New(CcTest::isolate()));
1441 v8::TryCatch try_catch;
1442 const char* script =
1443 "\"use strict\"; \n"
1444 "a = function() { \n"
1445 " b = function() { \n"
1446 " 01; \n"
1447 " }; \n"
1448 "}; \n";
1449 v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script));
1450 CHECK(try_catch.HasCaught());
1451 v8::String::Utf8Value exception(try_catch.Exception());
1452 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
1453 *exception);
1454 }
1455
1456
RunParserSyncTest(const char * context_data[][2],const char * statement_data[],ParserSyncTestResult result,const ParserFlag * flags=NULL,int flags_len=0)1457 void RunParserSyncTest(const char* context_data[][2],
1458 const char* statement_data[],
1459 ParserSyncTestResult result,
1460 const ParserFlag* flags = NULL,
1461 int flags_len = 0) {
1462 v8::HandleScope handles(CcTest::isolate());
1463 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1464 v8::Context::Scope context_scope(context);
1465
1466 int marker;
1467 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1468 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1469
1470 static const ParserFlag default_flags[] = {
1471 kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
1472 kAllowForOf, kAllowNativesSyntax
1473 };
1474 if (!flags) {
1475 flags = default_flags;
1476 flags_len = ARRAY_SIZE(default_flags);
1477 }
1478 for (int i = 0; context_data[i][0] != NULL; ++i) {
1479 for (int j = 0; statement_data[j] != NULL; ++j) {
1480 int kPrefixLen = i::StrLength(context_data[i][0]);
1481 int kStatementLen = i::StrLength(statement_data[j]);
1482 int kSuffixLen = i::StrLength(context_data[i][1]);
1483 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1484
1485 // Plug the source code pieces together.
1486 i::ScopedVector<char> program(kProgramSize + 1);
1487 int length = i::SNPrintF(program,
1488 "%s%s%s",
1489 context_data[i][0],
1490 statement_data[j],
1491 context_data[i][1]);
1492 CHECK(length == kProgramSize);
1493 TestParserSync(program.start(),
1494 flags,
1495 flags_len,
1496 result);
1497 }
1498 }
1499 }
1500
1501
TEST(ErrorsEvalAndArguments)1502 TEST(ErrorsEvalAndArguments) {
1503 // Tests that both preparsing and parsing produce the right kind of errors for
1504 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1505 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1506 // isn't.
1507 const char* context_data[][2] = {
1508 { "\"use strict\";", "" },
1509 { "var eval; function test_func() {\"use strict\"; ", "}"},
1510 { NULL, NULL }
1511 };
1512
1513 const char* statement_data[] = {
1514 "var eval;",
1515 "var arguments",
1516 "var foo, eval;",
1517 "var foo, arguments;",
1518 "try { } catch (eval) { }",
1519 "try { } catch (arguments) { }",
1520 "function eval() { }",
1521 "function arguments() { }",
1522 "function foo(eval) { }",
1523 "function foo(arguments) { }",
1524 "function foo(bar, eval) { }",
1525 "function foo(bar, arguments) { }",
1526 "eval = 1;",
1527 "arguments = 1;",
1528 "var foo = eval = 1;",
1529 "var foo = arguments = 1;",
1530 "++eval;",
1531 "++arguments;",
1532 "eval++;",
1533 "arguments++;",
1534 NULL
1535 };
1536
1537 RunParserSyncTest(context_data, statement_data, kError);
1538 }
1539
1540
TEST(NoErrorsEvalAndArgumentsSloppy)1541 TEST(NoErrorsEvalAndArgumentsSloppy) {
1542 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1543 // identifiers when needed.
1544 const char* context_data[][2] = {
1545 { "", "" },
1546 { "function test_func() {", "}"},
1547 { NULL, NULL }
1548 };
1549
1550 const char* statement_data[] = {
1551 "var eval;",
1552 "var arguments",
1553 "var foo, eval;",
1554 "var foo, arguments;",
1555 "try { } catch (eval) { }",
1556 "try { } catch (arguments) { }",
1557 "function eval() { }",
1558 "function arguments() { }",
1559 "function foo(eval) { }",
1560 "function foo(arguments) { }",
1561 "function foo(bar, eval) { }",
1562 "function foo(bar, arguments) { }",
1563 "eval = 1;",
1564 "arguments = 1;",
1565 "var foo = eval = 1;",
1566 "var foo = arguments = 1;",
1567 "++eval;",
1568 "++arguments;",
1569 "eval++;",
1570 "arguments++;",
1571 NULL
1572 };
1573
1574 RunParserSyncTest(context_data, statement_data, kSuccess);
1575 }
1576
1577
TEST(NoErrorsEvalAndArgumentsStrict)1578 TEST(NoErrorsEvalAndArgumentsStrict) {
1579 const char* context_data[][2] = {
1580 { "\"use strict\";", "" },
1581 { "function test_func() { \"use strict\";", "}" },
1582 { NULL, NULL }
1583 };
1584
1585 const char* statement_data[] = {
1586 "eval;",
1587 "arguments;",
1588 "var foo = eval;",
1589 "var foo = arguments;",
1590 "var foo = { eval: 1 };",
1591 "var foo = { arguments: 1 };",
1592 "var foo = { }; foo.eval = {};",
1593 "var foo = { }; foo.arguments = {};",
1594 NULL
1595 };
1596
1597 RunParserSyncTest(context_data, statement_data, kSuccess);
1598 }
1599
1600
TEST(ErrorsFutureStrictReservedWords)1601 TEST(ErrorsFutureStrictReservedWords) {
1602 // Tests that both preparsing and parsing produce the right kind of errors for
1603 // using future strict reserved words as identifiers. Without the strict mode,
1604 // it's ok to use future strict reserved words as identifiers. With the strict
1605 // mode, it isn't.
1606 const char* context_data[][2] = {
1607 { "\"use strict\";", "" },
1608 { "function test_func() {\"use strict\"; ", "}"},
1609 { NULL, NULL }
1610 };
1611
1612 const char* statement_data[] = {
1613 "var interface;",
1614 "var foo, interface;",
1615 "try { } catch (interface) { }",
1616 "function interface() { }",
1617 "function foo(interface) { }",
1618 "function foo(bar, interface) { }",
1619 "interface = 1;",
1620 "var foo = interface = 1;",
1621 "++interface;",
1622 "interface++;",
1623 NULL
1624 };
1625
1626 RunParserSyncTest(context_data, statement_data, kError);
1627 }
1628
1629
TEST(NoErrorsFutureStrictReservedWords)1630 TEST(NoErrorsFutureStrictReservedWords) {
1631 const char* context_data[][2] = {
1632 { "", "" },
1633 { "function test_func() {", "}"},
1634 { NULL, NULL }
1635 };
1636
1637 const char* statement_data[] = {
1638 "var interface;",
1639 "var foo, interface;",
1640 "try { } catch (interface) { }",
1641 "function interface() { }",
1642 "function foo(interface) { }",
1643 "function foo(bar, interface) { }",
1644 "interface = 1;",
1645 "var foo = interface = 1;",
1646 "++interface;",
1647 "interface++;",
1648 NULL
1649 };
1650
1651 RunParserSyncTest(context_data, statement_data, kSuccess);
1652 }
1653
1654
TEST(ErrorsReservedWords)1655 TEST(ErrorsReservedWords) {
1656 // Tests that both preparsing and parsing produce the right kind of errors for
1657 // using future reserved words as identifiers. These tests don't depend on the
1658 // strict mode.
1659 const char* context_data[][2] = {
1660 { "", "" },
1661 { "\"use strict\";", "" },
1662 { "var eval; function test_func() {", "}"},
1663 { "var eval; function test_func() {\"use strict\"; ", "}"},
1664 { NULL, NULL }
1665 };
1666
1667 const char* statement_data[] = {
1668 "var super;",
1669 "var foo, super;",
1670 "try { } catch (super) { }",
1671 "function super() { }",
1672 "function foo(super) { }",
1673 "function foo(bar, super) { }",
1674 "super = 1;",
1675 "var foo = super = 1;",
1676 "++super;",
1677 "super++;",
1678 "function foo super",
1679 NULL
1680 };
1681
1682 RunParserSyncTest(context_data, statement_data, kError);
1683 }
1684
1685
TEST(NoErrorsYieldSloppy)1686 TEST(NoErrorsYieldSloppy) {
1687 // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
1688 // generator (see next test).
1689 const char* context_data[][2] = {
1690 { "", "" },
1691 { "function is_not_gen() {", "}" },
1692 { NULL, NULL }
1693 };
1694
1695 const char* statement_data[] = {
1696 "var yield;",
1697 "var foo, yield;",
1698 "try { } catch (yield) { }",
1699 "function yield() { }",
1700 "function foo(yield) { }",
1701 "function foo(bar, yield) { }",
1702 "yield = 1;",
1703 "var foo = yield = 1;",
1704 "++yield;",
1705 "yield++;",
1706 NULL
1707 };
1708
1709 RunParserSyncTest(context_data, statement_data, kSuccess);
1710 }
1711
1712
TEST(ErrorsYieldSloppyGenerator)1713 TEST(ErrorsYieldSloppyGenerator) {
1714 const char* context_data[][2] = {
1715 { "function * is_gen() {", "}" },
1716 { NULL, NULL }
1717 };
1718
1719 const char* statement_data[] = {
1720 "var yield;",
1721 "var foo, yield;",
1722 "try { } catch (yield) { }",
1723 "function yield() { }",
1724 // BUG: These should not be allowed, but they are (if kAllowGenerators is
1725 // set)
1726 // "function foo(yield) { }",
1727 // "function foo(bar, yield) { }",
1728 "yield = 1;",
1729 "var foo = yield = 1;",
1730 "++yield;",
1731 "yield++;",
1732 NULL
1733 };
1734
1735 // If generators are not allowed, the error will be produced at the '*' token,
1736 // so this test works both with and without the kAllowGenerators flag.
1737 RunParserSyncTest(context_data, statement_data, kError);
1738 }
1739
1740
TEST(ErrorsYieldStrict)1741 TEST(ErrorsYieldStrict) {
1742 const char* context_data[][2] = {
1743 { "\"use strict\";", "" },
1744 { "\"use strict\"; function is_not_gen() {", "}" },
1745 { "function test_func() {\"use strict\"; ", "}"},
1746 { NULL, NULL }
1747 };
1748
1749 const char* statement_data[] = {
1750 "var yield;",
1751 "var foo, yield;",
1752 "try { } catch (yield) { }",
1753 "function yield() { }",
1754 "function foo(yield) { }",
1755 "function foo(bar, yield) { }",
1756 "yield = 1;",
1757 "var foo = yield = 1;",
1758 "++yield;",
1759 "yield++;",
1760 NULL
1761 };
1762
1763 RunParserSyncTest(context_data, statement_data, kError);
1764 }
1765
1766
TEST(ErrorsYield)1767 TEST(ErrorsYield) {
1768 const char* context_data[][2] = {
1769 { "function * is_gen() {", "}" },
1770 { NULL, NULL }
1771 };
1772
1773 const char* statement_data[] = {
1774 "yield 2;", // this is legal inside generator
1775 "yield * 2;", // this is legal inside generator
1776 NULL
1777 };
1778
1779 // Here we cannot assert that there is no error, since there will be without
1780 // the kAllowGenerators flag. However, we test that Parser and PreParser
1781 // produce the same errors.
1782 RunParserSyncTest(context_data, statement_data, kSuccessOrError);
1783 }
1784
1785
TEST(ErrorsNameOfStrictFunction)1786 TEST(ErrorsNameOfStrictFunction) {
1787 // Tests that illegal tokens as names of a strict function produce the correct
1788 // errors.
1789 const char* context_data[][2] = {
1790 { "", ""},
1791 { "\"use strict\";", ""},
1792 { NULL, NULL }
1793 };
1794
1795 const char* statement_data[] = {
1796 "function eval() {\"use strict\";}",
1797 "function arguments() {\"use strict\";}",
1798 "function interface() {\"use strict\";}",
1799 "function yield() {\"use strict\";}",
1800 // Future reserved words are always illegal
1801 "function super() { }",
1802 "function super() {\"use strict\";}",
1803 NULL
1804 };
1805
1806 RunParserSyncTest(context_data, statement_data, kError);
1807 }
1808
1809
TEST(NoErrorsNameOfStrictFunction)1810 TEST(NoErrorsNameOfStrictFunction) {
1811 const char* context_data[][2] = {
1812 { "", ""},
1813 { NULL, NULL }
1814 };
1815
1816 const char* statement_data[] = {
1817 "function eval() { }",
1818 "function arguments() { }",
1819 "function interface() { }",
1820 "function yield() { }",
1821 NULL
1822 };
1823
1824 RunParserSyncTest(context_data, statement_data, kSuccess);
1825 }
1826
1827
1828
TEST(ErrorsIllegalWordsAsLabelsSloppy)1829 TEST(ErrorsIllegalWordsAsLabelsSloppy) {
1830 // Using future reserved words as labels is always an error.
1831 const char* context_data[][2] = {
1832 { "", ""},
1833 { "function test_func() {", "}" },
1834 { NULL, NULL }
1835 };
1836
1837 const char* statement_data[] = {
1838 "super: while(true) { break super; }",
1839 NULL
1840 };
1841
1842 RunParserSyncTest(context_data, statement_data, kError);
1843 }
1844
1845
TEST(ErrorsIllegalWordsAsLabelsStrict)1846 TEST(ErrorsIllegalWordsAsLabelsStrict) {
1847 // Tests that illegal tokens as labels produce the correct errors.
1848 const char* context_data[][2] = {
1849 { "\"use strict\";", "" },
1850 { "function test_func() {\"use strict\"; ", "}"},
1851 { NULL, NULL }
1852 };
1853
1854 const char* statement_data[] = {
1855 "super: while(true) { break super; }",
1856 "interface: while(true) { break interface; }",
1857 "yield: while(true) { break yield; }",
1858 NULL
1859 };
1860
1861 RunParserSyncTest(context_data, statement_data, kError);
1862 }
1863
1864
TEST(NoErrorsIllegalWordsAsLabels)1865 TEST(NoErrorsIllegalWordsAsLabels) {
1866 // Using eval and arguments as labels is legal even in strict mode.
1867 const char* context_data[][2] = {
1868 { "", ""},
1869 { "function test_func() {", "}" },
1870 { "\"use strict\";", "" },
1871 { "\"use strict\"; function test_func() {", "}" },
1872 { NULL, NULL }
1873 };
1874
1875 const char* statement_data[] = {
1876 "mylabel: while(true) { break mylabel; }",
1877 "eval: while(true) { break eval; }",
1878 "arguments: while(true) { break arguments; }",
1879 NULL
1880 };
1881
1882 RunParserSyncTest(context_data, statement_data, kSuccess);
1883 }
1884
1885
TEST(ErrorsParenthesizedLabels)1886 TEST(ErrorsParenthesizedLabels) {
1887 // Parenthesized identifiers shouldn't be recognized as labels.
1888 const char* context_data[][2] = {
1889 { "", ""},
1890 { "function test_func() {", "}" },
1891 { NULL, NULL }
1892 };
1893
1894 const char* statement_data[] = {
1895 "(mylabel): while(true) { break mylabel; }",
1896 NULL
1897 };
1898
1899 RunParserSyncTest(context_data, statement_data, kError);
1900 }
1901
1902
TEST(NoErrorsParenthesizedDirectivePrologue)1903 TEST(NoErrorsParenthesizedDirectivePrologue) {
1904 // Parenthesized directive prologue shouldn't be recognized.
1905 const char* context_data[][2] = {
1906 { "", ""},
1907 { NULL, NULL }
1908 };
1909
1910 const char* statement_data[] = {
1911 "(\"use strict\"); var eval;",
1912 NULL
1913 };
1914
1915 RunParserSyncTest(context_data, statement_data, kSuccess);
1916 }
1917
1918
TEST(ErrorsNotAnIdentifierName)1919 TEST(ErrorsNotAnIdentifierName) {
1920 const char* context_data[][2] = {
1921 { "", ""},
1922 { "\"use strict\";", ""},
1923 { NULL, NULL }
1924 };
1925
1926 const char* statement_data[] = {
1927 "var foo = {}; foo.{;",
1928 "var foo = {}; foo.};",
1929 "var foo = {}; foo.=;",
1930 "var foo = {}; foo.888;",
1931 "var foo = {}; foo.-;",
1932 "var foo = {}; foo.--;",
1933 NULL
1934 };
1935
1936 RunParserSyncTest(context_data, statement_data, kError);
1937 }
1938
1939
TEST(NoErrorsIdentifierNames)1940 TEST(NoErrorsIdentifierNames) {
1941 // Keywords etc. are valid as property names.
1942 const char* context_data[][2] = {
1943 { "", ""},
1944 { "\"use strict\";", ""},
1945 { NULL, NULL }
1946 };
1947
1948 const char* statement_data[] = {
1949 "var foo = {}; foo.if;",
1950 "var foo = {}; foo.yield;",
1951 "var foo = {}; foo.super;",
1952 "var foo = {}; foo.interface;",
1953 "var foo = {}; foo.eval;",
1954 "var foo = {}; foo.arguments;",
1955 NULL
1956 };
1957
1958 RunParserSyncTest(context_data, statement_data, kSuccess);
1959 }
1960
1961
TEST(DontRegressPreParserDataSizes)1962 TEST(DontRegressPreParserDataSizes) {
1963 // These tests make sure that Parser doesn't start producing less "preparse
1964 // data" (data which the embedder can cache).
1965 v8::V8::Initialize();
1966 v8::Isolate* isolate = CcTest::isolate();
1967 v8::HandleScope handles(isolate);
1968
1969 int marker;
1970 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1971 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1972
1973 struct TestCase {
1974 const char* program;
1975 int functions;
1976 } test_cases[] = {
1977 // No functions.
1978 {"var x = 42;", 0},
1979 // Functions.
1980 {"function foo() {}", 1}, {"function foo() {} function bar() {}", 2},
1981 // Getter / setter functions are recorded as functions if they're on the top
1982 // level.
1983 {"var x = {get foo(){} };", 1},
1984 // Functions insize lazy functions are not recorded.
1985 {"function lazy() { function a() {} function b() {} function c() {} }", 1},
1986 {"function lazy() { var x = {get foo(){} } }", 1},
1987 {NULL, 0}
1988 };
1989
1990 for (int i = 0; test_cases[i].program; i++) {
1991 const char* program = test_cases[i].program;
1992 i::Factory* factory = CcTest::i_isolate()->factory();
1993 i::Handle<i::String> source =
1994 factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
1995 i::Handle<i::Script> script = factory->NewScript(source);
1996 i::CompilationInfoWithZone info(script);
1997 i::ScriptData* data = NULL;
1998 info.SetCachedData(&data, i::PRODUCE_CACHED_DATA);
1999 i::Parser::Parse(&info, true);
2000 CHECK(data);
2001 CHECK(!data->HasError());
2002
2003 if (data->function_count() != test_cases[i].functions) {
2004 i::OS::Print(
2005 "Expected preparse data for program:\n"
2006 "\t%s\n"
2007 "to contain %d functions, however, received %d functions.\n",
2008 program, test_cases[i].functions,
2009 data->function_count());
2010 CHECK(false);
2011 }
2012 delete data;
2013 }
2014 }
2015
2016
TEST(FunctionDeclaresItselfStrict)2017 TEST(FunctionDeclaresItselfStrict) {
2018 // Tests that we produce the right kinds of errors when a function declares
2019 // itself strict (we cannot produce there errors as soon as we see the
2020 // offending identifiers, because we don't know at that point whether the
2021 // function is strict or not).
2022 const char* context_data[][2] = {
2023 {"function eval() {", "}"},
2024 {"function arguments() {", "}"},
2025 {"function yield() {", "}"},
2026 {"function interface() {", "}"},
2027 {"function foo(eval) {", "}"},
2028 {"function foo(arguments) {", "}"},
2029 {"function foo(yield) {", "}"},
2030 {"function foo(interface) {", "}"},
2031 {"function foo(bar, eval) {", "}"},
2032 {"function foo(bar, arguments) {", "}"},
2033 {"function foo(bar, yield) {", "}"},
2034 {"function foo(bar, interface) {", "}"},
2035 {"function foo(bar, bar) {", "}"},
2036 { NULL, NULL }
2037 };
2038
2039 const char* strict_statement_data[] = {
2040 "\"use strict\";",
2041 NULL
2042 };
2043
2044 const char* non_strict_statement_data[] = {
2045 ";",
2046 NULL
2047 };
2048
2049 RunParserSyncTest(context_data, strict_statement_data, kError);
2050 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
2051 }
2052
2053
TEST(ErrorsTryWithoutCatchOrFinally)2054 TEST(ErrorsTryWithoutCatchOrFinally) {
2055 const char* context_data[][2] = {
2056 {"", ""},
2057 { NULL, NULL }
2058 };
2059
2060 const char* statement_data[] = {
2061 "try { }",
2062 "try { } foo();",
2063 "try { } catch (e) foo();",
2064 "try { } catch { }",
2065 "try { } finally foo();",
2066 NULL
2067 };
2068
2069 RunParserSyncTest(context_data, statement_data, kError);
2070 }
2071
2072
TEST(NoErrorsTryCatchFinally)2073 TEST(NoErrorsTryCatchFinally) {
2074 const char* context_data[][2] = {
2075 {"", ""},
2076 { NULL, NULL }
2077 };
2078
2079 const char* statement_data[] = {
2080 "try { } catch (e) { }",
2081 "try { } catch (e) { } finally { }",
2082 "try { } finally { }",
2083 NULL
2084 };
2085
2086 RunParserSyncTest(context_data, statement_data, kSuccess);
2087 }
2088
2089
TEST(ErrorsRegexpLiteral)2090 TEST(ErrorsRegexpLiteral) {
2091 const char* context_data[][2] = {
2092 {"var r = ", ""},
2093 { NULL, NULL }
2094 };
2095
2096 const char* statement_data[] = {
2097 "/unterminated",
2098 NULL
2099 };
2100
2101 RunParserSyncTest(context_data, statement_data, kError);
2102 }
2103
2104
TEST(NoErrorsRegexpLiteral)2105 TEST(NoErrorsRegexpLiteral) {
2106 const char* context_data[][2] = {
2107 {"var r = ", ""},
2108 { NULL, NULL }
2109 };
2110
2111 const char* statement_data[] = {
2112 "/foo/",
2113 "/foo/g",
2114 "/foo/whatever", // This is an error but not detected by the parser.
2115 NULL
2116 };
2117
2118 RunParserSyncTest(context_data, statement_data, kSuccess);
2119 }
2120
2121
TEST(Intrinsics)2122 TEST(Intrinsics) {
2123 const char* context_data[][2] = {
2124 {"", ""},
2125 { NULL, NULL }
2126 };
2127
2128 const char* statement_data[] = {
2129 "%someintrinsic(arg)",
2130 NULL
2131 };
2132
2133 // Parsing will fail or succeed depending on whether we allow natives syntax
2134 // or not.
2135 RunParserSyncTest(context_data, statement_data, kSuccessOrError);
2136 }
2137
2138
TEST(NoErrorsNewExpression)2139 TEST(NoErrorsNewExpression) {
2140 const char* context_data[][2] = {
2141 {"", ""},
2142 {"var f =", ""},
2143 { NULL, NULL }
2144 };
2145
2146 const char* statement_data[] = {
2147 "new foo",
2148 "new foo();",
2149 "new foo(1);",
2150 "new foo(1, 2);",
2151 // The first () will be processed as a part of the NewExpression and the
2152 // second () will be processed as part of LeftHandSideExpression.
2153 "new foo()();",
2154 // The first () will be processed as a part of the inner NewExpression and
2155 // the second () will be processed as a part of the outer NewExpression.
2156 "new new foo()();",
2157 "new foo.bar;",
2158 "new foo.bar();",
2159 "new foo.bar.baz;",
2160 "new foo.bar().baz;",
2161 "new foo[bar];",
2162 "new foo[bar]();",
2163 "new foo[bar][baz];",
2164 "new foo[bar]()[baz];",
2165 "new foo[bar].baz(baz)()[bar].baz;",
2166 "new \"foo\"", // Runtime error
2167 "new 1", // Runtime error
2168 // This even runs:
2169 "(new new Function(\"this.x = 1\")).x;",
2170 "new new Test_Two(String, 2).v(0123).length;",
2171 NULL
2172 };
2173
2174 RunParserSyncTest(context_data, statement_data, kSuccess);
2175 }
2176
2177
TEST(ErrorsNewExpression)2178 TEST(ErrorsNewExpression) {
2179 const char* context_data[][2] = {
2180 {"", ""},
2181 {"var f =", ""},
2182 { NULL, NULL }
2183 };
2184
2185 const char* statement_data[] = {
2186 "new foo bar",
2187 "new ) foo",
2188 "new ++foo",
2189 "new foo ++",
2190 NULL
2191 };
2192
2193 RunParserSyncTest(context_data, statement_data, kError);
2194 }
2195
2196
TEST(StrictObjectLiteralChecking)2197 TEST(StrictObjectLiteralChecking) {
2198 const char* strict_context_data[][2] = {
2199 {"\"use strict\"; var myobject = {", "};"},
2200 { NULL, NULL }
2201 };
2202 const char* non_strict_context_data[][2] = {
2203 {"var myobject = {", "};"},
2204 { NULL, NULL }
2205 };
2206
2207 // These are only errors in strict mode.
2208 const char* statement_data[] = {
2209 "foo: 1, foo: 2",
2210 "\"foo\": 1, \"foo\": 2",
2211 "foo: 1, \"foo\": 2",
2212 "1: 1, 1: 2",
2213 "1: 1, \"1\": 2",
2214 "get: 1, get: 2", // Not a getter for real, just a property called get.
2215 "set: 1, set: 2", // Not a setter for real, just a property called set.
2216 NULL
2217 };
2218
2219 RunParserSyncTest(non_strict_context_data, statement_data, kSuccess);
2220 RunParserSyncTest(strict_context_data, statement_data, kError);
2221 }
2222
2223
TEST(ErrorsObjectLiteralChecking)2224 TEST(ErrorsObjectLiteralChecking) {
2225 const char* context_data[][2] = {
2226 {"\"use strict\"; var myobject = {", "};"},
2227 {"var myobject = {", "};"},
2228 { NULL, NULL }
2229 };
2230
2231 const char* statement_data[] = {
2232 "foo: 1, get foo() {}",
2233 "foo: 1, set foo(v) {}",
2234 "\"foo\": 1, get \"foo\"() {}",
2235 "\"foo\": 1, set \"foo\"(v) {}",
2236 "1: 1, get 1() {}",
2237 "1: 1, set 1() {}",
2238 // It's counter-intuitive, but these collide too (even in classic
2239 // mode). Note that we can have "foo" and foo as properties in classic mode,
2240 // but we cannot have "foo" and get foo, or foo and get "foo".
2241 "foo: 1, get \"foo\"() {}",
2242 "foo: 1, set \"foo\"(v) {}",
2243 "\"foo\": 1, get foo() {}",
2244 "\"foo\": 1, set foo(v) {}",
2245 "1: 1, get \"1\"() {}",
2246 "1: 1, set \"1\"() {}",
2247 "\"1\": 1, get 1() {}"
2248 "\"1\": 1, set 1(v) {}"
2249 // Wrong number of parameters
2250 "get bar(x) {}",
2251 "get bar(x, y) {}",
2252 "set bar() {}",
2253 "set bar(x, y) {}",
2254 // Parsing FunctionLiteral for getter or setter fails
2255 "get foo( +",
2256 "get foo() \"error\"",
2257 NULL
2258 };
2259
2260 RunParserSyncTest(context_data, statement_data, kError);
2261 }
2262
2263
TEST(NoErrorsObjectLiteralChecking)2264 TEST(NoErrorsObjectLiteralChecking) {
2265 const char* context_data[][2] = {
2266 {"var myobject = {", "};"},
2267 {"\"use strict\"; var myobject = {", "};"},
2268 { NULL, NULL }
2269 };
2270
2271 const char* statement_data[] = {
2272 "foo: 1, bar: 2",
2273 "\"foo\": 1, \"bar\": 2",
2274 "1: 1, 2: 2",
2275 // Syntax: IdentifierName ':' AssignmentExpression
2276 "foo: bar = 5 + baz",
2277 // Syntax: 'get' PropertyName '(' ')' '{' FunctionBody '}'
2278 "get foo() {}",
2279 "get \"foo\"() {}",
2280 "get 1() {}",
2281 // Syntax: 'set' PropertyName '(' PropertySetParameterList ')'
2282 // '{' FunctionBody '}'
2283 "set foo(v) {}",
2284 "set \"foo\"(v) {}",
2285 "set 1(v) {}",
2286 // Non-colliding getters and setters -> no errors
2287 "foo: 1, get bar() {}",
2288 "foo: 1, set bar(v) {}",
2289 "\"foo\": 1, get \"bar\"() {}",
2290 "\"foo\": 1, set \"bar\"(v) {}",
2291 "1: 1, get 2() {}",
2292 "1: 1, set 2(v) {}",
2293 // Keywords, future reserved and strict future reserved are also allowed as
2294 // property names.
2295 "if: 4",
2296 "interface: 5",
2297 "super: 6",
2298 "eval: 7",
2299 "arguments: 8",
2300 NULL
2301 };
2302
2303 RunParserSyncTest(context_data, statement_data, kSuccess);
2304 }
2305
2306
TEST(TooManyArguments)2307 TEST(TooManyArguments) {
2308 const char* context_data[][2] = {
2309 {"foo(", "0)"},
2310 { NULL, NULL }
2311 };
2312
2313 using v8::internal::Code;
2314 char statement[Code::kMaxArguments * 2 + 1];
2315 for (int i = 0; i < Code::kMaxArguments; ++i) {
2316 statement[2 * i] = '0';
2317 statement[2 * i + 1] = ',';
2318 }
2319 statement[Code::kMaxArguments * 2] = 0;
2320
2321 const char* statement_data[] = {
2322 statement,
2323 NULL
2324 };
2325
2326 // The test is quite slow, so run it with a reduced set of flags.
2327 static const ParserFlag empty_flags[] = {kAllowLazy};
2328 RunParserSyncTest(context_data, statement_data, kError, empty_flags, 1);
2329 }
2330
2331
TEST(StrictDelete)2332 TEST(StrictDelete) {
2333 // "delete <Identifier>" is not allowed in strict mode.
2334 const char* strict_context_data[][2] = {
2335 {"\"use strict\"; ", ""},
2336 { NULL, NULL }
2337 };
2338
2339 const char* sloppy_context_data[][2] = {
2340 {"", ""},
2341 { NULL, NULL }
2342 };
2343
2344 // These are errors in the strict mode.
2345 const char* sloppy_statement_data[] = {
2346 "delete foo;",
2347 "delete foo + 1;",
2348 "delete (foo);",
2349 "delete eval;",
2350 "delete interface;",
2351 NULL
2352 };
2353
2354 // These are always OK
2355 const char* good_statement_data[] = {
2356 "delete this;",
2357 "delete 1;",
2358 "delete 1 + 2;",
2359 "delete foo();",
2360 "delete foo.bar;",
2361 "delete foo[bar];",
2362 "delete foo--;",
2363 "delete --foo;",
2364 "delete new foo();",
2365 "delete new foo(bar);",
2366 NULL
2367 };
2368
2369 // These are always errors
2370 const char* bad_statement_data[] = {
2371 "delete if;",
2372 NULL
2373 };
2374
2375 RunParserSyncTest(strict_context_data, sloppy_statement_data, kError);
2376 RunParserSyncTest(sloppy_context_data, sloppy_statement_data, kSuccess);
2377
2378 RunParserSyncTest(strict_context_data, good_statement_data, kSuccess);
2379 RunParserSyncTest(sloppy_context_data, good_statement_data, kSuccess);
2380
2381 RunParserSyncTest(strict_context_data, bad_statement_data, kError);
2382 RunParserSyncTest(sloppy_context_data, bad_statement_data, kError);
2383 }
2384
2385
TEST(InvalidLeftHandSide)2386 TEST(InvalidLeftHandSide) {
2387 const char* assignment_context_data[][2] = {
2388 {"", " = 1;"},
2389 {"\"use strict\"; ", " = 1;"},
2390 { NULL, NULL }
2391 };
2392
2393 const char* prefix_context_data[][2] = {
2394 {"++", ";"},
2395 {"\"use strict\"; ++", ";"},
2396 {NULL, NULL},
2397 };
2398
2399 const char* postfix_context_data[][2] = {
2400 {"", "++;"},
2401 {"\"use strict\"; ", "++;"},
2402 { NULL, NULL }
2403 };
2404
2405 // Good left hand sides for assigment or prefix / postfix operations.
2406 const char* good_statement_data[] = {
2407 "foo",
2408 "foo.bar",
2409 "foo[bar]",
2410 "foo()[bar]",
2411 "foo().bar",
2412 "this.foo",
2413 "this[foo]",
2414 "new foo()[bar]",
2415 "new foo().bar",
2416 "foo()",
2417 "foo(bar)",
2418 "foo[bar]()",
2419 "foo.bar()",
2420 "this()",
2421 "this.foo()",
2422 "this[foo].bar()",
2423 "this.foo[foo].bar(this)(bar)[foo]()",
2424 NULL
2425 };
2426
2427 // Bad left hand sides for assigment or prefix / postfix operations.
2428 const char* bad_statement_data_common[] = {
2429 "2",
2430 "new foo",
2431 "new foo()",
2432 "null",
2433 "if", // Unexpected token
2434 "{x: 1}", // Unexpected token
2435 "this",
2436 "\"bar\"",
2437 "(foo + bar)",
2438 "new new foo()[bar]", // means: new (new foo()[bar])
2439 "new new foo().bar", // means: new (new foo()[bar])
2440 NULL
2441 };
2442
2443 // These are not okay for assignment, but okay for prefix / postix.
2444 const char* bad_statement_data_for_assignment[] = {
2445 "++foo",
2446 "foo++",
2447 "foo + bar",
2448 NULL
2449 };
2450
2451 RunParserSyncTest(assignment_context_data, good_statement_data, kSuccess);
2452 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError);
2453 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment,
2454 kError);
2455
2456 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess);
2457 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError);
2458
2459 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess);
2460 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError);
2461 }
2462
2463
TEST(FuncNameInferrerBasic)2464 TEST(FuncNameInferrerBasic) {
2465 // Tests that function names are inferred properly.
2466 i::FLAG_allow_natives_syntax = true;
2467 v8::Isolate* isolate = CcTest::isolate();
2468 v8::HandleScope scope(isolate);
2469 LocalContext env;
2470 CompileRun("var foo1 = function() {}; "
2471 "var foo2 = function foo3() {}; "
2472 "function not_ctor() { "
2473 " var foo4 = function() {}; "
2474 " return %FunctionGetInferredName(foo4); "
2475 "} "
2476 "function Ctor() { "
2477 " var foo5 = function() {}; "
2478 " return %FunctionGetInferredName(foo5); "
2479 "} "
2480 "var obj1 = { foo6: function() {} }; "
2481 "var obj2 = { 'foo7': function() {} }; "
2482 "var obj3 = {}; "
2483 "obj3[1] = function() {}; "
2484 "var obj4 = {}; "
2485 "obj4[1] = function foo8() {}; "
2486 "var obj5 = {}; "
2487 "obj5['foo9'] = function() {}; "
2488 "var obj6 = { obj7 : { foo10: function() {} } };");
2489 ExpectString("%FunctionGetInferredName(foo1)", "foo1");
2490 // foo2 is not unnamed -> its name is not inferred.
2491 ExpectString("%FunctionGetInferredName(foo2)", "");
2492 ExpectString("not_ctor()", "foo4");
2493 ExpectString("Ctor()", "Ctor.foo5");
2494 ExpectString("%FunctionGetInferredName(obj1.foo6)", "obj1.foo6");
2495 ExpectString("%FunctionGetInferredName(obj2.foo7)", "obj2.foo7");
2496 ExpectString("%FunctionGetInferredName(obj3[1])",
2497 "obj3.(anonymous function)");
2498 ExpectString("%FunctionGetInferredName(obj4[1])", "");
2499 ExpectString("%FunctionGetInferredName(obj5['foo9'])", "obj5.foo9");
2500 ExpectString("%FunctionGetInferredName(obj6.obj7.foo10)", "obj6.obj7.foo10");
2501 }
2502
2503
TEST(FuncNameInferrerTwoByte)2504 TEST(FuncNameInferrerTwoByte) {
2505 // Tests function name inferring in cases where some parts of the inferred
2506 // function name are two-byte strings.
2507 i::FLAG_allow_natives_syntax = true;
2508 v8::Isolate* isolate = CcTest::isolate();
2509 v8::HandleScope scope(isolate);
2510 LocalContext env;
2511 uint16_t* two_byte_source = AsciiToTwoByteString(
2512 "var obj1 = { oXj2 : { foo1: function() {} } }; "
2513 "%FunctionGetInferredName(obj1.oXj2.foo1)");
2514 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
2515 // Make it really non-ASCII (replace the Xs with a non-ASCII character).
2516 two_byte_source[14] = two_byte_source[78] = two_byte_name[6] = 0x010d;
2517 v8::Local<v8::String> source =
2518 v8::String::NewFromTwoByte(isolate, two_byte_source);
2519 v8::Local<v8::Value> result = CompileRun(source);
2520 CHECK(result->IsString());
2521 v8::Local<v8::String> expected_name =
2522 v8::String::NewFromTwoByte(isolate, two_byte_name);
2523 CHECK(result->Equals(expected_name));
2524 i::DeleteArray(two_byte_source);
2525 i::DeleteArray(two_byte_name);
2526 }
2527
2528
TEST(FuncNameInferrerEscaped)2529 TEST(FuncNameInferrerEscaped) {
2530 // The same as FuncNameInferrerTwoByte, except that we express the two-byte
2531 // character as a unicode escape.
2532 i::FLAG_allow_natives_syntax = true;
2533 v8::Isolate* isolate = CcTest::isolate();
2534 v8::HandleScope scope(isolate);
2535 LocalContext env;
2536 uint16_t* two_byte_source = AsciiToTwoByteString(
2537 "var obj1 = { o\\u010dj2 : { foo1: function() {} } }; "
2538 "%FunctionGetInferredName(obj1.o\\u010dj2.foo1)");
2539 uint16_t* two_byte_name = AsciiToTwoByteString("obj1.oXj2.foo1");
2540 // Fix to correspond to the non-ASCII name in two_byte_source.
2541 two_byte_name[6] = 0x010d;
2542 v8::Local<v8::String> source =
2543 v8::String::NewFromTwoByte(isolate, two_byte_source);
2544 v8::Local<v8::Value> result = CompileRun(source);
2545 CHECK(result->IsString());
2546 v8::Local<v8::String> expected_name =
2547 v8::String::NewFromTwoByte(isolate, two_byte_name);
2548 CHECK(result->Equals(expected_name));
2549 i::DeleteArray(two_byte_source);
2550 i::DeleteArray(two_byte_name);
2551 }
2552