// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Default number of frames to include in the response to backtrace request.
const kDefaultBacktraceLength = 10;

const 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.
const 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,
                     NewFunction: 3,
                     BeforeCompile: 4,
                     AfterCompile: 5,
                     ScriptCollected: 6 };

// 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,
                     StepMin: 3,
                     StepInMin: 4 };

// The different types of scripts matching enum ScriptType in objects.h.
Debug.ScriptType = { Native: 0,
                     Extension: 1,
                     Normal: 2 };

// 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 };

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;
      %SetDisableBreak(!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();
      }
    }
  },
};
var lol_is_enabled = %HasLOLEnabled();


// 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.hit_count_ = 0;
  this.active_ = true;
  this.condition_ = null;
  this.ignoreCount_ = 0;
}


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.hit_count = function() {
  return this.hit_count_;
};


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.ignoreCount = function() {
  return this.ignoreCount_;
};


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.setIgnoreCount = function(ignoreCount) {
  this.ignoreCount_ = ignoreCount;
};


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) || !%ToBoolean(mirror.value_)) {
        return false;
      }
    } catch (e) {
      // Exception evaluating condition counts as not triggered.
      return false;
    }
  }

  // Update the hit count.
  this.hit_count_++;
  if (this.script_break_point_) {
    this.script_break_point_.hit_count_++;
  }

  // If the break point has an ignore count it is not triggered.
  if (this.ignoreCount_ > 0) {
    this.ignoreCount_--;
    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) {
  this.type_ = type;
  if (type == Debug.ScriptBreakPointType.ScriptId) {
    this.script_id_ = script_id_or_name;
  } else {  // type == Debug.ScriptBreakPointType.ScriptName
    this.script_name_ = script_id_or_name;
  }
  this.line_ = opt_line || 0;
  this.column_ = opt_column;
  this.groupId_ = opt_groupId;
  this.hit_count_ = 0;
  this.active_ = true;
  this.condition_ = null;
  this.ignoreCount_ = 0;
  this.break_points_ = [];
}


//Creates a clone of script breakpoint that is linked to another script.
ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
  var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
      other_script.id, this.line_, this.column_, this.groupId_);
  copy.number_ = next_break_point_number++;
  script_break_points.push(copy);

  copy.hit_count_ = this.hit_count_;
  copy.active_ = this.active_;
  copy.condition_ = this.condition_;
  copy.ignoreCount_ = this.ignoreCount_;
  return copy;
}


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.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.hit_count = function() {
  return this.hit_count_;
};


ScriptBreakPoint.prototype.active = function() {
  return this.active_;
};


ScriptBreakPoint.prototype.condition = function() {
  return this.condition_;
};


ScriptBreakPoint.prototype.ignoreCount = function() {
  return this.ignoreCount_;
};


ScriptBreakPoint.prototype.enable = function() {
  this.active_ = true;
};


ScriptBreakPoint.prototype.disable = function() {
  this.active_ = false;
};


ScriptBreakPoint.prototype.setCondition = function(condition) {
  this.condition_ = condition;
};


ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
  this.ignoreCount_ = ignoreCount;

  // Set ignore count on all break points created from this script break point.
  for (var i = 0; i < this.break_points_.length; i++) {
    this.break_points_[i].setIgnoreCount(ignoreCount);
  }
};


// 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 {  // this.type_ == Debug.ScriptBreakPointType.ScriptName
    return this.script_name_ == script.nameOrSourceURL() &&
           script.line_offset <= this.line_  &&
           this.line_ < script.line_offset + script.lineCount();
  }
};


// 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 = script.sourceLine(this.line());

    // Allocate array for caching the columns where the actual source starts.
    if (!script.sourceColumnStart_) {
      script.sourceColumnStart_ = new Array(script.lineCount());
    }

    // 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 (position === null) return;

  // Create a break point object and set the break point.
  break_point = MakeBreakPoint(position, this);
  break_point.setIgnoreCount(this.ignoreCount());
  var actual_position = %SetScriptBreakPoint(script, position, 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 };
  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_ = [];
};


// Function called from runtime when a new script is compiled to set any script
// break points set in this script.
function UpdateScriptBreakPoints(script) {
  for (var i = 0; i < script_break_points.length; i++) {
    if (script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptName &&
        script_break_points[i].matchesScript(script)) {
      script_break_points[i].set(script);
    }
  }
}


function GetScriptBreakPoints(script) {
  var result = [];
  for (var i = 0; i < script_break_points.length; i++) {
    if (script_break_points[i].matchesScript(script)) {
      result.push(script_break_points[i]);
    }
  }
  return result;
}


Debug.setListener = function(listener, opt_data) {
  if (!IS_FUNCTION(listener) && !IS_UNDEFINED(listener) && !IS_NULL(listener)) {
    throw new Error('Parameters have wrong types.');
  }
  %SetDebugEventListener(listener, opt_data);
};


Debug.breakExecution = function(f) {
  %Break();
};

Debug.breakLocations = function(f) {
  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
  return %GetBreakLocations(f);
};

// 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 (IS_REGEXP(func_or_script_name)) {
    var scripts = Debug.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 new Error('Parameters have wrong types.');
  return %FunctionGetSourceCode(f);
};

Debug.disassemble = function(f) {
  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
  return %DebugDisassembleFunction(f);
};

Debug.disassembleConstructor = function(f) {
  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
  return %DebugDisassembleConstructor(f);
};

Debug.ExecuteInDebugContext = function(f, without_debugger) {
  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
  return %ExecuteInDebugContext(f, !!without_debugger);
};

Debug.sourcePosition = function(f) {
  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
  return %FunctionGetScriptSourcePosition(f);
};


Debug.findFunctionSourceLocation = function(func, opt_line, opt_column) {
  var script = %FunctionGetScript(func);
  var script_offset = %FunctionGetScriptSourcePosition(func);
  return script.locationFromLine(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 = script.locationFromLine(opt_line, opt_column);
  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 new Error('Parameters have wrong types.');
  // Break points in API functions are not supported.
  if (%FunctionIsAPIFunction(func)) {
    throw new Error('Cannot set break point in native code.');
  }
  // Find source position relative to start of the function
  var break_position =
      this.findFunctionSourceLocation(func, opt_line, opt_column).position;
  var source_position = break_position - this.sourcePosition(func);
  // 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 new Error('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) {
    // Adjust the source position to be script relative.
    source_position += %FunctionGetScriptSourcePosition(func);
    // 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);
    actual_position += this.sourcePosition(func);
    var actual_location = script.locationFromPosition(actual_position, true);
    break_point.actual_location = { line: actual_location.line,
                                    column: actual_location.column };
    break_point.setCondition(opt_condition);
    return break_point.number();
  }
};


Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
                                                    condition, enabled)
{
  break_point = MakeBreakPoint(position);
  break_point.setCondition(condition);
  if (!enabled)
    break_point.disable();
  var scripts = this.scripts();
  for (var i = 0; i < scripts.length; i++) {
    if (script_id == scripts[i].id) {
      break_point.actual_position = %SetScriptBreakPoint(scripts[i], position,
                                                         break_point);
      break;
    }
  }
  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.changeBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
  if (ignoreCount < 0) {
    throw new Error('Invalid argument');
  }
  var break_point = this.findBreakPoint(break_point_number, false);
  break_point.setIgnoreCount(ignoreCount);
};


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 new Error('Invalid breakpoint');
    }
  }
};


Debug.clearAllBreakPoints = function() {
  for (var i = 0; i < break_points.length; i++) {
    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) {
  // Create script break point object.
  var script_break_point =
      new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
                           opt_groupId);

  // 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) {
  return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
                                  script_id, opt_line, opt_column,
                                  opt_condition, opt_groupId);
}


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.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.changeScriptBreakPointIgnoreCount = function(break_point_number, ignoreCount) {
  if (ignoreCount < 0) {
    throw new Error('Invalid argument');
  }
  var script_break_point = this.findScriptBreakPoint(break_point_number, false);
  script_break_point.setIgnoreCount(ignoreCount);
};


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) {
  if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
  var source = full ? this.scriptSource(f) : this.source(f);
  var offset = full ? this.sourcePosition(f) : 0;
  var locations = this.breakLocations(f);
  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();
};


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(opt_action, opt_count) {
  var action = Debug.StepAction.StepIn;
  if (!IS_UNDEFINED(opt_action)) action = %ToNumber(opt_action);
  var count = opt_count ? %ToNumber(opt_count) : 1;

  return %PrepareStep(this.break_id, action, count);
}

ExecutionState.prototype.evaluateGlobal = function(source, disable_break,
    opt_additional_context) {
  return MakeMirror(%DebugEvaluateGlobal(this.break_id, source,
                                         Boolean(disable_break),
                                         opt_additional_context));
};

ExecutionState.prototype.frameCount = function() {
  return %GetFrameCount(this.break_id);
};

ExecutionState.prototype.threadCount = function() {
  return %GetThreadCount(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 new Error('Illegal frame index.');
  return new FrameMirror(this.break_id, opt_index);
};

ExecutionState.prototype.setSelectedFrame = function(index) {
  var i = %ToNumber(index);
  if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
  this.selected_frame = i;
};

ExecutionState.prototype.selectedFrame = function() {
  return this.selected_frame;
};

ExecutionState.prototype.debugCommandProcessor = function(opt_is_running) {
  return new DebugCommandProcessor(this, opt_is_running);
};


function MakeBreakEvent(exec_state, break_points_hit) {
  return new BreakEvent(exec_state, break_points_hit);
}


function BreakEvent(exec_state, break_points_hit) {
  this.exec_state_ = exec_state;
  this.break_points_hit_ = break_points_hit;
}


BreakEvent.prototype.executionState = function() {
  return this.exec_state_;
};


BreakEvent.prototype.eventType = function() {
  return Debug.DebugEvent.Break;
};


BreakEvent.prototype.func = function() {
  return this.exec_state_.frame(0).func();
};


BreakEvent.prototype.sourceLine = function() {
  return this.exec_state_.frame(0).sourceLine();
};


BreakEvent.prototype.sourceColumn = function() {
  return this.exec_state_.frame(0).sourceColumn();
};


BreakEvent.prototype.sourceLineText = function() {
  return this.exec_state_.frame(0).sourceLineText();
};


BreakEvent.prototype.breakPointsHit = function() {
  return this.break_points_hit_;
};


BreakEvent.prototype.toJSONProtocol = function() {
  var o = { seq: next_response_seq++,
            type: "event",
            event: "break",
            body: { invocationText: this.exec_state_.frame(0).invocationText(),
                  }
          };

  // Add script related information to the event if available.
  var script = this.func().script();
  if (script) {
    o.body.sourceLine = this.sourceLine(),
    o.body.sourceColumn = this.sourceColumn(),
    o.body.sourceLineText = this.sourceLineText(),
    o.body.script = MakeScriptObject_(script, false);
  }

  // Add an Array of break points hit if any.
  if (this.breakPointsHit()) {
    o.body.breakpoints = [];
    for (var i = 0; i < this.breakPointsHit().length; i++) {
      // Find the break point number. For break points originating from a
      // script break point supply the script break point number.
      var breakpoint = this.breakPointsHit()[i];
      var script_break_point = breakpoint.script_break_point();
      var number;
      if (script_break_point) {
        number = script_break_point.number();
      } else {
        number = breakpoint.number();
      }
      o.body.breakpoints.push(number);
    }
  }
  return JSON.stringify(ObjectToProtocolObject_(o));
};


function MakeExceptionEvent(exec_state, exception, uncaught) {
  return new ExceptionEvent(exec_state, exception, uncaught);
}


function ExceptionEvent(exec_state, exception, uncaught) {
  this.exec_state_ = exec_state;
  this.exception_ = exception;
  this.uncaught_ = uncaught;
}


ExceptionEvent.prototype.executionState = function() {
  return this.exec_state_;
};


ExceptionEvent.prototype.eventType = function() {
  return Debug.DebugEvent.Exception;
};


ExceptionEvent.prototype.exception = function() {
  return this.exception_;
}


ExceptionEvent.prototype.uncaught = function() {
  return this.uncaught_;
}


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();
};


ExceptionEvent.prototype.toJSONProtocol = function() {
  var o = new ProtocolMessage();
  o.event = "exception";
  o.body = { uncaught: this.uncaught_,
             exception: MakeMirror(this.exception_)
           };

  // Exceptions might happen whithout any JavaScript frames.
  if (this.exec_state_.frameCount() > 0) {
    o.body.sourceLine = this.sourceLine();
    o.body.sourceColumn = this.sourceColumn();
    o.body.sourceLineText = this.sourceLineText();

    // Add script information to the event if available.
    var script = this.func().script();
    if (script) {
      o.body.script = MakeScriptObject_(script, false);
    }
  } else {
    o.body.sourceLine = -1;
  }

  return o.toJSONProtocol();
};


