mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 23:38:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
6
devtools/server/tests/unit/.eslintrc.js
Normal file
6
devtools/server/tests/unit/.eslintrc.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
// Extend from the common devtools xpcshell eslintrc config.
|
||||
"extends": "../../../.eslintrc.xpcshell.js"
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Test Addons Actor Upgrade",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "test-addons-actor@mozilla.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Test Addons Actor",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "test-addons-actor@mozilla.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Test Addons Actor 2",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "test-addons-actor2@mozilla.org"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
var add = require("./lib/add");
|
||||
var subtract = require("./lib/subtract");
|
||||
var upperCase = require("upper-case");
|
||||
|
||||
(function () {
|
||||
return add(1, 2);
|
||||
});
|
||||
|
||||
},{"./lib/add":2,"./lib/subtract":3,"upper-case":4}],2:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
module.exports = function (a, b) {
|
||||
return a + b;
|
||||
};
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
"use strict";
|
||||
|
||||
module.exports = function (a, b) {
|
||||
return a - b;
|
||||
};
|
||||
|
||||
},{}],4:[function(require,module,exports){
|
||||
/**
|
||||
* Special language-specific overrides.
|
||||
*
|
||||
* Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
var LANGUAGES = {
|
||||
tr: {
|
||||
regexp: /[\u0069]/g,
|
||||
map: {
|
||||
'\u0069': '\u0130'
|
||||
}
|
||||
},
|
||||
az: {
|
||||
regexp: /[\u0069]/g,
|
||||
map: {
|
||||
'\u0069': '\u0130'
|
||||
}
|
||||
},
|
||||
lt: {
|
||||
regexp: /[\u0069\u006A\u012F]\u0307|\u0069\u0307[\u0300\u0301\u0303]/g,
|
||||
map: {
|
||||
'\u0069\u0307': '\u0049',
|
||||
'\u006A\u0307': '\u004A',
|
||||
'\u012F\u0307': '\u012E',
|
||||
'\u0069\u0307\u0300': '\u00CC',
|
||||
'\u0069\u0307\u0301': '\u00CD',
|
||||
'\u0069\u0307\u0303': '\u0128'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upper case a string.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {String}
|
||||
*/
|
||||
module.exports = function (str, locale) {
|
||||
var lang = LANGUAGES[locale]
|
||||
|
||||
str = str == null ? '' : String(str)
|
||||
|
||||
if (lang) {
|
||||
str = str.replace(lang.regexp, function (m) { return lang.map[m] })
|
||||
}
|
||||
|
||||
return str.toUpperCase()
|
||||
}
|
||||
|
||||
},{}]},{},[1])
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi9Vc2Vycy9qc2FudGVsbC9EZXYvc291cmNlLW1hcC10ZXN0L2luZGV4LmpzIiwiL1VzZXJzL2pzYW50ZWxsL0Rldi9zb3VyY2UtbWFwLXRlc3QvbGliL2FkZC5qcyIsIi9Vc2Vycy9qc2FudGVsbC9EZXYvc291cmNlLW1hcC10ZXN0L2xpYi9zdWJ0cmFjdC5qcyIsIm5vZGVfbW9kdWxlcy91cHBlci1jYXNlL3VwcGVyLWNhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztBQ0FBLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUMvQixJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztBQUN6QyxJQUFJLFNBQVMsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7O0FBRXRDLENBQUM7U0FBTSxHQUFHLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQztFQUFBLENBQUU7Ozs7O0FDSmpCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFO0FBQy9CLFNBQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztDQUNkLENBQUM7Ozs7O0FDRkYsTUFBTSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQUU7QUFDL0IsU0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0NBQ2QsQ0FBQzs7O0FDRkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsInZhciBhZGQgPSByZXF1aXJlKFwiLi9saWIvYWRkXCIpO1xudmFyIHN1YnRyYWN0ID0gcmVxdWlyZShcIi4vbGliL3N1YnRyYWN0XCIpO1xudmFyIHVwcGVyQ2FzZSA9IHJlcXVpcmUoXCJ1cHBlci1jYXNlXCIpO1xuXG4oKCkgPT4gYWRkKDEsMikpO1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYSwgYikge1xuICByZXR1cm4gYSArIGI7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYSwgYikge1xuICByZXR1cm4gYSAtIGI7XG59O1xuIiwiLyoqXG4gKiBTcGVjaWFsIGxhbmd1YWdlLXNwZWNpZmljIG92ZXJyaWRlcy5cbiAqXG4gKiBTb3VyY2U6IGZ0cDovL2Z0cC51bmljb2RlLm9yZy9QdWJsaWMvVUNEL2xhdGVzdC91Y2QvU3BlY2lhbENhc2luZy50eHRcbiAqXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG52YXIgTEFOR1VBR0VTID0ge1xuICB0cjoge1xuICAgIHJlZ2V4cDogL1tcXHUwMDY5XS9nLFxuICAgIG1hcDoge1xuICAgICAgJ1xcdTAwNjknOiAnXFx1MDEzMCdcbiAgICB9XG4gIH0sXG4gIGF6OiB7XG4gICAgcmVnZXhwOiAvW1xcdTAwNjldL2csXG4gICAgbWFwOiB7XG4gICAgICAnXFx1MDA2OSc6ICdcXHUwMTMwJ1xuICAgIH1cbiAgfSxcbiAgbHQ6IHtcbiAgICByZWdleHA6IC9bXFx1MDA2OVxcdTAwNkFcXHUwMTJGXVxcdTAzMDd8XFx1MDA2OVxcdTAzMDdbXFx1MDMwMFxcdTAzMDFcXHUwMzAzXS9nLFxuICAgIG1hcDoge1xuICAgICAgJ1xcdTAwNjlcXHUwMzA3JzogJ1xcdTAwNDknLFxuICAgICAgJ1xcdTAwNkFcXHUwMzA3JzogJ1xcdTAwNEEnLFxuICAgICAgJ1xcdTAxMkZcXHUwMzA3JzogJ1xcdTAxMkUnLFxuICAgICAgJ1xcdTAwNjlcXHUwMzA3XFx1MDMwMCc6ICdcXHUwMENDJyxcbiAgICAgICdcXHUwMDY5XFx1MDMwN1xcdTAzMDEnOiAnXFx1MDBDRCcsXG4gICAgICAnXFx1MDA2OVxcdTAzMDdcXHUwMzAzJzogJ1xcdTAxMjgnXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVXBwZXIgY2FzZSBhIHN0cmluZy5cbiAqXG4gKiBAcGFyYW0gIHtTdHJpbmd9IHN0clxuICogQHJldHVybiB7U3RyaW5nfVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzdHIsIGxvY2FsZSkge1xuICB2YXIgbGFuZyA9IExBTkdVQUdFU1tsb2NhbGVdXG5cbiAgc3RyID0gc3RyID09IG51bGwgPyAnJyA6IFN0cmluZyhzdHIpXG5cbiAgaWYgKGxhbmcpIHtcbiAgICBzdHIgPSBzdHIucmVwbGFjZShsYW5nLnJlZ2V4cCwgZnVuY3Rpb24gKG0pIHsgcmV0dXJuIGxhbmcubWFwW21dIH0pXG4gIH1cblxuICByZXR1cm4gc3RyLnRvVXBwZXJDYXNlKClcbn1cbiJdfQ==
|
||||
862
devtools/server/tests/unit/head_dbg.js
Normal file
862
devtools/server/tests/unit/head_dbg.js
Normal file
|
|
@ -0,0 +1,862 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
var CC = Components.Constructor;
|
||||
|
||||
// Populate AppInfo before anything (like the shared loader) accesses
|
||||
// System.appinfo, which is a lazy getter.
|
||||
const _appInfo = {};
|
||||
Cu.import("resource://testing-common/AppInfo.jsm", _appInfo);
|
||||
_appInfo.updateAppInfo({
|
||||
ID: "devtools@tests.mozilla.org",
|
||||
name: "devtools-tests",
|
||||
version: "1",
|
||||
platformVersion: "42",
|
||||
crashReporter: true,
|
||||
});
|
||||
|
||||
const { require, loader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { worker } = Cu.import("resource://devtools/shared/worker/loader.js", {});
|
||||
const promise = require("promise");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { console } = require("resource://gre/modules/Console.jsm");
|
||||
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
const Services = require("Services");
|
||||
// Always log packets when running tests. runxpcshelltests.py will throw
|
||||
// the output away anyway, unless you give it the --verbose flag.
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
// Enable remote debugging for the relevant tests.
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
|
||||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
const { DebuggerServer: WorkerDebuggerServer } = worker.require("devtools/server/main");
|
||||
const { DebuggerClient, ObjectClient } = require("devtools/shared/client/main");
|
||||
const { MemoryFront } = require("devtools/shared/fronts/memory");
|
||||
|
||||
const { addDebuggerToGlobal } = Cu.import("resource://gre/modules/jsdebugger.jsm", {});
|
||||
|
||||
const systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
|
||||
|
||||
var loadSubScript = Cc[
|
||||
"@mozilla.org/moz/jssubscript-loader;1"
|
||||
].getService(Ci.mozIJSSubScriptLoader).loadSubScript;
|
||||
|
||||
/**
|
||||
* Initializes any test that needs to work with add-ons.
|
||||
*/
|
||||
function startupAddonsManager() {
|
||||
// Create a directory for extensions.
|
||||
const profileDir = do_get_profile().clone();
|
||||
profileDir.append("extensions");
|
||||
|
||||
const internalManager = Cc["@mozilla.org/addons/integration;1"]
|
||||
.getService(Ci.nsIObserver)
|
||||
.QueryInterface(Ci.nsITimerCallback);
|
||||
|
||||
internalManager.observe(null, "addons-startup", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `run_test` function that runs the given generator in a task after
|
||||
* having attached to a memory actor. When done, the memory actor is detached
|
||||
* from, the client is finished, and the test is finished.
|
||||
*
|
||||
* @param {GeneratorFunction} testGeneratorFunction
|
||||
* The generator function is passed (DebuggerClient, MemoryFront)
|
||||
* arguments.
|
||||
*
|
||||
* @returns `run_test` function
|
||||
*/
|
||||
function makeMemoryActorTest(testGeneratorFunction) {
|
||||
const TEST_GLOBAL_NAME = "test_MemoryActor";
|
||||
|
||||
return function run_test() {
|
||||
do_test_pending();
|
||||
startTestDebuggerServer(TEST_GLOBAL_NAME).then(client => {
|
||||
DebuggerServer.registerModule("devtools/server/actors/heap-snapshot-file", {
|
||||
prefix: "heapSnapshotFile",
|
||||
constructor: "HeapSnapshotFileActor",
|
||||
type: { global: true }
|
||||
});
|
||||
|
||||
getTestTab(client, TEST_GLOBAL_NAME, function (tabForm, rootForm) {
|
||||
if (!tabForm || !rootForm) {
|
||||
ok(false, "Could not attach to test tab: " + TEST_GLOBAL_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
Task.spawn(function* () {
|
||||
try {
|
||||
const memoryFront = new MemoryFront(client, tabForm, rootForm);
|
||||
yield memoryFront.attach();
|
||||
yield* testGeneratorFunction(client, memoryFront);
|
||||
yield memoryFront.detach();
|
||||
} catch (err) {
|
||||
DevToolsUtils.reportException("makeMemoryActorTest", err);
|
||||
ok(false, "Got an error: " + err);
|
||||
}
|
||||
|
||||
finishClient(client);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Save as makeMemoryActorTest but attaches the MemoryFront to the MemoryActor
|
||||
* scoped to the full runtime rather than to a tab.
|
||||
*/
|
||||
function makeFullRuntimeMemoryActorTest(testGeneratorFunction) {
|
||||
return function run_test() {
|
||||
do_test_pending();
|
||||
startTestDebuggerServer("test_MemoryActor").then(client => {
|
||||
DebuggerServer.registerModule("devtools/server/actors/heap-snapshot-file", {
|
||||
prefix: "heapSnapshotFile",
|
||||
constructor: "HeapSnapshotFileActor",
|
||||
type: { global: true }
|
||||
});
|
||||
|
||||
getChromeActors(client).then(function (form) {
|
||||
if (!form) {
|
||||
ok(false, "Could not attach to chrome actors");
|
||||
return;
|
||||
}
|
||||
|
||||
Task.spawn(function* () {
|
||||
try {
|
||||
const rootForm = yield listTabs(client);
|
||||
const memoryFront = new MemoryFront(client, form, rootForm);
|
||||
yield memoryFront.attach();
|
||||
yield* testGeneratorFunction(client, memoryFront);
|
||||
yield memoryFront.detach();
|
||||
} catch (err) {
|
||||
DevToolsUtils.reportException("makeMemoryActorTest", err);
|
||||
ok(false, "Got an error: " + err);
|
||||
}
|
||||
|
||||
finishClient(client);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function createTestGlobal(name) {
|
||||
let sandbox = Cu.Sandbox(
|
||||
Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal)
|
||||
);
|
||||
sandbox.__name = name;
|
||||
return sandbox;
|
||||
}
|
||||
|
||||
function connect(client) {
|
||||
dump("Connecting client.\n");
|
||||
return client.connect();
|
||||
}
|
||||
|
||||
function close(client) {
|
||||
dump("Closing client.\n");
|
||||
return client.close();
|
||||
}
|
||||
|
||||
function listTabs(client) {
|
||||
dump("Listing tabs.\n");
|
||||
return client.listTabs();
|
||||
}
|
||||
|
||||
function findTab(tabs, title) {
|
||||
dump("Finding tab with title '" + title + "'.\n");
|
||||
for (let tab of tabs) {
|
||||
if (tab.title === title) {
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function attachTab(client, tab) {
|
||||
dump("Attaching to tab with title '" + tab.title + "'.\n");
|
||||
return client.attachTab(tab.actor);
|
||||
}
|
||||
|
||||
function waitForNewSource(threadClient, url) {
|
||||
dump("Waiting for new source with url '" + url + "'.\n");
|
||||
return waitForEvent(threadClient, "newSource", function (packet) {
|
||||
return packet.source.url === url;
|
||||
});
|
||||
}
|
||||
|
||||
function attachThread(tabClient, options = {}) {
|
||||
dump("Attaching to thread.\n");
|
||||
return tabClient.attachThread(options);
|
||||
}
|
||||
|
||||
function resume(threadClient) {
|
||||
dump("Resuming thread.\n");
|
||||
return threadClient.resume();
|
||||
}
|
||||
|
||||
function getSources(threadClient) {
|
||||
dump("Getting sources.\n");
|
||||
return threadClient.getSources();
|
||||
}
|
||||
|
||||
function findSource(sources, url) {
|
||||
dump("Finding source with url '" + url + "'.\n");
|
||||
for (let source of sources) {
|
||||
if (source.url === url) {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function waitForPause(threadClient) {
|
||||
dump("Waiting for pause.\n");
|
||||
return waitForEvent(threadClient, "paused");
|
||||
}
|
||||
|
||||
function setBreakpoint(sourceClient, location) {
|
||||
dump("Setting breakpoint.\n");
|
||||
return sourceClient.setBreakpoint(location);
|
||||
}
|
||||
|
||||
function dumpn(msg) {
|
||||
dump("DBG-TEST: " + msg + "\n");
|
||||
}
|
||||
|
||||
function testExceptionHook(ex) {
|
||||
try {
|
||||
do_report_unexpected_exception(ex);
|
||||
} catch (ex) {
|
||||
return {throw: ex};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Convert an nsIScriptError 'aFlags' value into an appropriate string.
|
||||
function scriptErrorFlagsToKind(aFlags) {
|
||||
var kind;
|
||||
if (aFlags & Ci.nsIScriptError.warningFlag)
|
||||
kind = "warning";
|
||||
if (aFlags & Ci.nsIScriptError.exceptionFlag)
|
||||
kind = "exception";
|
||||
else
|
||||
kind = "error";
|
||||
|
||||
if (aFlags & Ci.nsIScriptError.strictFlag)
|
||||
kind = "strict " + kind;
|
||||
|
||||
return kind;
|
||||
}
|
||||
|
||||
// Register a console listener, so console messages don't just disappear
|
||||
// into the ether.
|
||||
var errorCount = 0;
|
||||
var listener = {
|
||||
observe: function (aMessage) {
|
||||
try {
|
||||
errorCount++;
|
||||
try {
|
||||
// If we've been given an nsIScriptError, then we can print out
|
||||
// something nicely formatted, for tools like Emacs to pick up.
|
||||
var scriptError = aMessage.QueryInterface(Ci.nsIScriptError);
|
||||
dumpn(aMessage.sourceName + ":" + aMessage.lineNumber + ": " +
|
||||
scriptErrorFlagsToKind(aMessage.flags) + ": " +
|
||||
aMessage.errorMessage);
|
||||
var string = aMessage.errorMessage;
|
||||
} catch (x) {
|
||||
// Be a little paranoid with message, as the whole goal here is to lose
|
||||
// no information.
|
||||
try {
|
||||
var string = "" + aMessage.message;
|
||||
} catch (x) {
|
||||
var string = "<error converting error message to string>";
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we exit all nested event loops so that the test can finish.
|
||||
while (DebuggerServer
|
||||
&& DebuggerServer.xpcInspector
|
||||
&& DebuggerServer.xpcInspector.eventLoopNestLevel > 0) {
|
||||
DebuggerServer.xpcInspector.exitNestedEventLoop();
|
||||
}
|
||||
|
||||
// In the world before bug 997440, exceptions were getting lost because of
|
||||
// the arbitrary JSContext being used in nsXPCWrappedJSClass::CallMethod.
|
||||
// In the new world, the wanderers have returned. However, because of the,
|
||||
// currently very-broken, exception reporting machinery in
|
||||
// XPCWrappedJSClass these get reported as errors to the console, even if
|
||||
// there's actually JS on the stack above that will catch them. If we
|
||||
// throw an error here because of them our tests start failing. So, we'll
|
||||
// just dump the message to the logs instead, to make sure the information
|
||||
// isn't lost.
|
||||
dumpn("head_dbg.js observed a console message: " + string);
|
||||
} catch (_) {
|
||||
// Swallow everything to avoid console reentrancy errors. We did our best
|
||||
// to log above, but apparently that didn't cut it.
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
|
||||
consoleService.registerListener(listener);
|
||||
|
||||
function check_except(func)
|
||||
{
|
||||
try {
|
||||
func();
|
||||
} catch (e) {
|
||||
do_check_true(true);
|
||||
return;
|
||||
}
|
||||
dumpn("Should have thrown an exception: " + func.toString());
|
||||
do_check_true(false);
|
||||
}
|
||||
|
||||
function testGlobal(aName) {
|
||||
let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(Ci.nsIPrincipal);
|
||||
|
||||
let sandbox = Cu.Sandbox(systemPrincipal);
|
||||
sandbox.__name = aName;
|
||||
return sandbox;
|
||||
}
|
||||
|
||||
function addTestGlobal(aName, aServer = DebuggerServer)
|
||||
{
|
||||
let global = testGlobal(aName);
|
||||
aServer.addTestGlobal(global);
|
||||
return global;
|
||||
}
|
||||
|
||||
// List the DebuggerClient |aClient|'s tabs, look for one whose title is
|
||||
// |aTitle|, and apply |aCallback| to the packet's entry for that tab.
|
||||
function getTestTab(aClient, aTitle, aCallback) {
|
||||
aClient.listTabs(function (aResponse) {
|
||||
for (let tab of aResponse.tabs) {
|
||||
if (tab.title === aTitle) {
|
||||
aCallback(tab, aResponse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
aCallback(null);
|
||||
});
|
||||
}
|
||||
|
||||
// Attach to |aClient|'s tab whose title is |aTitle|; pass |aCallback| the
|
||||
// response packet and a TabClient instance referring to that tab.
|
||||
function attachTestTab(aClient, aTitle, aCallback) {
|
||||
getTestTab(aClient, aTitle, function (aTab) {
|
||||
aClient.attachTab(aTab.actor, aCallback);
|
||||
});
|
||||
}
|
||||
|
||||
// Attach to |aClient|'s tab whose title is |aTitle|, and then attach to
|
||||
// that tab's thread. Pass |aCallback| the thread attach response packet, a
|
||||
// TabClient referring to the tab, and a ThreadClient referring to the
|
||||
// thread.
|
||||
function attachTestThread(aClient, aTitle, aCallback) {
|
||||
attachTestTab(aClient, aTitle, function (aTabResponse, aTabClient) {
|
||||
function onAttach(aResponse, aThreadClient) {
|
||||
aCallback(aResponse, aTabClient, aThreadClient, aTabResponse);
|
||||
}
|
||||
aTabClient.attachThread({
|
||||
useSourceMaps: true,
|
||||
autoBlackBox: true
|
||||
}, onAttach);
|
||||
});
|
||||
}
|
||||
|
||||
// Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's
|
||||
// thread, and then resume it. Pass |aCallback| the thread's response to
|
||||
// the 'resume' packet, a TabClient for the tab, and a ThreadClient for the
|
||||
// thread.
|
||||
function attachTestTabAndResume(aClient, aTitle, aCallback = () => {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
attachTestThread(aClient, aTitle, function (aResponse, aTabClient, aThreadClient) {
|
||||
aThreadClient.resume(function (aResponse) {
|
||||
aCallback(aResponse, aTabClient, aThreadClient);
|
||||
resolve([aResponse, aTabClient, aThreadClient]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the testing debugger server.
|
||||
*/
|
||||
function initTestDebuggerServer(aServer = DebuggerServer)
|
||||
{
|
||||
aServer.registerModule("xpcshell-test/testactors");
|
||||
// Allow incoming connections.
|
||||
aServer.init(function () { return true; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the testing debugger server with a tab whose title is |title|.
|
||||
*/
|
||||
function startTestDebuggerServer(title, server = DebuggerServer) {
|
||||
initTestDebuggerServer(server);
|
||||
addTestGlobal(title);
|
||||
DebuggerServer.addTabActors();
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
let client = new DebuggerClient(transport);
|
||||
|
||||
return connect(client).then(() => client);
|
||||
}
|
||||
|
||||
function finishClient(aClient)
|
||||
{
|
||||
aClient.close(function () {
|
||||
DebuggerServer.destroy();
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
||||
// Create a server, connect to it and fetch tab actors for the parent process;
|
||||
// pass |aCallback| the debugger client and tab actor form with all actor IDs.
|
||||
function get_chrome_actors(callback)
|
||||
{
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
DebuggerServer.allowChromeProcess = true;
|
||||
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
client.connect()
|
||||
.then(() => client.getProcess())
|
||||
.then(response => {
|
||||
callback(client, response.form);
|
||||
});
|
||||
}
|
||||
|
||||
function getChromeActors(client, server = DebuggerServer) {
|
||||
server.allowChromeProcess = true;
|
||||
return client.getProcess().then(response => response.form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a relative file path and returns the absolute file url for it.
|
||||
*/
|
||||
function getFileUrl(aName, aAllowMissing = false) {
|
||||
let file = do_get_file(aName, aAllowMissing);
|
||||
return Services.io.newFileURI(file).spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path of the file with the specified name in a
|
||||
* platform-independent and URL-like form.
|
||||
*/
|
||||
function getFilePath(aName, aAllowMissing = false, aUsePlatformPathSeparator = false)
|
||||
{
|
||||
let file = do_get_file(aName, aAllowMissing);
|
||||
let path = Services.io.newFileURI(file).spec;
|
||||
let filePrePath = "file://";
|
||||
if ("nsILocalFileWin" in Ci &&
|
||||
file instanceof Ci.nsILocalFileWin) {
|
||||
filePrePath += "/";
|
||||
}
|
||||
|
||||
path = path.slice(filePrePath.length);
|
||||
|
||||
if (aUsePlatformPathSeparator && path.match(/^\w:/)) {
|
||||
path = path.replace(/\//g, "\\");
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full text contents of the given file.
|
||||
*/
|
||||
function readFile(aFileName) {
|
||||
let f = do_get_file(aFileName);
|
||||
let s = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
s.init(f, -1, -1, false);
|
||||
try {
|
||||
return NetUtil.readInputStreamToString(s, s.available());
|
||||
} finally {
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(aFileName, aContent) {
|
||||
let file = do_get_file(aFileName, true);
|
||||
let stream = Cc["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(Ci.nsIFileOutputStream);
|
||||
stream.init(file, -1, -1, 0);
|
||||
try {
|
||||
do {
|
||||
let numWritten = stream.write(aContent, aContent.length);
|
||||
aContent = aContent.slice(numWritten);
|
||||
} while (aContent.length > 0);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
function connectPipeTracing() {
|
||||
return new TracingTransport(DebuggerServer.connectPipe());
|
||||
}
|
||||
|
||||
function TracingTransport(childTransport) {
|
||||
this.hooks = null;
|
||||
this.child = childTransport;
|
||||
this.child.hooks = this;
|
||||
|
||||
this.expectations = [];
|
||||
this.packets = [];
|
||||
this.checkIndex = 0;
|
||||
}
|
||||
|
||||
TracingTransport.prototype = {
|
||||
// Remove actor names
|
||||
normalize: function (packet) {
|
||||
return JSON.parse(JSON.stringify(packet, (key, value) => {
|
||||
if (key === "to" || key === "from" || key === "actor") {
|
||||
return "<actorid>";
|
||||
}
|
||||
return value;
|
||||
}));
|
||||
},
|
||||
send: function (packet) {
|
||||
this.packets.push({
|
||||
type: "sent",
|
||||
packet: this.normalize(packet)
|
||||
});
|
||||
return this.child.send(packet);
|
||||
},
|
||||
close: function () {
|
||||
return this.child.close();
|
||||
},
|
||||
ready: function () {
|
||||
return this.child.ready();
|
||||
},
|
||||
onPacket: function (packet) {
|
||||
this.packets.push({
|
||||
type: "received",
|
||||
packet: this.normalize(packet)
|
||||
});
|
||||
this.hooks.onPacket(packet);
|
||||
},
|
||||
onClosed: function () {
|
||||
this.hooks.onClosed();
|
||||
},
|
||||
|
||||
expectSend: function (expected) {
|
||||
let packet = this.packets[this.checkIndex++];
|
||||
do_check_eq(packet.type, "sent");
|
||||
deepEqual(packet.packet, this.normalize(expected));
|
||||
},
|
||||
|
||||
expectReceive: function (expected) {
|
||||
let packet = this.packets[this.checkIndex++];
|
||||
do_check_eq(packet.type, "received");
|
||||
deepEqual(packet.packet, this.normalize(expected));
|
||||
},
|
||||
|
||||
// Write your tests, call dumpLog at the end, inspect the output,
|
||||
// then sprinkle the calls through the right places in your test.
|
||||
dumpLog: function () {
|
||||
for (let entry of this.packets) {
|
||||
if (entry.type === "sent") {
|
||||
dumpn("trace.expectSend(" + entry.packet + ");");
|
||||
} else {
|
||||
dumpn("trace.expectReceive(" + entry.packet + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function StubTransport() { }
|
||||
StubTransport.prototype.ready = function () {};
|
||||
StubTransport.prototype.send = function () {};
|
||||
StubTransport.prototype.close = function () {};
|
||||
|
||||
function executeSoon(aFunc) {
|
||||
Services.tm.mainThread.dispatch({
|
||||
run: DevToolsUtils.makeInfallible(aFunc)
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// The do_check_* family of functions expect their last argument to be an
|
||||
// optional stack object. Unfortunately, most tests actually pass a in a string
|
||||
// containing an error message instead, which causes error reporting to break if
|
||||
// strict warnings as errors is turned on. To avoid this, we wrap these
|
||||
// functions here below to ensure the correct number of arguments is passed.
|
||||
//
|
||||
// TODO: Remove this once bug 906232 is resolved
|
||||
//
|
||||
var do_check_true_old = do_check_true;
|
||||
var do_check_true = function (condition) {
|
||||
do_check_true_old(condition);
|
||||
};
|
||||
|
||||
var do_check_false_old = do_check_false;
|
||||
var do_check_false = function (condition) {
|
||||
do_check_false_old(condition);
|
||||
};
|
||||
|
||||
var do_check_eq_old = do_check_eq;
|
||||
var do_check_eq = function (left, right) {
|
||||
do_check_eq_old(left, right);
|
||||
};
|
||||
|
||||
var do_check_neq_old = do_check_neq;
|
||||
var do_check_neq = function (left, right) {
|
||||
do_check_neq_old(left, right);
|
||||
};
|
||||
|
||||
var do_check_matches_old = do_check_matches;
|
||||
var do_check_matches = function (pattern, value) {
|
||||
do_check_matches_old(pattern, value);
|
||||
};
|
||||
|
||||
// Create async version of the object where calling each method
|
||||
// is equivalent of calling it with asyncall. Mainly useful for
|
||||
// destructuring objects with methods that take callbacks.
|
||||
const Async = target => new Proxy(target, Async);
|
||||
Async.get = (target, name) =>
|
||||
typeof (target[name]) === "function" ? asyncall.bind(null, target[name], target) :
|
||||
target[name];
|
||||
|
||||
// Calls async function that takes callback and errorback and returns
|
||||
// returns promise representing result.
|
||||
const asyncall = (fn, self, ...args) =>
|
||||
new Promise((...etc) => fn.call(self, ...args, ...etc));
|
||||
|
||||
const Test = task => () => {
|
||||
add_task(task);
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
const assert = do_check_true;
|
||||
|
||||
/**
|
||||
* Create a promise that is resolved on the next occurence of the given event.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param String event
|
||||
* @param Function predicate
|
||||
* @returns Promise
|
||||
*/
|
||||
function waitForEvent(client, type, predicate) {
|
||||
return new Promise(function (resolve) {
|
||||
function listener(type, packet) {
|
||||
if (!predicate(packet)) {
|
||||
return;
|
||||
}
|
||||
client.removeListener(listener);
|
||||
resolve(packet);
|
||||
}
|
||||
|
||||
if (predicate) {
|
||||
client.addListener(type, listener);
|
||||
} else {
|
||||
client.addOneTimeListener(type, function (type, packet) {
|
||||
resolve(packet);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action on the next tick and return a promise that is resolved on
|
||||
* the next pause.
|
||||
*
|
||||
* When using promises and Task.jsm, we often want to do an action that causes a
|
||||
* pause and continue the task once the pause has ocurred. Unfortunately, if we
|
||||
* do the action that causes the pause within the task's current tick we will
|
||||
* pause before we have a chance to yield the promise that waits for the pause
|
||||
* and we enter a dead lock. The solution is to create the promise that waits
|
||||
* for the pause, schedule the action to run on the next tick of the event loop,
|
||||
* and finally yield the promise.
|
||||
*
|
||||
* @param Function action
|
||||
* @param DebuggerClient client
|
||||
* @returns Promise
|
||||
*/
|
||||
function executeOnNextTickAndWaitForPause(action, client) {
|
||||
const paused = waitForPause(client);
|
||||
executeSoon(action);
|
||||
return paused;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt JS execution for the specified thread.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function interrupt(threadClient) {
|
||||
dumpn("Interrupting.");
|
||||
return threadClient.interrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume JS execution for the specified thread and then wait for the next pause
|
||||
* event.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function resumeAndWaitForPause(client, threadClient) {
|
||||
const paused = waitForPause(client);
|
||||
return resume(threadClient).then(() => paused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume JS execution for a single step and wait for the pause after the step
|
||||
* has been taken.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function stepIn(client, threadClient) {
|
||||
dumpn("Stepping in.");
|
||||
const paused = waitForPause(client);
|
||||
return threadClient.stepIn()
|
||||
.then(() => paused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume JS execution for a step over and wait for the pause after the step
|
||||
* has been taken.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function stepOver(client, threadClient) {
|
||||
dumpn("Stepping over.");
|
||||
return threadClient.stepOver()
|
||||
.then(() => waitForPause(client));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of `count` frames currently on stack, starting at the index
|
||||
* `first` for the specified thread.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @param Number first
|
||||
* @param Number count
|
||||
* @returns Promise
|
||||
*/
|
||||
function getFrames(threadClient, first, count) {
|
||||
dumpn("Getting frames.");
|
||||
return threadClient.getFrames(first, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Black box the specified source.
|
||||
*
|
||||
* @param SourceClient sourceClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function blackBox(sourceClient) {
|
||||
dumpn("Black boxing source: " + sourceClient.actor);
|
||||
return sourceClient.blackBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop black boxing the specified source.
|
||||
*
|
||||
* @param SourceClient sourceClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function unBlackBox(sourceClient) {
|
||||
dumpn("Un-black boxing source: " + sourceClient.actor);
|
||||
return sourceClient.unblackBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a "source" RDP request with the given SourceClient to get the source
|
||||
* content and content type.
|
||||
*
|
||||
* @param SourceClient sourceClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function getSourceContent(sourceClient) {
|
||||
dumpn("Getting source content for " + sourceClient.actor);
|
||||
return sourceClient.source();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a source at the specified url.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @param string url
|
||||
* @returns Promise<SourceClient>
|
||||
*/
|
||||
function getSource(threadClient, url) {
|
||||
let deferred = promise.defer();
|
||||
threadClient.getSources((res) => {
|
||||
let source = res.sources.filter(function (s) {
|
||||
return s.url === url;
|
||||
});
|
||||
if (source.length) {
|
||||
deferred.resolve(threadClient.source(source[0]));
|
||||
}
|
||||
else {
|
||||
deferred.reject(new Error("source not found"));
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a fake reload which clears the thread debugger
|
||||
*
|
||||
* @param TabClient tabClient
|
||||
* @returns Promise<response>
|
||||
*/
|
||||
function reload(tabClient) {
|
||||
let deferred = promise.defer();
|
||||
tabClient._reload({}, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of stack location strings given a thread and a sample.
|
||||
*
|
||||
* @param object thread
|
||||
* @param object sample
|
||||
* @returns object
|
||||
*/
|
||||
function getInflatedStackLocations(thread, sample) {
|
||||
let stackTable = thread.stackTable;
|
||||
let frameTable = thread.frameTable;
|
||||
let stringTable = thread.stringTable;
|
||||
let SAMPLE_STACK_SLOT = thread.samples.schema.stack;
|
||||
let STACK_PREFIX_SLOT = stackTable.schema.prefix;
|
||||
let STACK_FRAME_SLOT = stackTable.schema.frame;
|
||||
let FRAME_LOCATION_SLOT = frameTable.schema.location;
|
||||
|
||||
// Build the stack from the raw data and accumulate the locations in
|
||||
// an array.
|
||||
let stackIndex = sample[SAMPLE_STACK_SLOT];
|
||||
let locations = [];
|
||||
while (stackIndex !== null) {
|
||||
let stackEntry = stackTable.data[stackIndex];
|
||||
let frame = frameTable.data[stackEntry[STACK_FRAME_SLOT]];
|
||||
locations.push(stringTable[frame[FRAME_LOCATION_SLOT]]);
|
||||
stackIndex = stackEntry[STACK_PREFIX_SLOT];
|
||||
}
|
||||
|
||||
// The profiler tree is inverted, so reverse the array.
|
||||
return locations.reverse();
|
||||
}
|
||||
18
devtools/server/tests/unit/hello-actor.js
Normal file
18
devtools/server/tests/unit/hello-actor.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
|
||||
const helloSpec = protocol.generateActorSpec({
|
||||
typeName: "helloActor",
|
||||
|
||||
methods: {
|
||||
hello: {}
|
||||
}
|
||||
});
|
||||
|
||||
var HelloActor = protocol.ActorClassWithSpec(helloSpec, {
|
||||
hello: function () {
|
||||
return;
|
||||
}
|
||||
});
|
||||
17
devtools/server/tests/unit/post_init_global_actors.js
Normal file
17
devtools/server/tests/unit/post_init_global_actors.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function PostInitGlobalActor(aConnection) {}
|
||||
|
||||
PostInitGlobalActor.prototype = {
|
||||
actorPrefix: "postInitGlobal",
|
||||
onPing: function onPing(aRequest) {
|
||||
return { message: "pong" };
|
||||
},
|
||||
};
|
||||
|
||||
PostInitGlobalActor.prototype.requestTypes = {
|
||||
"ping": PostInitGlobalActor.prototype.onPing,
|
||||
};
|
||||
|
||||
DebuggerServer.addGlobalActor(PostInitGlobalActor, "postInitGlobalActor");
|
||||
17
devtools/server/tests/unit/post_init_tab_actors.js
Normal file
17
devtools/server/tests/unit/post_init_tab_actors.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function PostInitTabActor(aConnection) {}
|
||||
|
||||
PostInitTabActor.prototype = {
|
||||
actorPostfix: "postInitTab",
|
||||
onPing: function onPing(aRequest) {
|
||||
return { message: "pong" };
|
||||
},
|
||||
};
|
||||
|
||||
PostInitTabActor.prototype.requestTypes = {
|
||||
"ping": PostInitTabActor.prototype.onPing,
|
||||
};
|
||||
|
||||
DebuggerServer.addGlobalActor(PostInitTabActor, "postInitTabActor");
|
||||
17
devtools/server/tests/unit/pre_init_global_actors.js
Normal file
17
devtools/server/tests/unit/pre_init_global_actors.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function PreInitGlobalActor(aConnection) {}
|
||||
|
||||
PreInitGlobalActor.prototype = {
|
||||
actorPrefix: "preInitGlobal",
|
||||
onPing: function onPing(aRequest) {
|
||||
return { message: "pong" };
|
||||
},
|
||||
};
|
||||
|
||||
PreInitGlobalActor.prototype.requestTypes = {
|
||||
"ping": PreInitGlobalActor.prototype.onPing,
|
||||
};
|
||||
|
||||
DebuggerServer.addGlobalActor(PreInitGlobalActor, "preInitGlobalActor");
|
||||
17
devtools/server/tests/unit/pre_init_tab_actors.js
Normal file
17
devtools/server/tests/unit/pre_init_tab_actors.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function PreInitTabActor(aConnection) {}
|
||||
|
||||
PreInitTabActor.prototype = {
|
||||
actorPrefix: "preInitTab",
|
||||
onPing: function onPing(aRequest) {
|
||||
return { message: "pong" };
|
||||
},
|
||||
};
|
||||
|
||||
PreInitTabActor.prototype.requestTypes = {
|
||||
"ping": PreInitTabActor.prototype.onPing,
|
||||
};
|
||||
|
||||
DebuggerServer.addGlobalActor(PreInitTabActor, "preInitTabActor");
|
||||
15
devtools/server/tests/unit/registertestactors-01.js
Normal file
15
devtools/server/tests/unit/registertestactors-01.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function Actor() {}
|
||||
|
||||
exports.register = function (handle) {
|
||||
handle.addTabActor(Actor, "registeredActor1");
|
||||
handle.addGlobalActor(Actor, "registeredActor1");
|
||||
};
|
||||
|
||||
exports.unregister = function (handle) {
|
||||
handle.removeTabActor(Actor);
|
||||
handle.removeGlobalActor(Actor);
|
||||
};
|
||||
|
||||
15
devtools/server/tests/unit/registertestactors-02.js
Normal file
15
devtools/server/tests/unit/registertestactors-02.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function Actor() {}
|
||||
|
||||
exports.register = function (handle) {
|
||||
handle.addGlobalActor(Actor, "registeredActor2");
|
||||
handle.addTabActor(Actor, "registeredActor2");
|
||||
};
|
||||
|
||||
exports.unregister = function (handle) {
|
||||
handle.removeTabActor(Actor);
|
||||
handle.removeGlobalActor(Actor);
|
||||
};
|
||||
|
||||
40
devtools/server/tests/unit/registertestactors-03.js
Normal file
40
devtools/server/tests/unit/registertestactors-03.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var {method, RetVal, Actor, ActorClassWithSpec, Front, FrontClassWithSpec,
|
||||
generateActorSpec} = require("devtools/shared/protocol");
|
||||
var Services = require("Services");
|
||||
|
||||
const lazySpec = generateActorSpec({
|
||||
typeName: "lazy",
|
||||
|
||||
methods: {
|
||||
hello: {
|
||||
response: { str: RetVal("string") }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
exports.LazyActor = ActorClassWithSpec(lazySpec, {
|
||||
initialize: function (conn, id) {
|
||||
Actor.prototype.initialize.call(this, conn);
|
||||
|
||||
Services.obs.notifyObservers(null, "actor", "instantiated");
|
||||
},
|
||||
|
||||
hello: function (str) {
|
||||
return "world";
|
||||
}
|
||||
});
|
||||
|
||||
Services.obs.notifyObservers(null, "actor", "loaded");
|
||||
|
||||
exports.LazyFront = FrontClassWithSpec(lazySpec, {
|
||||
initialize: function (client, form) {
|
||||
Front.prototype.initialize.call(this, client);
|
||||
this.actorID = form.lazyActor;
|
||||
|
||||
client.addActorPool(this);
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
function f() {}
|
||||
|
||||
(function () {
|
||||
var a = 1; var b = 2; var c = 3;
|
||||
})();
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1; var b = 2;
|
||||
var c = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
function f() {}
|
||||
|
||||
(function () {
|
||||
var a = 1; var c = 3;
|
||||
})();
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1; var c = 3;
|
||||
}
|
||||
5
devtools/server/tests/unit/setBreakpoint-on-column.js
Normal file
5
devtools/server/tests/unit/setBreakpoint-on-column.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1; var b = 2; var c = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
function f() {}
|
||||
|
||||
(function () {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
})();
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
for (var i = 0; i < 1; ++i) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1; var b = 2; var c = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
"use strict";
|
||||
|
||||
function f() {}
|
||||
|
||||
(function () {
|
||||
var a = 1;
|
||||
|
||||
var c = 3;
|
||||
})();
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1;
|
||||
|
||||
var c = 3;
|
||||
}
|
||||
7
devtools/server/tests/unit/setBreakpoint-on-line.js
Normal file
7
devtools/server/tests/unit/setBreakpoint-on-line.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
function f() {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
foo = (n) ->
|
||||
return "foo" + i for i in [0...n]
|
||||
|
||||
[first, second, third] = foo(3)
|
||||
|
||||
debugger
|
||||
10
devtools/server/tests/unit/source-map-data/sourcemapped.map
Normal file
10
devtools/server/tests/unit/source-map-data/sourcemapped.map
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"version": 3,
|
||||
"file": "sourcemapped.js",
|
||||
"sourceRoot": "",
|
||||
"sources": [
|
||||
"sourcemapped.coffee"
|
||||
],
|
||||
"names": [],
|
||||
"mappings": ";AAAA;CAAA,KAAA,yBAAA;CAAA;CAAA,CAAA,CAAA,MAAO;CACL,IAAA,GAAA;AAAA,CAAA,EAAA,MAA0B,qDAA1B;CAAA,EAAe,EAAR,QAAA;CAAP,IADI;CAAN,EAAM;;CAAN,CAGA,CAAyB,IAAA;;CAEzB,UALA;CAAA"
|
||||
}
|
||||
16
devtools/server/tests/unit/sourcemapped.js
Normal file
16
devtools/server/tests/unit/sourcemapped.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Generated by CoffeeScript 1.6.1
|
||||
(function () {
|
||||
var first, foo, second, third, _ref;
|
||||
|
||||
foo = function (n) {
|
||||
var i, _i;
|
||||
for (i = _i = 0; 0 <= n ? _i < n : _i > n; i = 0 <= n ? ++_i : --_i) {
|
||||
return "foo" + i;
|
||||
}
|
||||
};
|
||||
|
||||
_ref = foo(3), first = _ref[0], second = _ref[1], third = _ref[2];
|
||||
|
||||
debugger;
|
||||
|
||||
}).call(this);
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that we can tell the memory actor to take a heap snapshot over the RDP
|
||||
// and then create a HeapSnapshot instance from the resulting file.
|
||||
|
||||
const { OS } = require("resource://gre/modules/osfile.jsm");
|
||||
|
||||
const run_test = makeMemoryActorTest(function* (client, memoryFront) {
|
||||
const snapshotFilePath = yield memoryFront.saveHeapSnapshot();
|
||||
ok(!!(yield OS.File.stat(snapshotFilePath)),
|
||||
"Should have the heap snapshot file");
|
||||
const snapshot = ThreadSafeChromeUtils.readHeapSnapshot(snapshotFilePath);
|
||||
ok(snapshot instanceof HeapSnapshot,
|
||||
"And we should be able to read a HeapSnapshot instance from the file");
|
||||
});
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that we can properly stream heap snapshot files over the RDP as bulk
|
||||
// data.
|
||||
|
||||
const { OS } = require("resource://gre/modules/osfile.jsm");
|
||||
|
||||
const run_test = makeMemoryActorTest(function* (client, memoryFront) {
|
||||
const snapshotFilePath = yield memoryFront.saveHeapSnapshot({
|
||||
forceCopy: true
|
||||
});
|
||||
ok(!!(yield OS.File.stat(snapshotFilePath)),
|
||||
"Should have the heap snapshot file");
|
||||
const snapshot = ThreadSafeChromeUtils.readHeapSnapshot(snapshotFilePath);
|
||||
ok(snapshot instanceof HeapSnapshot,
|
||||
"And we should be able to read a HeapSnapshot instance from the file");
|
||||
});
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that we can save full runtime heap snapshots when attached to the
|
||||
// ChromeActor or a ChildProcessActor.
|
||||
|
||||
const { OS } = require("resource://gre/modules/osfile.jsm");
|
||||
|
||||
const run_test = makeFullRuntimeMemoryActorTest(function* (client, memoryFront) {
|
||||
const snapshotFilePath = yield memoryFront.saveHeapSnapshot();
|
||||
ok(!!(yield OS.File.stat(snapshotFilePath)),
|
||||
"Should have the heap snapshot file");
|
||||
const snapshot = ThreadSafeChromeUtils.readHeapSnapshot(snapshotFilePath);
|
||||
ok(snapshot instanceof HeapSnapshot,
|
||||
"And we should be able to read a HeapSnapshot instance from the file");
|
||||
});
|
||||
80
devtools/server/tests/unit/test_actor-registry-actor.js
Normal file
80
devtools/server/tests/unit/test_actor-registry-actor.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that you can register new actors via the ActorRegistrationActor.
|
||||
*/
|
||||
|
||||
var gClient;
|
||||
var gRegistryFront;
|
||||
var gActorFront;
|
||||
var gOldPref;
|
||||
|
||||
const { ActorRegistryFront } = require("devtools/shared/fronts/actor-registry");
|
||||
|
||||
function run_test()
|
||||
{
|
||||
gOldPref = Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps");
|
||||
Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", false);
|
||||
initTestDebuggerServer();
|
||||
DebuggerServer.addBrowserActors();
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(getRegistry);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function getRegistry() {
|
||||
gClient.listTabs((response) => {
|
||||
gRegistryFront = ActorRegistryFront(gClient, response);
|
||||
registerNewActor();
|
||||
});
|
||||
}
|
||||
|
||||
function registerNewActor() {
|
||||
let options = {
|
||||
prefix: "helloActor",
|
||||
constructor: "HelloActor",
|
||||
type: { global: true }
|
||||
};
|
||||
|
||||
gRegistryFront
|
||||
.registerActor("resource://test/hello-actor.js", options)
|
||||
.then(actorFront => gActorFront = actorFront)
|
||||
.then(talkToNewActor)
|
||||
.then(null, e => {
|
||||
DevToolsUtils.reportException("registerNewActor", e);
|
||||
do_check_true(false);
|
||||
});
|
||||
}
|
||||
|
||||
function talkToNewActor() {
|
||||
gClient.listTabs(({ helloActor }) => {
|
||||
do_check_true(!!helloActor);
|
||||
gClient.request({
|
||||
to: helloActor,
|
||||
type: "hello"
|
||||
}, response => {
|
||||
do_check_true(!response.error);
|
||||
unregisterNewActor();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function unregisterNewActor() {
|
||||
gActorFront
|
||||
.unregister()
|
||||
.then(testActorIsUnregistered)
|
||||
.then(null, e => {
|
||||
DevToolsUtils.reportException("unregisterNewActor", e);
|
||||
do_check_true(false);
|
||||
});
|
||||
}
|
||||
|
||||
function testActorIsUnregistered() {
|
||||
gClient.listTabs(({ helloActor }) => {
|
||||
do_check_true(!helloActor);
|
||||
|
||||
Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", gOldPref);
|
||||
finishClient(gClient);
|
||||
});
|
||||
}
|
||||
107
devtools/server/tests/unit/test_add_actors.js
Normal file
107
devtools/server/tests/unit/test_add_actors.js
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gClient;
|
||||
var gActors;
|
||||
|
||||
/**
|
||||
* The purpose of these tests is to verify that it's possible to add actors
|
||||
* both before and after the DebuggerServer has been initialized, so addons
|
||||
* that add actors don't have to poll the object for its initialization state
|
||||
* in order to add actors after initialization but rather can add actors anytime
|
||||
* regardless of the object's state.
|
||||
*/
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.addActors("resource://test/pre_init_global_actors.js");
|
||||
DebuggerServer.addActors("resource://test/pre_init_tab_actors.js");
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
DebuggerServer.addActors("resource://test/post_init_global_actors.js");
|
||||
DebuggerServer.addActors("resource://test/post_init_tab_actors.js");
|
||||
|
||||
add_test(init);
|
||||
add_test(test_pre_init_global_actor);
|
||||
add_test(test_pre_init_tab_actor);
|
||||
add_test(test_post_init_global_actor);
|
||||
add_test(test_post_init_tab_actor);
|
||||
add_test(test_stable_global_actor_instances);
|
||||
add_test(close_client);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect()
|
||||
.then(() => gClient.listTabs())
|
||||
.then(aResponse => {
|
||||
gActors = aResponse;
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function test_pre_init_global_actor()
|
||||
{
|
||||
gClient.request({ to: gActors.preInitGlobalActor, type: "ping" },
|
||||
function onResponse(aResponse) {
|
||||
do_check_eq(aResponse.message, "pong");
|
||||
run_next_test();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_pre_init_tab_actor()
|
||||
{
|
||||
gClient.request({ to: gActors.preInitTabActor, type: "ping" },
|
||||
function onResponse(aResponse) {
|
||||
do_check_eq(aResponse.message, "pong");
|
||||
run_next_test();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_post_init_global_actor()
|
||||
{
|
||||
gClient.request({ to: gActors.postInitGlobalActor, type: "ping" },
|
||||
function onResponse(aResponse) {
|
||||
do_check_eq(aResponse.message, "pong");
|
||||
run_next_test();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function test_post_init_tab_actor()
|
||||
{
|
||||
gClient.request({ to: gActors.postInitTabActor, type: "ping" },
|
||||
function onResponse(aResponse) {
|
||||
do_check_eq(aResponse.message, "pong");
|
||||
run_next_test();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Get the object object, from the server side, for a given actor ID
|
||||
function getActorInstance(connID, actorID) {
|
||||
return DebuggerServer._connections[connID].getActor(actorID);
|
||||
}
|
||||
|
||||
function test_stable_global_actor_instances()
|
||||
{
|
||||
// Consider that there is only one connection,
|
||||
// and the first one is ours
|
||||
let connID = Object.keys(DebuggerServer._connections)[0];
|
||||
let postInitGlobalActor = getActorInstance(connID, gActors.postInitGlobalActor);
|
||||
let preInitGlobalActor = getActorInstance(connID, gActors.preInitGlobalActor);
|
||||
gClient.listTabs(function onListTabs(aResponse) {
|
||||
do_check_eq(postInitGlobalActor, getActorInstance(connID, aResponse.postInitGlobalActor));
|
||||
do_check_eq(preInitGlobalActor, getActorInstance(connID, aResponse.preInitGlobalActor));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function close_client() {
|
||||
gClient.close().then(() => run_next_test());
|
||||
}
|
||||
98
devtools/server/tests/unit/test_addon_reload.js
Normal file
98
devtools/server/tests/unit/test_addon_reload.js
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {AddonManager} = require("resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
startupAddonsManager();
|
||||
|
||||
function promiseAddonEvent(event) {
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
[event]: function (...args) {
|
||||
AddonManager.removeAddonListener(listener);
|
||||
resolve(args);
|
||||
}
|
||||
};
|
||||
|
||||
AddonManager.addAddonListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
function* findAddonInRootList(client, addonId) {
|
||||
const result = yield client.listAddons();
|
||||
const addonActor = result.addons.filter(addon => addon.id === addonId)[0];
|
||||
ok(addonActor, `Found add-on actor for ${addonId}`);
|
||||
return addonActor;
|
||||
}
|
||||
|
||||
function* reloadAddon(client, addonActor) {
|
||||
// The add-on will be re-installed after a successful reload.
|
||||
const onInstalled = promiseAddonEvent("onInstalled");
|
||||
yield client.request({to: addonActor.actor, type: "reload"});
|
||||
yield onInstalled;
|
||||
}
|
||||
|
||||
function getSupportFile(path) {
|
||||
const allowMissing = false;
|
||||
return do_get_file(path, allowMissing);
|
||||
}
|
||||
|
||||
add_task(function* testReloadExitedAddon() {
|
||||
const client = yield new Promise(resolve => {
|
||||
get_chrome_actors(client => resolve(client));
|
||||
});
|
||||
|
||||
// Install our main add-on to trigger reloads on.
|
||||
const addonFile = getSupportFile("addons/web-extension");
|
||||
const installedAddon = yield AddonManager.installTemporaryAddon(
|
||||
addonFile);
|
||||
|
||||
// Install a decoy add-on.
|
||||
const addonFile2 = getSupportFile("addons/web-extension2");
|
||||
const installedAddon2 = yield AddonManager.installTemporaryAddon(
|
||||
addonFile2);
|
||||
|
||||
let addonActor = yield findAddonInRootList(client, installedAddon.id);
|
||||
|
||||
yield reloadAddon(client, addonActor);
|
||||
|
||||
// Uninstall the decoy add-on, which should cause its actor to exit.
|
||||
const onUninstalled = promiseAddonEvent("onUninstalled");
|
||||
installedAddon2.uninstall();
|
||||
const [uninstalledAddon] = yield onUninstalled;
|
||||
|
||||
// Try to re-list all add-ons after a reload.
|
||||
// This was throwing an exception because of the exited actor.
|
||||
const newAddonActor = yield findAddonInRootList(client, installedAddon.id);
|
||||
equal(newAddonActor.id, addonActor.id);
|
||||
|
||||
// The actor id should be the same after the reload
|
||||
equal(newAddonActor.actor, addonActor.actor);
|
||||
|
||||
const onAddonListChanged = new Promise((resolve) => {
|
||||
client.addListener("addonListChanged", function listener() {
|
||||
client.removeListener("addonListChanged", listener);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// Install an upgrade version of the first add-on.
|
||||
const addonUpgradeFile = getSupportFile("addons/web-extension-upgrade");
|
||||
const upgradedAddon = yield AddonManager.installTemporaryAddon(
|
||||
addonUpgradeFile);
|
||||
|
||||
// Waiting for addonListChanged unsolicited event
|
||||
yield onAddonListChanged;
|
||||
|
||||
// re-list all add-ons after an upgrade.
|
||||
const upgradedAddonActor = yield findAddonInRootList(client, upgradedAddon.id);
|
||||
equal(upgradedAddonActor.id, addonActor.id);
|
||||
// The actor id should be the same after the upgrade.
|
||||
equal(upgradedAddonActor.actor, addonActor.actor);
|
||||
|
||||
// The addon metadata has been updated.
|
||||
equal(upgradedAddonActor.name, "Test Addons Actor Upgrade");
|
||||
|
||||
yield close(client);
|
||||
});
|
||||
51
devtools/server/tests/unit/test_addons_actor.js
Normal file
51
devtools/server/tests/unit/test_addons_actor.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const protocol = require("devtools/shared/protocol");
|
||||
const {AddonsActor} = require("devtools/server/actors/addons");
|
||||
const {AddonsFront} = require("devtools/shared/fronts/addons");
|
||||
|
||||
startupAddonsManager();
|
||||
|
||||
function* connect() {
|
||||
const client = yield new Promise(resolve => {
|
||||
get_chrome_actors(client => resolve(client));
|
||||
});
|
||||
const root = yield listTabs(client);
|
||||
const addonsActor = root.addonsActor;
|
||||
ok(addonsActor, "Got AddonsActor instance");
|
||||
|
||||
const addons = AddonsFront(client, {addonsActor});
|
||||
return [client, addons];
|
||||
}
|
||||
|
||||
add_task(function* testSuccessfulInstall() {
|
||||
const [client, addons] = yield connect();
|
||||
|
||||
const allowMissing = false;
|
||||
const usePlatformSeparator = true;
|
||||
const addonPath = getFilePath("addons/web-extension",
|
||||
allowMissing, usePlatformSeparator);
|
||||
const installedAddon = yield addons.installTemporaryAddon(addonPath);
|
||||
equal(installedAddon.id, "test-addons-actor@mozilla.org");
|
||||
// The returned object is currently not a proper actor.
|
||||
equal(installedAddon.actor, false);
|
||||
|
||||
const addonList = yield client.listAddons();
|
||||
ok(addonList && addonList.addons && addonList.addons.map(a => a.name),
|
||||
"Received list of add-ons");
|
||||
const addon = addonList.addons.filter(a => a.id === installedAddon.id)[0];
|
||||
ok(addon, "Test add-on appeared in root install list");
|
||||
|
||||
yield close(client);
|
||||
});
|
||||
|
||||
add_task(function* testNonExistantPath() {
|
||||
const [client, addons] = yield connect();
|
||||
|
||||
yield Assert.rejects(
|
||||
addons.installTemporaryAddon("some-non-existant-path"),
|
||||
/Could not install add-on.*Component returned failure/);
|
||||
|
||||
yield close(client);
|
||||
});
|
||||
87
devtools/server/tests/unit/test_animation_name.js
Normal file
87
devtools/server/tests/unit/test_animation_name.js
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that AnimationPlayerActor.getName returns the right name depending on
|
||||
// the type of an animation and the various properties available on it.
|
||||
|
||||
const { AnimationPlayerActor } = require("devtools/server/actors/animation");
|
||||
|
||||
function run_test() {
|
||||
// Mock a window with just the properties the AnimationPlayerActor uses.
|
||||
let window = {
|
||||
MutationObserver: function () {
|
||||
this.observe = () => {};
|
||||
},
|
||||
Animation: function () {
|
||||
this.effect = {target: getMockNode()};
|
||||
},
|
||||
CSSAnimation: function () {
|
||||
this.effect = {target: getMockNode()};
|
||||
},
|
||||
CSSTransition: function () {
|
||||
this.effect = {target: getMockNode()};
|
||||
}
|
||||
};
|
||||
|
||||
window.CSSAnimation.prototype = Object.create(window.Animation.prototype);
|
||||
window.CSSTransition.prototype = Object.create(window.Animation.prototype);
|
||||
|
||||
// Helper to get a mock DOM node.
|
||||
function getMockNode() {
|
||||
return {
|
||||
ownerDocument: {
|
||||
defaultView: window
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Objects in this array should contain the following properties:
|
||||
// - desc {String} For logging
|
||||
// - animation {Object} An animation object instantiated from one of the mock
|
||||
// window animation constructors.
|
||||
// - props {Objet} Properties of this object will be added to the animation
|
||||
// object.
|
||||
// - expectedName {String} The expected name returned by
|
||||
// AnimationPlayerActor.getName.
|
||||
const TEST_DATA = [{
|
||||
desc: "Animation with an id",
|
||||
animation: new window.Animation(),
|
||||
props: { id: "animation-id" },
|
||||
expectedName: "animation-id"
|
||||
}, {
|
||||
desc: "Animation without an id",
|
||||
animation: new window.Animation(),
|
||||
props: {},
|
||||
expectedName: ""
|
||||
}, {
|
||||
desc: "CSSTransition with an id",
|
||||
animation: new window.CSSTransition(),
|
||||
props: { id: "transition-with-id", transitionProperty: "width" },
|
||||
expectedName: "transition-with-id"
|
||||
}, {
|
||||
desc: "CSSAnimation with an id",
|
||||
animation: new window.CSSAnimation(),
|
||||
props: { id: "animation-with-id", animationName: "move" },
|
||||
expectedName: "animation-with-id"
|
||||
}, {
|
||||
desc: "CSSTransition without an id",
|
||||
animation: new window.CSSTransition(),
|
||||
props: { transitionProperty: "width" },
|
||||
expectedName: "width"
|
||||
}, {
|
||||
desc: "CSSAnimation without an id",
|
||||
animation: new window.CSSAnimation(),
|
||||
props: { animationName: "move" },
|
||||
expectedName: "move"
|
||||
}];
|
||||
|
||||
for (let { desc, animation, props, expectedName } of TEST_DATA) {
|
||||
do_print(desc);
|
||||
for (let key in props) {
|
||||
animation[key] = props[key];
|
||||
}
|
||||
let actor = AnimationPlayerActor({}, animation);
|
||||
do_check_eq(actor.getName(), expectedName);
|
||||
}
|
||||
}
|
||||
68
devtools/server/tests/unit/test_animation_type.js
Normal file
68
devtools/server/tests/unit/test_animation_type.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the output of AnimationPlayerActor.getType().
|
||||
|
||||
const { ANIMATION_TYPES, AnimationPlayerActor } =
|
||||
require("devtools/server/actors/animation");
|
||||
|
||||
function run_test() {
|
||||
// Mock a window with just the properties the AnimationPlayerActor uses.
|
||||
let window = {
|
||||
MutationObserver: function () {
|
||||
this.observe = () => {};
|
||||
},
|
||||
Animation: function () {
|
||||
this.effect = {target: getMockNode()};
|
||||
},
|
||||
CSSAnimation: function () {
|
||||
this.effect = {target: getMockNode()};
|
||||
},
|
||||
CSSTransition: function () {
|
||||
this.effect = {target: getMockNode()};
|
||||
}
|
||||
};
|
||||
|
||||
window.CSSAnimation.prototype = Object.create(window.Animation.prototype);
|
||||
window.CSSTransition.prototype = Object.create(window.Animation.prototype);
|
||||
|
||||
// Helper to get a mock DOM node.
|
||||
function getMockNode() {
|
||||
return {
|
||||
ownerDocument: {
|
||||
defaultView: window
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Objects in this array should contain the following properties:
|
||||
// - desc {String} For logging
|
||||
// - animation {Object} An animation object instantiated from one of the mock
|
||||
// window animation constructors.
|
||||
// - expectedType {String} The expected type returned by
|
||||
// AnimationPlayerActor.getType.
|
||||
const TEST_DATA = [{
|
||||
desc: "Test CSSAnimation type",
|
||||
animation: new window.CSSAnimation(),
|
||||
expectedType: ANIMATION_TYPES.CSS_ANIMATION
|
||||
}, {
|
||||
desc: "Test CSSTransition type",
|
||||
animation: new window.CSSTransition(),
|
||||
expectedType: ANIMATION_TYPES.CSS_TRANSITION
|
||||
}, {
|
||||
desc: "Test ScriptAnimation type",
|
||||
animation: new window.Animation(),
|
||||
expectedType: ANIMATION_TYPES.SCRIPT_ANIMATION
|
||||
}, {
|
||||
desc: "Test unknown type",
|
||||
animation: {effect: {target: getMockNode()}},
|
||||
expectedType: ANIMATION_TYPES.UNKNOWN
|
||||
}];
|
||||
|
||||
for (let { desc, animation, expectedType } of TEST_DATA) {
|
||||
do_print(desc);
|
||||
let actor = AnimationPlayerActor({}, animation);
|
||||
do_check_eq(actor.getType(), expectedType);
|
||||
}
|
||||
}
|
||||
37
devtools/server/tests/unit/test_attach.js
Normal file
37
devtools/server/tests/unit/test_attach.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gClient;
|
||||
var gDebuggee;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = testGlobal("test-1");
|
||||
DebuggerServer.addTestGlobal(gDebuggee);
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect().then(function ([aType, aTraits]) {
|
||||
attachTestTab(gClient, "test-1", function (aReply, aTabClient) {
|
||||
test_attach(aTabClient);
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_attach(aTabClient)
|
||||
{
|
||||
aTabClient.attachThread({}, function (aResponse, aThreadClient) {
|
||||
do_check_eq(aThreadClient.state, "paused");
|
||||
aThreadClient.resume(cleanup);
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
gClient.addListener("closed", function (aEvent) {
|
||||
do_test_finished();
|
||||
});
|
||||
gClient.close();
|
||||
}
|
||||
145
devtools/server/tests/unit/test_blackboxing-01.js
Normal file
145
devtools/server/tests/unit/test_blackboxing-01.js
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test basic black boxing.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
testBlackBox();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
const testBlackBox = Task.async(function* () {
|
||||
let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||
let source = gThreadClient.source(packet.frame.where.source);
|
||||
|
||||
yield setBreakpoint(source, {
|
||||
line: 2
|
||||
});
|
||||
yield resume(gThreadClient);
|
||||
|
||||
const { sources } = yield getSources(gThreadClient);
|
||||
let sourceClient = gThreadClient.source(
|
||||
sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
do_check_true(!sourceClient.isBlackBoxed,
|
||||
"By default the source is not black boxed.");
|
||||
|
||||
// Test that we can step into `doStuff` when we are not black boxed.
|
||||
yield runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.source.url, BLACK_BOXED_URL);
|
||||
do_check_eq(aLocation.line, 2);
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
do_check_true(!aFrames.some(f => f.where.source.isBlackBoxed));
|
||||
}
|
||||
);
|
||||
|
||||
let blackBoxResponse = yield blackBox(sourceClient);
|
||||
do_check_true(sourceClient.isBlackBoxed);
|
||||
|
||||
// Test that we step through `doStuff` when we are black boxed and its frame
|
||||
// doesn't show up.
|
||||
yield runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.source.url, SOURCE_URL);
|
||||
do_check_eq(aLocation.line, 4);
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
for (let f of aFrames) {
|
||||
if (f.where.source.url == BLACK_BOXED_URL) {
|
||||
do_check_true(f.where.source.isBlackBoxed);
|
||||
} else {
|
||||
do_check_true(!f.where.source.isBlackBoxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let unBlackBoxResponse = yield unBlackBox(sourceClient);
|
||||
do_check_true(!sourceClient.isBlackBoxed);
|
||||
|
||||
// Test that we can step into `doStuff` again.
|
||||
yield runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.source.url, BLACK_BOXED_URL);
|
||||
do_check_eq(aLocation.line, 2);
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
do_check_true(!aFrames.some(f => f.where.source.isBlackBoxed));
|
||||
}
|
||||
);
|
||||
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
function evalCode() {
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
let arg = 15; // line 2 - Step in here
|
||||
k(arg); // line 3
|
||||
}, // line 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
BLACK_BOXED_URL,
|
||||
1
|
||||
);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function runTest() { // line 1
|
||||
doStuff( // line 2 - Break here
|
||||
function (n) { // line 3 - Step through `doStuff` to here
|
||||
debugger; // line 4
|
||||
} // line 5
|
||||
); // line 6
|
||||
} + "\n" // line 7
|
||||
+ "debugger;", // line 8
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
const runTest = Task.async(function* (onSteppedLocation, onDebuggerStatementFrames) {
|
||||
let packet = yield executeOnNextTickAndWaitForPause(gDebuggee.runTest,
|
||||
gClient);
|
||||
do_check_eq(packet.why.type, "breakpoint");
|
||||
|
||||
yield stepIn(gClient, gThreadClient);
|
||||
yield stepIn(gClient, gThreadClient);
|
||||
yield stepIn(gClient, gThreadClient);
|
||||
|
||||
const location = yield getCurrentLocation();
|
||||
onSteppedLocation(location);
|
||||
|
||||
packet = yield resumeAndWaitForPause(gClient, gThreadClient);
|
||||
do_check_eq(packet.why.type, "debuggerStatement");
|
||||
|
||||
let { frames } = yield getFrames(gThreadClient, 0, 100);
|
||||
onDebuggerStatementFrames(frames);
|
||||
|
||||
return resume(gThreadClient);
|
||||
});
|
||||
|
||||
const getCurrentLocation = Task.async(function* () {
|
||||
const response = yield getFrames(gThreadClient, 0, 1);
|
||||
return response.frames[0].where;
|
||||
});
|
||||
113
devtools/server/tests/unit/test_blackboxing-02.js
Normal file
113
devtools/server/tests/unit/test_blackboxing-02.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we don't hit breakpoints in black boxed sources, and that when we
|
||||
* unblack box the source again, the breakpoint hasn't disappeared and we will
|
||||
* hit it again.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_black_box();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
function test_black_box()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.eval(aPacket.frame.actor, "doStuff", function (aResponse) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let obj = gThreadClient.pauseGrip(aPacket.why.frameFinished.return);
|
||||
obj.getDefinitionSite(runWithSource);
|
||||
});
|
||||
});
|
||||
|
||||
function runWithSource(aPacket) {
|
||||
let source = gThreadClient.source(aPacket.source);
|
||||
source.setBreakpoint({
|
||||
line: 2
|
||||
}, function (aResponse) {
|
||||
do_check_true(!aResponse.error, "Should be able to set breakpoint.");
|
||||
gThreadClient.resume(test_black_box_breakpoint);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
let arg = 15; // line 2 - Break here
|
||||
k(arg); // line 3
|
||||
}, // line 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
BLACK_BOXED_URL,
|
||||
1
|
||||
);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function runTest() { // line 1
|
||||
doStuff( // line 2
|
||||
function (n) { // line 3
|
||||
debugger; // line 5
|
||||
} // line 6
|
||||
); // line 7
|
||||
} // line 8
|
||||
+ "\n debugger;", // line 9
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
function test_black_box_breakpoint() {
|
||||
gThreadClient.getSources(function ({error, sources}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
sourceClient.blackBox(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement",
|
||||
"We should pass over the breakpoint since the source is black boxed.");
|
||||
gThreadClient.resume(test_unblack_box_breakpoint.bind(null, sourceClient));
|
||||
});
|
||||
gDebuggee.runTest();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_unblack_box_breakpoint(aSourceClient) {
|
||||
aSourceClient.unblackBox(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "breakpoint",
|
||||
"We should hit the breakpoint again");
|
||||
|
||||
// We will hit the debugger statement on resume, so do this nastiness to skip over it.
|
||||
gClient.addOneTimeListener(
|
||||
"paused",
|
||||
gThreadClient.resume.bind(
|
||||
gThreadClient,
|
||||
finishClient.bind(null, gClient)));
|
||||
gThreadClient.resume();
|
||||
});
|
||||
gDebuggee.runTest();
|
||||
});
|
||||
}
|
||||
102
devtools/server/tests/unit/test_blackboxing-03.js
Normal file
102
devtools/server/tests/unit/test_blackboxing-03.js
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we don't stop at debugger statements inside black boxed sources.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gBpClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_black_box();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
function test_black_box()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
source.setBreakpoint({
|
||||
line: 4
|
||||
}, function ({error}, bpClient) {
|
||||
gBpClient = bpClient;
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
gThreadClient.resume(test_black_box_dbg_statement);
|
||||
});
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
debugger; // line 2 - Break here
|
||||
k(100); // line 3
|
||||
}, // line 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
BLACK_BOXED_URL,
|
||||
1
|
||||
);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function runTest() { // line 1
|
||||
doStuff( // line 2
|
||||
function (n) { // line 3
|
||||
Math.abs(n); // line 4 - Break here
|
||||
} // line 5
|
||||
); // line 6
|
||||
} // line 7
|
||||
+ "\n debugger;", // line 8
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
function test_black_box_dbg_statement() {
|
||||
gThreadClient.getSources(function ({error, sources}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
|
||||
sourceClient.blackBox(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "breakpoint",
|
||||
"We should pass over the debugger statement.");
|
||||
gBpClient.remove(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
gThreadClient.resume(test_unblack_box_dbg_statement.bind(null, sourceClient));
|
||||
});
|
||||
});
|
||||
gDebuggee.runTest();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_unblack_box_dbg_statement(aSourceClient) {
|
||||
aSourceClient.unblackBox(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement",
|
||||
"We should stop at the debugger statement again");
|
||||
finishClient(gClient);
|
||||
});
|
||||
gDebuggee.runTest();
|
||||
});
|
||||
}
|
||||
88
devtools/server/tests/unit/test_blackboxing-04.js
Normal file
88
devtools/server/tests/unit/test_blackboxing-04.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test behavior of blackboxing sources we are currently paused in.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_black_box();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
function test_black_box()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.eval(aPacket.frame.actor, "doStuff", function (aResponse) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let obj = gThreadClient.pauseGrip(aPacket.why.frameFinished.return);
|
||||
obj.getDefinitionSite(runWithSource);
|
||||
});
|
||||
});
|
||||
|
||||
function runWithSource(aPacket) {
|
||||
let source = gThreadClient.source(aPacket.source);
|
||||
source.setBreakpoint({
|
||||
line: 2
|
||||
}, function (aResponse) {
|
||||
do_check_true(!aResponse.error, "Should be able to set breakpoint.");
|
||||
test_black_box_paused();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
debugger; // line 2
|
||||
k(100); // line 3
|
||||
}, // line 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
BLACK_BOXED_URL,
|
||||
1
|
||||
);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function runTest() { // line 1
|
||||
doStuff( // line 2
|
||||
function (n) { // line 3
|
||||
return n; // line 4
|
||||
} // line 5
|
||||
); // line 6
|
||||
} // line 7
|
||||
+ "\n runTest();", // line 8
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
function test_black_box_paused() {
|
||||
gThreadClient.getSources(function ({error, sources}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
|
||||
sourceClient.blackBox(function ({error, pausedInSource}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
do_check_true(pausedInSource, "We should be notified that we are currently paused in this source");
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
}
|
||||
84
devtools/server/tests/unit/test_blackboxing-05.js
Normal file
84
devtools/server/tests/unit/test_blackboxing-05.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test exceptions inside black boxed sources.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
// XXX: We have to do an executeSoon so that the error isn't caught and
|
||||
// reported by DebuggerClient.requester (because we are using the local
|
||||
// transport and share a stack) which causes the test to fail.
|
||||
Services.tm.mainThread.dispatch({
|
||||
run: test_black_box
|
||||
}, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
function test_black_box()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", test_black_box_exception);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
throw new Error("wu tang clan ain't nuthin' ta fuck wit"); // line 2
|
||||
k(100); // line 3
|
||||
}, // line 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
BLACK_BOXED_URL,
|
||||
1
|
||||
);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function runTest() { // line 1
|
||||
doStuff( // line 2
|
||||
function (n) { // line 3
|
||||
debugger; // line 4
|
||||
} // line 5
|
||||
); // line 6
|
||||
} // line 7
|
||||
+ "\ndebugger;\n" // line 8
|
||||
+ "try { runTest() } catch (ex) { }", // line 9
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
function test_black_box_exception() {
|
||||
gThreadClient.getSources(function ({error, sources}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
|
||||
sourceClient.blackBox(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
gThreadClient.pauseOnExceptions(true);
|
||||
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.frame.where.source.url, SOURCE_URL,
|
||||
"We shouldn't pause while in the black boxed source.");
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
}
|
||||
102
devtools/server/tests/unit/test_blackboxing-06.js
Normal file
102
devtools/server/tests/unit/test_blackboxing-06.js
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can black box source mapped sources.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
const {SourceNode} = require("source-map");
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
|
||||
promise.resolve(setup_code())
|
||||
.then(black_box_code)
|
||||
.then(run_code)
|
||||
.then(test_correct_location)
|
||||
.then(null, function (error) {
|
||||
do_check_true(false, "Should not get an error, got " + error);
|
||||
})
|
||||
.then(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function setup_code() {
|
||||
let { code, map } = (new SourceNode(null, null, null, [
|
||||
new SourceNode(1, 0, "a.js", "" + function a() {
|
||||
return b();
|
||||
}),
|
||||
"\n",
|
||||
new SourceNode(1, 0, "b.js", "" + function b() {
|
||||
debugger; // Don't want to stop here.
|
||||
return c();
|
||||
}),
|
||||
"\n",
|
||||
new SourceNode(1, 0, "c.js", "" + function c() {
|
||||
debugger; // Want to stop here.
|
||||
}),
|
||||
"\n"
|
||||
])).toStringWithSourceMap({
|
||||
file: "abc.js",
|
||||
sourceRoot: "http://example.com/"
|
||||
});
|
||||
|
||||
code += "//# sourceMappingURL=data:text/json," + map.toString();
|
||||
|
||||
Components.utils.evalInSandbox(code,
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"http://example.com/abc.js");
|
||||
}
|
||||
|
||||
function black_box_code() {
|
||||
const d = promise.defer();
|
||||
|
||||
gThreadClient.getSources(function ({ sources, error }) {
|
||||
do_check_true(!error, "Shouldn't get an error getting sources");
|
||||
const source = sources.filter((s) => {
|
||||
return s.url.indexOf("b.js") !== -1;
|
||||
})[0];
|
||||
do_check_true(!!source, "We should have our source in the sources list");
|
||||
|
||||
gThreadClient.source(source).blackBox(function ({ error }) {
|
||||
do_check_true(!error, "Should not get an error black boxing");
|
||||
d.resolve(true);
|
||||
});
|
||||
});
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function run_code() {
|
||||
const d = promise.defer();
|
||||
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
d.resolve(aPacket);
|
||||
gThreadClient.resume();
|
||||
});
|
||||
gDebuggee.a();
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function test_correct_location(aPacket) {
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement",
|
||||
"Should hit a debugger statement.");
|
||||
do_check_eq(aPacket.frame.where.source.url, "http://example.com/c.js",
|
||||
"Should have skipped over the debugger statement in the black boxed source");
|
||||
}
|
||||
62
devtools/server/tests/unit/test_blackboxing-07.js
Normal file
62
devtools/server/tests/unit/test_blackboxing-07.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that sources whose URL ends with ".min.js" automatically get black
|
||||
* boxed.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-black-box");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
testBlackBox();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const BLACK_BOXED_URL = "http://example.com/black-boxed.min.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
const testBlackBox = Task.async(function* () {
|
||||
yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||
|
||||
const { sources } = yield getSources(gThreadClient);
|
||||
equal(sources.length, 2);
|
||||
|
||||
const blackBoxedSource = sources.filter(s => s.url === BLACK_BOXED_URL)[0];
|
||||
equal(blackBoxedSource.isBlackBoxed, true);
|
||||
|
||||
const regularSource = sources.filter(s => s.url === SOURCE_URL)[0];
|
||||
equal(regularSource.isBlackBoxed, false);
|
||||
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
function evalCode() {
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function blackBoxed() {},
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
BLACK_BOXED_URL,
|
||||
1
|
||||
);
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function source() {}
|
||||
+ "\ndebugger;",
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
75
devtools/server/tests/unit/test_breakpoint-01.js
Normal file
75
devtools/server/tests/unit/test_breakpoint-01.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check basic breakpoint functionality.
|
||||
*/
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = {
|
||||
line: gDebuggee.line0 + 3
|
||||
};
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line0 + 1
|
||||
"var a = 1;\n" + // line0 + 2
|
||||
"var b = 2;\n", // line0 + 3
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
67
devtools/server/tests/unit/test_breakpoint-02.js
Normal file
67
devtools/server/tests/unit/test_breakpoint-02.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting breakpoints when the debuggee is running works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_breakpoint_running();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_breakpoint_running()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let location = { line: gDebuggee.line0 + 3 };
|
||||
|
||||
gThreadClient.resume();
|
||||
|
||||
// Setting the breakpoint later should interrupt the debuggee.
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "interrupted");
|
||||
});
|
||||
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
source.setBreakpoint(location, function (aResponse) {
|
||||
// Eval scripts don't stick around long enough for the breakpoint to be set,
|
||||
// so just make sure we got the expected response from the actor.
|
||||
do_check_neq(aResponse.error, "noScript");
|
||||
|
||||
do_execute_soon(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" +
|
||||
"var a = 1;\n" + // line0 + 2
|
||||
"var b = 2;\n", // line0 + 3
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
96
devtools/server/tests/unit/test_breakpoint-03.js
Normal file
96
devtools/server/tests/unit/test_breakpoint-03.js
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint on a line without code will skip
|
||||
* forward when we know the script isn't GCed (the debugger is connected,
|
||||
* so it's kept alive).
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var test_no_skip_breakpoint = Task.async(function*(source, location) {
|
||||
let [aResponse, bpClient] = yield source.setBreakpoint(
|
||||
Object.assign({}, location, { noSliding: true })
|
||||
);
|
||||
|
||||
do_check_true(!aResponse.actualLocation);
|
||||
do_check_eq(bpClient.location.line, gDebuggee.line0 + 3);
|
||||
yield bpClient.remove();
|
||||
});
|
||||
|
||||
var test_skip_breakpoint = function() {
|
||||
gThreadClient.addOneTimeListener("paused", Task.async(function *(aEvent, aPacket) {
|
||||
let location = { line: gDebuggee.line0 + 3 };
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
|
||||
// First, make sure that we can disable sliding with the
|
||||
// `noSliding` option.
|
||||
yield test_no_skip_breakpoint(source, location);
|
||||
|
||||
// Now make sure that the breakpoint properly slides forward one line.
|
||||
const [aResponse, bpClient] = yield source.setBreakpoint(location);
|
||||
do_check_true(!!aResponse.actualLocation);
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gThreadClient.resume();
|
||||
}));
|
||||
|
||||
// Use `evalInSandbox` to make the debugger treat it as normal
|
||||
// globally-scoped code, where breakpoint sliding rules apply.
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line0 + 1
|
||||
"var a = 1;\n" + // line0 + 2
|
||||
"// A comment.\n" + // line0 + 3
|
||||
"var b = 2;", // line0 + 4
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
80
devtools/server/tests/unit/test_breakpoint-04.js
Normal file
80
devtools/server/tests/unit/test_breakpoint-04.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line in a child script works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_child_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 3 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// actualLocation is not returned when breakpoints don't skip forward.
|
||||
do_check_eq(aResponse.actualLocation, undefined);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" this.b = 2;\n" + // line0 + 3
|
||||
"}\n" + // line0 + 4
|
||||
"debugger;\n" + // line0 + 5
|
||||
"foo();\n", // line0 + 6
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
82
devtools/server/tests/unit/test_breakpoint-05.js
Normal file
82
devtools/server/tests/unit/test_breakpoint-05.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in a child script
|
||||
* will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 3 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" // A comment.\n" + // line0 + 3
|
||||
" this.b = 2;\n" + // line0 + 4
|
||||
"}\n" + // line0 + 5
|
||||
"debugger;\n" + // line0 + 6
|
||||
"foo();\n", // line0 + 7
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
89
devtools/server/tests/unit/test_breakpoint-06.js
Normal file
89
devtools/server/tests/unit/test_breakpoint-06.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in a deeply-nested
|
||||
* child script will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_nested_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_nested_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 5 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" function bar() {\n" + // line0 + 2
|
||||
" function baz() {\n" + // line0 + 3
|
||||
" this.a = 1;\n" + // line0 + 4
|
||||
" // A comment.\n" + // line0 + 5
|
||||
" this.b = 2;\n" + // line0 + 6
|
||||
" }\n" + // line0 + 7
|
||||
" baz();\n" + // line0 + 8
|
||||
" }\n" + // line0 + 9
|
||||
" bar();\n" + // line0 + 10
|
||||
"}\n" + // line0 + 11
|
||||
"debugger;\n" + // line0 + 12
|
||||
"foo();\n", // line0 + 13
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
85
devtools/server/tests/unit/test_breakpoint-07.js
Normal file
85
devtools/server/tests/unit/test_breakpoint-07.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in the second child
|
||||
* script will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_second_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_second_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 6 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
|
||||
Cu.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" bar();\n" + // line0 + 2
|
||||
"}\n" + // line0 + 3
|
||||
"function bar() {\n" + // line0 + 4
|
||||
" this.a = 1;\n" + // line0 + 5
|
||||
" // A comment.\n" + // line0 + 6
|
||||
" this.b = 2;\n" + // line0 + 7
|
||||
"}\n" + // line0 + 8
|
||||
"debugger;\n" + // line0 + 9
|
||||
"foo();\n", // line0 + 10
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
96
devtools/server/tests/unit/test_breakpoint-08.js
Normal file
96
devtools/server/tests/unit/test_breakpoint-08.js
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in a child script
|
||||
* will skip forward, in a file with two scripts.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.eval(aPacket.frame.actor, "foo", function (aResponse) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let obj = gThreadClient.pauseGrip(aPacket.why.frameFinished.return);
|
||||
obj.getDefinitionSite(runWithBreakpoint);
|
||||
});
|
||||
});
|
||||
|
||||
function runWithBreakpoint(aPacket) {
|
||||
let source = gThreadClient.source(aPacket.source);
|
||||
let location = { line: gDebuggee.line0 + 3 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" // A comment.\n" + // line0 + 3
|
||||
" this.b = 2;\n" + // line0 + 4
|
||||
"}\n", // line0 + 5
|
||||
gDebuggee,
|
||||
"1.7",
|
||||
"script1.js");
|
||||
|
||||
Cu.evalInSandbox("var line1 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line1 + 1
|
||||
"foo();\n", // line1 + 2
|
||||
gDebuggee,
|
||||
"1.7",
|
||||
"script2.js");
|
||||
}
|
||||
88
devtools/server/tests/unit/test_breakpoint-09.js
Normal file
88
devtools/server/tests/unit/test_breakpoint-09.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that removing a breakpoint works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_remove_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_remove_breakpoint()
|
||||
{
|
||||
let done = false;
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 2 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
done = true;
|
||||
gThreadClient.addOneTimeListener("paused",
|
||||
function (aEvent, aPacket) {
|
||||
// The breakpoint should not be hit again.
|
||||
gThreadClient.resume(function () {
|
||||
do_check_true(false);
|
||||
});
|
||||
});
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"function foo(stop) {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" if (stop) return;\n" + // line0 + 3
|
||||
" delete this.a;\n" + // line0 + 4
|
||||
" foo(true);\n" + // line0 + 5
|
||||
"}\n" + // line0 + 6
|
||||
"debugger;\n" + // line1 + 7
|
||||
"foo();\n", // line1 + 8
|
||||
gDebuggee);
|
||||
if (!done) {
|
||||
do_check_true(false);
|
||||
}
|
||||
gClient.close().then(gCallback);
|
||||
}
|
||||
89
devtools/server/tests/unit/test_breakpoint-10.js
Normal file
89
devtools/server/tests/unit/test_breakpoint-10.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line with multiple entry points
|
||||
* triggers no matter which entry point we reach.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_child_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 3 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// actualLocation is not returned when breakpoints don't skip forward.
|
||||
do_check_eq(aResponse.actualLocation, undefined);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.i, 0);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.i, 1);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit again.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line0 + 1
|
||||
"var a, i = 0;\n" + // line0 + 2
|
||||
"for (i = 1; i <= 2; i++) {\n" + // line0 + 3
|
||||
" a = i;\n" + // line0 + 4
|
||||
"}\n", // line0 + 5
|
||||
gDebuggee);
|
||||
}
|
||||
88
devtools/server/tests/unit/test_breakpoint-11.js
Normal file
88
devtools/server/tests/unit/test_breakpoint-11.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that setting a breakpoint in a line with bytecodes in multiple
|
||||
* scripts, sets the breakpoint in all of them (bug 793214).
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_child_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 2 };
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// actualLocation is not returned when breakpoints don't skip forward.
|
||||
do_check_eq(aResponse.actualLocation, undefined);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, undefined);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a.b, 1);
|
||||
do_check_eq(gDebuggee.res, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit again.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line0 + 1
|
||||
"var a = { b: 1, f: function() { return 2; } };\n" + // line0+2
|
||||
"var res = a.f();\n", // line0 + 3
|
||||
gDebuggee);
|
||||
}
|
||||
113
devtools/server/tests/unit/test_breakpoint-12.js
Normal file
113
devtools/server/tests/unit/test_breakpoint-12.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that setting a breakpoint twice in a line without bytecodes works
|
||||
* as expected.
|
||||
*/
|
||||
|
||||
const NUM_BREAKPOINTS = 10;
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gBpActor;
|
||||
var gCount;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
gCount = 1;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 3};
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
gBpActor = aResponse.actor;
|
||||
|
||||
// Set more breakpoints at the same location.
|
||||
set_breakpoints(source, location);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" // A comment.\n" + // line0 + 3
|
||||
" this.b = 2;\n" + // line0 + 4
|
||||
"}\n" + // line0 + 5
|
||||
"debugger;\n" + // line0 + 6
|
||||
"foo();\n", // line0 + 7
|
||||
gDebuggee);
|
||||
}
|
||||
|
||||
// Set many breakpoints at the same location.
|
||||
function set_breakpoints(source, location) {
|
||||
do_check_neq(gCount, NUM_BREAKPOINTS);
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.source.actor, source.actor);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
// Check that the same breakpoint actor was returned.
|
||||
do_check_eq(aResponse.actor, gBpActor);
|
||||
|
||||
if (++gCount < NUM_BREAKPOINTS) {
|
||||
set_breakpoints(source, location);
|
||||
return;
|
||||
}
|
||||
|
||||
// After setting all the breakpoints, check that only one has effectively
|
||||
// remained.
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// We don't expect any more pauses after the breakpoint was hit once.
|
||||
do_check_true(false);
|
||||
});
|
||||
gThreadClient.resume(function () {
|
||||
// Give any remaining breakpoints a chance to trigger.
|
||||
do_timeout(1000, function () {
|
||||
gClient.close().then(gCallback);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
}
|
||||
115
devtools/server/tests/unit/test_breakpoint-13.js
Normal file
115
devtools/server/tests/unit/test_breakpoint-13.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that execution doesn't pause twice while stepping, when encountering
|
||||
* either a breakpoint or a debugger statement.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 2 };
|
||||
|
||||
source.setBreakpoint(location, Task.async(function* (aResponse, bpClient) {
|
||||
const testCallbacks = [
|
||||
function (aPacket) {
|
||||
// Check that the stepping worked.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// Entered the foo function call frame.
|
||||
do_check_eq(aPacket.frame.where.line, location.line);
|
||||
do_check_neq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// At the end of the foo function call frame.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||
do_check_neq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// Check that the breakpoint wasn't the reason for this pause, but
|
||||
// that the frame is about to be popped while stepping.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||
do_check_neq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
|
||||
},
|
||||
function (aPacket) {
|
||||
// The foo function call frame was just popped from the stack.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
do_check_eq(aPacket.poppedFrames.length, 1);
|
||||
},
|
||||
function (aPacket) {
|
||||
// Check that the debugger statement wasn't the reason for this pause.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
|
||||
do_check_neq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// Check that the debugger statement wasn't the reason for this pause.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
|
||||
do_check_neq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
];
|
||||
|
||||
for (let callback of testCallbacks) {
|
||||
let waiter = waitForPause(gThreadClient);
|
||||
gThreadClient.stepIn();
|
||||
let packet = yield waiter;
|
||||
callback(packet);
|
||||
}
|
||||
|
||||
// Remove the breakpoint and finish.
|
||||
let waiter = waitForPause(gThreadClient);
|
||||
gThreadClient.stepIn();
|
||||
yield waiter;
|
||||
bpClient.remove(() => gThreadClient.resume(() => gClient.close().then(gCallback)));
|
||||
}));
|
||||
});
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2 <-- Breakpoint is set here.
|
||||
"}\n" + // line0 + 3
|
||||
"debugger;\n" + // line0 + 4
|
||||
"foo();\n" + // line0 + 5
|
||||
"debugger;\n" + // line0 + 6
|
||||
"var b = 2;\n", // line0 + 7
|
||||
gDebuggee);
|
||||
}
|
||||
113
devtools/server/tests/unit/test_breakpoint-14.js
Normal file
113
devtools/server/tests/unit/test_breakpoint-14.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that a breakpoint or a debugger statement cause execution to pause even
|
||||
* in a stepped-over function.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-stack", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = { line: gDebuggee.line0 + 2 };
|
||||
|
||||
source.setBreakpoint(location, Task.async(function* (aResponse, bpClient) {
|
||||
const testCallbacks = [
|
||||
function (aPacket) {
|
||||
// Check that the stepping worked.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// Reached the breakpoint.
|
||||
do_check_eq(aPacket.frame.where.line, location.line);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_neq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// Stepped to the closing brace of the function.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// The frame is about to be popped while stepping.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||
do_check_neq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
do_check_eq(aPacket.why.frameFinished.return.type, "undefined");
|
||||
},
|
||||
function (aPacket) {
|
||||
// The foo function call frame was just popped from the stack.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
do_check_eq(aPacket.poppedFrames.length, 1);
|
||||
},
|
||||
function (aPacket) {
|
||||
// Check that the debugger statement wasn't the reason for this pause.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
|
||||
do_check_neq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
function (aPacket) {
|
||||
// Check that the debugger statement wasn't the reason for this pause.
|
||||
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7);
|
||||
do_check_neq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||
},
|
||||
];
|
||||
|
||||
for (let callback of testCallbacks) {
|
||||
let waiter = waitForPause(gThreadClient);
|
||||
gThreadClient.stepOver();
|
||||
let packet = yield waiter;
|
||||
callback(packet);
|
||||
}
|
||||
|
||||
// Remove the breakpoint and finish.
|
||||
let waiter = waitForPause(gThreadClient);
|
||||
gThreadClient.stepOver();
|
||||
yield waiter;
|
||||
bpClient.remove(() => gThreadClient.resume(() => gClient.close().then(gCallback)));
|
||||
}));
|
||||
});
|
||||
|
||||
Cu.evalInSandbox("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2 <-- Breakpoint is set here.
|
||||
"}\n" + // line0 + 3
|
||||
"debugger;\n" + // line0 + 4
|
||||
"foo();\n" + // line0 + 5
|
||||
"debugger;\n" + // line0 + 6
|
||||
"var b = 2;\n", // line0 + 7
|
||||
gDebuggee);
|
||||
}
|
||||
69
devtools/server/tests/unit/test_breakpoint-15.js
Normal file
69
devtools/server/tests/unit/test_breakpoint-15.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that adding a breakpoint in the same place returns the same actor.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
testSameBreakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
const testSameBreakpoint = Task.async(function* () {
|
||||
let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||
let source = gThreadClient.source(packet.frame.where.source);
|
||||
|
||||
// Whole line
|
||||
let wholeLineLocation = {
|
||||
line: 2
|
||||
};
|
||||
|
||||
let [firstResponse, firstBpClient] = yield setBreakpoint(source, wholeLineLocation);
|
||||
let [secondResponse, secondBpClient] = yield setBreakpoint(source, wholeLineLocation);
|
||||
|
||||
do_check_eq(firstBpClient.actor, secondBpClient.actor, "Should get the same actor w/ whole line breakpoints");
|
||||
|
||||
// Specific column
|
||||
|
||||
let columnLocation = {
|
||||
line: 2,
|
||||
column: 6
|
||||
};
|
||||
|
||||
[firstResponse, firstBpClient] = yield setBreakpoint(source, columnLocation);
|
||||
[secondResponse, secondBpClient] = yield setBreakpoint(source, columnLocation);
|
||||
|
||||
do_check_eq(secondBpClient.actor, secondBpClient.actor, "Should get the same actor column breakpoints");
|
||||
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
function evalCode() {
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
let arg = 15; // line 2 - Step in here
|
||||
k(arg); // line 3
|
||||
} + "\n" // line 4
|
||||
+ "debugger;", // line 5
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
1
|
||||
);
|
||||
}
|
||||
83
devtools/server/tests/unit/test_breakpoint-16.js
Normal file
83
devtools/server/tests/unit/test_breakpoint-16.js
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that we can set breakpoints in columns, not just lines.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-breakpoints", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient,
|
||||
"test-breakpoints",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_column_breakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_column_breakpoint()
|
||||
{
|
||||
// Debugger statement
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
let location = {
|
||||
line: gDebuggee.line0 + 1,
|
||||
column: 55
|
||||
};
|
||||
let timesBreakpointHit = 0;
|
||||
|
||||
source.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
gThreadClient.addListener("paused", function onPaused(aEvent, aPacket) {
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
do_check_eq(aPacket.frame.where.source.actor, source.actor);
|
||||
do_check_eq(aPacket.frame.where.line, location.line);
|
||||
do_check_eq(aPacket.frame.where.column, location.column);
|
||||
|
||||
do_check_eq(gDebuggee.acc, timesBreakpointHit);
|
||||
do_check_eq(aPacket.frame.environment.bindings.variables.i.value,
|
||||
timesBreakpointHit);
|
||||
|
||||
if (++timesBreakpointHit === 3) {
|
||||
gThreadClient.removeListener("paused", onPaused);
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(() => gClient.close().then(gCallback));
|
||||
});
|
||||
} else {
|
||||
gThreadClient.resume();
|
||||
}
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
Components.utils.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n" +
|
||||
"(function () { debugger; this.acc = 0; for (var i = 0; i < 3; i++) this.acc++; }());",
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
120
devtools/server/tests/unit/test_breakpoint-17.js
Normal file
120
devtools/server/tests/unit/test_breakpoint-17.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that when we add 2 breakpoints to the same line at different columns and
|
||||
* then remove one of them, we don't remove them both.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, do_test_finished);
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-breakpoints", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-breakpoints", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_breakpoints_columns();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const code =
|
||||
"(" + function (global) {
|
||||
global.foo = function () {
|
||||
Math.abs(-1); Math.log(0.5);
|
||||
debugger;
|
||||
};
|
||||
debugger;
|
||||
} + "(this))";
|
||||
|
||||
const firstLocation = {
|
||||
line: 3,
|
||||
column: 4
|
||||
};
|
||||
|
||||
const secondLocation = {
|
||||
line: 3,
|
||||
column: 18
|
||||
};
|
||||
|
||||
function test_breakpoints_columns() {
|
||||
gClient.addOneTimeListener("paused", set_breakpoints);
|
||||
|
||||
Components.utils.evalInSandbox(code, gDebuggee, "1.8", "http://example.com/", 1);
|
||||
}
|
||||
|
||||
function set_breakpoints(aEvent, aPacket) {
|
||||
let first, second;
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
|
||||
source.setBreakpoint(firstLocation, function ({ error, actualLocation },
|
||||
aBreakpointClient) {
|
||||
do_check_true(!error, "Should not get an error setting the breakpoint");
|
||||
do_check_true(!actualLocation, "Should not get an actualLocation");
|
||||
first = aBreakpointClient;
|
||||
|
||||
source.setBreakpoint(secondLocation, function ({ error, actualLocation },
|
||||
aBreakpointClient) {
|
||||
do_check_true(!error, "Should not get an error setting the breakpoint");
|
||||
do_check_true(!actualLocation, "Should not get an actualLocation");
|
||||
second = aBreakpointClient;
|
||||
|
||||
test_different_actors(first, second);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_different_actors(aFirst, aSecond) {
|
||||
do_check_neq(aFirst.actor, aSecond.actor,
|
||||
"Each breakpoint should have a different actor");
|
||||
test_remove_one(aFirst, aSecond);
|
||||
}
|
||||
|
||||
function test_remove_one(aFirst, aSecond) {
|
||||
aFirst.remove(function ({error}) {
|
||||
do_check_true(!error, "Should not get an error removing a breakpoint");
|
||||
|
||||
let hitSecond;
|
||||
gClient.addListener("paused", function _onPaused(aEvent, {why, frame}) {
|
||||
if (why.type == "breakpoint") {
|
||||
hitSecond = true;
|
||||
do_check_eq(why.actors.length, 1,
|
||||
"Should only be paused because of one breakpoint actor");
|
||||
do_check_eq(why.actors[0], aSecond.actor,
|
||||
"Should be paused because of the correct breakpoint actor");
|
||||
do_check_eq(frame.where.line, secondLocation.line,
|
||||
"Should be at the right line");
|
||||
do_check_eq(frame.where.column, secondLocation.column,
|
||||
"Should be at the right column");
|
||||
gThreadClient.resume();
|
||||
return;
|
||||
}
|
||||
|
||||
if (why.type == "debuggerStatement") {
|
||||
gClient.removeListener("paused", _onPaused);
|
||||
do_check_true(hitSecond,
|
||||
"We should still hit `second`, but not `first`.");
|
||||
|
||||
gClient.close().then(gCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
do_check_true(false, "Should never get here");
|
||||
});
|
||||
|
||||
gThreadClient.resume(() => gDebuggee.foo());
|
||||
});
|
||||
}
|
||||
82
devtools/server/tests/unit/test_breakpoint-18.js
Normal file
82
devtools/server/tests/unit/test_breakpoint-18.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that we only break on offsets that are entry points for the line we are
|
||||
* breaking on. Bug 907278.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-breakpoints", aServer);
|
||||
gDebuggee.console = { log: x => void x };
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient,
|
||||
"test-breakpoints",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
setUpCode();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setUpCode() {
|
||||
gClient.addOneTimeListener("paused", setBreakpoint);
|
||||
Cu.evalInSandbox(
|
||||
"debugger;\n" +
|
||||
function test() {
|
||||
console.log("foo bar");
|
||||
debugger;
|
||||
},
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"http://example.com/",
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
function setBreakpoint(aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
gClient.addOneTimeListener("resumed", runCode);
|
||||
|
||||
source.setBreakpoint({ line: 2 }, ({ error }) => {
|
||||
do_check_true(!error);
|
||||
gThreadClient.resume();
|
||||
});
|
||||
}
|
||||
|
||||
function runCode() {
|
||||
gClient.addOneTimeListener("paused", testBPHit);
|
||||
gDebuggee.test();
|
||||
}
|
||||
|
||||
function testBPHit(event, { why }) {
|
||||
do_check_eq(why.type, "breakpoint");
|
||||
gClient.addOneTimeListener("paused", testDbgStatement);
|
||||
gThreadClient.resume();
|
||||
}
|
||||
|
||||
function testDbgStatement(event, { why }) {
|
||||
// Should continue to the debugger statement.
|
||||
do_check_eq(why.type, "debuggerStatement");
|
||||
// Not break on another offset from the same line (that isn't an entry point
|
||||
// to the line)
|
||||
do_check_neq(why.type, "breakpoint");
|
||||
gClient.close().then(gCallback);
|
||||
}
|
||||
70
devtools/server/tests/unit/test_breakpoint-19.js
Normal file
70
devtools/server/tests/unit/test_breakpoint-19.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that setting a breakpoint in a not-yet-existing script doesn't throw
|
||||
* an error (see bug 897567). Also make sure that this breakpoint works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-breakpoints", aServer);
|
||||
gDebuggee.console = { log: x => void x };
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient,
|
||||
"test-breakpoints",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
testBreakpoint();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const URL = "test.js";
|
||||
|
||||
function setUpCode() {
|
||||
Cu.evalInSandbox(
|
||||
"" + function test() { // 1
|
||||
var a = 1; // 2
|
||||
debugger; // 3
|
||||
} + // 4
|
||||
"\ndebugger;", // 5
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
URL
|
||||
);
|
||||
}
|
||||
|
||||
const testBreakpoint = Task.async(function* () {
|
||||
let source = yield getSource(gThreadClient, URL);
|
||||
let [response, bpClient] = yield setBreakpoint(source, {line: 2});
|
||||
ok(!response.error);
|
||||
|
||||
let actor = response.actor;
|
||||
ok(actor);
|
||||
|
||||
yield executeOnNextTickAndWaitForPause(setUpCode, gClient);
|
||||
yield resume(gThreadClient);
|
||||
|
||||
let packet = yield executeOnNextTickAndWaitForPause(gDebuggee.test, gClient);
|
||||
equal(packet.why.type, "breakpoint");
|
||||
notEqual(packet.why.actors.indexOf(actor), -1);
|
||||
|
||||
finishClient(gClient);
|
||||
});
|
||||
108
devtools/server/tests/unit/test_breakpoint-20.js
Normal file
108
devtools/server/tests/unit/test_breakpoint-20.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verify that when two of the "same" source are loaded concurrently (like e10s
|
||||
* frame scripts), breakpoints get hit in scripts defined by all sources.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gTraceClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-breakpoints");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestThread(gClient, "test-breakpoints", testBreakpoint);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
const testBreakpoint = Task.async(function* (threadResponse, tabClient, threadClient, tabResponse) {
|
||||
evalSetupCode();
|
||||
|
||||
// Load the test source once.
|
||||
|
||||
evalTestCode();
|
||||
equal(gDebuggee.functions.length, 1,
|
||||
"The test code should have added a function.");
|
||||
|
||||
// Set a breakpoint in the test source.
|
||||
|
||||
const source = yield getSource(threadClient, "test.js");
|
||||
const [response, bpClient] = yield setBreakpoint(source, {
|
||||
line: 3
|
||||
});
|
||||
ok(!response.error, "Shouldn't get an error setting the BP.");
|
||||
ok(!response.actualLocation,
|
||||
"Shouldn't get an actualLocation, the location we provided was good.");
|
||||
const bpActor = response.actor;
|
||||
|
||||
yield resume(threadClient);
|
||||
|
||||
// Load the test source again.
|
||||
|
||||
evalTestCode();
|
||||
equal(gDebuggee.functions.length, 2,
|
||||
"The test code should have added another function.");
|
||||
|
||||
// Should hit our breakpoint in a script defined by the first instance of the
|
||||
// test source.
|
||||
|
||||
const bpPause1 = yield executeOnNextTickAndWaitForPause(gDebuggee.functions[0],
|
||||
gClient);
|
||||
equal(bpPause1.why.type, "breakpoint",
|
||||
"Should pause because of hitting our breakpoint (not debugger statement).");
|
||||
equal(bpPause1.why.actors[0], bpActor,
|
||||
"And the breakpoint actor should be correct.");
|
||||
const dbgStmtPause1 = yield executeOnNextTickAndWaitForPause(() => resume(threadClient),
|
||||
gClient);
|
||||
equal(dbgStmtPause1.why.type, "debuggerStatement",
|
||||
"And we should hit the debugger statement after the pause.");
|
||||
yield resume(threadClient);
|
||||
|
||||
// Should also hit our breakpoint in a script defined by the second instance
|
||||
// of the test source.
|
||||
|
||||
const bpPause2 = yield executeOnNextTickAndWaitForPause(gDebuggee.functions[1],
|
||||
gClient);
|
||||
equal(bpPause2.why.type, "breakpoint",
|
||||
"Should pause because of hitting our breakpoint (not debugger statement).");
|
||||
equal(bpPause2.why.actors[0], bpActor,
|
||||
"And the breakpoint actor should be correct.");
|
||||
const dbgStmtPause2 = yield executeOnNextTickAndWaitForPause(() => resume(threadClient),
|
||||
gClient);
|
||||
equal(dbgStmtPause2.why.type, "debuggerStatement",
|
||||
"And we should hit the debugger statement after the pause.");
|
||||
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
function evalSetupCode() {
|
||||
Cu.evalInSandbox(
|
||||
"this.functions = [];",
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"setup.js",
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
function evalTestCode() {
|
||||
Cu.evalInSandbox(
|
||||
` // 1
|
||||
this.functions.push(function () { // 2
|
||||
var setBreakpointHere = 1; // 3
|
||||
debugger; // 4
|
||||
}); // 5
|
||||
`,
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1
|
||||
);
|
||||
}
|
||||
85
devtools/server/tests/unit/test_breakpoint-21.js
Normal file
85
devtools/server/tests/unit/test_breakpoint-21.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Bug 1122064 - make sure that scripts introduced via onNewScripts
|
||||
* properly populate the `ScriptStore` with all there nested child
|
||||
* scripts, so you can set breakpoints on deeply nested scripts
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
var gCallback;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
run_test_with_server(DebuggerServer, function () {
|
||||
run_test_with_server(WorkerDebuggerServer, do_test_finished);
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function run_test_with_server(aServer, aCallback)
|
||||
{
|
||||
gCallback = aCallback;
|
||||
initTestDebuggerServer(aServer);
|
||||
gDebuggee = addTestGlobal("test-breakpoints", aServer);
|
||||
gClient = new DebuggerClient(aServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient,
|
||||
"test-breakpoints",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const test = Task.async(function* () {
|
||||
// Populate the `ScriptStore` so that we only test that the script
|
||||
// is added through `onNewScript`
|
||||
yield getSources(gThreadClient);
|
||||
|
||||
let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||
let source = gThreadClient.source(packet.frame.where.source);
|
||||
let location = {
|
||||
line: gDebuggee.line0 + 8
|
||||
};
|
||||
|
||||
let [res, bpClient] = yield setBreakpoint(source, location);
|
||||
ok(!res.error);
|
||||
|
||||
yield resume(gThreadClient);
|
||||
packet = yield waitForPause(gClient);
|
||||
do_check_eq(packet.type, "paused");
|
||||
do_check_eq(packet.why.type, "breakpoint");
|
||||
do_check_eq(packet.why.actors[0], bpClient.actor);
|
||||
do_check_eq(packet.frame.where.source.actor, source.actor);
|
||||
do_check_eq(packet.frame.where.line, location.line);
|
||||
|
||||
yield resume(gThreadClient);
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
function evalCode() {
|
||||
// Start a new script
|
||||
Components.utils.evalInSandbox(
|
||||
"var line0 = Error().lineNumber;\n(" + function () {
|
||||
debugger;
|
||||
var a = (function () {
|
||||
return (function () {
|
||||
return (function () {
|
||||
return (function () {
|
||||
return (function () {
|
||||
var x = 10; // This line gets a breakpoint
|
||||
return 1;
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
} + ")()",
|
||||
gDebuggee
|
||||
);
|
||||
}
|
||||
180
devtools/server/tests/unit/test_breakpoint-actor-map.js
Normal file
180
devtools/server/tests/unit/test_breakpoint-actor-map.js
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test the functionality of the BreakpointActorMap object.
|
||||
|
||||
const { BreakpointActorMap } = require("devtools/server/actors/script");
|
||||
|
||||
function run_test() {
|
||||
test_get_actor();
|
||||
test_set_actor();
|
||||
test_delete_actor();
|
||||
test_find_actors();
|
||||
test_duplicate_actors();
|
||||
}
|
||||
|
||||
function test_get_actor() {
|
||||
let bpStore = new BreakpointActorMap();
|
||||
let location = {
|
||||
originalSourceActor: { actor: "actor1" },
|
||||
originalLine: 3
|
||||
};
|
||||
let columnLocation = {
|
||||
originalSourceActor: { actor: "actor2" },
|
||||
originalLine: 5,
|
||||
originalColumn: 15
|
||||
};
|
||||
|
||||
// Shouldn't have breakpoint
|
||||
do_check_eq(null, bpStore.getActor(location),
|
||||
"Breakpoint not added and shouldn't exist.");
|
||||
|
||||
bpStore.setActor(location, {});
|
||||
do_check_true(!!bpStore.getActor(location),
|
||||
"Breakpoint added but not found in Breakpoint Store.");
|
||||
|
||||
bpStore.deleteActor(location);
|
||||
do_check_eq(null, bpStore.getActor(location),
|
||||
"Breakpoint removed but still exists.");
|
||||
|
||||
// Same checks for breakpoint with a column
|
||||
do_check_eq(null, bpStore.getActor(columnLocation),
|
||||
"Breakpoint with column not added and shouldn't exist.");
|
||||
|
||||
bpStore.setActor(columnLocation, {});
|
||||
do_check_true(!!bpStore.getActor(columnLocation),
|
||||
"Breakpoint with column added but not found in Breakpoint Store.");
|
||||
|
||||
bpStore.deleteActor(columnLocation);
|
||||
do_check_eq(null, bpStore.getActor(columnLocation),
|
||||
"Breakpoint with column removed but still exists in Breakpoint Store.");
|
||||
}
|
||||
|
||||
function test_set_actor() {
|
||||
// Breakpoint with column
|
||||
let bpStore = new BreakpointActorMap();
|
||||
let location = {
|
||||
originalSourceActor: { actor: "actor1" },
|
||||
originalLine: 10,
|
||||
originalColumn: 9
|
||||
};
|
||||
bpStore.setActor(location, {});
|
||||
do_check_true(!!bpStore.getActor(location),
|
||||
"We should have the column breakpoint we just added");
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
location = {
|
||||
originalSourceActor: { actor: "actor2" },
|
||||
originalLine: 103
|
||||
};
|
||||
bpStore.setActor(location, {});
|
||||
do_check_true(!!bpStore.getActor(location),
|
||||
"We should have the whole line breakpoint we just added");
|
||||
}
|
||||
|
||||
function test_delete_actor() {
|
||||
// Breakpoint with column
|
||||
let bpStore = new BreakpointActorMap();
|
||||
let location = {
|
||||
originalSourceActor: { actor: "actor1" },
|
||||
originalLine: 10,
|
||||
originalColumn: 9
|
||||
};
|
||||
bpStore.setActor(location, {});
|
||||
bpStore.deleteActor(location);
|
||||
do_check_eq(bpStore.getActor(location), null,
|
||||
"We should not have the column breakpoint anymore");
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
location = {
|
||||
originalSourceActor: { actor: "actor2" },
|
||||
originalLine: 103
|
||||
};
|
||||
bpStore.setActor(location, {});
|
||||
bpStore.deleteActor(location);
|
||||
do_check_eq(bpStore.getActor(location), null,
|
||||
"We should not have the whole line breakpoint anymore");
|
||||
}
|
||||
|
||||
function test_find_actors() {
|
||||
let bps = [
|
||||
{ originalSourceActor: { actor: "actor1" }, originalLine: 10 },
|
||||
{ originalSourceActor: { actor: "actor1" }, originalLine: 10, originalColumn: 3 },
|
||||
{ originalSourceActor: { actor: "actor1" }, originalLine: 10, originalColumn: 10 },
|
||||
{ originalSourceActor: { actor: "actor1" }, originalLine: 23, originalColumn: 89 },
|
||||
{ originalSourceActor: { actor: "actor2" }, originalLine: 10, originalColumn: 1 },
|
||||
{ originalSourceActor: { actor: "actor2" }, originalLine: 20, originalColumn: 5 },
|
||||
{ originalSourceActor: { actor: "actor2" }, originalLine: 30, originalColumn: 34 },
|
||||
{ originalSourceActor: { actor: "actor2" }, originalLine: 40, originalColumn: 56 }
|
||||
];
|
||||
|
||||
let bpStore = new BreakpointActorMap();
|
||||
|
||||
for (let bp of bps) {
|
||||
bpStore.setActor(bp, bp);
|
||||
}
|
||||
|
||||
// All breakpoints
|
||||
|
||||
let bpSet = new Set(bps);
|
||||
for (let bp of bpStore.findActors()) {
|
||||
bpSet.delete(bp);
|
||||
}
|
||||
do_check_eq(bpSet.size, 0,
|
||||
"Should be able to iterate over all breakpoints");
|
||||
|
||||
// Breakpoints by URL
|
||||
|
||||
bpSet = new Set(bps.filter(bp => { return bp.originalSourceActor.actorID === "actor1"; }));
|
||||
for (let bp of bpStore.findActors({ originalSourceActor: { actorID: "actor1" } })) {
|
||||
bpSet.delete(bp);
|
||||
}
|
||||
do_check_eq(bpSet.size, 0,
|
||||
"Should be able to filter the iteration by url");
|
||||
|
||||
// Breakpoints by URL and line
|
||||
|
||||
bpSet = new Set(bps.filter(bp => { return bp.originalSourceActor.actorID === "actor1" && bp.originalLine === 10; }));
|
||||
let first = true;
|
||||
for (let bp of bpStore.findActors({ originalSourceActor: { actorID: "actor1" }, originalLine: 10 })) {
|
||||
if (first) {
|
||||
do_check_eq(bp.originalColumn, undefined,
|
||||
"Should always get the whole line breakpoint first");
|
||||
first = false;
|
||||
} else {
|
||||
do_check_neq(bp.originalColumn, undefined,
|
||||
"Should not get the whole line breakpoint any time other than first.");
|
||||
}
|
||||
bpSet.delete(bp);
|
||||
}
|
||||
do_check_eq(bpSet.size, 0,
|
||||
"Should be able to filter the iteration by url and line");
|
||||
}
|
||||
|
||||
function test_duplicate_actors() {
|
||||
let bpStore = new BreakpointActorMap();
|
||||
|
||||
// Breakpoint with column
|
||||
let location = {
|
||||
originalSourceActor: { actorID: "foo-actor" },
|
||||
originalLine: 10,
|
||||
originalColumn: 9
|
||||
};
|
||||
bpStore.setActor(location, {});
|
||||
bpStore.setActor(location, {});
|
||||
do_check_eq(bpStore.size, 1, "We should have only 1 column breakpoint");
|
||||
bpStore.deleteActor(location);
|
||||
|
||||
// Breakpoint without column (whole line breakpoint)
|
||||
location = {
|
||||
originalSourceActor: { actorID: "foo-actor" },
|
||||
originalLine: 15
|
||||
};
|
||||
bpStore.setActor(location, {});
|
||||
bpStore.setActor(location, {});
|
||||
do_check_eq(bpStore.size, 1, "We should have only 1 whole line breakpoint");
|
||||
bpStore.deleteActor(location);
|
||||
}
|
||||
39
devtools/server/tests/unit/test_client_close.js
Normal file
39
devtools/server/tests/unit/test_client_close.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gClient;
|
||||
var gDebuggee;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = testGlobal("test-1");
|
||||
DebuggerServer.addTestGlobal(gDebuggee);
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect().then(function (aType, aTraits) {
|
||||
attachTestTab(gClient, "test-1", function (aReply, aTabClient) {
|
||||
test_close(transport);
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_close(aTransport)
|
||||
{
|
||||
// Check that, if we fake a transport shutdown
|
||||
// (like if a device is unplugged)
|
||||
// the client is automatically closed,
|
||||
// and we can still call client.close.
|
||||
let onClosed = function () {
|
||||
gClient.removeListener("closed", onClosed);
|
||||
ok(true, "Client emitted 'closed' event");
|
||||
gClient.close().then(function () {
|
||||
ok(true, "client.close() successfully called its callback");
|
||||
do_test_finished();
|
||||
});
|
||||
};
|
||||
gClient.addListener("closed", onClosed);
|
||||
aTransport.close();
|
||||
}
|
||||
214
devtools/server/tests/unit/test_client_request.js
Normal file
214
devtools/server/tests/unit/test_client_request.js
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test the DebuggerClient.request API.
|
||||
|
||||
var gClient, gActorId;
|
||||
|
||||
function TestActor(conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
TestActor.prototype = {
|
||||
actorPrefix: "test",
|
||||
|
||||
hello: function () {
|
||||
return {hello: "world"};
|
||||
},
|
||||
|
||||
error: function () {
|
||||
return {error: "code", message: "human message"};
|
||||
}
|
||||
};
|
||||
TestActor.prototype.requestTypes = {
|
||||
"hello": TestActor.prototype.hello,
|
||||
"error": TestActor.prototype.error
|
||||
};
|
||||
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.addGlobalActor(TestActor);
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
add_test(init);
|
||||
add_test(test_client_request_callback);
|
||||
add_test(test_client_request_promise);
|
||||
add_test(test_client_request_promise_error);
|
||||
add_test(test_client_request_event_emitter);
|
||||
add_test(test_close_client_while_sending_requests);
|
||||
add_test(test_client_request_after_close);
|
||||
add_test(test_client_request_after_close_callback);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect()
|
||||
.then(() => gClient.listTabs())
|
||||
.then(aResponse => {
|
||||
gActorId = aResponse.test;
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function checkStack(expectedName) {
|
||||
if (!Services.prefs.getBoolPref("javascript.options.asyncstack")) {
|
||||
do_print("Async stacks are disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
let stack = Components.stack;
|
||||
while (stack) {
|
||||
do_print(stack.name);
|
||||
if (stack.name == expectedName) {
|
||||
// Reached back to outer function before request
|
||||
ok(true, "Complete stack");
|
||||
return;
|
||||
}
|
||||
stack = stack.asyncCaller || stack.caller;
|
||||
}
|
||||
ok(false, "Incomplete stack");
|
||||
}
|
||||
|
||||
function test_client_request_callback()
|
||||
{
|
||||
// Test that DebuggerClient.request accepts a `onResponse` callback as 2nd argument
|
||||
gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
}, response => {
|
||||
do_check_eq(response.from, gActorId);
|
||||
do_check_eq(response.hello, "world");
|
||||
checkStack("test_client_request_callback");
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function test_client_request_promise()
|
||||
{
|
||||
// Test that DebuggerClient.request returns a promise that resolves on response
|
||||
let request = gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
});
|
||||
|
||||
request.then(response => {
|
||||
do_check_eq(response.from, gActorId);
|
||||
do_check_eq(response.hello, "world");
|
||||
checkStack("test_client_request_promise");
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function test_client_request_promise_error()
|
||||
{
|
||||
// Test that DebuggerClient.request returns a promise that reject when server
|
||||
// returns an explicit error message
|
||||
let request = gClient.request({
|
||||
to: gActorId,
|
||||
type: "error"
|
||||
});
|
||||
|
||||
request.then(() => {
|
||||
do_throw("Promise shouldn't be resolved on error");
|
||||
}, response => {
|
||||
do_check_eq(response.from, gActorId);
|
||||
do_check_eq(response.error, "code");
|
||||
do_check_eq(response.message, "human message");
|
||||
checkStack("test_client_request_promise_error");
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function test_client_request_event_emitter()
|
||||
{
|
||||
// Test that DebuggerClient.request returns also an EventEmitter object
|
||||
let request = gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
});
|
||||
request.on("json-reply", reply => {
|
||||
do_check_eq(reply.from, gActorId);
|
||||
do_check_eq(reply.hello, "world");
|
||||
checkStack("test_client_request_event_emitter");
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function test_close_client_while_sending_requests() {
|
||||
// First send a first request that will be "active"
|
||||
// while the connection is closed.
|
||||
// i.e. will be sent but no response received yet.
|
||||
let activeRequest = gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
});
|
||||
|
||||
// Pile up a second one that will be "pending".
|
||||
// i.e. won't event be sent.
|
||||
let pendingRequest = gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
});
|
||||
|
||||
let expectReply = promise.defer();
|
||||
gClient.expectReply("root", function (response) {
|
||||
do_check_eq(response.error, "connectionClosed");
|
||||
do_check_eq(response.message, "server side packet can't be received as the connection just closed.");
|
||||
expectReply.resolve();
|
||||
});
|
||||
|
||||
gClient.close().then(() => {
|
||||
activeRequest.then(() => {
|
||||
ok(false, "First request unexpectedly succeed while closing the connection");
|
||||
}, response => {
|
||||
do_check_eq(response.error, "connectionClosed");
|
||||
do_check_eq(response.message, "'hello' active request packet to '" + gActorId + "' can't be sent as the connection just closed.");
|
||||
})
|
||||
.then(() => pendingRequest)
|
||||
.then(() => {
|
||||
ok(false, "Second request unexpectedly succeed while closing the connection");
|
||||
}, response => {
|
||||
do_check_eq(response.error, "connectionClosed");
|
||||
do_check_eq(response.message, "'hello' pending request packet to '" + gActorId + "' can't be sent as the connection just closed.");
|
||||
})
|
||||
.then(() => expectReply.promise)
|
||||
.then(run_next_test);
|
||||
});
|
||||
}
|
||||
|
||||
function test_client_request_after_close()
|
||||
{
|
||||
// Test that DebuggerClient.request fails after we called client.close()
|
||||
// (with promise API)
|
||||
let request = gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
});
|
||||
|
||||
request.then(response => {
|
||||
ok(false, "Request succeed even after client.close");
|
||||
}, response => {
|
||||
ok(true, "Request failed after client.close");
|
||||
do_check_eq(response.error, "connectionClosed");
|
||||
ok(response.message.match(/'hello' request packet to '.*' can't be sent as the connection is closed./));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function test_client_request_after_close_callback()
|
||||
{
|
||||
// Test that DebuggerClient.request fails after we called client.close()
|
||||
// (with callback API)
|
||||
let request = gClient.request({
|
||||
to: gActorId,
|
||||
type: "hello"
|
||||
}, response => {
|
||||
ok(true, "Request failed after client.close");
|
||||
do_check_eq(response.error, "connectionClosed");
|
||||
ok(response.message.match(/'hello' request packet to '.*' can't be sent as the connection is closed./));
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
61
devtools/server/tests/unit/test_conditional_breakpoint-01.js
Normal file
61
devtools/server/tests/unit/test_conditional_breakpoint-01.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition evaluates to true.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-conditional-breakpoint");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
source.setBreakpoint({
|
||||
line: 3,
|
||||
condition: "a === 1"
|
||||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.frame.where.line, 3);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n", // 3
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1);
|
||||
}
|
||||
60
devtools/server/tests/unit/test_conditional_breakpoint-02.js
Normal file
60
devtools/server/tests/unit/test_conditional_breakpoint-02.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition evaluates to false.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-conditional-breakpoint");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
source.setBreakpoint({
|
||||
line: 3,
|
||||
condition: "a === 2"
|
||||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.frame.where.line, 4);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n" + // 3
|
||||
"debugger;", // 4
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1);
|
||||
}
|
||||
61
devtools/server/tests/unit/test_conditional_breakpoint-03.js
Normal file
61
devtools/server/tests/unit/test_conditional_breakpoint-03.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition throws and make sure it pauses
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-conditional-breakpoint");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let source = gThreadClient.source(aPacket.frame.where.source);
|
||||
source.setBreakpoint({
|
||||
line: 3,
|
||||
condition: "throw new Error()"
|
||||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "breakpointConditionThrown");
|
||||
do_check_eq(aPacket.frame.where.line, 3);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n", // 3
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
1);
|
||||
}
|
||||
116
devtools/server/tests/unit/test_dbgactor.js
Normal file
116
devtools/server/tests/unit/test_dbgactor.js
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gClient;
|
||||
var gDebuggee;
|
||||
|
||||
const xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = testGlobal("test-1");
|
||||
DebuggerServer.addTestGlobal(gDebuggee);
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.addListener("connected", function (aEvent, aType, aTraits) {
|
||||
gClient.listTabs((aResponse) => {
|
||||
do_check_true("tabs" in aResponse);
|
||||
for (let tab of aResponse.tabs) {
|
||||
if (tab.title == "test-1") {
|
||||
test_attach_tab(tab.actor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
do_check_true(false); // We should have found our tab in the list.
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
|
||||
gClient.connect();
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
// Attach to |aTabActor|, and check the response.
|
||||
function test_attach_tab(aTabActor)
|
||||
{
|
||||
gClient.request({ to: aTabActor, type: "attach" }, function (aResponse) {
|
||||
do_check_false("error" in aResponse);
|
||||
do_check_eq(aResponse.from, aTabActor);
|
||||
do_check_eq(aResponse.type, "tabAttached");
|
||||
do_check_true(typeof aResponse.threadActor === "string");
|
||||
|
||||
test_attach_thread(aResponse.threadActor);
|
||||
});
|
||||
}
|
||||
|
||||
// Attach to |aThreadActor|, check the response, and resume it.
|
||||
function test_attach_thread(aThreadActor)
|
||||
{
|
||||
gClient.request({ to: aThreadActor, type: "attach" }, function (aResponse) {
|
||||
do_check_false("error" in aResponse);
|
||||
do_check_eq(aResponse.from, aThreadActor);
|
||||
do_check_eq(aResponse.type, "paused");
|
||||
do_check_true("why" in aResponse);
|
||||
do_check_eq(aResponse.why.type, "attached");
|
||||
|
||||
test_resume_thread(aThreadActor);
|
||||
});
|
||||
}
|
||||
|
||||
// Resume |aThreadActor|, and see that it stops at the 'debugger'
|
||||
// statement.
|
||||
function test_resume_thread(aThreadActor)
|
||||
{
|
||||
// Allow the client to resume execution.
|
||||
gClient.request({ to: aThreadActor, type: "resume" }, function (aResponse) {
|
||||
do_check_false("error" in aResponse);
|
||||
do_check_eq(aResponse.from, aThreadActor);
|
||||
do_check_eq(aResponse.type, "resumed");
|
||||
|
||||
do_check_eq(xpcInspector.eventLoopNestLevel, 0);
|
||||
|
||||
// Now that we know we're resumed, we can make the debuggee do something.
|
||||
Cu.evalInSandbox("var a = true; var b = false; debugger; var b = true;", gDebuggee);
|
||||
// Now make sure that we've run the code after the debugger statement...
|
||||
do_check_true(gDebuggee.b);
|
||||
});
|
||||
|
||||
gClient.addListener("paused", function (aName, aPacket) {
|
||||
do_check_eq(aName, "paused");
|
||||
do_check_false("error" in aPacket);
|
||||
do_check_eq(aPacket.from, aThreadActor);
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_true("actor" in aPacket);
|
||||
do_check_true("why" in aPacket);
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
|
||||
// Reach around the protocol to check that the debuggee is in the state
|
||||
// we expect.
|
||||
do_check_true(gDebuggee.a);
|
||||
do_check_false(gDebuggee.b);
|
||||
|
||||
do_check_eq(xpcInspector.eventLoopNestLevel, 1);
|
||||
|
||||
// Let the debuggee continue execution.
|
||||
gClient.request({ to: aThreadActor, type: "resume" }, cleanup);
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
gClient.addListener("closed", function (aEvent, aResult) {
|
||||
do_test_finished();
|
||||
});
|
||||
|
||||
try {
|
||||
let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
do_check_eq(xpcInspector.eventLoopNestLevel, 0);
|
||||
} catch (e) {
|
||||
dump(e);
|
||||
}
|
||||
|
||||
gClient.close();
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gClient;
|
||||
var gTabClient;
|
||||
var gDebuggee;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = testGlobal("test-1");
|
||||
DebuggerServer.addTestGlobal(gDebuggee);
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect().then(function ([aType, aTraits]) {
|
||||
attachTestTab(gClient, "test-1", function (aReply, aTabClient) {
|
||||
gTabClient = aTabClient;
|
||||
test_threadAttach(aReply.threadActor);
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_threadAttach(aThreadActorID)
|
||||
{
|
||||
do_print("Trying to attach to thread " + aThreadActorID);
|
||||
gTabClient.attachThread({}, function (aResponse, aThreadClient) {
|
||||
do_check_eq(aThreadClient.state, "paused");
|
||||
do_check_eq(aThreadClient.actor, aThreadActorID);
|
||||
aThreadClient.resume(function () {
|
||||
do_check_eq(aThreadClient.state, "attached");
|
||||
test_debugger_statement(aThreadClient);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_debugger_statement(aThreadClient)
|
||||
{
|
||||
aThreadClient.addListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aThreadClient.state, "paused");
|
||||
// Reach around the protocol to check that the debuggee is in the state
|
||||
// we expect.
|
||||
do_check_true(gDebuggee.a);
|
||||
do_check_false(gDebuggee.b);
|
||||
|
||||
let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
do_check_eq(xpcInspector.eventLoopNestLevel, 1);
|
||||
|
||||
aThreadClient.resume(cleanup);
|
||||
});
|
||||
|
||||
Cu.evalInSandbox("var a = true; var b = false; debugger; var b = true;", gDebuggee);
|
||||
|
||||
// Now make sure that we've run the code after the debugger statement...
|
||||
do_check_true(gDebuggee.b);
|
||||
}
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
gClient.addListener("closed", function (aEvent) {
|
||||
do_test_finished();
|
||||
});
|
||||
|
||||
try {
|
||||
let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector);
|
||||
do_check_eq(xpcInspector.eventLoopNestLevel, 0);
|
||||
} catch (e) {
|
||||
dump(e);
|
||||
}
|
||||
|
||||
gClient.close();
|
||||
}
|
||||
62
devtools/server/tests/unit/test_dbgglobal.js
Normal file
62
devtools/server/tests/unit/test_dbgglobal.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Should get an exception if we try to interact with DebuggerServer
|
||||
// before we initialize it...
|
||||
check_except(function () {
|
||||
DebuggerServer.createListener();
|
||||
});
|
||||
check_except(DebuggerServer.closeAllListeners);
|
||||
check_except(DebuggerServer.connectPipe);
|
||||
|
||||
// Allow incoming connections.
|
||||
DebuggerServer.init();
|
||||
|
||||
// These should still fail because we haven't added a createRootActor
|
||||
// implementation yet.
|
||||
check_except(function () {
|
||||
DebuggerServer.createListener();
|
||||
});
|
||||
check_except(DebuggerServer.closeAllListeners);
|
||||
check_except(DebuggerServer.connectPipe);
|
||||
|
||||
DebuggerServer.registerModule("xpcshell-test/testactors");
|
||||
|
||||
// Now they should work.
|
||||
DebuggerServer.createListener();
|
||||
DebuggerServer.closeAllListeners();
|
||||
|
||||
// Make sure we got the test's root actor all set up.
|
||||
let client1 = DebuggerServer.connectPipe();
|
||||
client1.hooks = {
|
||||
onPacket: function (aPacket1) {
|
||||
do_check_eq(aPacket1.from, "root");
|
||||
do_check_eq(aPacket1.applicationType, "xpcshell-tests");
|
||||
|
||||
// Spin up a second connection, make sure it has its own root
|
||||
// actor.
|
||||
let client2 = DebuggerServer.connectPipe();
|
||||
client2.hooks = {
|
||||
onPacket: function (aPacket2) {
|
||||
do_check_eq(aPacket2.from, "root");
|
||||
do_check_neq(aPacket1.testConnectionPrefix,
|
||||
aPacket2.testConnectionPrefix);
|
||||
client2.close();
|
||||
},
|
||||
onClosed: function (aResult) {
|
||||
client1.close();
|
||||
},
|
||||
};
|
||||
client2.ready();
|
||||
},
|
||||
|
||||
onClosed: function (aResult) {
|
||||
do_test_finished();
|
||||
},
|
||||
};
|
||||
|
||||
client1.ready();
|
||||
do_test_pending();
|
||||
}
|
||||
58
devtools/server/tests/unit/test_eval-01.js
Normal file
58
devtools/server/tests/unit/test_eval-01.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check basic eval resume/re-pause
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_simple_eval();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_simple_eval()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let arg1Actor = aPacket.frame.arguments[0].actor;
|
||||
gThreadClient.eval(null, "({ obj: true })", function (aResponse) {
|
||||
do_check_eq(aResponse.type, "resumed");
|
||||
// Expect a pause notification immediately.
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value...
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "clientEvaluated");
|
||||
do_check_eq(aPacket.why.frameFinished.return.type, "object");
|
||||
do_check_eq(aPacket.why.frameFinished.return.class, "Object");
|
||||
|
||||
// Make sure the previous pause lifetime was correctly dropped.
|
||||
gClient.request({ to: arg1Actor, type: "bogusRequest" }, function (aResponse) {
|
||||
do_check_eq(aResponse.error, "noSuchActor");
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(arg1) { debugger; }
|
||||
stopMe({obj: true});
|
||||
} + ")()");
|
||||
}
|
||||
48
devtools/server/tests/unit/test_eval-02.js
Normal file
48
devtools/server/tests/unit/test_eval-02.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check eval resume/re-pause with a throw.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_throw_eval();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_throw_eval()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.eval(null, "throw 'failure'", function (aResponse) {
|
||||
do_check_eq(aResponse.type, "resumed");
|
||||
// Expect a pause notification immediately.
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value...
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "clientEvaluated");
|
||||
do_check_eq(aPacket.why.frameFinished.throw, "failure");
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(arg1) { debugger; }
|
||||
stopMe({obj: true});
|
||||
} + ")()");
|
||||
}
|
||||
50
devtools/server/tests/unit/test_eval-03.js
Normal file
50
devtools/server/tests/unit/test_eval-03.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check syntax errors in an eval.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_syntax_error_eval();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_syntax_error_eval()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.eval(null, "%$@!@#", function (aResponse) {
|
||||
do_check_eq(aResponse.type, "resumed");
|
||||
// Expect a pause notification immediately.
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value...
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "clientEvaluated");
|
||||
do_check_eq(aPacket.why.frameFinished.throw.type, "object");
|
||||
do_check_eq(aPacket.why.frameFinished.throw.class, "Error");
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(arg1) { debugger; }
|
||||
stopMe({obj: true});
|
||||
} + ")()");
|
||||
}
|
||||
69
devtools/server/tests/unit/test_eval-04.js
Normal file
69
devtools/server/tests/unit/test_eval-04.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check evals against different frames.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_syntax_error_eval();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_syntax_error_eval()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
|
||||
gThreadClient.getFrames(0, 2, function (aResponse) {
|
||||
let frame0 = aResponse.frames[0];
|
||||
let frame1 = aResponse.frames[1];
|
||||
|
||||
// Eval against the top frame...
|
||||
gThreadClient.eval(frame0.actor, "arg", function (aResponse) {
|
||||
do_check_eq(aResponse.type, "resumed");
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// 'arg' should have been evaluated in frame0
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "clientEvaluated");
|
||||
do_check_eq(aPacket.why.frameFinished.return, "arg0");
|
||||
|
||||
// Now eval against the second frame.
|
||||
gThreadClient.eval(frame1.actor, "arg", function (aResponse) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// 'arg' should have been evaluated in frame1
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.frameFinished.return, "arg1");
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function frame0(arg) {
|
||||
debugger;
|
||||
}
|
||||
function frame1(arg) {
|
||||
frame0("arg0");
|
||||
}
|
||||
frame1("arg1");
|
||||
} + ")()");
|
||||
}
|
||||
54
devtools/server/tests/unit/test_eval-05.js
Normal file
54
devtools/server/tests/unit/test_eval-05.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check pauses within evals.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_syntax_error_eval();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_syntax_error_eval()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.eval(null, "debugger", function (aResponse) {
|
||||
// Expect a resume then a debuggerStatement pause.
|
||||
do_check_eq(aResponse.type, "resumed");
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
// Resume from the debugger statement should immediately re-pause
|
||||
// with a clientEvaluated reason.
|
||||
gThreadClient.resume(function (aPacket) {
|
||||
do_check_eq(aPacket.type, "resumed");
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "clientEvaluated");
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(arg) {
|
||||
debugger;
|
||||
}
|
||||
stopMe();
|
||||
} + ")()");
|
||||
}
|
||||
59
devtools/server/tests/unit/test_eventlooplag_actor.js
Normal file
59
devtools/server/tests/unit/test_eventlooplag_actor.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test the eventLoopLag actor.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
function run_test()
|
||||
{
|
||||
let {EventLoopLagFront} = require("devtools/shared/fronts/eventlooplag");
|
||||
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.addBrowserActors();
|
||||
|
||||
// As seen in EventTracer.cpp
|
||||
let threshold = 20;
|
||||
let interval = 10;
|
||||
|
||||
|
||||
let front;
|
||||
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
|
||||
// Start tracking event loop lags.
|
||||
client.connect().then(function () {
|
||||
client.listTabs(function (resp) {
|
||||
front = new EventLoopLagFront(client, resp);
|
||||
front.start().then(success => {
|
||||
do_check_true(success);
|
||||
front.once("event-loop-lag", gotLagEvent);
|
||||
do_execute_soon(lag);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Force a lag
|
||||
function lag() {
|
||||
let start = new Date();
|
||||
let duration = threshold + interval + 1;
|
||||
while (true) {
|
||||
if (((new Date()) - start) > duration) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Got a lag event. The test will time out if the actor
|
||||
// fails to detect the lag.
|
||||
function gotLagEvent(time) {
|
||||
do_print("lag: " + time);
|
||||
do_check_true(time >= threshold);
|
||||
front.stop().then(() => {
|
||||
finishClient(client);
|
||||
});
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
196
devtools/server/tests/unit/test_forwardingprefix.js
Normal file
196
devtools/server/tests/unit/test_forwardingprefix.js
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Exercise prefix-based forwarding of packets to other transports. */
|
||||
|
||||
const { RootActor } = require("devtools/server/actors/root");
|
||||
|
||||
var gMainConnection, gMainTransport;
|
||||
var gSubconnection1, gSubconnection2;
|
||||
var gClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.init();
|
||||
|
||||
add_test(createMainConnection);
|
||||
add_test(TestNoForwardingYet);
|
||||
add_test(createSubconnection1);
|
||||
add_test(TestForwardPrefix1OnlyRoot);
|
||||
add_test(createSubconnection2);
|
||||
add_test(TestForwardPrefix12OnlyRoot);
|
||||
add_test(TestForwardPrefix12WithActor1);
|
||||
add_test(TestForwardPrefix12WithActor12);
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a pipe connection, and return an object |{ conn, transport }|,
|
||||
* where |conn| is the new DebuggerServerConnection instance, and
|
||||
* |transport| is the client side of the transport on which it communicates
|
||||
* (that is, packets sent on |transport| go to the new connection, and
|
||||
* |transport|'s hooks receive replies).
|
||||
*
|
||||
* |aPrefix| is optional; if present, it's the prefix (minus the '/') for
|
||||
* actors in the new connection.
|
||||
*/
|
||||
function newConnection(aPrefix)
|
||||
{
|
||||
var conn;
|
||||
DebuggerServer.createRootActor = function (aConn) {
|
||||
conn = aConn;
|
||||
return new RootActor(aConn, {});
|
||||
};
|
||||
|
||||
var transport = DebuggerServer.connectPipe(aPrefix);
|
||||
|
||||
return { conn: conn, transport: transport };
|
||||
}
|
||||
|
||||
/* Create the main connection for these tests. */
|
||||
function createMainConnection()
|
||||
{
|
||||
({ conn: gMainConnection, transport: gMainTransport } = newConnection());
|
||||
gClient = new DebuggerClient(gMainTransport);
|
||||
gClient.connect().then(([aType, aTraits]) => run_next_test());
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange 'echo' messages with five actors:
|
||||
* - root
|
||||
* - prefix1/root
|
||||
* - prefix1/actor
|
||||
* - prefix2/root
|
||||
* - prefix2/actor
|
||||
*
|
||||
* Expect proper echos from those named in |aReachables|, and 'noSuchActor'
|
||||
* errors from the others. When we've gotten all our replies (errors or
|
||||
* otherwise), call |aCompleted|.
|
||||
*
|
||||
* To avoid deep stacks, we call aCompleted from the next tick.
|
||||
*/
|
||||
function tryActors(aReachables, aCompleted) {
|
||||
let count = 0;
|
||||
|
||||
let outerActor;
|
||||
for (outerActor of [ "root",
|
||||
"prefix1/root", "prefix1/actor",
|
||||
"prefix2/root", "prefix2/actor" ]) {
|
||||
/*
|
||||
* Let each callback capture its own iteration's value; outerActor is
|
||||
* local to the whole loop, not to a single iteration.
|
||||
*/
|
||||
let actor = outerActor;
|
||||
|
||||
count++;
|
||||
|
||||
gClient.request({ to: actor, type: "echo", value: "tango"}, // phone home
|
||||
(aResponse) => {
|
||||
if (aReachables.has(actor))
|
||||
do_check_matches({ from: actor, to: actor, type: "echo", value: "tango" }, aResponse);
|
||||
else
|
||||
do_check_matches({ from: actor, error: "noSuchActor", message: "No such actor for ID: " + actor }, aResponse);
|
||||
|
||||
if (--count == 0)
|
||||
do_execute_soon(aCompleted, "tryActors callback " + aCompleted.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* With no forwarding established, sending messages to root should work,
|
||||
* but sending messages to prefixed actor names, or anyone else, should get
|
||||
* an error.
|
||||
*/
|
||||
function TestNoForwardingYet()
|
||||
{
|
||||
tryActors(new Set(["root"]), run_next_test);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new pipe connection which forwards its reply packets to
|
||||
* gMainConnection's client, and to which gMainConnection forwards packets
|
||||
* directed to actors whose names begin with |aPrefix + '/'|, and.
|
||||
*
|
||||
* Return an object { conn, transport }, as for newConnection.
|
||||
*/
|
||||
function newSubconnection(aPrefix)
|
||||
{
|
||||
let { conn, transport } = newConnection(aPrefix);
|
||||
transport.hooks = {
|
||||
onPacket: (aPacket) => gMainConnection.send(aPacket),
|
||||
onClosed: () => {}
|
||||
};
|
||||
gMainConnection.setForwarding(aPrefix, transport);
|
||||
|
||||
return { conn: conn, transport: transport };
|
||||
}
|
||||
|
||||
/* Create a second root actor, to which we can forward things. */
|
||||
function createSubconnection1()
|
||||
{
|
||||
let { conn, transport } = newSubconnection("prefix1");
|
||||
gSubconnection1 = conn;
|
||||
transport.ready();
|
||||
gClient.expectReply("prefix1/root", (aReply) => run_next_test());
|
||||
}
|
||||
|
||||
// Establish forwarding, but don't put any actors in that server.
|
||||
function TestForwardPrefix1OnlyRoot()
|
||||
{
|
||||
tryActors(new Set(["root", "prefix1/root"]), run_next_test);
|
||||
}
|
||||
|
||||
/* Create a third root actor, to which we can forward things. */
|
||||
function createSubconnection2()
|
||||
{
|
||||
let { conn, transport } = newSubconnection("prefix2");
|
||||
gSubconnection2 = conn;
|
||||
transport.ready();
|
||||
gClient.expectReply("prefix2/root", (aReply) => run_next_test());
|
||||
}
|
||||
|
||||
function TestForwardPrefix12OnlyRoot()
|
||||
{
|
||||
tryActors(new Set(["root", "prefix1/root", "prefix2/root"]), run_next_test);
|
||||
}
|
||||
|
||||
// A dumb actor that implements 'echo'.
|
||||
//
|
||||
// It's okay that both subconnections' actors behave identically, because
|
||||
// the reply-sending code attaches the replying actor's name to the packet,
|
||||
// so simply matching the 'from' field in the reply ensures that we heard
|
||||
// from the right actor.
|
||||
function EchoActor(aConnection)
|
||||
{
|
||||
this.conn = aConnection;
|
||||
}
|
||||
EchoActor.prototype.actorPrefix = "EchoActor";
|
||||
EchoActor.prototype.onEcho = function (aRequest) {
|
||||
/*
|
||||
* Request packets are frozen. Copy aRequest, so that
|
||||
* DebuggerServerConnection.onPacket can attach a 'from' property.
|
||||
*/
|
||||
return JSON.parse(JSON.stringify(aRequest));
|
||||
};
|
||||
EchoActor.prototype.requestTypes = {
|
||||
"echo": EchoActor.prototype.onEcho
|
||||
};
|
||||
|
||||
function TestForwardPrefix12WithActor1()
|
||||
{
|
||||
let actor = new EchoActor(gSubconnection1);
|
||||
actor.actorID = "prefix1/actor";
|
||||
gSubconnection1.addActor(actor);
|
||||
|
||||
tryActors(new Set(["root", "prefix1/root", "prefix1/actor", "prefix2/root"]), run_next_test);
|
||||
}
|
||||
|
||||
function TestForwardPrefix12WithActor12()
|
||||
{
|
||||
let actor = new EchoActor(gSubconnection2);
|
||||
actor.actorID = "prefix2/actor";
|
||||
gSubconnection2.addActor(actor);
|
||||
|
||||
tryActors(new Set(["root", "prefix1/root", "prefix1/actor", "prefix2/root", "prefix2/actor"]), run_next_test);
|
||||
}
|
||||
43
devtools/server/tests/unit/test_frameactor-01.js
Normal file
43
devtools/server/tests/unit/test_frameactor-01.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verify that we get a frame actor along with a debugger statement.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_true(!!aPacket.frame);
|
||||
do_check_true(!!aPacket.frame.actor);
|
||||
do_check_eq(aPacket.frame.callee.name, "stopMe");
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe() {
|
||||
debugger;
|
||||
}
|
||||
stopMe();
|
||||
} + ")()");
|
||||
}
|
||||
45
devtools/server/tests/unit/test_frameactor-02.js
Normal file
45
devtools/server/tests/unit/test_frameactor-02.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verify that two pauses in a row will keep the same frame actor.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket2) {
|
||||
do_check_eq(aPacket1.frame.actor, aPacket2.frame.actor);
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe() {
|
||||
debugger;
|
||||
debugger;
|
||||
}
|
||||
stopMe();
|
||||
} + ")()");
|
||||
}
|
||||
47
devtools/server/tests/unit/test_frameactor-03.js
Normal file
47
devtools/server/tests/unit/test_frameactor-03.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verify that a frame actor is properly expired when the frame goes away.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket2) {
|
||||
let poppedFrames = aPacket2.poppedFrames;
|
||||
do_check_eq(typeof (poppedFrames), typeof ([]));
|
||||
do_check_true(poppedFrames.indexOf(aPacket1.frame.actor) >= 0);
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe() {
|
||||
debugger;
|
||||
}
|
||||
stopMe();
|
||||
debugger;
|
||||
} + ")()");
|
||||
}
|
||||
91
devtools/server/tests/unit/test_frameactor-04.js
Normal file
91
devtools/server/tests/unit/test_frameactor-04.js
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verify the "frames" request on the thread.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
var gFrames = [
|
||||
// Function calls...
|
||||
{ type: "call", callee: { name: "depth3" } },
|
||||
{ type: "call", callee: { name: "depth2" } },
|
||||
{ type: "call", callee: { name: "depth1" } },
|
||||
|
||||
// Anonymous function call in our eval...
|
||||
{ type: "call", callee: { name: undefined } },
|
||||
|
||||
// The eval itself.
|
||||
{ type: "eval", callee: { name: undefined } },
|
||||
];
|
||||
|
||||
var gSliceTests = [
|
||||
{ start: 0, count: undefined, resetActors: true },
|
||||
{ start: 0, count: 1 },
|
||||
{ start: 2, count: 2 },
|
||||
{ start: 1, count: 15 },
|
||||
{ start: 15, count: undefined },
|
||||
];
|
||||
|
||||
function test_frame_slice() {
|
||||
if (gSliceTests.length == 0) {
|
||||
gThreadClient.resume(function () { finishClient(gClient); });
|
||||
return;
|
||||
}
|
||||
|
||||
let test = gSliceTests.shift();
|
||||
gThreadClient.getFrames(test.start, test.count, function (aResponse) {
|
||||
var testFrames = gFrames.slice(test.start, test.count ? test.start + test.count : undefined);
|
||||
do_check_eq(testFrames.length, aResponse.frames.length);
|
||||
for (var i = 0; i < testFrames.length; i++) {
|
||||
let expected = testFrames[i];
|
||||
let actual = aResponse.frames[i];
|
||||
|
||||
if (test.resetActors) {
|
||||
expected.actor = actual.actor;
|
||||
}
|
||||
|
||||
for (let key of ["type", "callee-name"]) {
|
||||
do_check_eq(expected[key] || undefined, actual[key]);
|
||||
}
|
||||
}
|
||||
test_frame_slice();
|
||||
});
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) {
|
||||
test_frame_slice();
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function depth3() {
|
||||
debugger;
|
||||
}
|
||||
function depth2() {
|
||||
depth3();
|
||||
}
|
||||
function depth1() {
|
||||
depth2();
|
||||
}
|
||||
depth1();
|
||||
} + ")()");
|
||||
}
|
||||
89
devtools/server/tests/unit/test_frameactor-05.js
Normal file
89
devtools/server/tests/unit/test_frameactor-05.js
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Verify that frame actors retrieved with the frames request
|
||||
* are included in the pause packet's popped-frames property.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_frame_slice() {
|
||||
if (gSliceTests.length == 0) {
|
||||
gThreadClient.resume(function () { finishClient(gClient); });
|
||||
return;
|
||||
}
|
||||
|
||||
let test = gSliceTests.shift();
|
||||
gThreadClient.getFrames(test.start, test.count, function (aResponse) {
|
||||
var testFrames = gFrames.slice(test.start, test.count ? test.start + test.count : undefined);
|
||||
do_check_eq(testFrames.length, aResponse.frames.length);
|
||||
for (var i = 0; i < testFrames.length; i++) {
|
||||
let expected = testFrames[i];
|
||||
let actual = aResponse.frames[i];
|
||||
|
||||
if (test.resetActors) {
|
||||
expected.actor = actual.actor;
|
||||
}
|
||||
|
||||
for (var key in expected) {
|
||||
do_check_eq(expected[key], actual[key]);
|
||||
}
|
||||
}
|
||||
test_frame_slice();
|
||||
});
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) {
|
||||
gThreadClient.getFrames(0, null, function (aFrameResponse) {
|
||||
do_check_eq(aFrameResponse.frames.length, 5);
|
||||
// Now wait for the next pause, after which the three
|
||||
// youngest actors should be popped..
|
||||
let expectPopped = aFrameResponse.frames.slice(0, 3).map(frame => frame.actor);
|
||||
expectPopped.sort();
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPausePacket) {
|
||||
let popped = aPausePacket.poppedFrames.sort();
|
||||
do_check_eq(popped.length, 3);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
do_check_eq(expectPopped[i], popped[i]);
|
||||
}
|
||||
|
||||
gThreadClient.resume(function () { finishClient(gClient); });
|
||||
});
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function depth3() {
|
||||
debugger;
|
||||
}
|
||||
function depth2() {
|
||||
depth3();
|
||||
}
|
||||
function depth1() {
|
||||
depth2();
|
||||
}
|
||||
depth1();
|
||||
debugger;
|
||||
} + ")()");
|
||||
}
|
||||
51
devtools/server/tests/unit/test_framearguments-01.js
Normal file
51
devtools/server/tests/unit/test_framearguments-01.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check a frame actor's arguments property.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let args = aPacket.frame["arguments"];
|
||||
do_check_eq(args.length, 6);
|
||||
do_check_eq(args[0], 42);
|
||||
do_check_eq(args[1], true);
|
||||
do_check_eq(args[2], "nasu");
|
||||
do_check_eq(args[3].type, "null");
|
||||
do_check_eq(args[4].type, "undefined");
|
||||
do_check_eq(args[5].type, "object");
|
||||
do_check_eq(args[5].class, "Object");
|
||||
do_check_true(!!args[5].actor);
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) {
|
||||
debugger;
|
||||
}
|
||||
stopMe(42, true, "nasu", null, undefined, { foo: "bar" });
|
||||
} + ")()");
|
||||
}
|
||||
77
devtools/server/tests/unit/test_framebindings-01.js
Normal file
77
devtools/server/tests/unit/test_framebindings-01.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check a frame actor's bindings property.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let bindings = aPacket.frame.environment.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
|
||||
do_check_eq(args.length, 6);
|
||||
do_check_eq(args[0].aNumber.value, 42);
|
||||
do_check_eq(args[1].aBool.value, true);
|
||||
do_check_eq(args[2].aString.value, "nasu");
|
||||
do_check_eq(args[3].aNull.value.type, "null");
|
||||
do_check_eq(args[4].aUndefined.value.type, "undefined");
|
||||
do_check_eq(args[5].aObject.value.type, "object");
|
||||
do_check_eq(args[5].aObject.value.class, "Object");
|
||||
do_check_true(!!args[5].aObject.value.actor);
|
||||
|
||||
do_check_eq(vars.a.value, 1);
|
||||
do_check_eq(vars.b.value, true);
|
||||
do_check_eq(vars.c.value.type, "object");
|
||||
do_check_eq(vars.c.value.class, "Object");
|
||||
do_check_true(!!vars.c.value.actor);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(vars.c.value);
|
||||
objClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.a.configurable, true);
|
||||
do_check_eq(aResponse.ownProperties.a.enumerable, true);
|
||||
do_check_eq(aResponse.ownProperties.a.writable, true);
|
||||
do_check_eq(aResponse.ownProperties.a.value, "a");
|
||||
|
||||
do_check_eq(aResponse.ownProperties.b.configurable, true);
|
||||
do_check_eq(aResponse.ownProperties.b.enumerable, true);
|
||||
do_check_eq(aResponse.ownProperties.b.writable, true);
|
||||
do_check_eq(aResponse.ownProperties.b.value.type, "undefined");
|
||||
do_check_false("class" in aResponse.ownProperties.b.value);
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) {
|
||||
var a = 1;
|
||||
var b = true;
|
||||
var c = { a: "a", b: undefined };
|
||||
debugger;
|
||||
}
|
||||
stopMe(42, true, "nasu", null, undefined, { foo: "bar" });
|
||||
} + ")()");
|
||||
}
|
||||
63
devtools/server/tests/unit/test_framebindings-02.js
Normal file
63
devtools/server/tests/unit/test_framebindings-02.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check a frame actor's parent bindings.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let parentEnv = aPacket.frame.environment.parent;
|
||||
let bindings = parentEnv.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
do_check_eq(args.length, 0);
|
||||
do_check_eq(vars.stopMe.value.type, "object");
|
||||
do_check_eq(vars.stopMe.value.class, "Function");
|
||||
do_check_true(!!vars.stopMe.value.actor);
|
||||
|
||||
// Skip the global lexical scope.
|
||||
parentEnv = parentEnv.parent.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
let objClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||
objClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.Object.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.Object.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.Object.value.actor);
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) {
|
||||
var a = 1;
|
||||
var b = true;
|
||||
var c = { a: "a" };
|
||||
debugger;
|
||||
}
|
||||
stopMe(42, true, "nasu", null, undefined, { foo: "bar" });
|
||||
} + ")()");
|
||||
}
|
||||
69
devtools/server/tests/unit/test_framebindings-03.js
Normal file
69
devtools/server/tests/unit/test_framebindings-03.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check a |with| frame actor's bindings.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let env = aPacket.frame.environment;
|
||||
do_check_neq(env, undefined);
|
||||
|
||||
let parentEnv = env.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let bindings = parentEnv.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
do_check_eq(args.length, 1);
|
||||
do_check_eq(args[0].aNumber.value, 10);
|
||||
do_check_eq(vars.r.value, 10);
|
||||
do_check_eq(vars.a.value, Math.PI * 100);
|
||||
do_check_eq(vars.arguments.value.class, "Arguments");
|
||||
do_check_true(!!vars.arguments.value.actor);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(aNumber) {
|
||||
var a;
|
||||
var r = aNumber;
|
||||
with (Math) {
|
||||
a = PI * r * r;
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
stopMe(10);
|
||||
} + ")()");
|
||||
}
|
||||
84
devtools/server/tests/unit/test_framebindings-04.js
Normal file
84
devtools/server/tests/unit/test_framebindings-04.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check the environment bindongs of a |with| within a |with|.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let env = aPacket.frame.environment;
|
||||
do_check_neq(env, undefined);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.one.value, 1);
|
||||
do_check_eq(aResponse.ownProperties.two.value, 2);
|
||||
do_check_eq(aResponse.ownProperties.foo, undefined);
|
||||
|
||||
let parentEnv = env.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let parentClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||
parentClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||
|
||||
parentEnv = parentEnv.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let bindings = parentEnv.bindings;
|
||||
let args = bindings.arguments;
|
||||
let vars = bindings.variables;
|
||||
do_check_eq(args.length, 1);
|
||||
do_check_eq(args[0].aNumber.value, 10);
|
||||
do_check_eq(vars.r.value, 10);
|
||||
do_check_eq(vars.a.value, Math.PI * 100);
|
||||
do_check_eq(vars.arguments.value.class, "Arguments");
|
||||
do_check_true(!!vars.arguments.value.actor);
|
||||
do_check_eq(vars.foo.value, 2 * Math.PI);
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
function stopMe(aNumber) {
|
||||
var a, obj = { one: 1, two: 2 };
|
||||
var r = aNumber;
|
||||
with (Math) {
|
||||
a = PI * r * r;
|
||||
with (obj) {
|
||||
var foo = two * PI;
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
}
|
||||
stopMe(10);
|
||||
} + ")()");
|
||||
}
|
||||
63
devtools/server/tests/unit/test_framebindings-05.js
Normal file
63
devtools/server/tests/unit/test_framebindings-05.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check the environment bindings of a |with| in global scope.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let env = aPacket.frame.environment;
|
||||
do_check_neq(env, undefined);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(env.object);
|
||||
objClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.PI.value, Math.PI);
|
||||
do_check_eq(aResponse.ownProperties.cos.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.cos.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.cos.value.actor);
|
||||
|
||||
// Skip the global lexical scope.
|
||||
let parentEnv = env.parent.parent;
|
||||
do_check_neq(parentEnv, undefined);
|
||||
|
||||
let parentClient = gThreadClient.pauseGrip(parentEnv.object);
|
||||
parentClient.getPrototypeAndProperties(function (aResponse) {
|
||||
do_check_eq(aResponse.ownProperties.a.value, Math.PI * 100);
|
||||
do_check_eq(aResponse.ownProperties.r.value, 10);
|
||||
do_check_eq(aResponse.ownProperties.Object.value.type, "object");
|
||||
do_check_eq(aResponse.ownProperties.Object.value.class, "Function");
|
||||
do_check_true(!!aResponse.ownProperties.Object.value.actor);
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("var a, r = 10;\n" +
|
||||
"with (Math) {\n" +
|
||||
" a = PI * r * r;\n" +
|
||||
" debugger;\n" +
|
||||
"}");
|
||||
}
|
||||
60
devtools/server/tests/unit/test_framebindings-06.js
Normal file
60
devtools/server/tests/unit/test_framebindings-06.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-grips");
|
||||
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_banana_environment();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_banana_environment()
|
||||
{
|
||||
|
||||
gThreadClient.addOneTimeListener("paused",
|
||||
function (aEvent, aPacket) {
|
||||
equal(aPacket.type, "paused");
|
||||
let env = aPacket.frame.environment;
|
||||
equal(env.type, "function");
|
||||
equal(env.function.name, "banana3");
|
||||
let parent = env.parent;
|
||||
equal(parent.type, "block");
|
||||
ok("banana3" in parent.bindings.variables);
|
||||
parent = parent.parent;
|
||||
equal(parent.type, "function");
|
||||
equal(parent.function.name, "banana2");
|
||||
parent = parent.parent;
|
||||
equal(parent.type, "block");
|
||||
ok("banana2" in parent.bindings.variables);
|
||||
parent = parent.parent;
|
||||
equal(parent.type, "function");
|
||||
equal(parent.function.name, "banana");
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("\
|
||||
function banana(x) { \n\
|
||||
return function banana2(y) { \n\
|
||||
return function banana3(z) { \n\
|
||||
debugger; \n\
|
||||
}; \n\
|
||||
}; \n\
|
||||
} \n\
|
||||
banana('x')('y')('z'); \n\
|
||||
");
|
||||
}
|
||||
64
devtools/server/tests/unit/test_framebindings-07.js
Normal file
64
devtools/server/tests/unit/test_framebindings-07.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
// Test that the EnvironmentClient's getBindings() method works as expected.
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-bindings");
|
||||
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-bindings", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_banana_environment();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_banana_environment()
|
||||
{
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let environment = aPacket.frame.environment;
|
||||
do_check_eq(environment.type, "function");
|
||||
|
||||
let parent = environment.parent;
|
||||
do_check_eq(parent.type, "block");
|
||||
|
||||
let grandpa = parent.parent;
|
||||
do_check_eq(grandpa.type, "function");
|
||||
|
||||
let envClient = gThreadClient.environment(environment);
|
||||
envClient.getBindings(aResponse => {
|
||||
do_check_eq(aResponse.bindings.arguments[0].z.value, "z");
|
||||
|
||||
let parentClient = gThreadClient.environment(parent);
|
||||
parentClient.getBindings(aResponse => {
|
||||
do_check_eq(aResponse.bindings.variables.banana3.value.class, "Function");
|
||||
|
||||
let grandpaClient = gThreadClient.environment(grandpa);
|
||||
grandpaClient.getBindings(aResponse => {
|
||||
do_check_eq(aResponse.bindings.arguments[0].y.value, "y");
|
||||
gThreadClient.resume(() => finishClient(gClient));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("\
|
||||
function banana(x) { \n\
|
||||
return function banana2(y) { \n\
|
||||
return function banana3(z) { \n\
|
||||
debugger; \n\
|
||||
}; \n\
|
||||
}; \n\
|
||||
} \n\
|
||||
banana('x')('y')('z'); \n\
|
||||
");
|
||||
}
|
||||
53
devtools/server/tests/unit/test_frameclient-01.js
Normal file
53
devtools/server/tests/unit/test_frameclient-01.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
gThreadClient.addOneTimeListener("framesadded", function () {
|
||||
do_check_eq(gThreadClient.cachedFrames.length, 3);
|
||||
do_check_true(gThreadClient.moreFrames);
|
||||
do_check_false(gThreadClient.fillFrames(3));
|
||||
|
||||
do_check_true(gThreadClient.fillFrames(30));
|
||||
gThreadClient.addOneTimeListener("framesadded", function () {
|
||||
do_check_false(gThreadClient.moreFrames);
|
||||
do_check_eq(gThreadClient.cachedFrames.length, 7);
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
do_check_true(gThreadClient.fillFrames(3));
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
var recurseLeft = 5;
|
||||
function recurse() {
|
||||
if (--recurseLeft == 0) {
|
||||
debugger;
|
||||
return;
|
||||
}
|
||||
recurse();
|
||||
}
|
||||
recurse();
|
||||
} + ")()");
|
||||
}
|
||||
46
devtools/server/tests/unit/test_frameclient-02.js
Normal file
46
devtools/server/tests/unit/test_frameclient-02.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_pause_frame();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_pause_frame()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Ask for exactly the number of frames we expect.
|
||||
gThreadClient.addOneTimeListener("framesadded", function () {
|
||||
do_check_false(gThreadClient.moreFrames);
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
do_check_true(gThreadClient.fillFrames(3));
|
||||
});
|
||||
|
||||
gDebuggee.eval("(" + function () {
|
||||
var recurseLeft = 1;
|
||||
function recurse() {
|
||||
if (--recurseLeft == 0) {
|
||||
debugger;
|
||||
return;
|
||||
}
|
||||
recurse();
|
||||
}
|
||||
recurse();
|
||||
} + ")()");
|
||||
}
|
||||
95
devtools/server/tests/unit/test_functiongrips-01.js
Normal file
95
devtools/server/tests/unit/test_functiongrips-01.js
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-grips");
|
||||
gDebuggee.eval(function stopMe(arg1) {
|
||||
debugger;
|
||||
}.toString());
|
||||
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function () {
|
||||
attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_named_function();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_named_function()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let args = aPacket.frame.arguments;
|
||||
|
||||
do_check_eq(args[0].class, "Function");
|
||||
do_check_eq(args[0].name, "stopMe");
|
||||
do_check_eq(args[0].displayName, "stopMe");
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(args[0]);
|
||||
objClient.getParameterNames(function (aResponse) {
|
||||
do_check_eq(aResponse.parameterNames.length, 1);
|
||||
do_check_eq(aResponse.parameterNames[0], "arg1");
|
||||
|
||||
gThreadClient.resume(test_inferred_name_function);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("stopMe(stopMe)");
|
||||
}
|
||||
|
||||
function test_inferred_name_function() {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let args = aPacket.frame.arguments;
|
||||
|
||||
do_check_eq(args[0].class, "Function");
|
||||
// No name for an anonymous function, but it should have an inferred name.
|
||||
do_check_eq(args[0].name, undefined);
|
||||
do_check_eq(args[0].displayName, "o.m");
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(args[0]);
|
||||
objClient.getParameterNames(function (aResponse) {
|
||||
do_check_eq(aResponse.parameterNames.length, 3);
|
||||
do_check_eq(aResponse.parameterNames[0], "foo");
|
||||
do_check_eq(aResponse.parameterNames[1], "bar");
|
||||
do_check_eq(aResponse.parameterNames[2], "baz");
|
||||
|
||||
gThreadClient.resume(test_anonymous_function);
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("var o = { m: function(foo, bar, baz) { } }; stopMe(o.m)");
|
||||
}
|
||||
|
||||
function test_anonymous_function() {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let args = aPacket.frame.arguments;
|
||||
|
||||
do_check_eq(args[0].class, "Function");
|
||||
// No name for an anonymous function, and no inferred name, either.
|
||||
do_check_eq(args[0].name, undefined);
|
||||
do_check_eq(args[0].displayName, undefined);
|
||||
|
||||
let objClient = gThreadClient.pauseGrip(args[0]);
|
||||
objClient.getParameterNames(function (aResponse) {
|
||||
do_check_eq(aResponse.parameterNames.length, 3);
|
||||
do_check_eq(aResponse.parameterNames[0], "foo");
|
||||
do_check_eq(aResponse.parameterNames[1], "bar");
|
||||
do_check_eq(aResponse.parameterNames[2], "baz");
|
||||
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gDebuggee.eval("stopMe(function(foo, bar, baz) { })");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Test if getExecutableLines return correct information
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
const SOURCE_MAPPED_FILE = getFileUrl("sourcemapped.js");
|
||||
|
||||
function run_test() {
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-get-executable-lines");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function _onConnect() {
|
||||
attachTestTabAndResume(
|
||||
gClient,
|
||||
"test-get-executable-lines",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_executable_lines();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_executable_lines() {
|
||||
gThreadClient.addOneTimeListener("newSource", function _onNewSource(evt, packet) {
|
||||
do_check_eq(evt, "newSource");
|
||||
|
||||
gThreadClient.getSources(function ({error, sources}) {
|
||||
do_check_true(!error);
|
||||
let source = gThreadClient.source(sources[0]);
|
||||
source.getExecutableLines(function (lines) {
|
||||
do_check_true(arrays_equal([1, 2, 4, 6], lines));
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let code = readFile("sourcemapped.js") + "\n//# sourceMappingURL=" +
|
||||
getFileUrl("source-map-data/sourcemapped.map");
|
||||
|
||||
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
|
||||
SOURCE_MAPPED_FILE, 1);
|
||||
}
|
||||
|
||||
function arrays_equal(a, b) {
|
||||
return !(a < b || b < a);
|
||||
}
|
||||
55
devtools/server/tests/unit/test_get-executable-lines.js
Normal file
55
devtools/server/tests/unit/test_get-executable-lines.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Test if getExecutableLines return correct information
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
const SOURCE_MAPPED_FILE = getFileUrl("sourcemapped.js");
|
||||
|
||||
function run_test() {
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-get-executable-lines");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect().then(function _onConnect() {
|
||||
attachTestTabAndResume(
|
||||
gClient,
|
||||
"test-get-executable-lines",
|
||||
function (aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_executable_lines();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_executable_lines() {
|
||||
gThreadClient.addOneTimeListener("newSource", function _onNewSource(evt, packet) {
|
||||
do_check_eq(evt, "newSource");
|
||||
|
||||
gThreadClient.getSources(function ({error, sources}) {
|
||||
do_check_true(!error);
|
||||
let source = gThreadClient.source(sources[0]);
|
||||
source.getExecutableLines(function (lines) {
|
||||
do_check_true(arrays_equal([2, 5, 7, 8, 10, 12, 14, 16], lines));
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
let code = readFile("sourcemapped.js");
|
||||
|
||||
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
|
||||
SOURCE_MAPPED_FILE, 1);
|
||||
}
|
||||
|
||||
function arrays_equal(a, b) {
|
||||
return !(a < b || b < a);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue