// Copyright 2012 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.
(function (global, utils) {
"use strict";
// ----------------------------------------------------------------------------
// Imports
var FrameMirror = global.FrameMirror;
var GlobalArray = global.Array;
var GlobalRegExp = global.RegExp;
var IsNaN = global.isNaN;
var MakeMirror = global.MakeMirror;
var MathMin = global.Math.min;
var Mirror = global.Mirror;
var ValueMirror = global.ValueMirror;
//----------------------------------------------------------------------------
// Default number of frames to include in the response to backtrace request.
var kDefaultBacktraceLength = 10;
var Debug = {};
// Regular expression to skip "crud" at the beginning of a source line which is
// not really code. Currently the regular expression matches whitespace and
// comments.
var sourceLineBeginningSkip = /^(?:\s*(?:\/\*.*?\*\/)*)*/;
// Debug events which can occour in the V8 JavaScript engine. These originate
// from the API include file debug.h.
Debug.DebugEvent = { Break: 1,
Exception: 2,
AfterCompile: 3,
CompileError: 4,
AsyncTaskEvent: 5 };
// Types of exceptions that can be broken upon.
Debug.ExceptionBreak = { Caught : 0,
Uncaught: 1 };
// The different types of steps.
Debug.StepAction = { StepOut: 0,
StepNext: 1,
StepIn: 2 };
// The different types of scripts matching enum ScriptType in objects.h.
Debug.ScriptType = { Native: 0,
Extension: 1,
Normal: 2,
Wasm: 3};
// The different types of script compilations matching enum
// Script::CompilationType in objects.h.
Debug.ScriptCompilationType = { Host: 0,
Eval: 1,
JSON: 2 };
// The different script break point types.
Debug.ScriptBreakPointType = { ScriptId: 0,
ScriptName: 1,
ScriptRegExp: 2 };
// The different types of breakpoint position alignments.
// Must match BreakPositionAlignment in debug.h.
Debug.BreakPositionAlignment = {
Statement: 0,
BreakPosition: 1
};
function ScriptTypeFlag(type) {
return (1 << type);
}
// Globals.
var next_response_seq = 0;
var next_break_point_number = 1;
var break_points = [];
var script_break_points = [];
var debugger_flags = {
breakPointsActive: {
value: true,
getValue: function() { return this.value; },
setValue: function(value) {
this.value = !!value;
%SetBreakPointsActive(this.value);
}
},
breakOnCaughtException: {
getValue: function() { return Debug.isBreakOnException(); },
setValue: function(value) {
if (value) {
Debug.setBreakOnException();
} else {
Debug.clearBreakOnException();
}
}
},
breakOnUncaughtException: {
getValue: function() { return Debug.isBreakOnUncaughtException(); },
setValue: function(value) {
if (value) {
Debug.setBreakOnUncaughtException();
} else {
Debug.clearBreakOnUncaughtException();
}
}
},
};
// Create a new break point object and add it to the list of break points.
function MakeBreakPoint(source_position, opt_script_break_point) {
var break_point = new BreakPoint(source_position, opt_script_break_point);
break_points.push(break_point);
return break_point;
}
// Object representing a break point.
// NOTE: This object does not have a reference to the function having break
// point as this would cause function not to be garbage collected when it is
// not used any more. We do not want break points to keep functions alive.
function BreakPoint(source_position, opt_script_break_point) {
this.source_position_ = source_position;
if (opt_script_break_point) {
this.script_break_point_ = opt_script_break_point;
} else {
this.number_ = next_break_point_number++;
}
this.active_ = true;
this.condition_ = null;
}
BreakPoint.prototype.number = function() {
return this.number_;
};
BreakPoint.prototype.func = function() {
return this.func_;
};
BreakPoint.prototype.source_position = function() {
return this.source_position_;
};
BreakPoint.prototype.active = function() {
if (this.script_break_point()) {
return this.script_break_point().active();
}
return this.active_;
};
BreakPoint.prototype.condition = function() {
if (this.script_break_point() && this.script_break_point().condition()) {
return this.script_break_point().condition();
}
return this.condition_;
};
BreakPoint.prototype.script_break_point = function() {
return this.script_break_point_;
};
BreakPoint.prototype.enable = function() {
this.active_ = true;
};
BreakPoint.prototype.disable = function() {
this.active_ = false;
};
BreakPoint.prototype.setCondition = function(condition) {
this.condition_ = condition;
};
BreakPoint.prototype.isTriggered = function(exec_state) {
// Break point not active - not triggered.
if (!this.active()) return false;
// Check for conditional break point.
if (this.condition()) {
// If break point has condition try to evaluate it in the top frame.
try {
var mirror = exec_state.frame(0).evaluate(this.condition());
// If no sensible mirror or non true value break point not triggered.
if (!(mirror instanceof ValueMirror) || !mirror.value_) {
return false;
}
} catch (e) {
// Exception evaluating condition counts as not triggered.
return false;
}
}
// Break point triggered.
return true;
};
// Function called from the runtime when a break point is hit. Returns true if
// the break point is triggered and supposed to break execution.
function IsBreakPointTriggered(break_id, break_point) {
return break_point.isTriggered(MakeExecutionState(break_id));
}
// Object representing a script break point. The script is referenced by its
// script name or script id and the break point is represented as line and
// column.
function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
opt_groupId, opt_position_alignment) {
this.type_ = type;
if (type == Debug.ScriptBreakPointType.ScriptId) {
this.script_id_ = script_id_or_name;
} else if (type == Debug.ScriptBreakPointType.ScriptName) {
this.script_name_ = script_id_or_name;
} else if (type == Debug.ScriptBreakPointType.ScriptRegExp) {
this.script_regexp_object_ = new GlobalRegExp(script_id_or_name);
} else {
throw %make_error(kDebugger, "Unexpected breakpoint type " + type);
}
this.line_ = opt_line || 0;
this.column_ = opt_column;
this.groupId_ = opt_groupId;
this.position_alignment_ = IS_UNDEFINED(opt_position_alignment)
? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
this.active_ = true;
this.condition_ = null;
this.break_points_ = [];
}
ScriptBreakPoint.prototype.number = function() {
return this.number_;
};
ScriptBreakPoint.prototype.groupId = function() {
return this.groupId_;
};
ScriptBreakPoint.prototype.type = function() {
return this.type_;
};
ScriptBreakPoint.prototype.script_id = function() {
return this.script_id_;
};
ScriptBreakPoint.prototype.script_name = function() {
return this.script_name_;
};
ScriptBreakPoint.prototype.script_regexp_object = function() {
return this.script_regexp_object_;
};
ScriptBreakPoint.prototype.line = function() {
return this.line_;
};
ScriptBreakPoint.prototype.column = function() {
return this.column_;
};
ScriptBreakPoint.prototype.actual_locations = function() {
var locations = [];
for (var i = 0; i < this.break_points_.length; i++) {
locations.push(this.break_points_[i].actual_location);
}
return locations;
};
ScriptBreakPoint.prototype.update_positions = function(line, column) {
this.line_ = line;
this.column_ = column;
};
ScriptBreakPoint.prototype.active = function() {
return this.active_;
};
ScriptBreakPoint.prototype.condition = function() {
return this.condition_;
};
ScriptBreakPoint.prototype.enable = function() {
this.active_ = true;
};
ScriptBreakPoint.prototype.disable = function() {
this.active_ = false;
};
ScriptBreakPoint.prototype.setCondition = function(condition) {
this.condition_ = condition;
};
// Check whether a script matches this script break point. Currently this is
// only based on script name.
ScriptBreakPoint.prototype.matchesScript = function(script) {
if (this.type_ == Debug.ScriptBreakPointType.ScriptId) {
return this.script_id_ == script.id;
} else {
// We might want to account columns here as well.
if (!(script.line_offset <= this.line_ &&
this.line_ < script.line_offset + %ScriptLineCount(script))) {
return false;
}
if (this.type_ == Debug.ScriptBreakPointType.ScriptName) {
return this.script_name_ == script.nameOrSourceURL();
} else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
return this.script_regexp_object_.test(script.nameOrSourceURL());
} else {
throw %make_error(kDebugger, "Unexpected breakpoint type " + this.type_);
}
}
};
// Set the script break point in a script.
ScriptBreakPoint.prototype.set = function (script) {
var column = this.column();
var line = this.line();
// If the column is undefined the break is on the line. To help locate the
// first piece of breakable code on the line try to find the column on the
// line which contains some source.
if (IS_UNDEFINED(column)) {
var source_line = %ScriptSourceLine(script, line || script.line_offset);
// Allocate array for caching the columns where the actual source starts.
if (!script.sourceColumnStart_) {
script.sourceColumnStart_ = new GlobalArray(%ScriptLineCount(script));
}
// Fill cache if needed and get column where the actual source starts.
if (IS_UNDEFINED(script.sourceColumnStart_[line])) {
script.sourceColumnStart_[line] =
source_line.match(sourceLineBeginningSkip)[0].length;
}
column = script.sourceColumnStart_[line];
}
// Convert the line and column into an absolute position within the script.
var position = Debug.findScriptSourcePosition(script, this.line(), column);
// If the position is not found in the script (the script might be shorter
// than it used to be) just ignore it.
if (IS_NULL(position)) return;
// Create a break point object and set the break point.
var break_point = MakeBreakPoint(position, this);
var actual_position = %SetScriptBreakPoint(script, position,
this.position_alignment_,
break_point);
if (IS_UNDEFINED(actual_position)) {
actual_position = position;
}
var actual_location = script.locationFromPosition(actual_position, true);
break_point.actual_location = { line: actual_location.line,
column: actual_location.column,
script_id: script.id };
this.break_points_.push(break_point);
return break_point;
};
// Clear all the break points created from this script break point
ScriptBreakPoint.prototype.clear = function () {
var remaining_break_points = [];
for (var i = 0; i < break_points.length; i++) {
if (break_points[i].script_break_point() &&
break_points[i].script_break_point() === this) {
%ClearBreakPoint(break_points[i]);
} else {
remaining_break_points.push(break_points[i]);
}
}
break_points = remaining_break_points;
this.break_points_ = [];
};
Debug.setListener = function(listener, opt_data) {
if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
throw %make_type_error(kDebuggerType);
}
%SetDebugEventListener(listener, opt_data);
};
// Returns a Script object. If the parameter is a function the return value
// is the script in which the function is defined. If the parameter is a string
// the return value is the script for which the script name has that string
// value. If it is a regexp and there is a unique script whose name matches
// we return that, otherwise undefined.
Debug.findScript = function(func_or_script_name) {
if (IS_FUNCTION(func_or_script_name)) {
return %FunctionGetScript(func_or_script_name);
} else if (%IsRegExp(func_or_script_name)) {
var scripts = this.scripts();
var last_result = null;
var result_count = 0;
for (var i in scripts) {
var script = scripts[i];
if (func_or_script_name.test(script.name)) {
last_result = script;
result_count++;
}
}
// Return the unique script matching the regexp. If there are more
// than one we don't return a value since there is no good way to
// decide which one to return. Returning a "random" one, say the
// first, would introduce nondeterminism (or something close to it)
// because the order is the heap iteration order.
if (result_count == 1) {
return last_result;
} else {
return UNDEFINED;
}
} else {
return %GetScript(func_or_script_name);
}
};
// Returns the script source. If the parameter is a function the return value
// is the script source for the script in which the function is defined. If the
// parameter is a string the return value is the script for which the script
// name has that string value.
Debug.scriptSource = function(func_or_script_name) {
return this.findScript(func_or_script_name).source;
};
Debug.source = function(f) {
if (!IS_FUNCTION(f)) throw %make_type_error(kDebuggerType);
return %FunctionGetSourceCode(f);
};
Debug.sourcePosition = function(f) {
if (!IS_FUNCTION(f)) throw %make_type_error(kDebuggerType);
return %FunctionGetScriptSourcePosition(f);
};
Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
var script = %FunctionGetScript(func);
var script_offset = %FunctionGetScriptSourcePosition(func);
return %ScriptLocationFromLine(script, opt_line, opt_column, script_offset);
};
// Returns the character position in a script based on a line number and an
// optional position within that line.
Debug.findScriptSourcePosition = function(script, opt_line, opt_column) {
var location = %ScriptLocationFromLine(script, opt_line, opt_column, 0);
return location ? location.position : null;
};
Debug.findBreakPoint = function(break_point_number, remove) {
var break_point;
for (var i = 0; i < break_points.length; i++) {
if (break_points[i].number() == break_point_number) {
break_point = break_points[i];
// Remove the break point from the list if requested.
if (remove) {
break_points.splice(i, 1);
}
break;
}
}
if (break_point) {
return break_point;
} else {
return this.findScriptBreakPoint(break_point_number, remove);
}
};
Debug.findBreakPointActualLocations = function(break_point_number) {
for (var i = 0; i < script_break_points.length; i++) {
if (script_break_points[i].number() == break_point_number) {
return script_break_points[i].actual_locations();
}
}
for (var i = 0; i < break_points.length; i++) {
if (break_points[i].number() == break_point_number) {
return [break_points[i].actual_location];
}
}
return [];
};
Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
if (!IS_FUNCTION(func)) throw %make_type_error(kDebuggerType);
// Break points in API functions are not supported.
if (%FunctionIsAPIFunction(func)) {
throw %make_error(kDebugger, 'Cannot set break point in native code.');
}
// Find source position.
var source_position =
this.findFunctionSourceLocation(func, opt_line, opt_column).position;
// Find the script for the function.
var script = %FunctionGetScript(func);
// Break in builtin JavaScript code is not supported.
if (script.type == Debug.ScriptType.Native) {
throw %make_error(kDebugger, 'Cannot set break point in native code.');
}
// If the script for the function has a name convert this to a script break
// point.
if (script && script.id) {
// Find line and column for the position in the script and set a script
// break point from that.
var location = script.locationFromPosition(source_position, false);
return this.setScriptBreakPointById(script.id,
location.line, location.column,
opt_condition);
} else {
// Set a break point directly on the function.
var break_point = MakeBreakPoint(source_position);
var actual_position =
%SetFunctionBreakPoint(func, source_position, break_point);
var actual_location = script.locationFromPosition(actual_position, true);
break_point.actual_location = { line: actual_location.line,
column: actual_location.column,
script_id: script.id };
break_point.setCondition(opt_condition);
return break_point.number();
}
};
Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
condition, enabled,
opt_position_alignment)
{
var break_point = MakeBreakPoint(position);
break_point.setCondition(condition);
if (!enabled) {
break_point.disable();
}
var script = scriptById(script_id);
if (script) {
var position_alignment = IS_UNDEFINED(opt_position_alignment)
? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
break_point.actual_position = %SetScriptBreakPoint(script, position,
position_alignment, break_point);
}
return break_point;
};
Debug.enableBreakPoint = function(break_point_number) {
var break_point = this.findBreakPoint(break_point_number, false);
// Only enable if the breakpoint hasn't been deleted:
if (break_point) {
break_point.enable();
}
};
Debug.disableBreakPoint = function(break_point_number) {
var break_point = this.findBreakPoint(break_point_number, false);
// Only enable if the breakpoint hasn't been deleted:
if (break_point) {
break_point.disable();
}
};
Debug.changeBreakPointCondition = function(break_point_number, condition) {
var break_point = this.findBreakPoint(break_point_number, false);
break_point.setCondition(condition);
};
Debug.clearBreakPoint = function(break_point_number) {
var break_point = this.findBreakPoint(break_point_number, true);
if (break_point) {
return %ClearBreakPoint(break_point);
} else {
break_point = this.findScriptBreakPoint(break_point_number, true);
if (!break_point) throw %make_error(kDebugger, 'Invalid breakpoint');
}
};
Debug.clearAllBreakPoints = function() {
for (var i = 0; i < break_points.length; i++) {
var break_point = break_points[i];
%ClearBreakPoint(break_point);
}
break_points = [];
};
Debug.disableAllBreakPoints = function() {
// Disable all user defined breakpoints:
for (var i = 1; i < next_break_point_number; i++) {
Debug.disableBreakPoint(i);
}
// Disable all exception breakpoints:
%ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
%ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
};
Debug.findScriptBreakPoint = function(break_point_number, remove) {
var script_break_point;
for (var i = 0; i < script_break_points.length; i++) {
if (script_break_points[i].number() == break_point_number) {
script_break_point = script_break_points[i];
// Remove the break point from the list if requested.
if (remove) {
script_break_point.clear();
script_break_points.splice(i,1);
}
break;
}
}
return script_break_point;
};
// Sets a breakpoint in a script identified through id or name at the
// specified source line and column within that line.
Debug.setScriptBreakPoint = function(type, script_id_or_name,
opt_line, opt_column, opt_condition,
opt_groupId, opt_position_alignment) {
// Create script break point object.
var script_break_point =
new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
opt_groupId, opt_position_alignment);
// Assign number to the new script break point and add it.
script_break_point.number_ = next_break_point_number++;
script_break_point.setCondition(opt_condition);
script_break_points.push(script_break_point);
// Run through all scripts to see if this script break point matches any
// loaded scripts.
var scripts = this.scripts();
for (var i = 0; i < scripts.length; i++) {
if (script_break_point.matchesScript(scripts[i])) {
script_break_point.set(scripts[i]);
}
}
return script_break_point.number();
};
Debug.setScriptBreakPointById = function(script_id,
opt_line, opt_column,
opt_condition, opt_groupId,
opt_position_alignment) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
script_id, opt_line, opt_column,
opt_condition, opt_groupId,
opt_position_alignment);
};
Debug.setScriptBreakPointByName = function(script_name,
opt_line, opt_column,
opt_condition, opt_groupId) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptName,
script_name, opt_line, opt_column,
opt_condition, opt_groupId);
};
Debug.setScriptBreakPointByRegExp = function(script_regexp,
opt_line, opt_column,
opt_condition, opt_groupId) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptRegExp,
script_regexp, opt_line, opt_column,
opt_condition, opt_groupId);
};
Debug.enableScriptBreakPoint = function(break_point_number) {
var script_break_point = this.findScriptBreakPoint(break_point_number, false);
script_break_point.enable();
};
Debug.disableScriptBreakPoint = function(break_point_number) {
var script_break_point = this.findScriptBreakPoint(break_point_number, false);
script_break_point.disable();
};
Debug.changeScriptBreakPointCondition = function(
break_point_number, condition) {
var script_break_point = this.findScriptBreakPoint(break_point_number, false);
script_break_point.setCondition(condition);
};
Debug.scriptBreakPoints = function() {
return script_break_points;
};
Debug.clearStepping = function() {
%ClearStepping();
};
Debug.setBreakOnException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, true);
};
Debug.clearBreakOnException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Caught, false);
};
Debug.isBreakOnException = function() {
return !!%IsBreakOnException(Debug.ExceptionBreak.Caught);
};
Debug.setBreakOnUncaughtException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, true);
};
Debug.clearBreakOnUncaughtException = function() {
return %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, false);
};
Debug.isBreakOnUncaughtException = function() {
return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
};
Debug.showBreakPoints = function(f, full, opt_position_alignment) {
if (!IS_FUNCTION(f)) throw %make_error(kDebuggerType);
var source = full ? this.scriptSource(f) : this.source(f);
var offset = full ? 0 : this.sourcePosition(f);
var position_alignment = IS_UNDEFINED(opt_position_alignment)
? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
var locations = %GetBreakLocations(f, position_alignment);
if (!locations) return source;
locations.sort(function(x, y) { return x - y; });
var result = "";
var prev_pos = 0;
var pos;
for (var i = 0; i < locations.length; i++) {
pos = locations[i] - offset;
result += source.slice(prev_pos, pos);
result += "[B" + i + "]";
prev_pos = pos;
}
pos = source.length;
result += source.substring(prev_pos, pos);
return result;
};
// Get all the scripts currently loaded. Locating all the scripts is based on
// scanning the heap.
Debug.scripts = function() {
// Collect all scripts in the heap.
return %DebugGetLoadedScripts();
};
// Get a specific script currently loaded. This is based on scanning the heap.
// TODO(clemensh): Create a runtime function for this.
function scriptById(scriptId) {
var scripts = Debug.scripts();
for (var script of scripts) {
if (script.id == scriptId) return script;
}
return UNDEFINED;
};
Debug.debuggerFlags = function() {
return debugger_flags;
};
Debug.MakeMirror = MakeMirror;
function MakeExecutionState(break_id) {
return new ExecutionState(break_id);
}
function ExecutionState(break_id) {
this.break_id = break_id;
this.selected_frame = 0;
}
ExecutionState.prototype.prepareStep = function(action) {
if (action === Debug.StepAction.StepIn ||
action === Debug.StepAction.StepOut ||
action === Debug.StepAction.StepNext) {
return %PrepareStep(this.break_id, action);
}
throw %make_type_error(kDebuggerType);
};
ExecutionState.prototype.evaluateGlobal = function(source) {
return MakeMirror(%DebugEvaluateGlobal(this.break_id, source));
};
ExecutionState.prototype.frameCount = function() {
return %GetFrameCount(this.break_id);
};
ExecutionState.prototype.frame = function(opt_index) {
// If no index supplied return the selected frame.
if (opt_index == null) opt_index = this.selected_frame;
if (opt_index < 0 || opt_index >= this.frameCount()) {
throw %make_type_error(kDebuggerFrame);
}
return new FrameMirror(this.break_id, opt_index);
};
ExecutionState.prototype.setSelectedFrame = function(index) {
var i = TO_NUMBER(index);
if (i < 0 || i >= this.frameCount()) {
throw %make_type_error(kDebuggerFrame);
}
this.selected_frame = i;
};
ExecutionState.prototype.selectedFrame = function() {
return this.selected_frame;
};
function MakeBreakEvent(break_id, break_points_hit) {
return new BreakEvent(break_id, break_points_hit);
}
function BreakEvent(break_id, break_points_hit) {
this.frame_ = new FrameMirror(break_id, 0);
this.break_points_hit_ = break_points_hit;
}
BreakEvent.prototype.eventType = function() {
return Debug.DebugEvent.Break;
};
BreakEvent.prototype.func = function() {
return this.frame_.func();
};
BreakEvent.prototype.sourceLine = function() {
return this.frame_.sourceLine();
};
BreakEvent.prototype.sourceColumn = function() {
return this.frame_.sourceColumn();
};
BreakEvent.prototype.sourceLineText = function() {
return this.frame_.sourceLineText();
};
BreakEvent.prototype.breakPointsHit = function() {
return this.break_points_hit_;
};
function MakeExceptionEvent(break_id, exception, uncaught, promise) {
return new ExceptionEvent(break_id, exception, uncaught, promise);
}
function ExceptionEvent(break_id, exception, uncaught, promise) {
this.exec_state_ = new ExecutionState(break_id);
this.exception_ = exception;
this.uncaught_ = uncaught;
this.promise_ = promise;
}
ExceptionEvent.prototype.eventType = function() {
return Debug.DebugEvent.Exception;
};
ExceptionEvent.prototype.exception = function() {
return this.exception_;
};
ExceptionEvent.prototype.uncaught = function() {
return this.uncaught_;
};
ExceptionEvent.prototype.promise = function() {
return this.promise_;
};
ExceptionEvent.prototype.func = function() {
return this.exec_state_.frame(0).func();
};
ExceptionEvent.prototype.sourceLine = function() {
return this.exec_state_.frame(0).sourceLine();
};
ExceptionEvent.prototype.sourceColumn = function() {
return this.exec_state_.frame(0).sourceColumn();
};
ExceptionEvent.prototype.sourceLineText = function() {
return this.exec_state_.frame(0).sourceLineText();
};
function MakeCompileEvent(script, type) {
return new CompileEvent(script, type);
}
function CompileEvent(script, type) {
this.script_ = MakeMirror(script);
this.type_ = type;
}
CompileEvent.prototype.eventType = function() {
return this.type_;
};
CompileEvent.prototype.script = function() {
return this.script_;
};
function MakeScriptObject_(script, include_source) {
var o = { id: script.id(),
name: script.name(),
lineOffset: script.lineOffset(),
columnOffset: script.columnOffset(),
lineCount: script.lineCount(),
};
if (!IS_UNDEFINED(script.data())) {
o.data = script.data();
}
if (include_source) {
o.source = script.source();
}
return o;
}
function MakeAsyncTaskEvent(type, id) {
return new AsyncTaskEvent(type, id);
}
function AsyncTaskEvent(type, id) {
this.type_ = type;
this.id_ = id;
}
AsyncTaskEvent.prototype.type = function() {
return this.type_;
}
AsyncTaskEvent.prototype.id = function() {
return this.id_;
}
// -------------------------------------------------------------------
// Exports
utils.InstallConstants(global, [
"Debug", Debug,
"BreakEvent", BreakEvent,
"CompileEvent", CompileEvent,
"BreakPoint", BreakPoint,
]);
// Functions needed by the debugger runtime.
utils.InstallFunctions(utils, DONT_ENUM, [
"MakeExecutionState", MakeExecutionState,
"MakeExceptionEvent", MakeExceptionEvent,
"MakeBreakEvent", MakeBreakEvent,
"MakeCompileEvent", MakeCompileEvent,
"MakeAsyncTaskEvent", MakeAsyncTaskEvent,
"IsBreakPointTriggered", IsBreakPointTriggered,
]);
})