function MakeCompileEvent(exec_state, script, before) {
  return new CompileEvent(exec_state, script, before);
}


function CompileEvent(exec_state, script, before) {
  this.exec_state_ = exec_state;
  this.script_ = MakeMirror(script);
  this.before_ = before;
}


CompileEvent.prototype.executionState = function() {
  return this.exec_state_;
};


CompileEvent.prototype.eventType = function() {
  if (this.before_) {
    return Debug.DebugEvent.BeforeCompile;
  } else {
    return Debug.DebugEvent.AfterCompile;
  }
};


CompileEvent.prototype.script = function() {
  return this.script_;
};


CompileEvent.prototype.toJSONProtocol = function() {
  var o = new ProtocolMessage();
  o.running = true;
  if (this.before_) {
    o.event = "beforeCompile";
  } else {
    o.event = "afterCompile";
  }
  o.body = {};
  o.body.script = this.script_;

  return o.toJSONProtocol();
}


function MakeNewFunctionEvent(func) {
  return new NewFunctionEvent(func);
}


function NewFunctionEvent(func) {
  this.func = func;
}


NewFunctionEvent.prototype.eventType = function() {
  return Debug.DebugEvent.NewFunction;
};


NewFunctionEvent.prototype.name = function() {
  return this.func.name;
};


NewFunctionEvent.prototype.setBreakPoint = function(p) {
  Debug.setBreakPoint(this.func, p || 0);
};


function MakeScriptCollectedEvent(exec_state, id) {
  return new ScriptCollectedEvent(exec_state, id);
}


function ScriptCollectedEvent(exec_state, id) {
  this.exec_state_ = exec_state;
  this.id_ = id;
}


ScriptCollectedEvent.prototype.id = function() {
  return this.id_;
};


ScriptCollectedEvent.prototype.executionState = function() {
  return this.exec_state_;
};


ScriptCollectedEvent.prototype.toJSONProtocol = function() {
  var o = new ProtocolMessage();
  o.running = true;
  o.event = "scriptCollected";
  o.body = {};
  o.body.script = { id: this.id() };
  return o.toJSONProtocol();
}


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 DebugCommandProcessor(exec_state, opt_is_running) {
  this.exec_state_ = exec_state;
  this.running_ = opt_is_running || false;
};


DebugCommandProcessor.prototype.processDebugRequest = function (request) {
  return this.processDebugJSONRequest(request);
}


function ProtocolMessage(request) {
  // Update sequence number.
  this.seq = next_response_seq++;

  if (request) {
    // If message is based on a request this is a response. Fill the initial
    // response from the request.
    this.type = 'response';
    this.request_seq = request.seq;
    this.command = request.command;
  } else {
    // If message is not based on a request it is a dabugger generated event.
    this.type = 'event';
  }
  this.success = true;
  // Handler may set this field to control debugger state.
  this.running = undefined;
}


ProtocolMessage.prototype.setOption = function(name, value) {
  if (!this.options_) {
    this.options_ = {};
  }
  this.options_[name] = value;
}


ProtocolMessage.prototype.failed = function(message) {
  this.success = false;
  this.message = message;
}


ProtocolMessage.prototype.toJSONProtocol = function() {
  // Encode the protocol header.
  var json = {};
  json.seq= this.seq;
  if (this.request_seq) {
    json.request_seq = this.request_seq;
  }
  json.type = this.type;
  if (this.event) {
    json.event = this.event;
  }
  if (this.command) {
    json.command = this.command;
  }
  if (this.success) {
    json.success = this.success;
  } else {
    json.success = false;
  }
  if (this.body) {
    // Encode the body part.
    var bodyJson;
    var serializer = MakeMirrorSerializer(true, this.options_);
    if (this.body instanceof Mirror) {
      bodyJson = serializer.serializeValue(this.body);
    } else if (this.body instanceof Array) {
      bodyJson = [];
      for (var i = 0; i < this.body.length; i++) {
        if (this.body[i] instanceof Mirror) {
          bodyJson.push(serializer.serializeValue(this.body[i]));
        } else {
          bodyJson.push(ObjectToProtocolObject_(this.body[i], serializer));
        }
      }
    } else {
      bodyJson = ObjectToProtocolObject_(this.body, serializer);
    }
    json.body = bodyJson;
    json.refs = serializer.serializeReferencedObjects();
  }
  if (this.message) {
    json.message = this.message;
  }
  json.running = this.running;
  return JSON.stringify(json);
}


DebugCommandProcessor.prototype.createResponse = function(request) {
  return new ProtocolMessage(request);
};


DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request) {
  var request;  // Current request.
  var response;  // Generated response.
  try {
    try {
      // Convert the JSON string to an object.
      request = %CompileString('(' + json_request + ')')();

      // Create an initial response.
      response = this.createResponse(request);

      if (!request.type) {
        throw new Error('Type not specified');
      }

      if (request.type != 'request') {
        throw new Error("Illegal type '" + request.type + "' in request");
      }

      if (!request.command) {
        throw new Error('Command not specified');
      }

      if (request.arguments) {
        var args = request.arguments;
        // TODO(yurys): remove request.arguments.compactFormat check once
        // ChromeDevTools are switched to 'inlineRefs'
        if (args.inlineRefs || args.compactFormat) {
          response.setOption('inlineRefs', true);
        }
        if (!IS_UNDEFINED(args.maxStringLength)) {
          response.setOption('maxStringLength', args.maxStringLength);
        }
      }

      if (request.command == 'continue') {
        this.continueRequest_(request, response);
      } else if (request.command == 'break') {
        this.breakRequest_(request, response);
      } else if (request.command == 'setbreakpoint') {
        this.setBreakPointRequest_(request, response);
      } else if (request.command == 'changebreakpoint') {
        this.changeBreakPointRequest_(request, response);
      } else if (request.command == 'clearbreakpoint') {
        this.clearBreakPointRequest_(request, response);
      } else if (request.command == 'clearbreakpointgroup') {
        this.clearBreakPointGroupRequest_(request, response);
      } else if (request.command == 'disconnect') {
        this.disconnectRequest_(request, response);
      } else if (request.command == 'setexceptionbreak') {
        this.setExceptionBreakRequest_(request, response);
      } else if (request.command == 'listbreakpoints') {
        this.listBreakpointsRequest_(request, response);
      } else if (request.command == 'backtrace') {
        this.backtraceRequest_(request, response);
      } else if (request.command == 'frame') {
        this.frameRequest_(request, response);
      } else if (request.command == 'scopes') {
        this.scopesRequest_(request, response);
      } else if (request.command == 'scope') {
        this.scopeRequest_(request, response);
      } else if (request.command == 'evaluate') {
        this.evaluateRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'getobj') {
        this.getobjRequest_(request, response);
      } else if (request.command == 'lookup') {
        this.lookupRequest_(request, response);
      } else if (request.command == 'references') {
        this.referencesRequest_(request, response);
      } else if (request.command == 'source') {
        this.sourceRequest_(request, response);
      } else if (request.command == 'scripts') {
        this.scriptsRequest_(request, response);
      } else if (request.command == 'threads') {
        this.threadsRequest_(request, response);
      } else if (request.command == 'suspend') {
        this.suspendRequest_(request, response);
      } else if (request.command == 'version') {
        this.versionRequest_(request, response);
      } else if (request.command == 'profile') {
        this.profileRequest_(request, response);
      } else if (request.command == 'changelive') {
        this.changeLiveRequest_(request, response);
      } else if (request.command == 'flags') {
        this.debuggerFlagsRequest_(request, response);
      } else if (request.command == 'v8flags') {
        this.v8FlagsRequest_(request, response);

      // GC tools:
      } else if (request.command == 'gc') {
        this.gcRequest_(request, response);

      // LiveObjectList tools:
      } else if (lol_is_enabled && request.command == 'lol-capture') {
        this.lolCaptureRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-delete') {
        this.lolDeleteRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-diff') {
        this.lolDiffRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-getid') {
        this.lolGetIdRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-info') {
        this.lolInfoRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-reset') {
        this.lolResetRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-retainers') {
        this.lolRetainersRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-path') {
        this.lolPathRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-print') {
        this.lolPrintRequest_(request, response);
      } else if (lol_is_enabled && request.command == 'lol-stats') {
        this.lolStatsRequest_(request, response);

      } else {
        throw new Error('Unknown command "' + request.command + '" in request');
      }
    } catch (e) {
      // If there is no response object created one (without command).
      if (!response) {
        response = this.createResponse();
      }
      response.success = false;
      response.message = %ToString(e);
    }

    // Return the response as a JSON encoded string.
    try {
      if (!IS_UNDEFINED(response.running)) {
        // Response controls running state.
        this.running_ = response.running;
      }
      response.running = this.running_;
      return response.toJSONProtocol();
    } catch (e) {
      // Failed to generate response - return generic error.
      return '{"seq":' + response.seq + ',' +
              '"request_seq":' + request.seq + ',' +
              '"type":"response",' +
              '"success":false,' +
              '"message":"Internal error: ' + %ToString(e) + '"}';
    }
  } catch (e) {
    // Failed in one of the catch blocks above - most generic error.
    return '{"seq":0,"type":"response","success":false,"message":"Internal error"}';
  }
};


DebugCommandProcessor.prototype.continueRequest_ = function(request, response) {
  // Check for arguments for continue.
  if (request.arguments) {
    var count = 1;
    var action = Debug.StepAction.StepIn;

    // Pull out arguments.
    var stepaction = request.arguments.stepaction;
    var stepcount = request.arguments.stepcount;

    // Get the stepcount argument if any.
    if (stepcount) {
      count = %ToNumber(stepcount);
      if (count < 0) {
        throw new Error('Invalid stepcount argument "' + stepcount + '".');
      }
    }

    // Get the stepaction argument.
    if (stepaction) {
      if (stepaction == 'in') {
        action = Debug.StepAction.StepIn;
      } else if (stepaction == 'min') {
        action = Debug.StepAction.StepMin;
      } else if (stepaction == 'next') {
        action = Debug.StepAction.StepNext;
      } else if (stepaction == 'out') {
        action = Debug.StepAction.StepOut;
      } else {
        throw new Error('Invalid stepaction argument "' + stepaction + '".');
      }
    }

    // Setup the VM for stepping.
    this.exec_state_.prepareStep(action, count);
  }

  // VM should be running after executing this request.
  response.running = true;
};


DebugCommandProcessor.prototype.breakRequest_ = function(request, response) {
  // Ignore as break command does not do anything when broken.
};


DebugCommandProcessor.prototype.setBreakPointRequest_ =
    function(request, response) {
  // Check for legal request.
  if (!request.arguments) {
    response.failed('Missing arguments');
    return;
  }

  // Pull out arguments.
  var type = request.arguments.type;
  var target = request.arguments.target;
  var line = request.arguments.line;
  var column = request.arguments.column;
  var enabled = IS_UNDEFINED(request.arguments.enabled) ?
      true : request.arguments.enabled;
  var condition = request.arguments.condition;
  var ignoreCount = request.arguments.ignoreCount;
  var groupId = request.arguments.groupId;

  // Check for legal arguments.
  if (!type || IS_UNDEFINED(target)) {
    response.failed('Missing argument "type" or "target"');
    return;
  }
  if (type != 'function' && type != 'handle' &&
      type != 'script' && type != 'scriptId') {
    response.failed('Illegal type "' + type + '"');
    return;
  }

  // Either function or script break point.
  var break_point_number;
  if (type == 'function') {
    // Handle function break point.
    if (!IS_STRING(target)) {
      response.failed('Argument "target" is not a string value');
      return;
    }
    var f;
    try {
      // Find the function through a global evaluate.
      f = this.exec_state_.evaluateGlobal(target).value();
    } catch (e) {
      response.failed('Error: "' + %ToString(e) +
                      '" evaluating "' + target + '"');
      return;
    }
    if (!IS_FUNCTION(f)) {
      response.failed('"' + target + '" does not evaluate to a function');
      return;
    }

    // Set function break point.
    break_point_number = Debug.setBreakPoint(f, line, column, condition);
  } else if (type == 'handle') {
    // Find the object pointed by the specified handle.
    var handle = parseInt(target, 10);
    var mirror = LookupMirror(handle);
    if (!mirror) {
      return response.failed('Object #' + handle + '# not found');
    }
    if (!mirror.isFunction()) {
      return response.failed('Object #' + handle + '# is not a function');
    }

    // Set function break point.
    break_point_number = Debug.setBreakPoint(mirror.value(),
                                             line, column, condition);
  } else if (type == 'script') {
    // set script break point.
    break_point_number =
        Debug.setScriptBreakPointByName(target, line, column, condition,
                                        groupId);
  } else {  // type == 'scriptId.
    break_point_number =
        Debug.setScriptBreakPointById(target, line, column, condition, groupId);
  }

  // Set additional break point properties.
  var break_point = Debug.findBreakPoint(break_point_number);
  if (ignoreCount) {
    Debug.changeBreakPointIgnoreCount(break_point_number, ignoreCount);
  }
  if (!enabled) {
    Debug.disableBreakPoint(break_point_number);
  }

  // Add the break point number to the response.
  response.body = { type: type,
                    breakpoint: break_point_number }

  // Add break point information to the response.
  if (break_point instanceof ScriptBreakPoint) {
    if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
      response.body.type = 'scriptId';
      response.body.script_id = break_point.script_id();
    } else {
      response.body.type = 'scriptName';
      response.body.script_name = break_point.script_name();
    }
    response.body.line = break_point.line();
    response.body.column = break_point.column();
    response.body.actual_locations = break_point.actual_locations();
  } else {
    response.body.type = 'function';
    response.body.actual_locations = [break_point.actual_location];
  }
};


