Commit d3c98121 authored by Mathias Bynens's avatar Mathias Bynens Committed by Commit Bot

[parser] Add use counter for U+2028 & U+2029

The context is the following proposal to make JSON a subset of
JavaScript: https://github.com/tc39/proposal-json-superset

There’s interest in performing a side investigation to answer the
question of what would happen if we stopped treating U+2028 and U+2029
as `LineTerminator`s *entirely*. (Note that this is separate from the
proposal, which just changes how these characters are handled in
ECMAScript strings.) This is technically a breaking change, and IMHO it
would be wonderful if we could get away with it, but no one really has
any data on whether or not we could. Adding this use counter lets us get
that data.

BUG=v8:6827

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: Ia22e8db1634df4d3f965bec8e1cfa11cc7b5e9aa
Reviewed-on: https://chromium-review.googlesource.com/693155
Commit-Queue: Mathias Bynens <mathias@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48260}
parent 7283b57c
...@@ -7048,6 +7048,7 @@ class V8_EXPORT Isolate { ...@@ -7048,6 +7048,7 @@ class V8_EXPORT Isolate {
kPromiseConstructorReturnedUndefined = 38, kPromiseConstructorReturnedUndefined = 38,
kConstructorNonUndefinedPrimitiveReturn = 39, kConstructorNonUndefinedPrimitiveReturn = 39,
kLabeledExpressionStatement = 40, kLabeledExpressionStatement = 40,
kLineOrParagraphSeparatorAsLineTerminator = 41,
// If you add new values here, you'll also need to update Chromium's: // If you add new values here, you'll also need to update Chromium's:
// UseCounter.h, V8PerIsolateData.cpp, histograms.xml // UseCounter.h, V8PerIsolateData.cpp, histograms.xml
......
...@@ -464,7 +464,7 @@ Parser::Parser(ParseInfo* info) ...@@ -464,7 +464,7 @@ Parser::Parser(ParseInfo* info)
: ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
info->extension(), info->GetOrCreateAstValueFactory(), info->extension(), info->GetOrCreateAstValueFactory(),
info->runtime_call_stats(), true), info->runtime_call_stats(), true),
scanner_(info->unicode_cache()), scanner_(info->unicode_cache(), use_counts_),
reusable_preparser_(nullptr), reusable_preparser_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly. mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
source_range_map_(info->source_range_map()), source_range_map_(info->source_range_map()),
......
...@@ -173,14 +173,30 @@ bool Scanner::BookmarkScope::HasBeenApplied() { ...@@ -173,14 +173,30 @@ bool Scanner::BookmarkScope::HasBeenApplied() {
return bookmark_ == kBookmarkWasApplied; return bookmark_ == kBookmarkWasApplied;
} }
// LineTerminator: 'JS_Line_Terminator' in point.properties
// ES#sec-line-terminators lists exactly 4 code points:
// LF (U+000A), CR (U+000D), LS(U+2028), PS(U+2029)
bool Scanner::IsLineTerminator(uc32 c) {
if (c == 0x000A || c == 0x000D) {
return true;
}
if (c == 0x2028 || c == 0x2029) {
++use_counts_[v8::Isolate::UseCounterFeature::
kLineOrParagraphSeparatorAsLineTerminator];
return true;
}
return false;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Scanner // Scanner
Scanner::Scanner(UnicodeCache* unicode_cache) Scanner::Scanner(UnicodeCache* unicode_cache, int* use_counts)
: unicode_cache_(unicode_cache), : unicode_cache_(unicode_cache),
octal_pos_(Location::invalid()), octal_pos_(Location::invalid()),
octal_message_(MessageTemplate::kNone), octal_message_(MessageTemplate::kNone),
found_html_comment_(false) {} found_html_comment_(false),
use_counts_(use_counts) {}
void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) { void Scanner::Initialize(Utf16CharacterStream* source, bool is_module) {
DCHECK_NOT_NULL(source); DCHECK_NOT_NULL(source);
...@@ -439,7 +455,7 @@ Token::Value Scanner::SkipWhiteSpace() { ...@@ -439,7 +455,7 @@ Token::Value Scanner::SkipWhiteSpace() {
// Advance as long as character is a WhiteSpace or LineTerminator. // Advance as long as character is a WhiteSpace or LineTerminator.
// Remember if the latter is the case. // Remember if the latter is the case.
if (unibrow::IsLineTerminator(c0_)) { if (IsLineTerminator(c0_)) {
has_line_terminator_before_next_ = true; has_line_terminator_before_next_ = true;
} else if (!unicode_cache_->IsWhiteSpace(c0_)) { } else if (!unicode_cache_->IsWhiteSpace(c0_)) {
break; break;
...@@ -496,7 +512,7 @@ Token::Value Scanner::SkipSingleLineComment() { ...@@ -496,7 +512,7 @@ Token::Value Scanner::SkipSingleLineComment() {
// separately by the lexical grammar and becomes part of the // separately by the lexical grammar and becomes part of the
// stream of input elements for the syntactic grammar (see // stream of input elements for the syntactic grammar (see
// ECMA-262, section 7.4). // ECMA-262, section 7.4).
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
Advance(); Advance();
} }
...@@ -506,7 +522,7 @@ Token::Value Scanner::SkipSingleLineComment() { ...@@ -506,7 +522,7 @@ Token::Value Scanner::SkipSingleLineComment() {
Token::Value Scanner::SkipSourceURLComment() { Token::Value Scanner::SkipSourceURLComment() {
TryToParseSourceURLComment(); TryToParseSourceURLComment();
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
Advance(); Advance();
} }
...@@ -542,7 +558,7 @@ void Scanner::TryToParseSourceURLComment() { ...@@ -542,7 +558,7 @@ void Scanner::TryToParseSourceURLComment() {
while (c0_ != kEndOfInput && unicode_cache_->IsWhiteSpace(c0_)) { while (c0_ != kEndOfInput && unicode_cache_->IsWhiteSpace(c0_)) {
Advance(); Advance();
} }
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
// Disallowed characters. // Disallowed characters.
if (c0_ == '"' || c0_ == '\'') { if (c0_ == '"' || c0_ == '\'') {
value->Reset(); value->Reset();
...@@ -555,7 +571,7 @@ void Scanner::TryToParseSourceURLComment() { ...@@ -555,7 +571,7 @@ void Scanner::TryToParseSourceURLComment() {
Advance(); Advance();
} }
// Allow whitespace at the end. // Allow whitespace at the end.
while (c0_ != kEndOfInput && !unibrow::IsLineTerminator(c0_)) { while (c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
if (!unicode_cache_->IsWhiteSpace(c0_)) { if (!unicode_cache_->IsWhiteSpace(c0_)) {
value->Reset(); value->Reset();
break; break;
...@@ -572,7 +588,7 @@ Token::Value Scanner::SkipMultiLineComment() { ...@@ -572,7 +588,7 @@ Token::Value Scanner::SkipMultiLineComment() {
while (c0_ != kEndOfInput) { while (c0_ != kEndOfInput) {
uc32 ch = c0_; uc32 ch = c0_;
Advance(); Advance();
if (c0_ != kEndOfInput && unibrow::IsLineTerminator(ch)) { if (c0_ != kEndOfInput && IsLineTerminator(ch)) {
// Following ECMA-262, section 7.4, a comment containing // Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator. // a newline will make the comment count as a line-terminator.
has_multiline_comment_before_next_ = true; has_multiline_comment_before_next_ = true;
...@@ -968,8 +984,7 @@ bool Scanner::ScanEscape() { ...@@ -968,8 +984,7 @@ bool Scanner::ScanEscape() {
Advance<capture_raw>(); Advance<capture_raw>();
// Skip escaped newlines. // Skip escaped newlines.
if (!in_template_literal && c0_ != kEndOfInput && if (!in_template_literal && c0_ != kEndOfInput && IsLineTerminator(c)) {
unibrow::IsLineTerminator(c)) {
// Allow escaped CR+LF newlines in multiline string literals. // Allow escaped CR+LF newlines in multiline string literals.
if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>(); if (IsCarriageReturn(c) && IsLineFeed(c0_)) Advance<capture_raw>();
return true; return true;
...@@ -1062,8 +1077,7 @@ Token::Value Scanner::ScanString() { ...@@ -1062,8 +1077,7 @@ Token::Value Scanner::ScanString() {
AddLiteralChar(c); AddLiteralChar(c);
} }
while (c0_ != quote && c0_ != kEndOfInput && while (c0_ != quote && c0_ != kEndOfInput && !IsLineTerminator(c0_)) {
!unibrow::IsLineTerminator(c0_)) {
uc32 c = c0_; uc32 c = c0_;
Advance(); Advance();
if (c == '\\') { if (c == '\\') {
...@@ -1119,7 +1133,7 @@ Token::Value Scanner::ScanTemplateSpan() { ...@@ -1119,7 +1133,7 @@ Token::Value Scanner::ScanTemplateSpan() {
ReduceRawLiteralLength(2); ReduceRawLiteralLength(2);
break; break;
} else if (c == '\\') { } else if (c == '\\') {
if (c0_ != kEndOfInput && unibrow::IsLineTerminator(c0_)) { if (c0_ != kEndOfInput && IsLineTerminator(c0_)) {
// The TV of LineContinuation :: \ LineTerminatorSequence is the empty // The TV of LineContinuation :: \ LineTerminatorSequence is the empty
// code unit sequence. // code unit sequence.
uc32 lastChar = c0_; uc32 lastChar = c0_;
...@@ -1660,12 +1674,12 @@ bool Scanner::ScanRegExpPattern() { ...@@ -1660,12 +1674,12 @@ bool Scanner::ScanRegExpPattern() {
} }
while (c0_ != '/' || in_character_class) { while (c0_ != '/' || in_character_class) {
if (c0_ == kEndOfInput || unibrow::IsLineTerminator(c0_)) { if (c0_ == kEndOfInput || IsLineTerminator(c0_)) {
return false; return false;
} }
if (c0_ == '\\') { // Escape sequence. if (c0_ == '\\') { // Escape sequence.
AddLiteralCharAdvance(); AddLiteralCharAdvance();
if (c0_ == kEndOfInput || unibrow::IsLineTerminator(c0_)) { if (c0_ == kEndOfInput || IsLineTerminator(c0_)) {
return false; return false;
} }
AddLiteralCharAdvance(); AddLiteralCharAdvance();
......
...@@ -207,7 +207,7 @@ class Scanner { ...@@ -207,7 +207,7 @@ class Scanner {
static const int kNoOctalLocation = -1; static const int kNoOctalLocation = -1;
static const uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput; static const uc32 kEndOfInput = Utf16CharacterStream::kEndOfInput;
explicit Scanner(UnicodeCache* scanner_contants); explicit Scanner(UnicodeCache* scanner_contants, int* use_counts_);
void Initialize(Utf16CharacterStream* source, bool is_module); void Initialize(Utf16CharacterStream* source, bool is_module);
...@@ -735,6 +735,8 @@ class Scanner { ...@@ -735,6 +735,8 @@ class Scanner {
bool is_module_; bool is_module_;
bool IsLineTerminator(uc32 c);
Token::Value ScanTemplateSpan(); Token::Value ScanTemplateSpan();
// Return the current source position. // Return the current source position.
...@@ -799,6 +801,8 @@ class Scanner { ...@@ -799,6 +801,8 @@ class Scanner {
// Whether this scanner encountered an HTML comment. // Whether this scanner encountered an HTML comment.
bool found_html_comment_; bool found_html_comment_;
int* use_counts_;
MessageTemplate::Template scanner_error_; MessageTemplate::Template scanner_error_;
Location scanner_error_location_; Location scanner_error_location_;
}; };
......
...@@ -198,7 +198,7 @@ struct V8_EXPORT_PRIVATE WhiteSpace { ...@@ -198,7 +198,7 @@ struct V8_EXPORT_PRIVATE WhiteSpace {
// ES#sec-line-terminators lists exactly 4 code points: // ES#sec-line-terminators lists exactly 4 code points:
// LF (U+000A), CR (U+000D), LS(U+2028), PS(U+2029) // LF (U+000A), CR (U+000D), LS(U+2028), PS(U+2029)
V8_INLINE bool IsLineTerminator(uchar c) { V8_INLINE bool IsLineTerminator(uchar c) {
return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029; return c == 0x000A || c == 0x000D || c == 0x2028 || c == 0x2029;
} }
#ifndef V8_INTL_SUPPORT #ifndef V8_INTL_SUPPORT
......
...@@ -29,6 +29,7 @@ struct ScannerTestHelper { ...@@ -29,6 +29,7 @@ struct ScannerTestHelper {
std::unique_ptr<UnicodeCache> unicode_cache; std::unique_ptr<UnicodeCache> unicode_cache;
std::unique_ptr<Utf16CharacterStream> stream; std::unique_ptr<Utf16CharacterStream> stream;
std::unique_ptr<Scanner> scanner; std::unique_ptr<Scanner> scanner;
int use_counts[v8::Isolate::kUseCounterFeatureCount];
Scanner* operator->() const { return scanner.get(); } Scanner* operator->() const { return scanner.get(); }
Scanner* get() const { return scanner.get(); } Scanner* get() const { return scanner.get(); }
...@@ -38,8 +39,11 @@ ScannerTestHelper make_scanner(const char* src) { ...@@ -38,8 +39,11 @@ ScannerTestHelper make_scanner(const char* src) {
ScannerTestHelper helper; ScannerTestHelper helper;
helper.unicode_cache = std::unique_ptr<UnicodeCache>(new UnicodeCache); helper.unicode_cache = std::unique_ptr<UnicodeCache>(new UnicodeCache);
helper.stream = ScannerStream::ForTesting(src); helper.stream = ScannerStream::ForTesting(src);
helper.scanner = for (int i = 0; i < v8::Isolate::kUseCounterFeatureCount; i++) {
std::unique_ptr<Scanner>(new Scanner(helper.unicode_cache.get())); helper.use_counts[i] = 0;
}
helper.scanner = std::unique_ptr<Scanner>(
new Scanner(helper.unicode_cache.get(), helper.use_counts));
helper.scanner->Initialize(helper.stream.get(), false); helper.scanner->Initialize(helper.stream.get(), false);
return helper; return helper;
} }
......
...@@ -61,6 +61,17 @@ namespace v8 { ...@@ -61,6 +61,17 @@ namespace v8 {
namespace internal { namespace internal {
namespace test_parsing { namespace test_parsing {
namespace {
int* global_use_counts = NULL;
void MockUseCounterCallback(v8::Isolate* isolate,
v8::Isolate::UseCounterFeature feature) {
++global_use_counts[feature];
}
} // namespace
TEST(ScanKeywords) { TEST(ScanKeywords) {
struct KeywordToken { struct KeywordToken {
const char* keyword; const char* keyword;
...@@ -82,7 +93,7 @@ TEST(ScanKeywords) { ...@@ -82,7 +93,7 @@ TEST(ScanKeywords) {
CHECK(static_cast<int>(sizeof(buffer)) >= length); CHECK(static_cast<int>(sizeof(buffer)) >= length);
{ {
auto stream = i::ScannerStream::ForTesting(keyword, length); auto stream = i::ScannerStream::ForTesting(keyword, length);
i::Scanner scanner(&unicode_cache); i::Scanner scanner(&unicode_cache, global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
CHECK_EQ(key_token.token, scanner.Next()); CHECK_EQ(key_token.token, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next());
...@@ -90,7 +101,7 @@ TEST(ScanKeywords) { ...@@ -90,7 +101,7 @@ TEST(ScanKeywords) {
// Removing characters will make keyword matching fail. // Removing characters will make keyword matching fail.
{ {
auto stream = i::ScannerStream::ForTesting(keyword, length - 1); auto stream = i::ScannerStream::ForTesting(keyword, length - 1);
i::Scanner scanner(&unicode_cache); i::Scanner scanner(&unicode_cache, global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next());
...@@ -101,7 +112,7 @@ TEST(ScanKeywords) { ...@@ -101,7 +112,7 @@ TEST(ScanKeywords) {
i::MemMove(buffer, keyword, length); i::MemMove(buffer, keyword, length);
buffer[length] = chars_to_append[j]; buffer[length] = chars_to_append[j];
auto stream = i::ScannerStream::ForTesting(buffer, length + 1); auto stream = i::ScannerStream::ForTesting(buffer, length + 1);
i::Scanner scanner(&unicode_cache); i::Scanner scanner(&unicode_cache, global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next());
...@@ -111,7 +122,7 @@ TEST(ScanKeywords) { ...@@ -111,7 +122,7 @@ TEST(ScanKeywords) {
i::MemMove(buffer, keyword, length); i::MemMove(buffer, keyword, length);
buffer[length - 1] = '_'; buffer[length - 1] = '_';
auto stream = i::ScannerStream::ForTesting(buffer, length); auto stream = i::ScannerStream::ForTesting(buffer, length);
i::Scanner scanner(&unicode_cache); i::Scanner scanner(&unicode_cache, global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next());
...@@ -177,7 +188,7 @@ TEST(ScanHTMLEndComments) { ...@@ -177,7 +188,7 @@ TEST(ScanHTMLEndComments) {
for (int i = 0; tests[i]; i++) { for (int i = 0; tests[i]; i++) {
const char* source = tests[i]; const char* source = tests[i];
auto stream = i::ScannerStream::ForTesting(source); auto stream = i::ScannerStream::ForTesting(source);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); i::Scanner scanner(CcTest::i_isolate()->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory( i::AstValueFactory ast_value_factory(
...@@ -196,7 +207,7 @@ TEST(ScanHTMLEndComments) { ...@@ -196,7 +207,7 @@ TEST(ScanHTMLEndComments) {
for (int i = 0; fail_tests[i]; i++) { for (int i = 0; fail_tests[i]; i++) {
const char* source = fail_tests[i]; const char* source = fail_tests[i];
auto stream = i::ScannerStream::ForTesting(source); auto stream = i::ScannerStream::ForTesting(source);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); i::Scanner scanner(CcTest::i_isolate()->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory( i::AstValueFactory ast_value_factory(
...@@ -221,7 +232,7 @@ TEST(ScanHtmlComments) { ...@@ -221,7 +232,7 @@ TEST(ScanHtmlComments) {
// Disallow HTML comments. // Disallow HTML comments.
{ {
auto stream = i::ScannerStream::ForTesting(src); auto stream = i::ScannerStream::ForTesting(src);
i::Scanner scanner(&unicode_cache); i::Scanner scanner(&unicode_cache, global_use_counts);
scanner.Initialize(stream.get(), true); scanner.Initialize(stream.get(), true);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::ILLEGAL, scanner.Next()); CHECK_EQ(i::Token::ILLEGAL, scanner.Next());
...@@ -230,7 +241,7 @@ TEST(ScanHtmlComments) { ...@@ -230,7 +241,7 @@ TEST(ScanHtmlComments) {
// Skip HTML comments: // Skip HTML comments:
{ {
auto stream = i::ScannerStream::ForTesting(src); auto stream = i::ScannerStream::ForTesting(src);
i::Scanner scanner(&unicode_cache); i::Scanner scanner(&unicode_cache, global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next()); CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next()); CHECK_EQ(i::Token::EOS, scanner.Next());
...@@ -389,7 +400,7 @@ TEST(StandAlonePreParser) { ...@@ -389,7 +400,7 @@ TEST(StandAlonePreParser) {
uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit(); uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
for (int i = 0; programs[i]; i++) { for (int i = 0; programs[i]; i++) {
auto stream = i::ScannerStream::ForTesting(programs[i]); auto stream = i::ScannerStream::ForTesting(programs[i]);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); i::Scanner scanner(CcTest::i_isolate()->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
...@@ -425,7 +436,7 @@ TEST(StandAlonePreParserNoNatives) { ...@@ -425,7 +436,7 @@ TEST(StandAlonePreParserNoNatives) {
uintptr_t stack_limit = isolate->stack_guard()->real_climit(); uintptr_t stack_limit = isolate->stack_guard()->real_climit();
for (int i = 0; programs[i]; i++) { for (int i = 0; programs[i]; i++) {
auto stream = i::ScannerStream::ForTesting(programs[i]); auto stream = i::ScannerStream::ForTesting(programs[i]);
i::Scanner scanner(isolate->unicode_cache()); i::Scanner scanner(isolate->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
// Preparser defaults to disallowing natives syntax. // Preparser defaults to disallowing natives syntax.
...@@ -495,7 +506,7 @@ TEST(RegressChromium62639) { ...@@ -495,7 +506,7 @@ TEST(RegressChromium62639) {
// failed in debug mode, and sometimes crashed in release mode. // failed in debug mode, and sometimes crashed in release mode.
auto stream = i::ScannerStream::ForTesting(program); auto stream = i::ScannerStream::ForTesting(program);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); i::Scanner scanner(CcTest::i_isolate()->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory( i::AstValueFactory ast_value_factory(
...@@ -570,7 +581,7 @@ TEST(PreParseOverflow) { ...@@ -570,7 +581,7 @@ TEST(PreParseOverflow) {
uintptr_t stack_limit = isolate->stack_guard()->real_climit(); uintptr_t stack_limit = isolate->stack_guard()->real_climit();
auto stream = i::ScannerStream::ForTesting(program.get(), kProgramSize); auto stream = i::ScannerStream::ForTesting(program.get(), kProgramSize);
i::Scanner scanner(isolate->unicode_cache()); i::Scanner scanner(isolate->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
...@@ -590,7 +601,7 @@ void TestStreamScanner(i::Utf16CharacterStream* stream, ...@@ -590,7 +601,7 @@ void TestStreamScanner(i::Utf16CharacterStream* stream,
i::Token::Value* expected_tokens, i::Token::Value* expected_tokens,
int skip_pos = 0, // Zero means not skipping. int skip_pos = 0, // Zero means not skipping.
int skip_to = 0) { int skip_to = 0) {
i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); i::Scanner scanner(CcTest::i_isolate()->unicode_cache(), global_use_counts);
scanner.Initialize(stream, false); scanner.Initialize(stream, false);
int i = 0; int i = 0;
...@@ -668,7 +679,7 @@ TEST(StreamScanner) { ...@@ -668,7 +679,7 @@ TEST(StreamScanner) {
void TestScanRegExp(const char* re_source, const char* expected) { void TestScanRegExp(const char* re_source, const char* expected) {
auto stream = i::ScannerStream::ForTesting(re_source); auto stream = i::ScannerStream::ForTesting(re_source);
i::HandleScope scope(CcTest::i_isolate()); i::HandleScope scope(CcTest::i_isolate());
i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); i::Scanner scanner(CcTest::i_isolate()->unicode_cache(), global_use_counts);
scanner.Initialize(stream.get(), false); scanner.Initialize(stream.get(), false);
i::Token::Value start = scanner.peek(); i::Token::Value start = scanner.peek();
...@@ -1333,7 +1344,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, ...@@ -1333,7 +1344,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
// Preparse the data. // Preparse the data.
i::PendingCompilationErrorHandler pending_error_handler; i::PendingCompilationErrorHandler pending_error_handler;
if (test_preparser) { if (test_preparser) {
i::Scanner scanner(isolate->unicode_cache()); i::Scanner scanner(isolate->unicode_cache(), global_use_counts);
std::unique_ptr<i::Utf16CharacterStream> stream( std::unique_ptr<i::Utf16CharacterStream> stream(
i::ScannerStream::For(source)); i::ScannerStream::For(source));
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
...@@ -3963,16 +3974,6 @@ TEST(AsmModuleFlag) { ...@@ -3963,16 +3974,6 @@ TEST(AsmModuleFlag) {
CHECK(s->IsAsmModule() && s->AsDeclarationScope()->asm_module()); CHECK(s->IsAsmModule() && s->AsDeclarationScope()->asm_module());
} }
namespace {
int* global_use_counts = NULL;
void MockUseCounterCallback(v8::Isolate* isolate,
v8::Isolate::UseCounterFeature feature) {
++global_use_counts[feature];
}
} // namespace
TEST(UseAsmUseCount) { TEST(UseAsmUseCount) {
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
...@@ -4032,6 +4033,34 @@ TEST(BothModesUseCount) { ...@@ -4032,6 +4033,34 @@ TEST(BothModesUseCount) {
CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]); CHECK_LT(0, use_counts[v8::Isolate::kStrictMode]);
} }
TEST(LineOrParagraphSeparatorAsLineTerminator) {
// Tests that both preparsing and parsing accept U+2028 LINE SEPARATOR and
// U+2029 PARAGRAPH SEPARATOR as LineTerminator symbols.
const char* context_data[][2] = {{"", ""}, {nullptr, nullptr}};
const char* statement_data[] = {"\x31\xE2\x80\xA8\x32", // "1<U+2028>2"
"\x31\xE2\x80\xA9\x32", // "1<U+2029>2"
nullptr};
RunParserSyncTest(context_data, statement_data, kError);
}
TEST(LineOrParagraphSeparatorAsLineTerminatorUseCount) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
LocalContext env;
int use_counts[v8::Isolate::kUseCounterFeatureCount] = {};
global_use_counts = use_counts;
CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback);
CompileRun("");
CHECK_EQ(0, use_counts[v8::Isolate::UseCounterFeature::
kLineOrParagraphSeparatorAsLineTerminator]);
CompileRun("// Foo\xE2\x80\xA8"); // "// Foo<U+2028>"
CHECK_LT(0, use_counts[v8::Isolate::UseCounterFeature::
kLineOrParagraphSeparatorAsLineTerminator]);
CompileRun("// Foo\xE2\x80\xA9"); // "// Foo<U+2029>"
CHECK_LT(1, use_counts[v8::Isolate::UseCounterFeature::
kLineOrParagraphSeparatorAsLineTerminator]);
}
TEST(ErrorsArrowFormalParameters) { TEST(ErrorsArrowFormalParameters) {
const char* context_data[][2] = { const char* context_data[][2] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment