Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(431)

Side by Side Diff: test/cctest/test-parsing.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/cctest/test-microtask-delivery.cc ('k') | test/cctest/test-platform.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 230
231 // Syntax error. 231 // Syntax error.
232 v8::ScriptData* error_preparse = v8::ScriptData::PreCompile( 232 v8::ScriptData* error_preparse = v8::ScriptData::PreCompile(
233 v8::String::NewFromUtf8(isolate, 233 v8::String::NewFromUtf8(isolate,
234 error_source, 234 error_source,
235 v8::String::kNormalString, 235 v8::String::kNormalString,
236 error_source_length)); 236 error_source_length));
237 CHECK(error_preparse->HasError()); 237 CHECK(error_preparse->HasError());
238 i::ScriptDataImpl *pre_impl = 238 i::ScriptDataImpl *pre_impl =
239 reinterpret_cast<i::ScriptDataImpl*>(error_preparse); 239 reinterpret_cast<i::ScriptDataImpl*>(error_preparse);
240 i::ScannerBase::Location error_location = 240 i::Scanner::Location error_location =
241 pre_impl->MessageLocation(); 241 pre_impl->MessageLocation();
242 // Error is at "z" in source, location 10..11. 242 // Error is at "z" in source, location 10..11.
243 CHECK_EQ(10, error_location.beg_pos); 243 CHECK_EQ(10, error_location.beg_pos);
244 CHECK_EQ(11, error_location.end_pos); 244 CHECK_EQ(11, error_location.end_pos);
245 // Should not crash. 245 // Should not crash.
246 const char* message = pre_impl->BuildMessage(); 246 const char* message = pre_impl->BuildMessage();
247 pre_impl->BuildArgs(); 247 i::Vector<const char*> args = pre_impl->BuildArgs();
248 CHECK_GT(strlen(message), 0); 248 CHECK_GT(strlen(message), 0);
249 args.Dispose();
250 i::DeleteArray(message);
251 delete error_preparse;
249 } 252 }
250 253
251 254
252 TEST(StandAlonePreParser) { 255 TEST(StandAlonePreParser) {
253 v8::V8::Initialize(); 256 v8::V8::Initialize();
254 257
255 int marker; 258 int marker;
256 CcTest::i_isolate()->stack_guard()->SetStackLimit( 259 CcTest::i_isolate()->stack_guard()->SetStackLimit(
257 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); 260 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
258 261
259 const char* programs[] = { 262 const char* programs[] = {
260 "{label: 42}", 263 "{label: 42}",
261 "var x = 42;", 264 "var x = 42;",
262 "function foo(x, y) { return x + y; }", 265 "function foo(x, y) { return x + y; }",
263 "%ArgleBargle(glop);", 266 "%ArgleBargle(glop);",
264 "var x = new new Function('this.x = 42');", 267 "var x = new new Function('this.x = 42');",
265 NULL 268 NULL
266 }; 269 };
267 270
268 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 271 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
269 for (int i = 0; programs[i]; i++) { 272 for (int i = 0; programs[i]; i++) {
270 i::HandleScope handle_scope(CcTest::i_isolate()); 273 const char* program = programs[i];
271 i::Handle<i::String> source = 274 i::Utf8ToUtf16CharacterStream stream(
272 CcTest::i_isolate()->factory()->NewStringFromAscii( 275 reinterpret_cast<const i::byte*>(program),
273 i::Vector<const char>(programs[i], strlen(programs[i]))); 276 static_cast<unsigned>(strlen(program)));
274 i::CompleteParserRecorder log; 277 i::CompleteParserRecorder log;
275 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); 278 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
276 scanner.Init(); 279 scanner.Initialize(&stream);
277 280
278 i::PreParser preparser(&scanner, &log, stack_limit); 281 i::PreParser preparser(&scanner, &log, stack_limit);
279 preparser.set_allow_lazy(true); 282 preparser.set_allow_lazy(true);
280 preparser.set_allow_natives_syntax(true); 283 preparser.set_allow_natives_syntax(true);
281 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 284 i::PreParser::PreParseResult result = preparser.PreParseProgram();
282 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 285 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
283 i::ScriptDataImpl data(log.ExtractData()); 286 i::ScriptDataImpl data(log.ExtractData());
284 CHECK(!data.has_error()); 287 CHECK(!data.has_error());
285 } 288 }
286 } 289 }
287 290
288 291
289 TEST(StandAlonePreParserNoNatives) { 292 TEST(StandAlonePreParserNoNatives) {
290 v8::V8::Initialize(); 293 v8::V8::Initialize();
291 294
292 int marker; 295 int marker;
293 CcTest::i_isolate()->stack_guard()->SetStackLimit( 296 CcTest::i_isolate()->stack_guard()->SetStackLimit(
294 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); 297 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
295 298
296 const char* programs[] = { 299 const char* programs[] = {
297 "%ArgleBargle(glop);", 300 "%ArgleBargle(glop);",
298 "var x = %_IsSmi(42);", 301 "var x = %_IsSmi(42);",
299 NULL 302 NULL
300 }; 303 };
301 304
302 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 305 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
303 for (int i = 0; programs[i]; i++) { 306 for (int i = 0; programs[i]; i++) {
304 i::HandleScope handle_scope(CcTest::i_isolate()); 307 const char* program = programs[i];
305 i::Handle<i::String> source = 308 i::Utf8ToUtf16CharacterStream stream(
306 CcTest::i_isolate()->factory()->NewStringFromAscii( 309 reinterpret_cast<const i::byte*>(program),
307 i::Vector<const char>(programs[i], strlen(programs[i]))); 310 static_cast<unsigned>(strlen(program)));
308 i::CompleteParserRecorder log; 311 i::CompleteParserRecorder log;
309 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); 312 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
310 scanner.Init(); 313 scanner.Initialize(&stream);
314
311 // Preparser defaults to disallowing natives syntax. 315 // Preparser defaults to disallowing natives syntax.
312 i::PreParser preparser(&scanner, &log, stack_limit); 316 i::PreParser preparser(&scanner, &log, stack_limit);
313 preparser.set_allow_lazy(true); 317 preparser.set_allow_lazy(true);
314 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 318 i::PreParser::PreParseResult result = preparser.PreParseProgram();
315 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 319 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
316 i::ScriptDataImpl data(log.ExtractData()); 320 i::ScriptDataImpl data(log.ExtractData());
317 // Data contains syntax error. 321 // Data contains syntax error.
318 CHECK(data.has_error()); 322 CHECK(data.has_error());
319 } 323 }
320 } 324 }
321 325
322 326
327 TEST(PreparsingObjectLiterals) {
328 // Regression test for a bug where the symbol stream produced by PreParser
329 // didn't match what Parser wanted to consume.
330 v8::Isolate* isolate = CcTest::isolate();
331 v8::HandleScope handles(isolate);
332 v8::Local<v8::Context> context = v8::Context::New(isolate);
333 v8::Context::Scope context_scope(context);
334 int marker;
335 CcTest::i_isolate()->stack_guard()->SetStackLimit(
336 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
337
338 {
339 const char* source = "var myo = {if: \"foo\"}; myo.if;";
340 v8::Local<v8::Value> result = PreCompileCompileRun(source);
341 CHECK(result->IsString());
342 v8::String::Utf8Value utf8(result);
343 CHECK_EQ("foo", *utf8);
344 }
345
346 {
347 const char* source = "var myo = {\"bar\": \"foo\"}; myo[\"bar\"];";
348 v8::Local<v8::Value> result = PreCompileCompileRun(source);
349 CHECK(result->IsString());
350 v8::String::Utf8Value utf8(result);
351 CHECK_EQ("foo", *utf8);
352 }
353
354 {
355 const char* source = "var myo = {1: \"foo\"}; myo[1];";
356 v8::Local<v8::Value> result = PreCompileCompileRun(source);
357 CHECK(result->IsString());
358 v8::String::Utf8Value utf8(result);
359 CHECK_EQ("foo", *utf8);
360 }
361 }
362
363 namespace v8 {
364 namespace internal {
365
366 void FakeWritingSymbolIdInPreParseData(i::CompleteParserRecorder* log,
367 int number) {
368 log->WriteNumber(number);
369 if (log->symbol_id_ < number + 1) {
370 log->symbol_id_ = number + 1;
371 }
372 }
373
374 }
375 }
376
377
378 TEST(StoringNumbersInPreParseData) {
379 // Symbol IDs are split into chunks of 7 bits for storing. This is a
380 // regression test for a bug where a symbol id was incorrectly stored if some
381 // of the chunks in the middle were all zeros.
382 i::CompleteParserRecorder log;
383 for (int i = 0; i < 18; ++i) {
384 FakeWritingSymbolIdInPreParseData(&log, 1 << i);
385 }
386 for (int i = 1; i < 18; ++i) {
387 FakeWritingSymbolIdInPreParseData(&log, (1 << i) + 1);
388 }
389 for (int i = 6; i < 18; ++i) {
390 FakeWritingSymbolIdInPreParseData(&log, (3 << i) + (5 << (i - 6)));
391 }
392 i::Vector<unsigned> store = log.ExtractData();
393 i::ScriptDataImpl script_data(store);
394 script_data.Initialize();
395 // Check that we get the same symbols back.
396 for (int i = 0; i < 18; ++i) {
397 CHECK_EQ(1 << i, script_data.GetSymbolIdentifier());
398 }
399 for (int i = 1; i < 18; ++i) {
400 CHECK_EQ((1 << i) + 1, script_data.GetSymbolIdentifier());
401 }
402 for (int i = 6; i < 18; ++i) {
403 CHECK_EQ((3 << i) + (5 << (i - 6)), script_data.GetSymbolIdentifier());
404 }
405 }
406
407
323 TEST(RegressChromium62639) { 408 TEST(RegressChromium62639) {
324 v8::V8::Initialize(); 409 v8::V8::Initialize();
325 i::Isolate* isolate = CcTest::i_isolate(); 410 i::Isolate* isolate = CcTest::i_isolate();
326 411
327 int marker; 412 int marker;
328 isolate->stack_guard()->SetStackLimit( 413 isolate->stack_guard()->SetStackLimit(
329 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); 414 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
330 415
331 const char* program = "var x = 'something';\n" 416 const char* program = "var x = 'something';\n"
332 "escape: function() {}"; 417 "escape: function() {}";
333 // Fails parsing expecting an identifier after "function". 418 // Fails parsing expecting an identifier after "function".
334 // Before fix, didn't check *ok after Expect(Token::Identifier, ok), 419 // Before fix, didn't check *ok after Expect(Token::Identifier, ok),
335 // and then used the invalid currently scanned literal. This always 420 // and then used the invalid currently scanned literal. This always
336 // failed in debug mode, and sometimes crashed in release mode. 421 // failed in debug mode, and sometimes crashed in release mode.
337 422
338 v8::HandleScope handles(CcTest::isolate()); 423 i::Utf8ToUtf16CharacterStream stream(
339 i::Handle<i::String> source = isolate->factory()->NewStringFromAscii( 424 reinterpret_cast<const i::byte*>(program),
340 i::Vector<const char>(reinterpret_cast<const char*>(program), 425 static_cast<unsigned>(strlen(program)));
341 strlen(program))); 426 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream);
342 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, source);
343 CHECK(data->HasError()); 427 CHECK(data->HasError());
344 delete data; 428 delete data;
345 } 429 }
346 430
347 431
348 TEST(Regress928) { 432 TEST(Regress928) {
349 v8::V8::Initialize(); 433 v8::V8::Initialize();
350 i::Isolate* isolate = CcTest::i_isolate(); 434 i::Isolate* isolate = CcTest::i_isolate();
351 i::Factory* factory = isolate->factory(); 435 i::Factory* factory = isolate->factory();
352 436
353 // Preparsing didn't consider the catch clause of a try statement 437 // Preparsing didn't consider the catch clause of a try statement
354 // as with-content, which made it assume that a function inside 438 // as with-content, which made it assume that a function inside
355 // the block could be lazily compiled, and an extra, unexpected, 439 // the block could be lazily compiled, and an extra, unexpected,
356 // entry was added to the data. 440 // entry was added to the data.
357 int marker; 441 int marker;
358 isolate->stack_guard()->SetStackLimit( 442 isolate->stack_guard()->SetStackLimit(
359 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); 443 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
360 444
361 const char* program = 445 const char* program =
362 "try { } catch (e) { var foo = function () { /* first */ } }" 446 "try { } catch (e) { var foo = function () { /* first */ } }"
363 "var bar = function () { /* second */ }"; 447 "var bar = function () { /* second */ }";
364 448
365 v8::HandleScope handles(CcTest::isolate()); 449 v8::HandleScope handles(CcTest::isolate());
366 i::Handle<i::String> source( 450 i::Handle<i::String> source(
367 factory->NewStringFromAscii(i::CStrVector(program))); 451 factory->NewStringFromAscii(i::CStrVector(program)));
368 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, source); 452 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
453 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream);
369 CHECK(!data->HasError()); 454 CHECK(!data->HasError());
370 455
371 data->Initialize(); 456 data->Initialize();
372 457
373 int first_function = 458 int first_function =
374 static_cast<int>(strstr(program, "function") - program); 459 static_cast<int>(strstr(program, "function") - program);
375 int first_lbrace = first_function + i::StrLength("function () "); 460 int first_lbrace = first_function + i::StrLength("function () ");
376 CHECK_EQ('{', program[first_lbrace]); 461 CHECK_EQ('{', program[first_lbrace]);
377 i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace); 462 i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace);
378 CHECK(!entry1.is_valid()); 463 CHECK(!entry1.is_valid());
(...skipping 17 matching lines...) Expand all
396 CcTest::i_isolate()->stack_guard()->SetStackLimit( 481 CcTest::i_isolate()->stack_guard()->SetStackLimit(
397 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); 482 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
398 483
399 size_t kProgramSize = 1024 * 1024; 484 size_t kProgramSize = 1024 * 1024;
400 i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1)); 485 i::SmartArrayPointer<char> program(i::NewArray<char>(kProgramSize + 1));
401 memset(program.get(), '(', kProgramSize); 486 memset(program.get(), '(', kProgramSize);
402 program[kProgramSize] = '\0'; 487 program[kProgramSize] = '\0';
403 488
404 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); 489 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
405 490
406 i::HandleScope handle_scope(CcTest::i_isolate()); 491 i::Utf8ToUtf16CharacterStream stream(
407 i::Handle<i::String> source = 492 reinterpret_cast<const i::byte*>(program.get()),
408 CcTest::i_isolate()->factory()->NewStringFromAscii( 493 static_cast<unsigned>(kProgramSize));
409 i::Vector<const char>(program.get(), kProgramSize));
410 i::CompleteParserRecorder log; 494 i::CompleteParserRecorder log;
411 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); 495 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
412 scanner.Init(); 496 scanner.Initialize(&stream);
413 497
414 i::PreParser preparser(&scanner, &log, stack_limit); 498 i::PreParser preparser(&scanner, &log, stack_limit);
415 preparser.set_allow_lazy(true); 499 preparser.set_allow_lazy(true);
416 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 500 i::PreParser::PreParseResult result = preparser.PreParseProgram();
417 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result); 501 CHECK_EQ(i::PreParser::kPreParseStackOverflow, result);
418 } 502 }
419 503
420 504
421 class TestExternalResource: public v8::String::ExternalStringResource { 505 class TestExternalResource: public v8::String::ExternalStringResource {
422 public: 506 public:
423 explicit TestExternalResource(uint16_t* data, int length) 507 explicit TestExternalResource(uint16_t* data, int length)
424 : data_(data), length_(static_cast<size_t>(length)) { } 508 : data_(data), length_(static_cast<size_t>(length)) { }
425 509
426 ~TestExternalResource() { } 510 ~TestExternalResource() { }
427 511
428 const uint16_t* data() const { 512 const uint16_t* data() const {
429 return data_; 513 return data_;
430 } 514 }
431 515
432 size_t length() const { 516 size_t length() const {
433 return length_; 517 return length_;
434 } 518 }
435 private: 519 private:
436 uint16_t* data_; 520 uint16_t* data_;
437 size_t length_; 521 size_t length_;
438 }; 522 };
439 523
440 524
525 #ifndef V8_USE_GENERATED_LEXER
526
527
441 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2)) 528 #define CHECK_EQU(v1, v2) CHECK_EQ(static_cast<int>(v1), static_cast<int>(v2))
442 529
530
443 void TestCharacterStream(const char* ascii_source, 531 void TestCharacterStream(const char* ascii_source,
444 unsigned length, 532 unsigned length,
445 unsigned start = 0, 533 unsigned start = 0,
446 unsigned end = 0) { 534 unsigned end = 0) {
447 if (end == 0) end = length; 535 if (end == 0) end = length;
448 unsigned sub_length = end - start; 536 unsigned sub_length = end - start;
449 i::Isolate* isolate = CcTest::i_isolate(); 537 i::Isolate* isolate = CcTest::i_isolate();
450 i::Factory* factory = isolate->factory(); 538 i::Factory* factory = isolate->factory();
451 i::HandleScope test_scope(isolate); 539 i::HandleScope test_scope(isolate);
452 i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]); 540 i::SmartArrayPointer<i::uc16> uc16_buffer(new i::uc16[length]);
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 } else { 705 } else {
618 CHECK_EQ(-1, c); 706 CHECK_EQ(-1, c);
619 } 707 }
620 i += 1; 708 i += 1;
621 CHECK_EQU(i, stream.pos()); 709 CHECK_EQU(i, stream.pos());
622 } 710 }
623 } 711 }
624 712
625 #undef CHECK_EQU 713 #undef CHECK_EQU
626 714
715
716 #endif
717
718
627 void TestStreamScanner(i::Utf16CharacterStream* stream, 719 void TestStreamScanner(i::Utf16CharacterStream* stream,
628 i::Token::Value* expected_tokens, 720 i::Token::Value* expected_tokens,
629 int skip_pos = 0, // Zero means not skipping. 721 int skip_pos = 0, // Zero means not skipping.
630 int skip_to = 0) { 722 int skip_to = 0) {
631 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); 723 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
632 scanner.Initialize(stream); 724 scanner.Initialize(stream);
633 725
634 int i = 0; 726 int i = 0;
635 do { 727 do {
636 i::Token::Value expected = expected_tokens[i]; 728 i::Token::Value expected = expected_tokens[i];
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 1104
1013 for (int i = 0; source_data[i].outer_prefix; i++) { 1105 for (int i = 0; source_data[i].outer_prefix; i++) {
1014 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix); 1106 int kPrefixLen = Utf8LengthHelper(source_data[i].outer_prefix);
1015 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source); 1107 int kInnerLen = Utf8LengthHelper(source_data[i].inner_source);
1016 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix); 1108 int kSuffixLen = Utf8LengthHelper(source_data[i].outer_suffix);
1017 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix); 1109 int kPrefixByteLen = i::StrLength(source_data[i].outer_prefix);
1018 int kInnerByteLen = i::StrLength(source_data[i].inner_source); 1110 int kInnerByteLen = i::StrLength(source_data[i].inner_source);
1019 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix); 1111 int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
1020 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen; 1112 int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
1021 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen; 1113 int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
1022 i::Vector<char> program = i::Vector<char>::New(kProgramByteSize + 1); 1114 i::ScopedVector<char> program(kProgramByteSize + 1);
1023 i::OS::SNPrintF(program, "%s%s%s", 1115 i::OS::SNPrintF(program, "%s%s%s",
1024 source_data[i].outer_prefix, 1116 source_data[i].outer_prefix,
1025 source_data[i].inner_source, 1117 source_data[i].inner_source,
1026 source_data[i].outer_suffix); 1118 source_data[i].outer_suffix);
1027 1119
1028 // Parse program source. 1120 // Parse program source.
1029 i::Handle<i::String> source( 1121 i::Handle<i::String> source(
1030 factory->NewStringFromUtf8(i::CStrVector(program.start()))); 1122 factory->NewStringFromUtf8(i::CStrVector(program.start())));
1031 CHECK_EQ(source->length(), kProgramSize); 1123 CHECK_EQ(source->length(), kProgramSize);
1032 i::Handle<i::Script> script = factory->NewScript(source); 1124 i::Handle<i::Script> script = factory->NewScript(source);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 kAllowLazy, 1184 kAllowLazy,
1093 kAllowNativesSyntax, 1185 kAllowNativesSyntax,
1094 kAllowHarmonyScoping, 1186 kAllowHarmonyScoping,
1095 kAllowModules, 1187 kAllowModules,
1096 kAllowGenerators, 1188 kAllowGenerators,
1097 kAllowForOf, 1189 kAllowForOf,
1098 kAllowHarmonyNumericLiterals 1190 kAllowHarmonyNumericLiterals
1099 }; 1191 };
1100 1192
1101 1193
1102 void SetParserFlags(i::ParserBase* parser, i::EnumSet<ParserFlag> flags) { 1194 enum ParserSyncTestResult {
1195 kSuccessOrError,
1196 kSuccess,
1197 kError
1198 };
1199
1200 template <typename Traits>
1201 void SetParserFlags(i::ParserBase<Traits>* parser,
1202 i::EnumSet<ParserFlag> flags) {
1103 parser->set_allow_lazy(flags.Contains(kAllowLazy)); 1203 parser->set_allow_lazy(flags.Contains(kAllowLazy));
1104 parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax)); 1204 parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
1105 parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping)); 1205 parser->set_allow_harmony_scoping(flags.Contains(kAllowHarmonyScoping));
1106 parser->set_allow_modules(flags.Contains(kAllowModules)); 1206 parser->set_allow_modules(flags.Contains(kAllowModules));
1107 parser->set_allow_generators(flags.Contains(kAllowGenerators)); 1207 parser->set_allow_generators(flags.Contains(kAllowGenerators));
1108 parser->set_allow_for_of(flags.Contains(kAllowForOf)); 1208 parser->set_allow_for_of(flags.Contains(kAllowForOf));
1109 parser->set_allow_harmony_numeric_literals( 1209 parser->set_allow_harmony_numeric_literals(
1110 flags.Contains(kAllowHarmonyNumericLiterals)); 1210 flags.Contains(kAllowHarmonyNumericLiterals));
1111 } 1211 }
1112 1212
1113 1213
1114 void TestParserSyncWithFlags(i::Handle<i::String> source, 1214 void TestParserSyncWithFlags(i::Handle<i::String> source,
1115 i::EnumSet<ParserFlag> flags) { 1215 i::EnumSet<ParserFlag> flags,
1216 ParserSyncTestResult result) {
1116 i::Isolate* isolate = CcTest::i_isolate(); 1217 i::Isolate* isolate = CcTest::i_isolate();
1117 i::Factory* factory = isolate->factory(); 1218 i::Factory* factory = isolate->factory();
1118 1219
1119 uintptr_t stack_limit = isolate->stack_guard()->real_climit(); 1220 uintptr_t stack_limit = isolate->stack_guard()->real_climit();
1120 1221
1121 // Preparse the data. 1222 // Preparse the data.
1122 i::CompleteParserRecorder log; 1223 i::CompleteParserRecorder log;
1123 { 1224 {
1124 i::ExperimentalScanner<uint8_t> scanner(source, CcTest::i_isolate()); 1225 i::Scanner scanner(isolate->unicode_cache());
1226 i::GenericStringUtf16CharacterStream stream(source, 0, source->length());
1125 i::PreParser preparser(&scanner, &log, stack_limit); 1227 i::PreParser preparser(&scanner, &log, stack_limit);
1126 SetParserFlags(&preparser, flags); 1228 SetParserFlags(&preparser, flags);
1127 scanner.Init(); 1229 scanner.Initialize(&stream);
1128 i::PreParser::PreParseResult result = preparser.PreParseProgram(); 1230 i::PreParser::PreParseResult result = preparser.PreParseProgram();
1129 CHECK_EQ(i::PreParser::kPreParseSuccess, result); 1231 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
1130 } 1232 }
1131 i::ScriptDataImpl data(log.ExtractData()); 1233 i::ScriptDataImpl data(log.ExtractData());
1132 1234
1133 // Parse the data 1235 // Parse the data
1134 i::FunctionLiteral* function; 1236 i::FunctionLiteral* function;
1135 { 1237 {
1136 i::Handle<i::Script> script = factory->NewScript(source); 1238 i::Handle<i::Script> script = factory->NewScript(source);
1137 i::CompilationInfoWithZone info(script); 1239 i::CompilationInfoWithZone info(script);
1138 i::Parser parser(&info); 1240 i::Parser parser(&info);
1139 SetParserFlags(&parser, flags); 1241 SetParserFlags(&parser, flags);
1140 info.MarkAsGlobal(); 1242 info.MarkAsGlobal();
1141 parser.Parse(); 1243 parser.Parse();
1142 function = info.function(); 1244 function = info.function();
1143 } 1245 }
1144 1246
1145 // Check that preparsing fails iff parsing fails. 1247 // Check that preparsing fails iff parsing fails.
1146 if (function == NULL) { 1248 if (function == NULL) {
1147 // Extract exception from the parser. 1249 // Extract exception from the parser.
1148 CHECK(isolate->has_pending_exception()); 1250 CHECK(isolate->has_pending_exception());
1149 i::MaybeObject* maybe_object = isolate->pending_exception(); 1251 i::MaybeObject* maybe_object = isolate->pending_exception();
1150 i::JSObject* exception = NULL; 1252 i::JSObject* exception = NULL;
1151 CHECK(maybe_object->To(&exception)); 1253 CHECK(maybe_object->To(&exception));
1152 i::Handle<i::JSObject> exception_handle(exception); 1254 i::Handle<i::JSObject> exception_handle(exception);
1153 i::Handle<i::String> message_string = 1255 i::Handle<i::String> message_string =
1154 i::Handle<i::String>::cast(i::GetProperty(exception_handle, "message")); 1256 i::Handle<i::String>::cast(i::GetProperty(exception_handle, "message"));
1257
1258 if (result == kSuccess) {
1259 i::OS::Print(
1260 "Parser failed on:\n"
1261 "\t%s\n"
1262 "with error:\n"
1263 "\t%s\n"
1264 "However, we expected no error.",
1265 source->ToCString().get(), message_string->ToCString().get());
1266 CHECK(false);
1267 }
1155 1268
1156 if (!data.has_error()) { 1269 if (!data.has_error()) {
1157 i::OS::Print( 1270 i::OS::Print(
1158 "Parser failed on:\n" 1271 "Parser failed on:\n"
1159 "\t%s\n" 1272 "\t%s\n"
1160 "with error:\n" 1273 "with error:\n"
1161 "\t%s\n" 1274 "\t%s\n"
1162 "However, the preparser succeeded", 1275 "However, the preparser succeeded",
1163 source->ToCString().get(), message_string->ToCString().get()); 1276 source->ToCString().get(), message_string->ToCString().get());
1164 CHECK(false); 1277 CHECK(false);
(...skipping 14 matching lines...) Expand all
1179 } 1292 }
1180 } else if (data.has_error()) { 1293 } else if (data.has_error()) {
1181 i::OS::Print( 1294 i::OS::Print(
1182 "Preparser failed on:\n" 1295 "Preparser failed on:\n"
1183 "\t%s\n" 1296 "\t%s\n"
1184 "with error:\n" 1297 "with error:\n"
1185 "\t%s\n" 1298 "\t%s\n"
1186 "However, the parser succeeded", 1299 "However, the parser succeeded",
1187 source->ToCString().get(), FormatMessage(&data)->ToCString().get()); 1300 source->ToCString().get(), FormatMessage(&data)->ToCString().get());
1188 CHECK(false); 1301 CHECK(false);
1302 } else if (result == kError) {
1303 i::OS::Print(
1304 "Expected error on:\n"
1305 "\t%s\n"
1306 "However, parser and preparser succeeded",
1307 source->ToCString().get());
1308 CHECK(false);
1189 } 1309 }
1190 } 1310 }
1191 1311
1192 1312
1193 void TestParserSync(const char* source, 1313 void TestParserSync(const char* source,
1194 const ParserFlag* flag_list, 1314 const ParserFlag* flag_list,
1195 size_t flag_list_length) { 1315 size_t flag_list_length,
1316 ParserSyncTestResult result = kSuccessOrError) {
1196 i::Handle<i::String> str = 1317 i::Handle<i::String> str =
1197 CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source)); 1318 CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source));
1198 for (int bits = 0; bits < (1 << flag_list_length); bits++) { 1319 for (int bits = 0; bits < (1 << flag_list_length); bits++) {
1199 i::EnumSet<ParserFlag> flags; 1320 i::EnumSet<ParserFlag> flags;
1200 for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) { 1321 for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) {
1201 if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]); 1322 if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]);
1202 } 1323 }
1203 TestParserSyncWithFlags(str, flags); 1324 TestParserSyncWithFlags(str, flags, result);
1204 } 1325 }
1205 } 1326 }
1206 1327
1207 1328
1208 TEST(ParserSync) { 1329 TEST(ParserSync) {
1209 const char* context_data[][2] = { 1330 const char* context_data[][2] = {
1210 { "", "" }, 1331 { "", "" },
1211 { "{", "}" }, 1332 { "{", "}" },
1212 { "if (true) ", " else {}" }, 1333 { "if (true) ", " else {}" },
1213 { "if (true) {} else ", "" }, 1334 { "if (true) {} else ", "" },
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 " b = function() { \n" 1458 " b = function() { \n"
1338 " 01; \n" 1459 " 01; \n"
1339 " }; \n" 1460 " }; \n"
1340 "}; \n"; 1461 "}; \n";
1341 v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script)); 1462 v8::Script::Compile(v8::String::NewFromUtf8(CcTest::isolate(), script));
1342 CHECK(try_catch.HasCaught()); 1463 CHECK(try_catch.HasCaught());
1343 v8::String::Utf8Value exception(try_catch.Exception()); 1464 v8::String::Utf8Value exception(try_catch.Exception());
1344 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.", 1465 CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
1345 *exception); 1466 *exception);
1346 } 1467 }
1468
1469
1470 void RunParserSyncTest(const char* context_data[][2],
1471 const char* statement_data[],
1472 ParserSyncTestResult result) {
1473 v8::HandleScope handles(CcTest::isolate());
1474 v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
1475 v8::Context::Scope context_scope(context);
1476
1477 int marker;
1478 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1479 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1480
1481 static const ParserFlag flags[] = {
1482 kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
1483 kAllowForOf, kAllowNativesSyntax
1484 };
1485 for (int i = 0; context_data[i][0] != NULL; ++i) {
1486 for (int j = 0; statement_data[j] != NULL; ++j) {
1487 int kPrefixLen = i::StrLength(context_data[i][0]);
1488 int kStatementLen = i::StrLength(statement_data[j]);
1489 int kSuffixLen = i::StrLength(context_data[i][1]);
1490 int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
1491
1492 // Plug the source code pieces together.
1493 i::ScopedVector<char> program(kProgramSize + 1);
1494 int length = i::OS::SNPrintF(program,
1495 "%s%s%s",
1496 context_data[i][0],
1497 statement_data[j],
1498 context_data[i][1]);
1499 CHECK(length == kProgramSize);
1500 TestParserSync(program.start(),
1501 flags,
1502 ARRAY_SIZE(flags),
1503 result);
1504 }
1505 }
1506 }
1507
1508
1509 TEST(ErrorsEvalAndArguments) {
1510 // Tests that both preparsing and parsing produce the right kind of errors for
1511 // using "eval" and "arguments" as identifiers. Without the strict mode, it's
1512 // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
1513 // isn't.
1514 const char* context_data[][2] = {
1515 { "\"use strict\";", "" },
1516 { "var eval; function test_func() {\"use strict\"; ", "}"},
1517 { NULL, NULL }
1518 };
1519
1520 const char* statement_data[] = {
1521 "var eval;",
1522 "var arguments",
1523 "var foo, eval;",
1524 "var foo, arguments;",
1525 "try { } catch (eval) { }",
1526 "try { } catch (arguments) { }",
1527 "function eval() { }",
1528 "function arguments() { }",
1529 "function foo(eval) { }",
1530 "function foo(arguments) { }",
1531 "function foo(bar, eval) { }",
1532 "function foo(bar, arguments) { }",
1533 "eval = 1;",
1534 "arguments = 1;",
1535 "var foo = eval = 1;",
1536 "var foo = arguments = 1;",
1537 "++eval;",
1538 "++arguments;",
1539 "eval++;",
1540 "arguments++;",
1541 NULL
1542 };
1543
1544 RunParserSyncTest(context_data, statement_data, kError);
1545 }
1546
1547
1548 TEST(NoErrorsEvalAndArgumentsClassic) {
1549 // Tests that both preparsing and parsing accept "eval" and "arguments" as
1550 // identifiers when needed.
1551 const char* context_data[][2] = {
1552 { "", "" },
1553 { "function test_func() {", "}"},
1554 { NULL, NULL }
1555 };
1556
1557 const char* statement_data[] = {
1558 "var eval;",
1559 "var arguments",
1560 "var foo, eval;",
1561 "var foo, arguments;",
1562 "try { } catch (eval) { }",
1563 "try { } catch (arguments) { }",
1564 "function eval() { }",
1565 "function arguments() { }",
1566 "function foo(eval) { }",
1567 "function foo(arguments) { }",
1568 "function foo(bar, eval) { }",
1569 "function foo(bar, arguments) { }",
1570 "eval = 1;",
1571 "arguments = 1;",
1572 "var foo = eval = 1;",
1573 "var foo = arguments = 1;",
1574 "++eval;",
1575 "++arguments;",
1576 "eval++;",
1577 "arguments++;",
1578 NULL
1579 };
1580
1581 RunParserSyncTest(context_data, statement_data, kSuccess);
1582 }
1583
1584
1585 TEST(NoErrorsEvalAndArgumentsStrict) {
1586 const char* context_data[][2] = {
1587 { "\"use strict\";", "" },
1588 { "function test_func() { \"use strict\";", "}" },
1589 { NULL, NULL }
1590 };
1591
1592 const char* statement_data[] = {
1593 "eval;",
1594 "arguments;",
1595 "var foo = eval;",
1596 "var foo = arguments;",
1597 "var foo = { eval: 1 };",
1598 "var foo = { arguments: 1 };",
1599 "var foo = { }; foo.eval = {};",
1600 "var foo = { }; foo.arguments = {};",
1601 NULL
1602 };
1603
1604 RunParserSyncTest(context_data, statement_data, kSuccess);
1605 }
1606
1607
1608 TEST(ErrorsFutureStrictReservedWords) {
1609 // Tests that both preparsing and parsing produce the right kind of errors for
1610 // using future strict reserved words as identifiers. Without the strict mode,
1611 // it's ok to use future strict reserved words as identifiers. With the strict
1612 // mode, it isn't.
1613 const char* context_data[][2] = {
1614 { "\"use strict\";", "" },
1615 { "function test_func() {\"use strict\"; ", "}"},
1616 { NULL, NULL }
1617 };
1618
1619 const char* statement_data[] = {
1620 "var interface;",
1621 "var foo, interface;",
1622 "try { } catch (interface) { }",
1623 "function interface() { }",
1624 "function foo(interface) { }",
1625 "function foo(bar, interface) { }",
1626 "interface = 1;",
1627 "var foo = interface = 1;",
1628 "++interface;",
1629 "interface++;",
1630 NULL
1631 };
1632
1633 RunParserSyncTest(context_data, statement_data, kError);
1634 }
1635
1636
1637 TEST(NoErrorsFutureStrictReservedWords) {
1638 const char* context_data[][2] = {
1639 { "", "" },
1640 { "function test_func() {", "}"},
1641 { NULL, NULL }
1642 };
1643
1644 const char* statement_data[] = {
1645 "var interface;",
1646 "var foo, interface;",
1647 "try { } catch (interface) { }",
1648 "function interface() { }",
1649 "function foo(interface) { }",
1650 "function foo(bar, interface) { }",
1651 "interface = 1;",
1652 "var foo = interface = 1;",
1653 "++interface;",
1654 "interface++;",
1655 NULL
1656 };
1657
1658 RunParserSyncTest(context_data, statement_data, kSuccess);
1659 }
1660
1661
1662 TEST(ErrorsReservedWords) {
1663 // Tests that both preparsing and parsing produce the right kind of errors for
1664 // using future reserved words as identifiers. These tests don't depend on the
1665 // strict mode.
1666 const char* context_data[][2] = {
1667 { "", "" },
1668 { "\"use strict\";", "" },
1669 { "var eval; function test_func() {", "}"},
1670 { "var eval; function test_func() {\"use strict\"; ", "}"},
1671 { NULL, NULL }
1672 };
1673
1674 const char* statement_data[] = {
1675 "var super;",
1676 "var foo, super;",
1677 "try { } catch (super) { }",
1678 "function super() { }",
1679 "function foo(super) { }",
1680 "function foo(bar, super) { }",
1681 "super = 1;",
1682 "var foo = super = 1;",
1683 "++super;",
1684 "super++;",
1685 "function foo super",
1686 NULL
1687 };
1688
1689 RunParserSyncTest(context_data, statement_data, kError);
1690 }
1691
1692
1693 TEST(NoErrorsYieldClassic) {
1694 // In classic mode, it's okay to use "yield" as identifier, *except* inside a
1695 // generator (see next test).
1696 const char* context_data[][2] = {
1697 { "", "" },
1698 { "function is_not_gen() {", "}" },
1699 { NULL, NULL }
1700 };
1701
1702 const char* statement_data[] = {
1703 "var yield;",
1704 "var foo, yield;",
1705 "try { } catch (yield) { }",
1706 "function yield() { }",
1707 "function foo(yield) { }",
1708 "function foo(bar, yield) { }",
1709 "yield = 1;",
1710 "var foo = yield = 1;",
1711 "++yield;",
1712 "yield++;",
1713 NULL
1714 };
1715
1716 RunParserSyncTest(context_data, statement_data, kSuccess);
1717 }
1718
1719
1720 TEST(ErrorsYieldClassicGenerator) {
1721 const char* context_data[][2] = {
1722 { "function * is_gen() {", "}" },
1723 { NULL, NULL }
1724 };
1725
1726 const char* statement_data[] = {
1727 "var yield;",
1728 "var foo, yield;",
1729 "try { } catch (yield) { }",
1730 "function yield() { }",
1731 // BUG: These should not be allowed, but they are (if kAllowGenerators is
1732 // set)
1733 // "function foo(yield) { }",
1734 // "function foo(bar, yield) { }",
1735 "yield = 1;",
1736 "var foo = yield = 1;",
1737 "++yield;",
1738 "yield++;",
1739 NULL
1740 };
1741
1742 // If generators are not allowed, the error will be produced at the '*' token,
1743 // so this test works both with and without the kAllowGenerators flag.
1744 RunParserSyncTest(context_data, statement_data, kError);
1745 }
1746
1747
1748 TEST(ErrorsYieldStrict) {
1749 const char* context_data[][2] = {
1750 { "\"use strict\";", "" },
1751 { "\"use strict\"; function is_not_gen() {", "}" },
1752 { "function test_func() {\"use strict\"; ", "}"},
1753 { NULL, NULL }
1754 };
1755
1756 const char* statement_data[] = {
1757 "var yield;",
1758 "var foo, yield;",
1759 "try { } catch (yield) { }",
1760 "function yield() { }",
1761 "function foo(yield) { }",
1762 "function foo(bar, yield) { }",
1763 "yield = 1;",
1764 "var foo = yield = 1;",
1765 "++yield;",
1766 "yield++;",
1767 NULL
1768 };
1769
1770 RunParserSyncTest(context_data, statement_data, kError);
1771 }
1772
1773
1774 TEST(ErrorsYield) {
1775 const char* context_data[][2] = {
1776 { "function * is_gen() {", "}" },
1777 { NULL, NULL }
1778 };
1779
1780 const char* statement_data[] = {
1781 "yield 2;", // this is legal inside generator
1782 "yield * 2;", // this is legal inside generator
1783 NULL
1784 };
1785
1786 // Here we cannot assert that there is no error, since there will be without
1787 // the kAllowGenerators flag. However, we test that Parser and PreParser
1788 // produce the same errors.
1789 RunParserSyncTest(context_data, statement_data, kSuccessOrError);
1790 }
1791
1792
1793 TEST(ErrorsNameOfStrictFunction) {
1794 // Tests that illegal tokens as names of a strict function produce the correct
1795 // errors.
1796 const char* context_data[][2] = {
1797 { "", ""},
1798 { "\"use strict\";", ""},
1799 { NULL, NULL }
1800 };
1801
1802 const char* statement_data[] = {
1803 "function eval() {\"use strict\";}",
1804 "function arguments() {\"use strict\";}",
1805 "function interface() {\"use strict\";}",
1806 "function yield() {\"use strict\";}",
1807 // Future reserved words are always illegal
1808 "function super() { }",
1809 "function super() {\"use strict\";}",
1810 NULL
1811 };
1812
1813 RunParserSyncTest(context_data, statement_data, kError);
1814 }
1815
1816
1817 TEST(NoErrorsNameOfStrictFunction) {
1818 const char* context_data[][2] = {
1819 { "", ""},
1820 { NULL, NULL }
1821 };
1822
1823 const char* statement_data[] = {
1824 "function eval() { }",
1825 "function arguments() { }",
1826 "function interface() { }",
1827 "function yield() { }",
1828 NULL
1829 };
1830
1831 RunParserSyncTest(context_data, statement_data, kSuccess);
1832 }
1833
1834
1835
1836 TEST(ErrorsIllegalWordsAsLabelsClassic) {
1837 // Using future reserved words as labels is always an error.
1838 const char* context_data[][2] = {
1839 { "", ""},
1840 { "function test_func() {", "}" },
1841 { NULL, NULL }
1842 };
1843
1844 const char* statement_data[] = {
1845 "super: while(true) { break super; }",
1846 NULL
1847 };
1848
1849 RunParserSyncTest(context_data, statement_data, kError);
1850 }
1851
1852
1853 TEST(ErrorsIllegalWordsAsLabelsStrict) {
1854 // Tests that illegal tokens as labels produce the correct errors.
1855 const char* context_data[][2] = {
1856 { "\"use strict\";", "" },
1857 { "function test_func() {\"use strict\"; ", "}"},
1858 { NULL, NULL }
1859 };
1860
1861 const char* statement_data[] = {
1862 "super: while(true) { break super; }",
1863 "interface: while(true) { break interface; }",
1864 "yield: while(true) { break yield; }",
1865 NULL
1866 };
1867
1868 RunParserSyncTest(context_data, statement_data, kError);
1869 }
1870
1871
1872 TEST(NoErrorsIllegalWordsAsLabels) {
1873 // Using eval and arguments as labels is legal even in strict mode.
1874 const char* context_data[][2] = {
1875 { "", ""},
1876 { "function test_func() {", "}" },
1877 { "\"use strict\";", "" },
1878 { "\"use strict\"; function test_func() {", "}" },
1879 { NULL, NULL }
1880 };
1881
1882 const char* statement_data[] = {
1883 "mylabel: while(true) { break mylabel; }",
1884 "eval: while(true) { break eval; }",
1885 "arguments: while(true) { break arguments; }",
1886 NULL
1887 };
1888
1889 RunParserSyncTest(context_data, statement_data, kSuccess);
1890 }
1891
1892
1893 TEST(ErrorsParenthesizedLabels) {
1894 // Parenthesized identifiers shouldn't be recognized as labels.
1895 const char* context_data[][2] = {
1896 { "", ""},
1897 { "function test_func() {", "}" },
1898 { NULL, NULL }
1899 };
1900
1901 const char* statement_data[] = {
1902 "(mylabel): while(true) { break mylabel; }",
1903 NULL
1904 };
1905
1906 RunParserSyncTest(context_data, statement_data, kError);
1907 }
1908
1909
1910 TEST(NoErrorsParenthesizedDirectivePrologue) {
1911 // Parenthesized directive prologue shouldn't be recognized.
1912 const char* context_data[][2] = {
1913 { "", ""},
1914 { NULL, NULL }
1915 };
1916
1917 const char* statement_data[] = {
1918 "(\"use strict\"); var eval;",
1919 NULL
1920 };
1921
1922 RunParserSyncTest(context_data, statement_data, kSuccess);
1923 }
1924
1925
1926 TEST(ErrorsNotAnIdentifierName) {
1927 const char* context_data[][2] = {
1928 { "", ""},
1929 { "\"use strict\";", ""},
1930 { NULL, NULL }
1931 };
1932
1933 const char* statement_data[] = {
1934 "var foo = {}; foo.{;",
1935 "var foo = {}; foo.};",
1936 "var foo = {}; foo.=;",
1937 "var foo = {}; foo.888;",
1938 "var foo = {}; foo.-;",
1939 "var foo = {}; foo.--;",
1940 NULL
1941 };
1942
1943 RunParserSyncTest(context_data, statement_data, kError);
1944 }
1945
1946
1947 TEST(NoErrorsIdentifierNames) {
1948 // Keywords etc. are valid as property names.
1949 const char* context_data[][2] = {
1950 { "", ""},
1951 { "\"use strict\";", ""},
1952 { NULL, NULL }
1953 };
1954
1955 const char* statement_data[] = {
1956 "var foo = {}; foo.if;",
1957 "var foo = {}; foo.yield;",
1958 "var foo = {}; foo.super;",
1959 "var foo = {}; foo.interface;",
1960 "var foo = {}; foo.eval;",
1961 "var foo = {}; foo.arguments;",
1962 NULL
1963 };
1964
1965 RunParserSyncTest(context_data, statement_data, kSuccess);
1966 }
1967
1968
1969 TEST(DontRegressPreParserDataSizes) {
1970 // These tests make sure that PreParser doesn't start producing less data.
1971
1972 v8::V8::Initialize();
1973
1974 int marker;
1975 CcTest::i_isolate()->stack_guard()->SetStackLimit(
1976 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
1977
1978 struct TestCase {
1979 const char* program;
1980 int symbols;
1981 int functions;
1982 } test_cases[] = {
1983 // Labels, variables and functions are recorded as symbols.
1984 {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0},
1985 {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0},
1986 {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2},
1987 // Labels, variables and functions insize lazy functions are not recorded.
1988 {"function lazy() { var a, b, c; }", 1, 1},
1989 {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1},
1990 {"function lazy() { function a() {} function b() {} function c() {} }", 1,
1991 1},
1992 {NULL, 0, 0}
1993 };
1994 // Each function adds 5 elements to the preparse function data.
1995 const int kDataPerFunction = 5;
1996
1997 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
1998 for (int i = 0; test_cases[i].program; i++) {
1999 const char* program = test_cases[i].program;
2000 i::Utf8ToUtf16CharacterStream stream(
2001 reinterpret_cast<const i::byte*>(program),
2002 static_cast<unsigned>(strlen(program)));
2003 i::CompleteParserRecorder log;
2004 i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
2005 scanner.Initialize(&stream);
2006
2007 i::PreParser preparser(&scanner, &log, stack_limit);
2008 preparser.set_allow_lazy(true);
2009 preparser.set_allow_natives_syntax(true);
2010 i::PreParser::PreParseResult result = preparser.PreParseProgram();
2011 CHECK_EQ(i::PreParser::kPreParseSuccess, result);
2012 if (log.symbol_ids() != test_cases[i].symbols) {
2013 i::OS::Print(
2014 "Expected preparse data for program:\n"
2015 "\t%s\n"
2016 "to contain %d symbols, however, received %d symbols.\n",
2017 program, test_cases[i].symbols, log.symbol_ids());
2018 CHECK(false);
2019 }
2020 if (log.function_position() != test_cases[i].functions * kDataPerFunction) {
2021 i::OS::Print(
2022 "Expected preparse data for program:\n"
2023 "\t%s\n"
2024 "to contain %d functions, however, received %d functions.\n",
2025 program, test_cases[i].functions,
2026 log.function_position() / kDataPerFunction);
2027 CHECK(false);
2028 }
2029 i::ScriptDataImpl data(log.ExtractData());
2030 CHECK(!data.has_error());
2031 }
2032 }
2033
2034
2035 TEST(FunctionDeclaresItselfStrict) {
2036 // Tests that we produce the right kinds of errors when a function declares
2037 // itself strict (we cannot produce there errors as soon as we see the
2038 // offending identifiers, because we don't know at that point whether the
2039 // function is strict or not).
2040 const char* context_data[][2] = {
2041 {"function eval() {", "}"},
2042 {"function arguments() {", "}"},
2043 {"function yield() {", "}"},
2044 {"function interface() {", "}"},
2045 {"function foo(eval) {", "}"},
2046 {"function foo(arguments) {", "}"},
2047 {"function foo(yield) {", "}"},
2048 {"function foo(interface) {", "}"},
2049 {"function foo(bar, eval) {", "}"},
2050 {"function foo(bar, arguments) {", "}"},
2051 {"function foo(bar, yield) {", "}"},
2052 {"function foo(bar, interface) {", "}"},
2053 {"function foo(bar, bar) {", "}"},
2054 { NULL, NULL }
2055 };
2056
2057 const char* strict_statement_data[] = {
2058 "\"use strict\";",
2059 NULL
2060 };
2061
2062 const char* non_strict_statement_data[] = {
2063 ";",
2064 NULL
2065 };
2066
2067 RunParserSyncTest(context_data, strict_statement_data, kError);
2068 RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
2069 }
2070
2071
2072 TEST(ErrorsTryWithoutCatchOrFinally) {
2073 const char* context_data[][2] = {
2074 {"", ""},
2075 { NULL, NULL }
2076 };
2077
2078 const char* statement_data[] = {
2079 "try { }",
2080 "try { } foo();",
2081 "try { } catch (e) foo();",
2082 "try { } catch { }",
2083 "try { } finally foo();",
2084 NULL
2085 };
2086
2087 RunParserSyncTest(context_data, statement_data, kError);
2088 }
2089
2090
2091 TEST(NoErrorsTryCatchFinally) {
2092 const char* context_data[][2] = {
2093 {"", ""},
2094 { NULL, NULL }
2095 };
2096
2097 const char* statement_data[] = {
2098 "try { } catch (e) { }",
2099 "try { } catch (e) { } finally { }",
2100 "try { } finally { }",
2101 NULL
2102 };
2103
2104 RunParserSyncTest(context_data, statement_data, kSuccess);
2105 }
2106
2107
2108 TEST(ErrorsRegexpLiteral) {
2109 const char* context_data[][2] = {
2110 {"var r = ", ""},
2111 { NULL, NULL }
2112 };
2113
2114 const char* statement_data[] = {
2115 "/unterminated",
2116 NULL
2117 };
2118
2119 RunParserSyncTest(context_data, statement_data, kError);
2120 }
2121
2122
2123 TEST(NoErrorsRegexpLiteral) {
2124 const char* context_data[][2] = {
2125 {"var r = ", ""},
2126 { NULL, NULL }
2127 };
2128
2129 const char* statement_data[] = {
2130 "/foo/",
2131 "/foo/g",
2132 "/foo/whatever", // This is an error but not detected by the parser.
2133 NULL
2134 };
2135
2136 RunParserSyncTest(context_data, statement_data, kSuccess);
2137 }
2138
2139
2140 TEST(Intrinsics) {
2141 const char* context_data[][2] = {
2142 {"", ""},
2143 { NULL, NULL }
2144 };
2145
2146 const char* statement_data[] = {
2147 "%someintrinsic(arg)",
2148 NULL
2149 };
2150
2151 // Parsing will fail or succeed depending on whether we allow natives syntax
2152 // or not.
2153 RunParserSyncTest(context_data, statement_data, kSuccessOrError);
2154 }
2155
2156
2157 TEST(NoErrorsNewExpression) {
2158 const char* context_data[][2] = {
2159 {"", ""},
2160 {"var f =", ""},
2161 { NULL, NULL }
2162 };
2163
2164 const char* statement_data[] = {
2165 "new foo",
2166 "new foo();",
2167 "new foo(1);",
2168 "new foo(1, 2);",
2169 // The first () will be processed as a part of the NewExpression and the
2170 // second () will be processed as part of LeftHandSideExpression.
2171 "new foo()();",
2172 // The first () will be processed as a part of the inner NewExpression and
2173 // the second () will be processed as a part of the outer NewExpression.
2174 "new new foo()();",
2175 "new foo.bar;",
2176 "new foo.bar();",
2177 "new foo.bar.baz;",
2178 "new foo.bar().baz;",
2179 "new foo[bar];",
2180 "new foo[bar]();",
2181 "new foo[bar][baz];",
2182 "new foo[bar]()[baz];",
2183 "new foo[bar].baz(baz)()[bar].baz;",
2184 "new \"foo\"", // Runtime error
2185 "new 1", // Runtime error
2186 "new foo++",
2187 // This even runs:
2188 "(new new Function(\"this.x = 1\")).x;",
2189 "new new Test_Two(String, 2).v(0123).length;",
2190 NULL
2191 };
2192
2193 RunParserSyncTest(context_data, statement_data, kSuccess);
2194 }
2195
2196
2197 TEST(ErrorsNewExpression) {
2198 const char* context_data[][2] = {
2199 {"", ""},
2200 {"var f =", ""},
2201 { NULL, NULL }
2202 };
2203
2204 const char* statement_data[] = {
2205 "new foo bar",
2206 "new ) foo",
2207 "new ++foo",
2208 NULL
2209 };
2210
2211 RunParserSyncTest(context_data, statement_data, kError);
2212 }
OLDNEW
« no previous file with comments | « test/cctest/test-microtask-delivery.cc ('k') | test/cctest/test-platform.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698