DebugCommandProcessor.prototype.changeBreakPointRequest_ = function(request, response) {
  // Check for legal request.
  if (!request.arguments) {
    response.failed('Missing arguments');
    return;
  }

  // Pull out arguments.
  var break_point = %ToNumber(request.arguments.breakpoint);
  var enabled = request.arguments.enabled;
  var condition = request.arguments.condition;
  var ignoreCount = request.arguments.ignoreCount;

  // Check for legal arguments.
  if (!break_point) {
    response.failed('Missing argument "breakpoint"');
    return;
  }

  // Change enabled state if supplied.
  if (!IS_UNDEFINED(enabled)) {
    if (enabled) {
      Debug.enableBreakPoint(break_point);
    } else {
      Debug.disableBreakPoint(break_point);
    }
  }

  // Change condition if supplied
  if (!IS_UNDEFINED(condition)) {
    Debug.changeBreakPointCondition(break_point, condition);
  }

  // Change ignore count if supplied
  if (!IS_UNDEFINED(ignoreCount)) {
    Debug.changeBreakPointIgnoreCount(break_point, ignoreCount);
  }
}


DebugCommandProcessor.prototype.clearBreakPointGroupRequest_ = function(request, response) {
  // Check for legal request.
  if (!request.arguments) {
    response.failed('Missing arguments');
    return;
  }

  // Pull out arguments.
  var group_id = request.arguments.groupId;

  // Check for legal arguments.
  if (!group_id) {
    response.failed('Missing argument "groupId"');
    return;
  }

  var cleared_break_points = [];
  var new_script_break_points = [];
  for (var i = 0; i < script_break_points.length; i++) {
    var next_break_point = script_break_points[i];
    if (next_break_point.groupId() == group_id) {
      cleared_break_points.push(next_break_point.number());
      next_break_point.clear();
    } else {
      new_script_break_points.push(next_break_point);
    }
  }
  script_break_points = new_script_break_points;

  // Add the cleared break point numbers to the response.
  response.body = { breakpoints: cleared_break_points };
}


DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(request, response) {
  // Check for legal request.
  if (!request.arguments) {
    response.failed('Missing arguments');
    return;
  }

  // Pull out arguments.
  var break_point = %ToNumber(request.arguments.breakpoint);

  // Check for legal arguments.
  if (!break_point) {
    response.failed('Missing argument "breakpoint"');
    return;
  }

  // Clear break point.
  Debug.clearBreakPoint(break_point);

  // Add the cleared break point number to the response.
  response.body = { breakpoint: break_point }
}


DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(request, response) {
  var array = [];
  for (var i = 0; i < script_break_points.length; i++) {
    var break_point = script_break_points[i];

    var description = {
      number: break_point.number(),
      line: break_point.line(),
      column: break_point.column(),
      groupId: break_point.groupId(),
      hit_count: break_point.hit_count(),
      active: break_point.active(),
      condition: break_point.condition(),
      ignoreCount: break_point.ignoreCount(),
      actual_locations: break_point.actual_locations()
    }

    if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
      description.type = 'scriptId';
      description.script_id = break_point.script_id();
    } else {
      description.type = 'scriptName';
      description.script_name = break_point.script_name();
    }
    array.push(description);
  }

  response.body = {
    breakpoints: array,
    breakOnExceptions: Debug.isBreakOnException(),
    breakOnUncaughtExceptions: Debug.isBreakOnUncaughtException()
  }
}


DebugCommandProcessor.prototype.disconnectRequest_ =
    function(request, response) {
  Debug.disableAllBreakPoints();
  this.continueRequest_(request, response);
}


DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
    function(request, response) {
  // Check for legal request.
  if (!request.arguments) {
    response.failed('Missing arguments');
    return;
  }

  // Pull out and check the 'type' argument:
  var type = request.arguments.type;
  if (!type) {
    response.failed('Missing argument "type"');
    return;
  }

  // Initialize the default value of enable:
  var enabled;
  if (type == 'all') {
    enabled = !Debug.isBreakOnException();
  } else if (type == 'uncaught') {
    enabled = !Debug.isBreakOnUncaughtException();
  }  

  // Pull out and check the 'enabled' argument if present:
  if (!IS_UNDEFINED(request.arguments.enabled)) {
    enabled = request.arguments.enabled;
    if ((enabled != true) && (enabled != false)) {
      response.failed('Illegal value for "enabled":"' + enabled + '"');
    }
  }

  // Now set the exception break state:
  if (type == 'all') {
    %ChangeBreakOnException(Debug.ExceptionBreak.Caught, enabled);
  } else if (type == 'uncaught') {
    %ChangeBreakOnException(Debug.ExceptionBreak.Uncaught, enabled);
  } else {
    response.failed('Unknown "type":"' + type + '"');
  }

  // Add the cleared break point number to the response.
  response.body = { 'type': type, 'enabled': enabled };
}


DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) {
  // Get the number of frames.
  var total_frames = this.exec_state_.frameCount();

  // Create simple response if there are no frames.
  if (total_frames == 0) {
    response.body = {
      totalFrames: total_frames
    }
    return;
  }

  // Default frame range to include in backtrace.
  var from_index = 0
  var to_index = kDefaultBacktraceLength;

  // Get the range from the arguments.
  if (request.arguments) {
    if (request.arguments.fromFrame) {
      from_index = request.arguments.fromFrame;
    }
    if (request.arguments.toFrame) {
      to_index = request.arguments.toFrame;
    }
    if (request.arguments.bottom) {
      var tmp_index = total_frames - from_index;
      from_index = total_frames - to_index
      to_index = tmp_index;
    }
    if (from_index < 0 || to_index < 0) {
      return response.failed('Invalid frame number');
    }
  }

  // Adjust the index.
  to_index = Math.min(total_frames, to_index);

  if (to_index <= from_index) {
    var error = 'Invalid frame range';
    return response.failed(error);
  }

  // Create the response body.
  var frames = [];
  for (var i = from_index; i < to_index; i++) {
    frames.push(this.exec_state_.frame(i));
  }
  response.body = {
    fromFrame: from_index,
    toFrame: to_index,
    totalFrames: total_frames,
    frames: frames
  }
};


DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
  // No frames no source.
  if (this.exec_state_.frameCount() == 0) {
    return response.failed('No frames');
  }

  // With no arguments just keep the selected frame.
  if (request.arguments) {
    var index = request.arguments.number;
    if (index < 0 || this.exec_state_.frameCount() <= index) {
      return response.failed('Invalid frame number');
    }

    this.exec_state_.setSelectedFrame(request.arguments.number);
  }
  response.body = this.exec_state_.frame();
};


DebugCommandProcessor.prototype.frameForScopeRequest_ = function(request) {
  // Get the frame for which the scope or scopes are requested. With no frameNumber
  // argument use the currently selected frame.
  if (request.arguments && !IS_UNDEFINED(request.arguments.frameNumber)) {
    frame_index = request.arguments.frameNumber;
    if (frame_index < 0 || this.exec_state_.frameCount() <= frame_index) {
      return response.failed('Invalid frame number');
    }
    return this.exec_state_.frame(frame_index);
  } else {
    return this.exec_state_.frame();
  }
}


DebugCommandProcessor.prototype.scopesRequest_ = function(request, response) {
  // No frames no scopes.
  if (this.exec_state_.frameCount() == 0) {
    return response.failed('No scopes');
  }

  // Get the frame for which the scopes are requested.
  var frame = this.frameForScopeRequest_(request);

  // Fill all scopes for this frame.
  var total_scopes = frame.scopeCount();
  var scopes = [];
  for (var i = 0; i < total_scopes; i++) {
    scopes.push(frame.scope(i));
  }
  response.body = {
    fromScope: 0,
    toScope: total_scopes,
    totalScopes: total_scopes,
    scopes: scopes
  }
};


DebugCommandProcessor.prototype.scopeRequest_ = function(request, response) {
  // No frames no scopes.
  if (this.exec_state_.frameCount() == 0) {
    return response.failed('No scopes');
  }

  // Get the frame for which the scope is requested.
  var frame = this.frameForScopeRequest_(request);

  // With no scope argument just return top scope.
  var scope_index = 0;
  if (request.arguments && !IS_UNDEFINED(request.arguments.number)) {
    scope_index = %ToNumber(request.arguments.number);
    if (scope_index < 0 || frame.scopeCount() <= scope_index) {
      return response.failed('Invalid scope number');
    }
  }

  response.body = frame.scope(scope_index);
};


DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
  if (!request.arguments) {
    return response.failed('Missing arguments');
  }

  // Pull out arguments.
  var expression = request.arguments.expression;
  var frame = request.arguments.frame;
  var global = request.arguments.global;
  var disable_break = request.arguments.disable_break;
  var additional_context = request.arguments.additional_context;

  // The expression argument could be an integer so we convert it to a
  // string.
  try {
    expression = String(expression);
  } catch(e) {
    return response.failed('Failed to convert expression argument to string');
  }

  // Check for legal arguments.
  if (!IS_UNDEFINED(frame) && global) {
    return response.failed('Arguments "frame" and "global" are exclusive');
  }
  
  var additional_context_object;
  if (additional_context) {
    additional_context_object = {};
    for (var i = 0; i < additional_context.length; i++) {
      var mapping = additional_context[i];
      if (!IS_STRING(mapping.name) || !IS_NUMBER(mapping.handle)) {
        return response.failed("Context element #" + i + 
            " must contain name:string and handle:number");
      } 
      var context_value_mirror = LookupMirror(mapping.handle);
      if (!context_value_mirror) {
        return response.failed("Context object '" + mapping.name +
            "' #" + mapping.handle + "# not found");
      }
      additional_context_object[mapping.name] = context_value_mirror.value(); 
    }
  }

  // Global evaluate.
  if (global) {
    // Evaluate in the global context.
    response.body = this.exec_state_.evaluateGlobal(
        expression, Boolean(disable_break), additional_context_object);
    return;
  }

  // Default value for disable_break is true.
  if (IS_UNDEFINED(disable_break)) {
    disable_break = true;
  }

  // No frames no evaluate in frame.
  if (this.exec_state_.frameCount() == 0) {
    return response.failed('No frames');
  }

  // Check whether a frame was specified.
  if (!IS_UNDEFINED(frame)) {
    var frame_number = %ToNumber(frame);
    if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
      return response.failed('Invalid frame "' + frame + '"');
    }
    // Evaluate in the specified frame.
    response.body = this.exec_state_.frame(frame_number).evaluate(
        expression, Boolean(disable_break), additional_context_object);
    return;
  } else {
    // Evaluate in the selected frame.
    response.body = this.exec_state_.frame().evaluate(
        expression, Boolean(disable_break), additional_context_object);
    return;
  }
};


DebugCommandProcessor.prototype.getobjRequest_ = function(request, response) {
  if (!request.arguments) {
    return response.failed('Missing arguments');
  }

  // Pull out arguments.
  var obj_id = request.arguments.obj_id;

  // Check for legal arguments.
  if (IS_UNDEFINED(obj_id)) {
    return response.failed('Argument "obj_id" missing');
  }

  // Dump the object.
  response.body = MakeMirror(%GetLOLObj(obj_id));
};


DebugCommandProcessor.prototype.lookupRequest_ = function(request, response) {
  if (!request.arguments) {
    return response.failed('Missing arguments');
  }

  // Pull out arguments.
  var handles = request.arguments.handles;

  // Check for legal arguments.
  if (IS_UNDEFINED(handles)) {
    return response.failed('Argument "handles" missing');
  }

  // Set 'includeSource' option for script lookup.
  if (!IS_UNDEFINED(request.arguments.includeSource)) {
    includeSource = %ToBoolean(request.arguments.includeSource);
    response.setOption('includeSource', includeSource);
  }

  // Lookup handles.
  var mirrors = {};
  for (var i = 0; i < handles.length; i++) {
    var handle = handles[i];
    var mirror = LookupMirror(handle);
    if (!mirror) {
      return response.failed('Object #' + handle + '# not found');
    }
    mirrors[handle] = mirror;
  }
  response.body = mirrors;
};


