Revert of Refactor script position calculation (patchset #3 id:40001 of https://codereview.chromium.org/2003483002/ )
Reason for revert: Crashes gc stress with custom snapshot: https://build.chromium.org/p/client.v8/builders/V8%20Linux64%20GC%20Stress%20-%20custom%20snapshot/builds/5763 Original issue's description: > Refactor script position calculation > > Script position calculation logic (i.e. line & column numbers for a > given code position) is now based on a single method > Script::GetPositionInfo(). Refactored related code in isolate.cc and > js/messages.js to use the new method. The line_ends accessor is still > in use by chromium and thus cannot be removed yet. > > R=yangguo@chromium.org > BUG= > > Committed: https://crrev.com/2f3879d54633c4076d38e9fc85b6e2e157c61548 > Cr-Commit-Position: refs/heads/master@{#36398} TBR=yangguo@chromium.org,jgruber@chromium.org,jgruber@google.com # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG= Review-Url: https://codereview.chromium.org/1995323002 Cr-Commit-Position: refs/heads/master@{#36403}
This commit is contained in:
parent
4001d55e69
commit
2f8a0077ae
@ -1950,7 +1950,7 @@ FrameMirror.prototype.sourceColumn = function() {
|
||||
FrameMirror.prototype.sourceLineText = function() {
|
||||
var location = this.sourceLocation();
|
||||
if (location) {
|
||||
return location.sourceText;
|
||||
return location.sourceText();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
V(cell_value_string, "%cell_value") \
|
||||
V(char_at_string, "CharAt") \
|
||||
V(closure_string, "(closure)") \
|
||||
V(column_string, "column") \
|
||||
V(compare_ic_string, "==") \
|
||||
V(configurable_string, "configurable") \
|
||||
V(constructor_string, "constructor") \
|
||||
@ -83,7 +82,6 @@
|
||||
V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \
|
||||
V(last_index_string, "lastIndex") \
|
||||
V(length_string, "length") \
|
||||
V(line_string, "line") \
|
||||
V(Map_string, "Map") \
|
||||
V(minus_infinity_string, "-Infinity") \
|
||||
V(minus_zero_string, "-0") \
|
||||
@ -97,7 +95,6 @@
|
||||
V(object_string, "object") \
|
||||
V(Object_string, "Object") \
|
||||
V(ownKeys_string, "ownKeys") \
|
||||
V(position_string, "position") \
|
||||
V(preventExtensions_string, "preventExtensions") \
|
||||
V(private_api_string, "private_api") \
|
||||
V(Promise_string, "Promise") \
|
||||
@ -106,13 +103,11 @@
|
||||
V(Proxy_string, "Proxy") \
|
||||
V(query_colon_string, "(?:)") \
|
||||
V(RegExp_string, "RegExp") \
|
||||
V(script_string, "script") \
|
||||
V(setPrototypeOf_string, "setPrototypeOf") \
|
||||
V(set_string, "set") \
|
||||
V(Set_string, "Set") \
|
||||
V(source_mapping_url_string, "source_mapping_url") \
|
||||
V(source_string, "source") \
|
||||
V(sourceText_string, "sourceText") \
|
||||
V(source_url_string, "source_url") \
|
||||
V(stack_string, "stack") \
|
||||
V(strict_compare_ic_string, "===") \
|
||||
|
@ -551,17 +551,28 @@ class CaptureStackTraceHelper {
|
||||
Handle<Script> script(Script::cast(fun->shared()->script()));
|
||||
|
||||
if (!line_key_.is_null()) {
|
||||
Script::PositionInfo info;
|
||||
bool valid_pos =
|
||||
script->GetPositionInfo(position, &info, Script::WITH_OFFSET);
|
||||
|
||||
if (!column_key_.is_null() && valid_pos) {
|
||||
int script_line_offset = script->line_offset();
|
||||
int line_number = Script::GetLineNumber(script, position);
|
||||
// line_number is already shifted by the script_line_offset.
|
||||
int relative_line_number = line_number - script_line_offset;
|
||||
if (!column_key_.is_null() && relative_line_number >= 0) {
|
||||
Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
|
||||
int start =
|
||||
(relative_line_number == 0)
|
||||
? 0
|
||||
: Smi::cast(line_ends->get(relative_line_number - 1))->value() +
|
||||
1;
|
||||
int column_offset = position - start;
|
||||
if (relative_line_number == 0) {
|
||||
// For the case where the code is on the same line as the script tag.
|
||||
column_offset += script->column_offset();
|
||||
}
|
||||
JSObject::AddProperty(stack_frame, column_key_,
|
||||
handle(Smi::FromInt(info.column + 1), isolate_),
|
||||
handle(Smi::FromInt(column_offset + 1), isolate_),
|
||||
NONE);
|
||||
}
|
||||
JSObject::AddProperty(stack_frame, line_key_,
|
||||
handle(Smi::FromInt(info.line + 1), isolate_),
|
||||
handle(Smi::FromInt(line_number + 1), isolate_),
|
||||
NONE);
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ function GetSourceLine(message) {
|
||||
var start_position = %MessageGetStartPosition(message);
|
||||
var location = script.locationFromPosition(start_position, true);
|
||||
if (location == null) return "";
|
||||
return location.sourceText;
|
||||
return location.sourceText();
|
||||
}
|
||||
|
||||
|
||||
@ -225,27 +225,68 @@ function GetSourceLine(message) {
|
||||
else the line number.
|
||||
*/
|
||||
function ScriptLineFromPosition(position) {
|
||||
var info = %ScriptPositionInfo(this, position, false);
|
||||
return (info == null) ? -1 : info.line;
|
||||
var lower = 0;
|
||||
var upper = this.lineCount() - 1;
|
||||
var line_ends = this.line_ends;
|
||||
|
||||
// We'll never find invalid positions so bail right away.
|
||||
if (position > line_ends[upper]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// This means we don't have to safe-guard indexing line_ends[i - 1].
|
||||
if (position <= line_ends[0]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Binary search to find line # from position range.
|
||||
while (upper >= 1) {
|
||||
var i = (lower + upper) >> 1;
|
||||
|
||||
if (position > line_ends[i]) {
|
||||
lower = i + 1;
|
||||
} else if (position <= line_ends[i - 1]) {
|
||||
upper = i - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get information on a specific source position.
|
||||
* Returns an object with the following following properties:
|
||||
* script : script object for the source
|
||||
* line : source line number
|
||||
* column : source column within the line
|
||||
* position : position within the source
|
||||
* sourceText : a string containing the current line
|
||||
* @param {number} position The source position
|
||||
* @param {boolean} include_resource_offset Set to true to have the resource
|
||||
* offset added to the location
|
||||
* @return If line is negative or not in the source null is returned.
|
||||
* @return {SourceLocation}
|
||||
* If line is negative or not in the source null is returned.
|
||||
*/
|
||||
function ScriptLocationFromPosition(position,
|
||||
include_resource_offset) {
|
||||
return %ScriptPositionInfo(this, position, !!include_resource_offset);
|
||||
var line = this.lineFromPosition(position);
|
||||
if (line == -1) return null;
|
||||
|
||||
// Determine start, end and column.
|
||||
var line_ends = this.line_ends;
|
||||
var start = line == 0 ? 0 : line_ends[line - 1] + 1;
|
||||
var end = line_ends[line];
|
||||
if (end > 0 && %_StringCharAt(this.source, end - 1) === '\r') {
|
||||
end--;
|
||||
}
|
||||
var column = position - start;
|
||||
|
||||
// Adjust according to the offset within the resource.
|
||||
if (include_resource_offset) {
|
||||
line += this.line_offset;
|
||||
if (line == this.line_offset) {
|
||||
column += this.column_offset;
|
||||
}
|
||||
}
|
||||
|
||||
return new SourceLocation(this, position, line, column, start, end);
|
||||
}
|
||||
|
||||
|
||||
@ -261,7 +302,8 @@ function ScriptLocationFromPosition(position,
|
||||
* @param {number} opt_offset_position The offset from the begining of the
|
||||
* source from where the line and column calculation starts.
|
||||
* Default value is 0
|
||||
* @return If line is negative or not in the source null is returned.
|
||||
* @return {SourceLocation}
|
||||
* If line is negative or not in the source null is returned.
|
||||
*/
|
||||
function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
|
||||
// Default is the first line in the script. Lines in the script is relative
|
||||
@ -291,7 +333,7 @@ function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
|
||||
}
|
||||
|
||||
return this.locationFromPosition(
|
||||
%ScriptLineStartPosition(this, offset_line + line) + column);
|
||||
this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,14 +367,15 @@ function ScriptSourceSlice(opt_from_line, opt_to_line) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var from_position = %ScriptLineStartPosition(this, from_line);
|
||||
var to_position = %ScriptLineStartPosition(this, to_line);
|
||||
var line_ends = this.line_ends;
|
||||
var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
|
||||
var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
|
||||
|
||||
// Return a source slice with line numbers re-adjusted to the resource.
|
||||
return new SourceSlice(this,
|
||||
from_line + this.line_offset,
|
||||
to_line + this.line_offset,
|
||||
from_position, to_position);
|
||||
from_position, to_position);
|
||||
}
|
||||
|
||||
|
||||
@ -350,8 +393,9 @@ function ScriptSourceLine(opt_line) {
|
||||
}
|
||||
|
||||
// Return the source line.
|
||||
var start = %ScriptLineStartPosition(this, line);
|
||||
var end = %ScriptLineEndPosition(this, line);
|
||||
var line_ends = this.line_ends;
|
||||
var start = line == 0 ? 0 : line_ends[line - 1] + 1;
|
||||
var end = line_ends[line];
|
||||
return %_Call(StringSubstring, this.source, start, end);
|
||||
}
|
||||
|
||||
@ -363,7 +407,17 @@ function ScriptSourceLine(opt_line) {
|
||||
*/
|
||||
function ScriptLineCount() {
|
||||
// Return number of source lines.
|
||||
return %ScriptLineCount(this);
|
||||
return this.line_ends.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the position of the nth line end.
|
||||
* @return {number}
|
||||
* Zero-based position of the nth line end in the script.
|
||||
*/
|
||||
function ScriptLineEnd(n) {
|
||||
return this.line_ends[n];
|
||||
}
|
||||
|
||||
|
||||
@ -388,6 +442,7 @@ utils.SetUpLockedPrototype(Script, [
|
||||
"name",
|
||||
"source_url",
|
||||
"source_mapping_url",
|
||||
"line_ends",
|
||||
"line_offset",
|
||||
"column_offset"
|
||||
], [
|
||||
@ -398,10 +453,58 @@ utils.SetUpLockedPrototype(Script, [
|
||||
"sourceLine", ScriptSourceLine,
|
||||
"lineCount", ScriptLineCount,
|
||||
"nameOrSourceURL", ScriptNameOrSourceURL,
|
||||
"lineEnd", ScriptLineEnd
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Class for source location. A source location is a position within some
|
||||
* source with the following properties:
|
||||
* script : script object for the source
|
||||
* line : source line number
|
||||
* column : source column within the line
|
||||
* position : position within the source
|
||||
* start : position of start of source context (inclusive)
|
||||
* end : position of end of source context (not inclusive)
|
||||
* Source text for the source context is the character interval
|
||||
* [start, end[. In most cases end will point to a newline character.
|
||||
* It might point just past the final position of the source if the last
|
||||
* source line does not end with a newline character.
|
||||
* @param {Script} script The Script object for which this is a location
|
||||
* @param {number} position Source position for the location
|
||||
* @param {number} line The line number for the location
|
||||
* @param {number} column The column within the line for the location
|
||||
* @param {number} start Source position for start of source context
|
||||
* @param {number} end Source position for end of source context
|
||||
* @constructor
|
||||
*/
|
||||
function SourceLocation(script, position, line, column, start, end) {
|
||||
this.script = script;
|
||||
this.position = position;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the source text for a SourceLocation
|
||||
* @return {String}
|
||||
* Source text for this location.
|
||||
*/
|
||||
function SourceLocationSourceText() {
|
||||
return %_Call(StringSubstring, this.script.source, this.start, this.end);
|
||||
}
|
||||
|
||||
|
||||
utils.SetUpLockedPrototype(SourceLocation,
|
||||
["script", "position", "line", "column", "start", "end"],
|
||||
["sourceText", SourceLocationSourceText]
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Class for a source slice. A source slice is a part of a script source with
|
||||
* the following properties:
|
||||
|
107
src/objects.cc
107
src/objects.cc
@ -12365,93 +12365,42 @@ void Script::InitLineEnds(Handle<Script> script) {
|
||||
DCHECK(script->line_ends()->IsFixedArray());
|
||||
}
|
||||
|
||||
#define SMI_VALUE(x) (Smi::cast(x)->value())
|
||||
bool Script::GetPositionInfo(int position, PositionInfo* info,
|
||||
OffsetFlag offset_flag) {
|
||||
Handle<Script> script(this);
|
||||
InitLineEnds(script);
|
||||
|
||||
DisallowHeapAllocation no_allocation;
|
||||
|
||||
DCHECK(line_ends()->IsFixedArray());
|
||||
FixedArray* ends = FixedArray::cast(line_ends());
|
||||
|
||||
const int ends_len = ends->length();
|
||||
if (ends_len == 0) return false;
|
||||
|
||||
// Return early on invalid positions. Negative positions behave as if 0 was
|
||||
// passed, and positions beyond the end of the script return as failure.
|
||||
if (position < 0) {
|
||||
position = 0;
|
||||
} else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine line number by doing a binary search on the line ends array.
|
||||
if (SMI_VALUE(ends->get(0)) >= position) {
|
||||
info->line = 0;
|
||||
info->line_start = 0;
|
||||
info->column = position;
|
||||
} else {
|
||||
int left = 0;
|
||||
int right = ends_len - 1;
|
||||
|
||||
while (right > 0) {
|
||||
DCHECK_LE(left, right);
|
||||
const int mid = (left + right) / 2;
|
||||
if (position > SMI_VALUE(ends->get(mid))) {
|
||||
left = mid + 1;
|
||||
} else if (position <= SMI_VALUE(ends->get(mid - 1))) {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
info->line = mid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
|
||||
SMI_VALUE(ends->get(info->line - 1)) < position);
|
||||
info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
|
||||
info->column = position - info->line_start;
|
||||
}
|
||||
|
||||
// Line end is position of the linebreak character.
|
||||
info->line_end = SMI_VALUE(ends->get(info->line));
|
||||
if (info->line_end > 0) {
|
||||
DCHECK(source()->IsString());
|
||||
Handle<String> src(String::cast(source()));
|
||||
if (src->Get(info->line_end - 1) == '\r') {
|
||||
info->line_end--;
|
||||
}
|
||||
}
|
||||
|
||||
// Add offsets if requested.
|
||||
if (offset_flag == WITH_OFFSET) {
|
||||
if (info->line == 0) {
|
||||
info->column += column_offset();
|
||||
}
|
||||
info->line += line_offset();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#undef SMI_VALUE
|
||||
|
||||
int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
|
||||
PositionInfo info;
|
||||
if (!script->GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
|
||||
return -1;
|
||||
}
|
||||
int line_number = GetLineNumber(script, code_pos);
|
||||
if (line_number == -1) return -1;
|
||||
|
||||
return info.column;
|
||||
DisallowHeapAllocation no_allocation;
|
||||
FixedArray* line_ends_array = FixedArray::cast(script->line_ends());
|
||||
line_number = line_number - script->line_offset();
|
||||
if (line_number == 0) return code_pos + script->column_offset();
|
||||
int prev_line_end_pos =
|
||||
Smi::cast(line_ends_array->get(line_number - 1))->value();
|
||||
return code_pos - (prev_line_end_pos + 1);
|
||||
}
|
||||
|
||||
|
||||
int Script::GetLineNumberWithArray(int code_pos) {
|
||||
PositionInfo info;
|
||||
if (!GetPositionInfo(code_pos, &info, WITH_OFFSET)) {
|
||||
return -1;
|
||||
DisallowHeapAllocation no_allocation;
|
||||
DCHECK(line_ends()->IsFixedArray());
|
||||
FixedArray* line_ends_array = FixedArray::cast(line_ends());
|
||||
int line_ends_len = line_ends_array->length();
|
||||
if (line_ends_len == 0) return -1;
|
||||
|
||||
if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) {
|
||||
return line_offset();
|
||||
}
|
||||
|
||||
return info.line;
|
||||
int left = 0;
|
||||
int right = line_ends_len;
|
||||
while (int half = (right - left) / 2) {
|
||||
if ((Smi::cast(line_ends_array->get(left + half)))->value() > code_pos) {
|
||||
right -= half;
|
||||
} else {
|
||||
left += half;
|
||||
}
|
||||
}
|
||||
return right + line_offset();
|
||||
}
|
||||
|
||||
|
||||
|
@ -6416,6 +6416,14 @@ class Script: public Struct {
|
||||
// resource is accessible. Otherwise, always return true.
|
||||
inline bool HasValidSource();
|
||||
|
||||
// Convert code offset into column number.
|
||||
static int GetColumnNumber(Handle<Script> script, int code_offset);
|
||||
|
||||
// Convert code offset into (zero-based) line number.
|
||||
// The non-handlified version does not allocate, but may be much slower.
|
||||
static int GetLineNumber(Handle<Script> script, int code_offset);
|
||||
int GetLineNumber(int code_pos);
|
||||
|
||||
static Handle<Object> GetNameOrSourceURL(Handle<Script> script);
|
||||
|
||||
// Set eval origin for stack trace formatting.
|
||||
@ -6428,33 +6436,6 @@ class Script: public Struct {
|
||||
// Init line_ends array with source code positions of line ends.
|
||||
static void InitLineEnds(Handle<Script> script);
|
||||
|
||||
// Convert code offset into column number.
|
||||
static int GetColumnNumber(Handle<Script> script, int code_offset);
|
||||
|
||||
// Convert code offset into (zero-based) line number.
|
||||
// The non-handlified version does not allocate, but may be much slower.
|
||||
static int GetLineNumber(Handle<Script> script, int code_offset);
|
||||
int GetLineNumber(int code_pos);
|
||||
|
||||
// Carries information about a source position.
|
||||
struct PositionInfo {
|
||||
PositionInfo() : line(-1), column(-1), line_start(-1), line_end(-1) {}
|
||||
|
||||
int line; // Zero-based line number.
|
||||
int column; // Zero-based column number.
|
||||
int line_start; // Position of first character in line.
|
||||
int line_end; // Position of last (non-linebreak) character in line.
|
||||
};
|
||||
|
||||
// Specifies whether to add offsets to position infos.
|
||||
enum OffsetFlag { NO_OFFSET = 0, WITH_OFFSET = 1 };
|
||||
|
||||
// Retrieves information about the given position, optionally with an offset.
|
||||
// Returns false on failure, and otherwise writes into the given info object
|
||||
// on success.
|
||||
bool GetPositionInfo(int position, PositionInfo* info,
|
||||
OffsetFlag offset_flag);
|
||||
|
||||
// Get the JS object wrapping the given script; create it if none exists.
|
||||
static Handle<JSObject> GetWrapper(Handle<Script> script);
|
||||
|
||||
|
@ -1501,105 +1501,6 @@ RUNTIME_FUNCTION(Runtime_GetScript) {
|
||||
return *Script::GetWrapper(found);
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ScriptLineCount) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
CONVERT_ARG_CHECKED(JSValue, script, 0);
|
||||
|
||||
RUNTIME_ASSERT(script->value()->IsScript());
|
||||
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
|
||||
|
||||
Script::InitLineEnds(script_handle);
|
||||
|
||||
FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
|
||||
return Smi::FromInt(line_ends_array->length());
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ScriptLineStartPosition) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 2);
|
||||
CONVERT_ARG_CHECKED(JSValue, script, 0);
|
||||
CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
|
||||
|
||||
RUNTIME_ASSERT(script->value()->IsScript());
|
||||
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
|
||||
|
||||
Script::InitLineEnds(script_handle);
|
||||
|
||||
FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
|
||||
const int line_count = line_ends_array->length();
|
||||
|
||||
// If line == line_count, we return the first position beyond the last line.
|
||||
if (line < 0 || line > line_count) {
|
||||
return Smi::FromInt(-1);
|
||||
} else if (line == 0) {
|
||||
return Smi::FromInt(0);
|
||||
} else {
|
||||
DCHECK(0 < line && line <= line_count);
|
||||
const int pos = Smi::cast(line_ends_array->get(line - 1))->value() + 1;
|
||||
return Smi::FromInt(pos);
|
||||
}
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 2);
|
||||
CONVERT_ARG_CHECKED(JSValue, script, 0);
|
||||
CONVERT_NUMBER_CHECKED(int32_t, line, Int32, args[1]);
|
||||
|
||||
RUNTIME_ASSERT(script->value()->IsScript());
|
||||
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
|
||||
|
||||
Script::InitLineEnds(script_handle);
|
||||
|
||||
FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
|
||||
const int line_count = line_ends_array->length();
|
||||
|
||||
if (line < 0 || line >= line_count) {
|
||||
return Smi::FromInt(-1);
|
||||
} else {
|
||||
return Smi::cast(line_ends_array->get(line));
|
||||
}
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
CONVERT_ARG_CHECKED(JSValue, script, 0);
|
||||
CONVERT_NUMBER_CHECKED(int32_t, position, Int32, args[1]);
|
||||
CONVERT_BOOLEAN_ARG_CHECKED(with_offset, 2);
|
||||
|
||||
RUNTIME_ASSERT(script->value()->IsScript());
|
||||
Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
|
||||
|
||||
Script::PositionInfo info;
|
||||
const Script::OffsetFlag offset_flag =
|
||||
with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
|
||||
if (!script_handle->GetPositionInfo(position, &info, offset_flag)) {
|
||||
return isolate->heap()->null_value();
|
||||
}
|
||||
|
||||
Handle<String> source =
|
||||
handle(String::cast(script_handle->source()), isolate);
|
||||
Handle<String> sourceText =
|
||||
isolate->factory()->NewSubString(source, info.line_start, info.line_end);
|
||||
|
||||
Handle<JSObject> jsinfo =
|
||||
isolate->factory()->NewJSObject(isolate->object_function());
|
||||
|
||||
JSObject::AddProperty(jsinfo, isolate->factory()->script_string(),
|
||||
script_handle, NONE);
|
||||
JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
|
||||
handle(Smi::FromInt(position), isolate), NONE);
|
||||
JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
|
||||
handle(Smi::FromInt(info.line), isolate), NONE);
|
||||
JSObject::AddProperty(jsinfo, isolate->factory()->column_string(),
|
||||
handle(Smi::FromInt(info.column), isolate), NONE);
|
||||
JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
|
||||
sourceText, NONE);
|
||||
|
||||
return *jsinfo;
|
||||
}
|
||||
|
||||
// Set one shot breakpoints for the callback function that is passed to a
|
||||
// built-in function such as Array.forEach to enable stepping into the callback,
|
||||
|
@ -180,10 +180,6 @@ namespace internal {
|
||||
F(CollectGarbage, 1, 1) \
|
||||
F(GetHeapUsage, 0, 1) \
|
||||
F(GetScript, 1, 1) \
|
||||
F(ScriptLineCount, 1, 1) \
|
||||
F(ScriptLineStartPosition, 2, 1) \
|
||||
F(ScriptLineEndPosition, 2, 1) \
|
||||
F(ScriptPositionInfo, 3, 1) \
|
||||
F(DebugPrepareStepInIfStepping, 1, 1) \
|
||||
F(DebugPushPromise, 2, 1) \
|
||||
F(DebugPopPromise, 0, 1) \
|
||||
|
@ -23422,88 +23422,6 @@ TEST(ScriptNameAndLineNumber) {
|
||||
CHECK_EQ(13, line_number);
|
||||
}
|
||||
|
||||
TEST(ScriptPositionInfo) {
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
const char* url = "http://www.foo.com/foo.js";
|
||||
v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
|
||||
v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
|
||||
"var bar;\n"
|
||||
"var fisk = foo + bar;\n"),
|
||||
origin);
|
||||
Local<Script> script =
|
||||
v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
|
||||
|
||||
i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
|
||||
v8::Utils::OpenHandle(*script->GetUnboundScript()));
|
||||
CHECK(obj->script()->IsScript());
|
||||
|
||||
i::Handle<i::Script> script1(i::Script::cast(obj->script()));
|
||||
|
||||
v8::internal::Script::PositionInfo info;
|
||||
|
||||
// With offset.
|
||||
|
||||
// Behave as if 0 was passed if position is negative.
|
||||
CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
|
||||
CHECK_EQ(13, info.line);
|
||||
CHECK_EQ(0, info.column);
|
||||
CHECK_EQ(0, info.line_start);
|
||||
CHECK_EQ(8, info.line_end);
|
||||
|
||||
CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
|
||||
CHECK_EQ(13, info.line);
|
||||
CHECK_EQ(0, info.column);
|
||||
CHECK_EQ(0, info.line_start);
|
||||
CHECK_EQ(8, info.line_end);
|
||||
|
||||
CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
|
||||
CHECK_EQ(13, info.line);
|
||||
CHECK_EQ(8, info.column);
|
||||
CHECK_EQ(0, info.line_start);
|
||||
CHECK_EQ(8, info.line_end);
|
||||
|
||||
CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
|
||||
CHECK_EQ(14, info.line);
|
||||
CHECK_EQ(0, info.column);
|
||||
CHECK_EQ(9, info.line_start);
|
||||
CHECK_EQ(17, info.line_end);
|
||||
|
||||
// Fail when position is larger than script size.
|
||||
CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
|
||||
|
||||
// Without offset.
|
||||
|
||||
// Behave as if 0 was passed if position is negative.
|
||||
CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
|
||||
CHECK_EQ(0, info.line);
|
||||
CHECK_EQ(0, info.column);
|
||||
CHECK_EQ(0, info.line_start);
|
||||
CHECK_EQ(8, info.line_end);
|
||||
|
||||
CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
|
||||
CHECK_EQ(0, info.line);
|
||||
CHECK_EQ(0, info.column);
|
||||
CHECK_EQ(0, info.line_start);
|
||||
CHECK_EQ(8, info.line_end);
|
||||
|
||||
CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
|
||||
CHECK_EQ(0, info.line);
|
||||
CHECK_EQ(8, info.column);
|
||||
CHECK_EQ(0, info.line_start);
|
||||
CHECK_EQ(8, info.line_end);
|
||||
|
||||
CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
|
||||
CHECK_EQ(1, info.line);
|
||||
CHECK_EQ(0, info.column);
|
||||
CHECK_EQ(9, info.line_start);
|
||||
CHECK_EQ(17, info.line_end);
|
||||
|
||||
// Fail when position is larger than script size.
|
||||
CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
|
||||
}
|
||||
|
||||
void CheckMagicComments(Local<Script> script, const char* expected_source_url,
|
||||
const char* expected_source_mapping_url) {
|
||||
if (expected_source_url != NULL) {
|
||||
|
@ -6081,48 +6081,53 @@ class EmptyExternalStringResource : public v8::String::ExternalStringResource {
|
||||
::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
|
||||
};
|
||||
|
||||
TEST(DebugScriptLineEndsAreAscending) {
|
||||
|
||||
TEST(DebugGetLoadedScripts) {
|
||||
DebugLocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
env.ExposeDebug();
|
||||
|
||||
// Compile a test script.
|
||||
v8::Local<v8::String> script = v8_str(isolate,
|
||||
"function f() {\n"
|
||||
" debugger;\n"
|
||||
"}\n");
|
||||
v8::Local<v8::Context> context = env.context();
|
||||
EmptyExternalStringResource source_ext_str;
|
||||
v8::Local<v8::String> source =
|
||||
v8::String::NewExternalTwoByte(env->GetIsolate(), &source_ext_str)
|
||||
.ToLocalChecked();
|
||||
CHECK(v8::Script::Compile(context, source).IsEmpty());
|
||||
Handle<i::ExternalTwoByteString> i_source(
|
||||
i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
|
||||
// This situation can happen if source was an external string disposed
|
||||
// by its owner.
|
||||
i_source->set_resource(0);
|
||||
|
||||
v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8_str(isolate, "name"));
|
||||
v8::Local<v8::Script> script1 =
|
||||
v8::Script::Compile(env.context(), script, &origin1).ToLocalChecked();
|
||||
USE(script1);
|
||||
bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
|
||||
i::FLAG_allow_natives_syntax = true;
|
||||
EnableDebugger(env->GetIsolate());
|
||||
v8::MaybeLocal<v8::Value> result =
|
||||
CompileRun(env.context(),
|
||||
"var scripts = %DebugGetLoadedScripts();"
|
||||
"var count = scripts.length;"
|
||||
"for (var i = 0; i < count; ++i) {"
|
||||
" var lines = scripts[i].lineCount();"
|
||||
" if (lines < 1) throw 'lineCount';"
|
||||
" var last = -1;"
|
||||
" for (var j = 0; j < lines; ++j) {"
|
||||
" var end = scripts[i].lineEnd(j);"
|
||||
" if (last >= end) throw 'lineEnd';"
|
||||
" last = end;"
|
||||
" }"
|
||||
"}");
|
||||
CHECK(!result.IsEmpty());
|
||||
DisableDebugger(env->GetIsolate());
|
||||
// Must not crash while accessing line_ends.
|
||||
i::FLAG_allow_natives_syntax = allow_natives_syntax;
|
||||
|
||||
Handle<v8::internal::FixedArray> instances;
|
||||
{
|
||||
v8::internal::Debug* debug = CcTest::i_isolate()->debug();
|
||||
v8::internal::DebugScope debug_scope(debug);
|
||||
CHECK(!debug_scope.failed());
|
||||
instances = debug->GetLoadedScripts();
|
||||
}
|
||||
|
||||
CHECK_GT(instances->length(), 0);
|
||||
for (int i = 0; i < instances->length(); i++) {
|
||||
Handle<v8::internal::Script> script = Handle<v8::internal::Script>(
|
||||
v8::internal::Script::cast(instances->get(i)));
|
||||
|
||||
v8::internal::Script::InitLineEnds(script);
|
||||
v8::internal::FixedArray* ends =
|
||||
v8::internal::FixedArray::cast(script->line_ends());
|
||||
CHECK_GT(ends->length(), 0);
|
||||
|
||||
int prev_end = -1;
|
||||
for (int j = 0; j < ends->length(); j++) {
|
||||
const int curr_end = v8::internal::Smi::cast(ends->get(j))->value();
|
||||
CHECK_GT(curr_end, prev_end);
|
||||
prev_end = curr_end;
|
||||
}
|
||||
}
|
||||
// Some scripts are retrieved - at least the number of native scripts.
|
||||
CHECK_GT(env->Global()
|
||||
->Get(context, v8_str(env->GetIsolate(), "count"))
|
||||
.ToLocalChecked()
|
||||
->Int32Value(context)
|
||||
.FromJust(),
|
||||
8);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user