/** * V8Debugger * * Copyright (c) 2010 Ajax.org B.V. * * The MIT License (MIT) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ define(function(require, exports, module) { "use strict"; var oop = require("ace/lib/oop"); var EventEmitter = require("ace/lib/event_emitter").EventEmitter; var V8Message = require("./V8Message"); var V8Debugger = module.exports = function(tabId, v8service) { this.tabId = tabId; this.$running = true; this.$service = v8service; var pending = this.$pending = {}; var self = this; this.$service.addEventListener("debugger_command_" + tabId, function(e) { var response = V8Message.fromObject(e.data); //console.log("Incoming debugger message for event " + response.event + " (" + response.request_seq + "): ", response); var requestSeq = response.request_seq; if (pending[requestSeq]) { pending[requestSeq](response.body, response.refs || null, !response.success && { message: response.message } || null); delete pending[requestSeq]; } else if (response.event) { self._signal(response.event, { data: response.body }); } self.$updateRunning(response); }); }; (function() { oop.implement(this, EventEmitter); this.$seq = 0; this.$updateRunning = function(response) { // workaround for V8 bug // http://code.google.com/p/v8/issues/detail?id=724 if (response.event == "scriptCollected") return; var running = true; if (response.type == "response") { running = response.running; } else if (response.type == "event") { if (response.event == "break" || response.event == "exception") running = false; } if (running !== this.$running) { this.$running = running; this._signal("changeRunning", { data: running }); } }; this.isRunning = function() { return this.$running; }; this.continueScript = function(stepaction, stepcount, callback) { var msg = new V8Message("request"); msg.command = "continue"; if (stepaction) { msg.arguments = { stepcount: stepcount || 1, stepaction: stepaction }; } this.$send(msg, callback); }; this.lookup = function(handles, includeSource, callback) { var msg = new V8Message("request"); msg.command = "lookup"; msg.arguments = { inlineRefs: false, handles: handles }; if (includeSource) msg.arguments.includesSource = includeSource; this.$send(msg, callback); }; this.backtrace = function(fromFrame, toFrame, bottom, inlineRefs, callback) { var msg = new V8Message("request"); msg.command = "backtrace"; msg.arguments = { inlineRefs: !!inlineRefs }; if (typeof fromFrame == "number") msg.arguments.fromFrame = fromFrame; if (typeof toFrame == "number") msg.arguments.toFrame = toFrame; if (typeof(bottom) === "boolean") msg.arguments.bottom = bottom; this.$send(msg, callback); }; this.scope = function(number, frameNumber, inlineRefs, callback) { var msg = new V8Message("request"); msg.command = "scope"; msg.arguments = { number: number, inlineRefs: !!inlineRefs }; if (typeof frameNumber == "number") msg.arguments.frameNumber = frameNumber; this.$send(msg, callback); }; this.version = function(callback) { var msg = new V8Message("request"); msg.command = "version"; this.$send(msg, callback); }; this.scripts = function(types, ids, includeSource, callback) { var msg = new V8Message("request"); msg.command = "scripts"; msg.arguments = { types: types || V8Debugger.NORMAL_SCRIPTS, includeSource: !!includeSource }; if (ids) msg.arguments.ids = ids; this.$send(msg, function(scripts, refs, err) { callback(scripts || [], refs, err); }); }; this.evaluate = function(expression, frame, global, disableBreak, callback) { var msg = new V8Message("request"); msg.command = "evaluate"; msg.arguments = { expression: expression }; if (typeof frame == "number") msg.arguments.frame = frame; if (global) msg.arguments.global = global; if (disableBreak) msg.arguments.disable_break = disableBreak; this.$send(msg, callback); }; this.simpleevaluate = function(expression, frame, global, additionalContext, callback) { var msg = new V8Message("request"); msg.command = "evaluate"; msg.arguments = { expression: expression }; if (typeof frame == "number") msg.arguments.frame = frame; if (global) msg.arguments.global = global; msg.arguments.disable_break = true; if (additionalContext) msg.arguments.additional_context = additionalContext; this.$send(msg, callback); }; this.setexceptionbreak = function(type, enabled, callback) { var msg = new V8Message("request"); msg.command = "setexceptionbreak"; msg.arguments = { type: type, enabled: enabled }; this.$send(msg, callback); }; this.setvariablevalue = function(name, value, scopeNumber, frameIndex, callback) { var msg = new V8Message("request"); msg.command = "setVariableValue"; // var value; // if (type == "undefined") // value = { type: type }; // else if (type == "null") // value = { value: null }; // else if (type.charAt(0) == "\"") // value = { value: JSON.parse(type) }; // else // value = { value: type }; msg.arguments = { name: name, scope: { number: scopeNumber, frameNumber: frameIndex }, newValue: value }; this.$send(msg, callback); }; this.setbreakpoint = function(type, target, line, column, enabled, condition, ignoreCount, callback) { var msg = new V8Message("request"); msg.command = "setbreakpoint"; msg.arguments = { type: type, target: target, line: line, enabled: enabled !== true ? false : true }; if (column) msg.arguments.column = column; if (condition) msg.arguments.condition = condition; if (ignoreCount) msg.arguments.ignoreCount = ignoreCount; this.$send(msg, callback); }; this.changebreakpoint = function(breakpoint, enabled, condition, ignoreCount, callback) { var msg = new V8Message("request"); msg.command = "changebreakpoint"; msg.arguments = { enabled: enabled !== true ? false : true, breakpoint: breakpoint }; if (condition) msg.arguments.condition = condition; if (ignoreCount) msg.arguments.ignoreCount = ignoreCount; this.$send(msg, callback); }; this.clearbreakpoint = function(breakpoint, callback) { var msg = new V8Message("request"); msg.command = "clearbreakpoint"; msg.arguments = { breakpoint: breakpoint }; this.$send(msg, callback); }; this.listbreakpoints = function(callback) { var msg = new V8Message("request"); msg.command = "listbreakpoints"; this.$send(msg, callback); }; this.suspend = function(callback) { var msg = new V8Message("request"); msg.command = "suspend"; this.$send(msg, callback); }; this.changelive = function(scriptId, newSource, previewOnly, callback) { var msg = new V8Message("request"); msg.command = "changelive"; msg.arguments = { script_id: scriptId, new_source: newSource, preview_only: !!previewOnly }; this.$send(msg, callback); }; this.restartframe = function(frameId, callback) { var msg = new V8Message("request"); msg.command = "restartframe"; msg.arguments = { frame: frameId }; this.$send(msg, callback); }; this.$send = function(msg, callback) { if (callback) this.$pending[msg.seq] = callback; this.$service.debuggerCommand(this.tabId, msg); }; }).call(V8Debugger.prototype); V8Debugger.NATIVE_SCRIPTS = 1; V8Debugger.EXTENSION_SCRIPTS = 2; V8Debugger.NORMAL_SCRIPTS = 4; });