DebugCommandProcessor.prototype.referencesRequest_ =
    function(request, response) {
  if (!request.arguments) {
    return response.failed('Missing arguments');
  }

  // Pull out arguments.
  var type = request.arguments.type;
  var handle = request.arguments.handle;

  // Check for legal arguments.
  if (IS_UNDEFINED(type)) {
    return response.failed('Argument "type" missing');
  }
  if (IS_UNDEFINED(handle)) {
    return response.failed('Argument "handle" missing');
  }
  if (type != 'referencedBy' && type != 'constructedBy') {
    return response.failed('Invalid type "' + type + '"');
  }

  // Lookup handle and return objects with references the object.
  var mirror = LookupMirror(handle);
  if (mirror) {
    if (type == 'referencedBy') {
      response.body = mirror.referencedBy();
    } else {
      response.body = mirror.constructedBy();
    }
  } else {
    return response.failed('Object #' + handle + '# not found');
  }
};


DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
  // No frames no source.
  if (this.exec_state_.frameCount() == 0) {
    return response.failed('No source');
  }

  var from_line;
  var to_line;
  var frame = this.exec_state_.frame();
  if (request.arguments) {
    // Pull out arguments.
    from_line = request.arguments.fromLine;
    to_line = request.arguments.toLine;

    if (!IS_UNDEFINED(request.arguments.frame)) {
      var frame_number = %ToNumber(request.arguments.frame);
      if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
        return response.failed('Invalid frame "' + frame + '"');
      }
      frame = this.exec_state_.frame(frame_number);
    }
  }

  // Get the script selected.
  var script = frame.func().script();
  if (!script) {
    return response.failed('No source');
  }

  // Get the source slice and fill it into the response.
  var slice = script.sourceSlice(from_line, to_line);
  if (!slice) {
    return response.failed('Invalid line interval');
  }
  response.body = {};
  response.body.source = slice.sourceText();
  response.body.fromLine = slice.from_line;
  response.body.toLine = slice.to_line;
  response.body.fromPosition = slice.from_position;
  response.body.toPosition = slice.to_position;
  response.body.totalLines = script.lineCount();
};


DebugCommandProcessor.prototype.scriptsRequest_ = function(request, response) {
  var types = ScriptTypeFlag(Debug.ScriptType.Normal);
  var includeSource = false;
  var idsToInclude = null;
  if (request.arguments) {
    // Pull out arguments.
    if (!IS_UNDEFINED(request.arguments.types)) {
      types = %ToNumber(request.arguments.types);
      if (isNaN(types) || types < 0) {
        return response.failed('Invalid types "' + request.arguments.types + '"');
      }
    }

    if (!IS_UNDEFINED(request.arguments.includeSource)) {
      includeSource = %ToBoolean(request.arguments.includeSource);
      response.setOption('includeSource', includeSource);
    }

    if (IS_ARRAY(request.arguments.ids)) {
      idsToInclude = {};
      var ids = request.arguments.ids;
      for (var i = 0; i < ids.length; i++) {
        idsToInclude[ids[i]] = true;
      }
    }

    var filterStr = null;
    var filterNum = null;
    if (!IS_UNDEFINED(request.arguments.filter)) {
      var num = %ToNumber(request.arguments.filter);
      if (!isNaN(num)) {
        filterNum = num;
      }
      filterStr = request.arguments.filter;
    }
  }

  // Collect all scripts in the heap.
  var scripts = %DebugGetLoadedScripts();

  response.body = [];

  for (var i = 0; i < scripts.length; i++) {
    if (idsToInclude && !idsToInclude[scripts[i].id]) {
      continue;
    }
    if (filterStr || filterNum) {
      var script = scripts[i];
      var found = false;
      if (filterNum && !found) {
        if (script.id && script.id === filterNum) {
          found = true;
        }
      }
      if (filterStr && !found) {
        if (script.name && script.name.indexOf(filterStr) >= 0) {
          found = true;
        }
      }
      if (!found) continue;
    }
    if (types & ScriptTypeFlag(scripts[i].type)) {
      response.body.push(MakeMirror(scripts[i]));
    }
  }
};


DebugCommandProcessor.prototype.threadsRequest_ = function(request, response) {
  // Get the number of threads.
  var total_threads = this.exec_state_.threadCount();

  // Get information for all threads.
  var threads = [];
  for (var i = 0; i < total_threads; i++) {
    var details = %GetThreadDetails(this.exec_state_.break_id, i);
    var thread_info = { current: details[0],
                        id: details[1]
                      }
    threads.push(thread_info);
  }

  // Create the response body.
  response.body = {
    totalThreads: total_threads,
    threads: threads
  }
};


DebugCommandProcessor.prototype.suspendRequest_ = function(request, response) {
  response.running = false;
};


DebugCommandProcessor.prototype.versionRequest_ = function(request, response) {
  response.body = {
    V8Version: %GetV8Version()
  }
};


DebugCommandProcessor.prototype.profileRequest_ = function(request, response) {
  if (!request.arguments) {
    return response.failed('Missing arguments');
  }
  var modules = parseInt(request.arguments.modules);
  if (isNaN(modules)) {
    return response.failed('Modules is not an integer');
  }
  var tag = parseInt(request.arguments.tag);
  if (isNaN(tag)) {
    tag = 0;
  }
  if (request.arguments.command == 'resume') {
    %ProfilerResume(modules, tag);
  } else if (request.arguments.command == 'pause') {
    %ProfilerPause(modules, tag);
  } else {
    return response.failed('Unknown command');
  }
  response.body = {};
};


DebugCommandProcessor.prototype.changeLiveRequest_ = function(request, response) {
  if (!Debug.LiveEdit) {
    return response.failed('LiveEdit feature is not supported');
  }
  if (!request.arguments) {
    return response.failed('Missing arguments');
  }
  var script_id = request.arguments.script_id;
  var preview_only = !!request.arguments.preview_only;

  var scripts = %DebugGetLoadedScripts();

  var the_script = null;
  for (var i = 0; i < scripts.length; i++) {
    if (scripts[i].id == script_id) {
      the_script = scripts[i];
    }
  }
  if (!the_script) {
    response.failed('Script not found');
    return;
  }

  var change_log = new Array();

  if (!IS_STRING(request.arguments.new_source)) {
    throw "new_source argument expected";
  }

  var new_source = request.arguments.new_source;

  var result_description = Debug.LiveEdit.SetScriptSource(the_script,
      new_source, preview_only, change_log);
  response.body = {change_log: change_log, result: result_description};

  if (!preview_only && !this.running_ && result_description.stack_modified) {
    response.body.stepin_recommended = true;
  }
};


