OLD | NEW |
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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 "x/* precomment\n */ --> 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", | 138 "var x = 42; --> is eol-comment\nvar y = 37;\n", |
139 "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n", | 139 "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n", |
140 NULL | 140 NULL |
141 }; | 141 }; |
142 | 142 |
143 // Parser/Scanner needs a stack limit. | 143 // Parser/Scanner needs a stack limit. |
144 int marker; | 144 int marker; |
145 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 145 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
146 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 146 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
147 | 147 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); |
148 for (int i = 0; tests[i]; i++) { | 148 for (int i = 0; tests[i]; i++) { |
149 v8::Handle<v8::String> source = v8::String::NewFromUtf8( | 149 const i::byte* source = |
150 isolate, tests[i], v8::String::kNormalString, i::StrLength(tests[i])); | 150 reinterpret_cast<const i::byte*>(tests[i]); |
151 v8::ScriptData* data = v8::ScriptData::PreCompile(source); | 151 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(tests[i])); |
152 CHECK(data != NULL && !data->HasError()); | 152 i::CompleteParserRecorder log; |
153 delete data; | 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::ScriptDataImpl data(log.ExtractData()); |
| 160 CHECK(!data.has_error()); |
154 } | 161 } |
155 | 162 |
156 for (int i = 0; fail_tests[i]; i++) { | 163 for (int i = 0; fail_tests[i]; i++) { |
157 v8::Handle<v8::String> source = | 164 const i::byte* source = |
158 v8::String::NewFromUtf8(isolate, | 165 reinterpret_cast<const i::byte*>(fail_tests[i]); |
159 fail_tests[i], | 166 i::Utf8ToUtf16CharacterStream stream(source, i::StrLength(fail_tests[i])); |
160 v8::String::kNormalString, | 167 i::CompleteParserRecorder log; |
161 i::StrLength(fail_tests[i])); | 168 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
162 v8::ScriptData* data = v8::ScriptData::PreCompile(source); | 169 scanner.Initialize(&stream); |
163 CHECK(data == NULL || data->HasError()); | 170 i::PreParser preparser(&scanner, &log, stack_limit); |
164 delete data; | 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::ScriptDataImpl data(log.ExtractData()); |
| 176 CHECK(data.has_error()); |
165 } | 177 } |
166 } | 178 } |
167 | 179 |
168 | 180 |
169 class ScriptResource : public v8::String::ExternalAsciiStringResource { | 181 class ScriptResource : public v8::String::ExternalAsciiStringResource { |
170 public: | 182 public: |
171 ScriptResource(const char* data, size_t length) | 183 ScriptResource(const char* data, size_t length) |
172 : data_(data), length_(length) { } | 184 : data_(data), length_(length) { } |
173 | 185 |
174 const char* data() const { return data_; } | 186 const char* data() const { return data_; } |
175 size_t length() const { return length_; } | 187 size_t length() const { return length_; } |
176 | 188 |
177 private: | 189 private: |
178 const char* data_; | 190 const char* data_; |
179 size_t length_; | 191 size_t length_; |
180 }; | 192 }; |
181 | 193 |
182 | 194 |
183 TEST(Preparsing) { | 195 TEST(UsingCachedData) { |
184 v8::Isolate* isolate = CcTest::isolate(); | 196 v8::Isolate* isolate = CcTest::isolate(); |
185 v8::HandleScope handles(isolate); | 197 v8::HandleScope handles(isolate); |
186 v8::Local<v8::Context> context = v8::Context::New(isolate); | 198 v8::Local<v8::Context> context = v8::Context::New(isolate); |
187 v8::Context::Scope context_scope(context); | 199 v8::Context::Scope context_scope(context); |
188 int marker; | 200 int marker; |
189 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 201 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
190 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 202 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
191 | 203 |
192 // Source containing functions that might be lazily compiled and all types | 204 // Source containing functions that might be lazily compiled and all types |
193 // of symbols (string, propertyName, regexp). | 205 // of symbols (string, propertyName, regexp). |
194 const char* source = | 206 const char* source = |
195 "var x = 42;" | 207 "var x = 42;" |
196 "function foo(a) { return function nolazy(b) { return a + b; } }" | 208 "function foo(a) { return function nolazy(b) { return a + b; } }" |
197 "function bar(a) { if (a) return function lazy(b) { return b; } }" | 209 "function bar(a) { if (a) return function lazy(b) { return b; } }" |
198 "var z = {'string': 'string literal', bareword: 'propertyName', " | 210 "var z = {'string': 'string literal', bareword: 'propertyName', " |
199 " 42: 'number literal', for: 'keyword as propertyName', " | 211 " 42: 'number literal', for: 'keyword as propertyName', " |
200 " f\\u006fr: 'keyword propertyname with escape'};" | 212 " f\\u006fr: 'keyword propertyname with escape'};" |
201 "var v = /RegExp Literal/;" | 213 "var v = /RegExp Literal/;" |
202 "var w = /RegExp Literal\\u0020With Escape/gin;" | 214 "var w = /RegExp Literal\\u0020With Escape/gin;" |
203 "var y = { get getter() { return 42; }, " | 215 "var y = { get getter() { return 42; }, " |
204 " set setter(v) { this.value = v; }};"; | 216 " set setter(v) { this.value = v; }};"; |
205 int source_length = i::StrLength(source); | 217 int source_length = i::StrLength(source); |
206 const char* error_source = "var x = y z;"; | |
207 int error_source_length = i::StrLength(error_source); | |
208 | 218 |
209 v8::ScriptData* preparse = v8::ScriptData::PreCompile(v8::String::NewFromUtf8( | 219 // ScriptResource will be deleted when the corresponding String is GCd. |
210 isolate, source, v8::String::kNormalString, source_length)); | 220 v8::ScriptCompiler::Source script_source(v8::String::NewExternal( |
211 CHECK(!preparse->HasError()); | 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. |
212 bool lazy_flag = i::FLAG_lazy; | 228 bool lazy_flag = i::FLAG_lazy; |
213 { | 229 i::FLAG_lazy = true; |
214 i::FLAG_lazy = true; | 230 v8::ScriptCompiler::Compile(isolate, &script_source); |
215 ScriptResource* resource = new ScriptResource(source, source_length); | 231 i::FLAG_lazy = false; |
216 v8::ScriptCompiler::Source script_source( | 232 v8::ScriptCompiler::CompileUnbound(isolate, &script_source); |
217 v8::String::NewExternal(isolate, resource), | |
218 new v8::ScriptCompiler::CachedData( | |
219 reinterpret_cast<const uint8_t*>(preparse->Data()), | |
220 preparse->Length())); | |
221 v8::ScriptCompiler::Compile(isolate, | |
222 &script_source); | |
223 } | |
224 | |
225 { | |
226 i::FLAG_lazy = false; | |
227 | |
228 ScriptResource* resource = new ScriptResource(source, source_length); | |
229 v8::ScriptCompiler::Source script_source( | |
230 v8::String::NewExternal(isolate, resource), | |
231 new v8::ScriptCompiler::CachedData( | |
232 reinterpret_cast<const uint8_t*>(preparse->Data()), | |
233 preparse->Length())); | |
234 v8::ScriptCompiler::CompileUnbound(isolate, &script_source); | |
235 } | |
236 delete preparse; | |
237 i::FLAG_lazy = lazy_flag; | 233 i::FLAG_lazy = lazy_flag; |
238 | |
239 // Syntax error. | |
240 v8::ScriptData* error_preparse = v8::ScriptData::PreCompile( | |
241 v8::String::NewFromUtf8(isolate, | |
242 error_source, | |
243 v8::String::kNormalString, | |
244 error_source_length)); | |
245 CHECK(error_preparse->HasError()); | |
246 i::ScriptDataImpl *pre_impl = | |
247 reinterpret_cast<i::ScriptDataImpl*>(error_preparse); | |
248 i::Scanner::Location error_location = | |
249 pre_impl->MessageLocation(); | |
250 // Error is at "z" in source, location 10..11. | |
251 CHECK_EQ(10, error_location.beg_pos); | |
252 CHECK_EQ(11, error_location.end_pos); | |
253 // Should not crash. | |
254 const char* message = pre_impl->BuildMessage(); | |
255 i::Vector<const char*> args = pre_impl->BuildArgs(); | |
256 CHECK_GT(strlen(message), 0); | |
257 args.Dispose(); | |
258 i::DeleteArray(message); | |
259 delete error_preparse; | |
260 } | 234 } |
261 | 235 |
262 | 236 |
263 TEST(PreparseFunctionDataIsUsed) { | 237 TEST(PreparseFunctionDataIsUsed) { |
264 // This tests that we actually do use the function data generated by the | 238 // This tests that we actually do use the function data generated by the |
265 // preparser. | 239 // preparser. |
266 | 240 |
267 // Make preparsing work for short scripts. | 241 // Make preparsing work for short scripts. |
268 i::FLAG_min_preparse_length = 0; | 242 i::FLAG_min_preparse_length = 0; |
269 | 243 |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 namespace internal { | 439 namespace internal { |
466 | 440 |
467 struct CompleteParserRecorderFriend { | 441 struct CompleteParserRecorderFriend { |
468 static void FakeWritingSymbolIdInPreParseData(CompleteParserRecorder* log, | 442 static void FakeWritingSymbolIdInPreParseData(CompleteParserRecorder* log, |
469 int number) { | 443 int number) { |
470 log->WriteNumber(number); | 444 log->WriteNumber(number); |
471 if (log->symbol_id_ < number + 1) { | 445 if (log->symbol_id_ < number + 1) { |
472 log->symbol_id_ = number + 1; | 446 log->symbol_id_ = number + 1; |
473 } | 447 } |
474 } | 448 } |
475 static int symbol_position(CompleteParserRecorder* log) { | |
476 return log->symbol_store_.size(); | |
477 } | |
478 static int symbol_ids(CompleteParserRecorder* log) { | |
479 return log->symbol_id_; | |
480 } | |
481 static int function_position(CompleteParserRecorder* log) { | |
482 return log->function_store_.size(); | |
483 } | |
484 }; | 449 }; |
485 | 450 |
486 } | 451 } |
487 } | 452 } |
488 | 453 |
489 | 454 |
490 TEST(StoringNumbersInPreParseData) { | 455 TEST(StoringNumbersInPreParseData) { |
491 // Symbol IDs are split into chunks of 7 bits for storing. This is a | 456 // Symbol IDs are split into chunks of 7 bits for storing. This is a |
492 // regression test for a bug where a symbol id was incorrectly stored if some | 457 // regression test for a bug where a symbol id was incorrectly stored if some |
493 // of the chunks in the middle were all zeros. | 458 // of the chunks in the middle were all zeros. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 const char* program = "var x = 'something';\n" | 494 const char* program = "var x = 'something';\n" |
530 "escape: function() {}"; | 495 "escape: function() {}"; |
531 // Fails parsing expecting an identifier after "function". | 496 // Fails parsing expecting an identifier after "function". |
532 // Before fix, didn't check *ok after Expect(Token::Identifier, ok), | 497 // Before fix, didn't check *ok after Expect(Token::Identifier, ok), |
533 // and then used the invalid currently scanned literal. This always | 498 // and then used the invalid currently scanned literal. This always |
534 // failed in debug mode, and sometimes crashed in release mode. | 499 // failed in debug mode, and sometimes crashed in release mode. |
535 | 500 |
536 i::Utf8ToUtf16CharacterStream stream( | 501 i::Utf8ToUtf16CharacterStream stream( |
537 reinterpret_cast<const i::byte*>(program), | 502 reinterpret_cast<const i::byte*>(program), |
538 static_cast<unsigned>(strlen(program))); | 503 static_cast<unsigned>(strlen(program))); |
539 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream); | 504 i::CompleteParserRecorder log; |
540 CHECK(data->HasError()); | 505 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
541 delete data; | 506 scanner.Initialize(&stream); |
| 507 i::PreParser preparser(&scanner, &log, |
| 508 CcTest::i_isolate()->stack_guard()->real_climit()); |
| 509 preparser.set_allow_lazy(true); |
| 510 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 511 // Even in the case of a syntax error, kPreParseSuccess is returned. |
| 512 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
| 513 i::ScriptDataImpl data(log.ExtractData()); |
| 514 CHECK(data.has_error()); |
542 } | 515 } |
543 | 516 |
544 | 517 |
545 TEST(Regress928) { | 518 TEST(Regress928) { |
546 v8::V8::Initialize(); | 519 v8::V8::Initialize(); |
547 i::Isolate* isolate = CcTest::i_isolate(); | 520 i::Isolate* isolate = CcTest::i_isolate(); |
548 i::Factory* factory = isolate->factory(); | 521 i::Factory* factory = isolate->factory(); |
549 | 522 |
550 // Preparsing didn't consider the catch clause of a try statement | 523 // Preparsing didn't consider the catch clause of a try statement |
551 // as with-content, which made it assume that a function inside | 524 // as with-content, which made it assume that a function inside |
552 // the block could be lazily compiled, and an extra, unexpected, | 525 // the block could be lazily compiled, and an extra, unexpected, |
553 // entry was added to the data. | 526 // entry was added to the data. |
554 int marker; | 527 int marker; |
555 isolate->stack_guard()->SetStackLimit( | 528 isolate->stack_guard()->SetStackLimit( |
556 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 529 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
557 | 530 |
558 const char* program = | 531 const char* program = |
559 "try { } catch (e) { var foo = function () { /* first */ } }" | 532 "try { } catch (e) { var foo = function () { /* first */ } }" |
560 "var bar = function () { /* second */ }"; | 533 "var bar = function () { /* second */ }"; |
561 | 534 |
562 v8::HandleScope handles(CcTest::isolate()); | 535 v8::HandleScope handles(CcTest::isolate()); |
563 i::Handle<i::String> source( | 536 i::Handle<i::String> source( |
564 factory->NewStringFromAscii(i::CStrVector(program))); | 537 factory->NewStringFromAscii(i::CStrVector(program))); |
565 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); | 538 i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
566 i::ScriptDataImpl* data = i::PreParserApi::PreParse(isolate, &stream); | 539 i::CompleteParserRecorder log; |
567 CHECK(!data->HasError()); | 540 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); |
568 | 541 scanner.Initialize(&stream); |
569 data->Initialize(); | 542 i::PreParser preparser(&scanner, &log, |
| 543 CcTest::i_isolate()->stack_guard()->real_climit()); |
| 544 preparser.set_allow_lazy(true); |
| 545 i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
| 546 CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
| 547 i::ScriptDataImpl data(log.ExtractData()); |
| 548 CHECK(!data.has_error()); |
| 549 data.Initialize(); |
570 | 550 |
571 int first_function = | 551 int first_function = |
572 static_cast<int>(strstr(program, "function") - program); | 552 static_cast<int>(strstr(program, "function") - program); |
573 int first_lbrace = first_function + i::StrLength("function () "); | 553 int first_lbrace = first_function + i::StrLength("function () "); |
574 CHECK_EQ('{', program[first_lbrace]); | 554 CHECK_EQ('{', program[first_lbrace]); |
575 i::FunctionEntry entry1 = data->GetFunctionEntry(first_lbrace); | 555 i::FunctionEntry entry1 = data.GetFunctionEntry(first_lbrace); |
576 CHECK(!entry1.is_valid()); | 556 CHECK(!entry1.is_valid()); |
577 | 557 |
578 int second_function = | 558 int second_function = |
579 static_cast<int>(strstr(program + first_lbrace, "function") - program); | 559 static_cast<int>(strstr(program + first_lbrace, "function") - program); |
580 int second_lbrace = | 560 int second_lbrace = |
581 second_function + i::StrLength("function () "); | 561 second_function + i::StrLength("function () "); |
582 CHECK_EQ('{', program[second_lbrace]); | 562 CHECK_EQ('{', program[second_lbrace]); |
583 i::FunctionEntry entry2 = data->GetFunctionEntry(second_lbrace); | 563 i::FunctionEntry entry2 = data.GetFunctionEntry(second_lbrace); |
584 CHECK(entry2.is_valid()); | 564 CHECK(entry2.is_valid()); |
585 CHECK_EQ('}', program[entry2.end_pos() - 1]); | 565 CHECK_EQ('}', program[entry2.end_pos() - 1]); |
586 delete data; | |
587 } | 566 } |
588 | 567 |
589 | 568 |
590 TEST(PreParseOverflow) { | 569 TEST(PreParseOverflow) { |
591 v8::V8::Initialize(); | 570 v8::V8::Initialize(); |
592 | 571 |
593 int marker; | 572 int marker; |
594 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 573 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
595 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 574 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
596 | 575 |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 // the combinatorial explosion. | 1528 // the combinatorial explosion. |
1550 static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals }; | 1529 static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals }; |
1551 TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2)); | 1530 TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2)); |
1552 TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2)); | 1531 TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2)); |
1553 | 1532 |
1554 static const ParserFlag flags3[] = { kAllowNativesSyntax }; | 1533 static const ParserFlag flags3[] = { kAllowNativesSyntax }; |
1555 TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3)); | 1534 TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3)); |
1556 } | 1535 } |
1557 | 1536 |
1558 | 1537 |
1559 TEST(PreparserStrictOctal) { | 1538 TEST(StrictOctal) { |
1560 // Test that syntax error caused by octal literal is reported correctly as | 1539 // Test that syntax error caused by octal literal is reported correctly as |
1561 // such (issue 2220). | 1540 // such (issue 2220). |
1562 v8::internal::FLAG_min_preparse_length = 1; // Force preparsing. | |
1563 v8::V8::Initialize(); | 1541 v8::V8::Initialize(); |
1564 v8::HandleScope scope(CcTest::isolate()); | 1542 v8::HandleScope scope(CcTest::isolate()); |
1565 v8::Context::Scope context_scope( | 1543 v8::Context::Scope context_scope( |
1566 v8::Context::New(CcTest::isolate())); | 1544 v8::Context::New(CcTest::isolate())); |
1567 v8::TryCatch try_catch; | 1545 v8::TryCatch try_catch; |
1568 const char* script = | 1546 const char* script = |
1569 "\"use strict\"; \n" | 1547 "\"use strict\"; \n" |
1570 "a = function() { \n" | 1548 "a = function() { \n" |
1571 " b = function() { \n" | 1549 " b = function() { \n" |
1572 " 01; \n" | 1550 " 01; \n" |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2079 "var foo = {}; foo.eval;", | 2057 "var foo = {}; foo.eval;", |
2080 "var foo = {}; foo.arguments;", | 2058 "var foo = {}; foo.arguments;", |
2081 NULL | 2059 NULL |
2082 }; | 2060 }; |
2083 | 2061 |
2084 RunParserSyncTest(context_data, statement_data, kSuccess); | 2062 RunParserSyncTest(context_data, statement_data, kSuccess); |
2085 } | 2063 } |
2086 | 2064 |
2087 | 2065 |
2088 TEST(DontRegressPreParserDataSizes) { | 2066 TEST(DontRegressPreParserDataSizes) { |
2089 // These tests make sure that PreParser doesn't start producing less data. | 2067 // These tests make sure that Parser doesn't start producing less "preparse |
| 2068 // data" (data which the embedder can cache). |
| 2069 v8::V8::Initialize(); |
| 2070 v8::Isolate* isolate = CcTest::isolate(); |
| 2071 v8::HandleScope handles(isolate); |
2090 | 2072 |
2091 v8::V8::Initialize(); | |
2092 int marker; | 2073 int marker; |
2093 CcTest::i_isolate()->stack_guard()->SetStackLimit( | 2074 CcTest::i_isolate()->stack_guard()->SetStackLimit( |
2094 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); | 2075 reinterpret_cast<uintptr_t>(&marker) - 128 * 1024); |
2095 | 2076 |
2096 struct TestCase { | 2077 struct TestCase { |
2097 const char* program; | 2078 const char* program; |
2098 int symbols; | 2079 int symbols; |
2099 int functions; | 2080 int functions; |
2100 } test_cases[] = { | 2081 } test_cases[] = { |
2101 // Labels and variables are recorded as symbols. | 2082 // Labels and variables are recorded as symbols. |
2102 {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0}, | 2083 {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0}, |
2103 {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0}, | 2084 {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0}, |
2104 {"var x = {y: 1};", 2, 0}, | 2085 {"var x = {y: 1};", 2, 0}, |
2105 {"var x = {}; x.y = 1", 2, 0}, | 2086 {"var x = {}; x.y = 1", 2, 0}, |
2106 // "get" is recorded as a symbol too. | 2087 // "get" is recorded as a symbol too. |
2107 {"var x = {get foo(){} };", 3, 1}, | 2088 {"var x = {get foo(){} };", 3, 1}, |
2108 // When keywords are used as identifiers, they're logged as symbols, too: | 2089 // When keywords are used as identifiers, they're logged as symbols, too: |
2109 {"var x = {if: 1};", 2, 0}, | 2090 {"var x = {if: 1};", 2, 0}, |
2110 {"var x = {}; x.if = 1", 2, 0}, | 2091 {"var x = {}; x.if = 1", 2, 0}, |
2111 {"var x = {get if(){} };", 3, 1}, | 2092 {"var x = {get if(){} };", 3, 1}, |
2112 // Functions | 2093 // Functions |
2113 {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2}, | 2094 {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2}, |
2114 // Labels, variables and functions insize lazy functions are not recorded. | 2095 // Labels, variables and functions insize lazy functions are not recorded. |
2115 {"function lazy() { var a, b, c; }", 1, 1}, | 2096 {"function lazy() { var a, b, c; }", 1, 1}, |
2116 {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1}, | 2097 {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1}, |
2117 {"function lazy() { function a() {} function b() {} function c() {} }", 1, | 2098 {"function lazy() { function a() {} function b() {} function c() {} }", 1, |
2118 1}, | 2099 1}, |
2119 {NULL, 0, 0} | 2100 {NULL, 0, 0} |
2120 }; | 2101 }; |
2121 // Each function adds 5 elements to the preparse function data. | |
2122 const int kDataPerFunction = 5; | |
2123 | 2102 |
2124 typedef i::CompleteParserRecorderFriend F; | |
2125 uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); | |
2126 for (int i = 0; test_cases[i].program; i++) { | 2103 for (int i = 0; test_cases[i].program; i++) { |
2127 const char* program = test_cases[i].program; | 2104 const char* program = test_cases[i].program; |
2128 i::Utf8ToUtf16CharacterStream stream( | 2105 i::Factory* factory = CcTest::i_isolate()->factory(); |
2129 reinterpret_cast<const i::byte*>(program), | 2106 i::Handle<i::String> source( |
2130 static_cast<unsigned>(strlen(program))); | 2107 factory->NewStringFromUtf8(i::CStrVector(program))); |
2131 i::CompleteParserRecorder log; | 2108 i::Handle<i::Script> script = factory->NewScript(source); |
2132 i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); | 2109 i::CompilationInfoWithZone info(script); |
2133 scanner.Initialize(&stream); | 2110 i::ScriptDataImpl* data = NULL; |
| 2111 info.SetCachedData(&data, i::PRODUCE_CACHED_DATA); |
| 2112 i::Parser::Parse(&info, true); |
| 2113 CHECK(data); |
| 2114 CHECK(!data->HasError()); |
2134 | 2115 |
2135 i::PreParser preparser(&scanner, &log, stack_limit); | 2116 if (data->symbol_count() != test_cases[i].symbols) { |
2136 preparser.set_allow_lazy(true); | |
2137 preparser.set_allow_natives_syntax(true); | |
2138 i::PreParser::PreParseResult result = preparser.PreParseProgram(); | |
2139 CHECK_EQ(i::PreParser::kPreParseSuccess, result); | |
2140 if (F::symbol_ids(&log) != test_cases[i].symbols) { | |
2141 i::OS::Print( | 2117 i::OS::Print( |
2142 "Expected preparse data for program:\n" | 2118 "Expected preparse data for program:\n" |
2143 "\t%s\n" | 2119 "\t%s\n" |
2144 "to contain %d symbols, however, received %d symbols.\n", | 2120 "to contain %d symbols, however, received %d symbols.\n", |
2145 program, test_cases[i].symbols, F::symbol_ids(&log)); | 2121 program, test_cases[i].symbols, data->symbol_count()); |
2146 CHECK(false); | 2122 CHECK(false); |
2147 } | 2123 } |
2148 if (F::function_position(&log) != | 2124 if (data->function_count() != test_cases[i].functions) { |
2149 test_cases[i].functions * kDataPerFunction) { | |
2150 i::OS::Print( | 2125 i::OS::Print( |
2151 "Expected preparse data for program:\n" | 2126 "Expected preparse data for program:\n" |
2152 "\t%s\n" | 2127 "\t%s\n" |
2153 "to contain %d functions, however, received %d functions.\n", | 2128 "to contain %d functions, however, received %d functions.\n", |
2154 program, test_cases[i].functions, | 2129 program, test_cases[i].functions, |
2155 F::function_position(&log) / kDataPerFunction); | 2130 data->function_count()); |
2156 CHECK(false); | 2131 CHECK(false); |
2157 } | 2132 } |
2158 i::ScriptDataImpl data(log.ExtractData()); | |
2159 CHECK(!data.has_error()); | |
2160 } | 2133 } |
2161 } | 2134 } |
2162 | 2135 |
2163 | 2136 |
2164 TEST(FunctionDeclaresItselfStrict) { | 2137 TEST(FunctionDeclaresItselfStrict) { |
2165 // Tests that we produce the right kinds of errors when a function declares | 2138 // Tests that we produce the right kinds of errors when a function declares |
2166 // itself strict (we cannot produce there errors as soon as we see the | 2139 // itself strict (we cannot produce there errors as soon as we see the |
2167 // offending identifiers, because we don't know at that point whether the | 2140 // offending identifiers, because we don't know at that point whether the |
2168 // function is strict or not). | 2141 // function is strict or not). |
2169 const char* context_data[][2] = { | 2142 const char* context_data[][2] = { |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2597 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError); | 2570 RunParserSyncTest(assignment_context_data, bad_statement_data_common, kError); |
2598 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment, | 2571 RunParserSyncTest(assignment_context_data, bad_statement_data_for_assignment, |
2599 kError); | 2572 kError); |
2600 | 2573 |
2601 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess); | 2574 RunParserSyncTest(prefix_context_data, good_statement_data, kSuccess); |
2602 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError); | 2575 RunParserSyncTest(prefix_context_data, bad_statement_data_common, kError); |
2603 | 2576 |
2604 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess); | 2577 RunParserSyncTest(postfix_context_data, good_statement_data, kSuccess); |
2605 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError); | 2578 RunParserSyncTest(postfix_context_data, bad_statement_data_common, kError); |
2606 } | 2579 } |
OLD | NEW |