| Index: src/runtime/runtime-debug.cc
|
| diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc
|
| index b65324fb8fc076a968fc926dbca95705bfb1af10..72e2120fc4469f42a1df60aabc13b565c00f16a2 100644
|
| --- a/src/runtime/runtime-debug.cc
|
| +++ b/src/runtime/runtime-debug.cc
|
| @@ -1562,33 +1562,23 @@ RUNTIME_FUNCTION(Runtime_ScriptLineEndPosition) {
|
| }
|
| }
|
|
|
| -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()));
|
| -
|
| +static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position,
|
| + Script::OffsetFlag offset_flag,
|
| + Isolate* isolate) {
|
| 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();
|
| + if (!script->GetPositionInfo(position, &info, offset_flag)) {
|
| + return handle(isolate->heap()->null_value(), isolate);
|
| }
|
|
|
| - Handle<String> source =
|
| - handle(String::cast(script_handle->source()), isolate);
|
| + Handle<String> source = handle(String::cast(script->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()->script_string(), script,
|
| + NONE);
|
| JSObject::AddProperty(jsinfo, isolate->factory()->position_string(),
|
| handle(Smi::FromInt(position), isolate), NONE);
|
| JSObject::AddProperty(jsinfo, isolate->factory()->line_string(),
|
| @@ -1598,7 +1588,124 @@ RUNTIME_FUNCTION(Runtime_ScriptPositionInfo) {
|
| JSObject::AddProperty(jsinfo, isolate->factory()->sourceText_string(),
|
| sourceText, NONE);
|
|
|
| - return *jsinfo;
|
| + return jsinfo;
|
| +}
|
| +
|
| +// Get information on a specific source line and column possibly offset by a
|
| +// fixed source position. This function is used to find a source position from
|
| +// a line and column position. The fixed source position offset is typically
|
| +// used to find a source position in a function based on a line and column in
|
| +// the source for the function alone. The offset passed will then be the
|
| +// start position of the source for the function within the full script source.
|
| +// Note that incoming line and column parameters may be undefined, and are
|
| +// assumed to be passed *with* offsets.
|
| +RUNTIME_FUNCTION(Runtime_ScriptLocationFromLine) {
|
| + HandleScope scope(isolate);
|
| + DCHECK(args.length() == 4);
|
| + CONVERT_ARG_CHECKED(JSValue, script, 0);
|
| +
|
| + RUNTIME_ASSERT(script->value()->IsScript());
|
| + Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
|
| +
|
| + // Line and column are possibly undefined and we need to handle these cases,
|
| + // additionally subtracting corresponding offsets.
|
| +
|
| + int32_t line;
|
| + if (args[1]->IsNull() || args[1]->IsUndefined()) {
|
| + line = 0;
|
| + } else {
|
| + RUNTIME_ASSERT(args[1]->IsNumber());
|
| + line = NumberToInt32(args[1]) - script_handle->line_offset();
|
| + }
|
| +
|
| + int32_t column;
|
| + if (args[2]->IsNull() || args[2]->IsUndefined()) {
|
| + column = 0;
|
| + } else {
|
| + RUNTIME_ASSERT(args[2]->IsNumber());
|
| + column = NumberToInt32(args[2]);
|
| + if (line == 0) column -= script_handle->column_offset();
|
| + }
|
| +
|
| + CONVERT_NUMBER_CHECKED(int32_t, offset_position, Int32, args[3]);
|
| +
|
| + if (line < 0 || column < 0 || offset_position < 0) {
|
| + return isolate->heap()->null_value();
|
| + }
|
| +
|
| + Script::InitLineEnds(script_handle);
|
| +
|
| + FixedArray* line_ends_array = FixedArray::cast(script_handle->line_ends());
|
| + const int line_count = line_ends_array->length();
|
| +
|
| + int position;
|
| + if (line == 0) {
|
| + position = offset_position + column;
|
| + } else {
|
| + Script::PositionInfo info;
|
| + if (!script_handle->GetPositionInfo(offset_position, &info,
|
| + Script::NO_OFFSET) ||
|
| + info.line + line >= line_count) {
|
| + return isolate->heap()->null_value();
|
| + }
|
| +
|
| + const int offset_line = info.line + line;
|
| + const int offset_line_position =
|
| + (offset_line == 0)
|
| + ? 0
|
| + : Smi::cast(line_ends_array->get(offset_line - 1))->value() + 1;
|
| + position = offset_line_position + column;
|
| + }
|
| +
|
| + return *GetJSPositionInfo(script_handle, position, Script::NO_OFFSET,
|
| + isolate);
|
| +}
|
| +
|
| +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()));
|
| +
|
| + const Script::OffsetFlag offset_flag =
|
| + with_offset ? Script::WITH_OFFSET : Script::NO_OFFSET;
|
| + return *GetJSPositionInfo(script_handle, position, offset_flag, isolate);
|
| +}
|
| +
|
| +// Returns the given line as a string, or null if line is out of bounds.
|
| +// The parameter line is expected to include the script's line offset.
|
| +RUNTIME_FUNCTION(Runtime_ScriptSourceLine) {
|
| + 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();
|
| +
|
| + line -= script_handle->line_offset();
|
| + if (line < 0 || line_count <= line) {
|
| + return isolate->heap()->null_value();
|
| + }
|
| +
|
| + const int start =
|
| + (line == 0) ? 0 : Smi::cast(line_ends_array->get(line - 1))->value() + 1;
|
| + const int end = Smi::cast(line_ends_array->get(line))->value();
|
| +
|
| + Handle<String> source =
|
| + handle(String::cast(script_handle->source()), isolate);
|
| + Handle<String> str = isolate->factory()->NewSubString(source, start, end);
|
| +
|
| + return *str;
|
| }
|
|
|
| // Set one shot breakpoints for the callback function that is passed to a
|
|
|