DebugCommandProcessor.prototype.debuggerFlagsRequest_ = function(request,
                                                                 response) {
  // Check for legal request.
  if (!request.arguments) {
    response.failed('Missing arguments');
    return;
  }

  // Pull out arguments.
  var flags = request.arguments.flags;

  response.body = { flags: [] };
  if (!IS_UNDEFINED(flags)) {
    for (var i = 0; i < flags.length; i++) {
      var name = flags[i].name;
      var debugger_flag = debugger_flags[name];
      if (!debugger_flag) {
        continue;
      }
      if ('value' in flags[i]) {
        debugger_flag.setValue(flags[i].value);
      }
      response.body.flags.push({ name: name, value: debugger_flag.getValue() });
    }
  } else {
    for (var name in debugger_flags) {
      var value = debugger_flags[name].getValue();
      response.body.flags.push({ name: name, value: value });
    }
  }
}


DebugCommandProcessor.prototype.v8FlagsRequest_ = function(request, response) {
  var flags = request.arguments.flags;
  if (!flags) flags = '';
  %SetFlags(flags);
};


DebugCommandProcessor.prototype.gcRequest_ = function(request, response) {
  var type = request.arguments.type;
  if (!type) type = 'all';

  var before = %GetHeapUsage();
  %CollectGarbage(type);
  var after = %GetHeapUsage();

  response.body = { "before": before, "after": after };
};


DebugCommandProcessor.prototype.lolCaptureRequest_ =
    function(request, response) {
  response.body = %CaptureLOL();
};


DebugCommandProcessor.prototype.lolDeleteRequest_ =
    function(request, response) {
  var id = request.arguments.id;
  var result = %DeleteLOL(id);
  if (result) {
    response.body = { id: id };
  } else {
    response.failed('Failed to delete: live object list ' + id + ' not found.');
  }
};


DebugCommandProcessor.prototype.lolDiffRequest_ = function(request, response) {
  var id1 = request.arguments.id1;
  var id2 = request.arguments.id2;
  var verbose = request.arguments.verbose;
  var filter = request.arguments.filter;
  if (verbose === true) {
    var start = request.arguments.start;
    var count = request.arguments.count;
    response.body = %DumpLOL(id1, id2, start, count, filter);
  } else {
    response.body = %SummarizeLOL(id1, id2, filter);
  }
};


DebugCommandProcessor.prototype.lolGetIdRequest_ = function(request, response) {
  var address = request.arguments.address;
  response.body = {};
  response.body.id = %GetLOLObjId(address);
};


DebugCommandProcessor.prototype.lolInfoRequest_ = function(request, response) {
  var start = request.arguments.start;
  var count = request.arguments.count;
  response.body = %InfoLOL(start, count);
};


DebugCommandProcessor.prototype.lolResetRequest_ = function(request, response) {
  %ResetLOL();
};


DebugCommandProcessor.prototype.lolRetainersRequest_ =
    function(request, response) {
  var id = request.arguments.id;
  var verbose = request.arguments.verbose;
  var start = request.arguments.start;
  var count = request.arguments.count;
  var filter = request.arguments.filter;

  response.body = %GetLOLObjRetainers(id, Mirror.prototype, verbose,
                                      start, count, filter);
};


DebugCommandProcessor.prototype.lolPathRequest_ = function(request, response) {
  var id1 = request.arguments.id1;
  var id2 = request.arguments.id2;
  response.body = {};
  response.body.path = %GetLOLPath(id1, id2, Mirror.prototype);
};


DebugCommandProcessor.prototype.lolPrintRequest_ = function(request, response) {
  var id = request.arguments.id;
  response.body = {};
  response.body.dump = %PrintLOLObj(id);
};


// Check whether the previously processed command caused the VM to become
// running.
DebugCommandProcessor.prototype.isRunning = function() {
  return this.running_;
}


DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
  return %SystemBreak();
};


function NumberToHex8Str(n) {
  var r = "";
  for (var i = 0; i < 8; ++i) {
    var c = hexCharArray[n & 0x0F];  // hexCharArray is defined in uri.js
    r = c + r;
    n = n >>> 4;
  }
  return r;
};


/**
 * Convert an Object to its debugger protocol representation. The representation
 * may be serilized to a JSON object using JSON.stringify().
 * This implementation simply runs through all string property names, converts
 * each property value to a protocol value and adds the property to the result
 * object. For type "object" the function will be called recursively. Note that
 * circular structures will cause infinite recursion.
 * @param {Object} object The object to format as protocol object.
 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
 *     mirror objects are encountered.
 * @return {Object} Protocol object value.
 */
function ObjectToProtocolObject_(object, mirror_serializer) {
  var content = {};
  for (var key in object) {
    // Only consider string keys.
    if (typeof key == 'string') {
      // Format the value based on its type.
      var property_value_json = ValueToProtocolValue_(object[key],
                                                      mirror_serializer);
      // Add the property if relevant.
      if (!IS_UNDEFINED(property_value_json)) {
        content[key] = property_value_json;
      }
    }
  }

  return content;
}


/**
 * Convert an array to its debugger protocol representation. It will convert
 * each array element to a protocol value.
 * @param {Array} array The array to format as protocol array.
 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
 *     mirror objects are encountered.
 * @return {Array} Protocol array value.
 */
function ArrayToProtocolArray_(array, mirror_serializer) {
  var json = [];
  for (var i = 0; i < array.length; i++) {
    json.push(ValueToProtocolValue_(array[i], mirror_serializer));
  }
  return json;
}


/**
 * Convert a value to its debugger protocol representation.
 * @param {*} value The value to format as protocol value.
 * @param {MirrorSerializer} mirror_serializer The serializer to use if any
 *     mirror objects are encountered.
 * @return {*} Protocol value.
 */
function ValueToProtocolValue_(value, mirror_serializer) {
  // Format the value based on its type.
  var json;
  switch (typeof value) {
    case 'object':
      if (value instanceof Mirror) {
        json = mirror_serializer.serializeValue(value);
      } else if (IS_ARRAY(value)){
        json = ArrayToProtocolArray_(value, mirror_serializer);
      } else {
        json = ObjectToProtocolObject_(value, mirror_serializer);
      }
      break;

    case 'boolean':
    case 'string':
    case 'number':
      json = value;
      break

    default:
      json = null;
  }
  return json;
}
