From 2050994d8029a0fb80cd962d56eda581c16badd8 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Thu, 8 Jan 2015 11:45:58 +0100 Subject: [PATCH] Correctly parse line ends for debugging. Instead of using only \n as line terminator, we now use the definition in http://www.ecma-international.org/ecma-262/5.1/#sec-7.3 R=marja@chromium.org BUG=v8:2825 LOG=Y Review URL: https://codereview.chromium.org/821383009 Cr-Commit-Position: refs/heads/master@{#25989} --- src/objects.cc | 26 +++++++++++------------ src/scanner.h | 6 ++++++ test/mjsunit/regress/regress-2825.js | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 test/mjsunit/regress/regress-2825.js diff --git a/src/objects.cc b/src/objects.cc index 5e772ab..10ae80a 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -8764,20 +8764,18 @@ static void CalculateLineEndsImpl(Isolate* isolate, Vector src, bool include_ending_line) { const int src_len = src.length(); - StringSearch search(isolate, STATIC_CHAR_VECTOR("\n")); - - // Find and record line ends. - int position = 0; - while (position != -1 && position < src_len) { - position = search.Search(src, position); - if (position != -1) { - line_ends->Add(position); - position++; - } else if (include_ending_line) { - // Even if the last line misses a line end, it is counted. - line_ends->Add(src_len); - return; - } + UnicodeCache* cache = isolate->unicode_cache(); + for (int i = 0; i < src_len - 1; i++) { + SourceChar current = src[i]; + SourceChar next = src[i + 1]; + if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i); + } + + if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) { + line_ends->Add(src_len - 1); + } else if (include_ending_line) { + // Even if the last line misses a line end, it is counted. + line_ends->Add(src_len); } } diff --git a/src/scanner.h b/src/scanner.h index 6e668fd..8537c53 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -121,6 +121,12 @@ class UnicodeCache { bool IsIdentifierStart(unibrow::uchar c) { return kIsIdentifierStart.get(c); } bool IsIdentifierPart(unibrow::uchar c) { return kIsIdentifierPart.get(c); } bool IsLineTerminator(unibrow::uchar c) { return kIsLineTerminator.get(c); } + bool IsLineTerminatorSequence(unibrow::uchar c, unibrow::uchar next) { + if (!IsLineTerminator(c)) return false; + if (c == 0x000d && next == 0x000a) return false; // CR with following LF. + return true; + } + bool IsWhiteSpace(unibrow::uchar c) { return kIsWhiteSpace.get(c); } bool IsWhiteSpaceOrLineTerminator(unibrow::uchar c) { return kIsWhiteSpaceOrLineTerminator.get(c); diff --git a/test/mjsunit/regress/regress-2825.js b/test/mjsunit/regress/regress-2825.js new file mode 100644 index 0000000..6ffd8ec --- /dev/null +++ b/test/mjsunit/regress/regress-2825.js @@ -0,0 +1,40 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug + +// Do not edit this file with an editor that replaces \r with \r\n. +// Variable definitions for i0 through i3 are each terminated with \r. +function f() { + var i0 = 0; var i1 = 1; var i2 = 2; var i3 = 3; + var j0 = 0; + var j1 = 1; + var j2 = 2; + var j3 = 3; +} + +Debug = debug.Debug; +var exception = null; +var break_point_hit = false; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + break_point_hit = true; + assertEquals(" var i2 = 2;", exec_state.frame(0).sourceLineText()); + } catch (e) { + print(e + e.stack); + exception = e; + } +} + +Debug.setListener(listener); + +Debug.setBreakPoint(f, 3, 0); + +f(); + +Debug.setListener(null); +assertTrue(break_point_hit); +assertNull(exception); -- 2.7.4