зеркало из https://github.com/mozilla/gecko-dev.git
Bug 694539: Implement 'long string' grips. r=jimb
This commit is contained in:
Родитель
b8470437f3
Коммит
fa9547d0c6
|
@ -208,7 +208,8 @@ const DebugProtocolTypes = {
|
|||
"prototypeAndProperties": "prototypeAndProperties",
|
||||
"resume": "resume",
|
||||
"scripts": "scripts",
|
||||
"setBreakpoint": "setBreakpoint"
|
||||
"setBreakpoint": "setBreakpoint",
|
||||
"substring": "substring"
|
||||
};
|
||||
|
||||
const ROOT_ACTOR_NAME = "root";
|
||||
|
@ -514,6 +515,7 @@ function ThreadClient(aClient, aActor) {
|
|||
this._actor = aActor;
|
||||
this._frameCache = [];
|
||||
this._scriptCache = {};
|
||||
this._pauseGrips = {};
|
||||
}
|
||||
|
||||
ThreadClient.prototype = {
|
||||
|
@ -878,10 +880,6 @@ ThreadClient.prototype = {
|
|||
* A pause-lifetime object grip returned by the protocol.
|
||||
*/
|
||||
pauseGrip: function TC_pauseGrip(aGrip) {
|
||||
if (!this._pauseGrips) {
|
||||
this._pauseGrips = {};
|
||||
}
|
||||
|
||||
if (aGrip.actor in this._pauseGrips) {
|
||||
return this._pauseGrips[aGrip.actor];
|
||||
}
|
||||
|
@ -891,6 +889,22 @@ ThreadClient.prototype = {
|
|||
return client;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return an instance of LongStringClient for the given long string grip.
|
||||
*
|
||||
* @param aGrip Object
|
||||
* The long string grip returned by the protocol.
|
||||
*/
|
||||
longString: function TC_longString(aGrip) {
|
||||
if (aGrip.actor in this._pauseGrips) {
|
||||
return this._pauseGrips[aGrip.actor];
|
||||
}
|
||||
|
||||
let client = new LongStringClient(this._client, aGrip);
|
||||
this._pauseGrips[aGrip.actor] = client;
|
||||
return client;
|
||||
},
|
||||
|
||||
/**
|
||||
* Invalidate pause-lifetime grip clients and clear the list of
|
||||
* current grip clients.
|
||||
|
@ -899,7 +913,7 @@ ThreadClient.prototype = {
|
|||
for each (let grip in this._pauseGrips) {
|
||||
grip.valid = false;
|
||||
}
|
||||
this._pauseGrips = null;
|
||||
this._pauseGrips = {};
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -933,9 +947,7 @@ function GripClient(aClient, aGrip)
|
|||
GripClient.prototype = {
|
||||
get actor() { return this._grip.actor },
|
||||
|
||||
_valid: true,
|
||||
get valid() { return this._valid; },
|
||||
set valid(aValid) { this._valid = !!aValid; },
|
||||
valid: true,
|
||||
|
||||
/**
|
||||
* Request the name of the function and its formal parameters.
|
||||
|
@ -1017,6 +1029,45 @@ GripClient.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A LongStringClient provides a way to access "very long" strings from the
|
||||
* debugger server.
|
||||
*
|
||||
* @param aClient DebuggerClient
|
||||
* The debugger client parent.
|
||||
* @param aGrip Object
|
||||
* A pause-lifetime long string grip returned by the protocol.
|
||||
*/
|
||||
function LongStringClient(aClient, aGrip) {
|
||||
this._grip = aGrip;
|
||||
this._client = aClient;
|
||||
}
|
||||
|
||||
LongStringClient.prototype = {
|
||||
get actor() { return this._grip.actor; },
|
||||
get length() { return this._grip.length; },
|
||||
|
||||
valid: true,
|
||||
|
||||
/**
|
||||
* Get the substring of this LongString from aStart to aEnd.
|
||||
*
|
||||
* @param aStart Number
|
||||
* The starting index.
|
||||
* @param aEnd Number
|
||||
* The ending index.
|
||||
* @param aCallback Function
|
||||
* The function called when we receive the substring.
|
||||
*/
|
||||
substring: function LSC_substring(aStart, aEnd, aCallback) {
|
||||
let packet = { to: this.actor,
|
||||
type: DebugProtocolTypes.substring,
|
||||
start: aStart,
|
||||
end: aEnd };
|
||||
this._client.request(packet, aCallback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Breakpoint clients are used to remove breakpoints that are no longer used.
|
||||
*
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* JSD2 actors.
|
||||
*/
|
||||
|
@ -786,6 +787,11 @@ ThreadActor.prototype = {
|
|||
*/
|
||||
createValueGrip: function TA_createValueGrip(aValue) {
|
||||
let type = typeof(aValue);
|
||||
|
||||
if (type === "string" && this._stringIsLong(aValue)) {
|
||||
return this.longStringGrip(aValue);
|
||||
}
|
||||
|
||||
if (type === "boolean" || type === "string" || type === "number") {
|
||||
return aValue;
|
||||
}
|
||||
|
@ -872,6 +878,42 @@ ThreadActor.prototype = {
|
|||
return this.objectGrip(aValue, this.threadLifetimePool);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a grip for the given string.
|
||||
*
|
||||
* @param aString String
|
||||
* The string we are creating a grip for.
|
||||
*/
|
||||
longStringGrip: function TA_longStringGrip(aString) {
|
||||
if (!this._pausePool) {
|
||||
throw new Error("LongString grip requested while not paused.");
|
||||
}
|
||||
|
||||
if (!this._pausePool.longStringActors) {
|
||||
this._pausePool.longStringActors = {};
|
||||
}
|
||||
|
||||
if (this._pausePool.longStringActors.hasOwnProperty(aString)) {
|
||||
return this._pausePool.longStringActors[aString].grip();
|
||||
}
|
||||
|
||||
let actor = new LongStringActor(aString, this);
|
||||
this._pausePool.addActor(actor);
|
||||
this._pausePool.longStringActors[aString] = actor;
|
||||
return actor.grip();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the string is long enough to use a LongStringActor instead
|
||||
* of passing the value directly over the protocol.
|
||||
*
|
||||
* @param aString String
|
||||
* The string we are checking the length of.
|
||||
*/
|
||||
_stringIsLong: function TA__stringIsLong(aString) {
|
||||
return aString.length >= DebuggerServer.LONG_STRING_LENGTH;
|
||||
},
|
||||
|
||||
// JS Debugger API hooks.
|
||||
|
||||
/**
|
||||
|
@ -1020,6 +1062,75 @@ PauseActor.prototype = {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* A base actor for any actors that should only respond receive messages in the
|
||||
* paused state. Subclasses may expose a `threadActor` which is used to help
|
||||
* determine when we are in a paused state. Subclasses should set their own
|
||||
* "constructor" property if they want better error messages. You should never
|
||||
* instantiate a PauseScopedActor directly, only through subclasses.
|
||||
*/
|
||||
function PauseScopedActor()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A function decorator for creating methods to handle protocol messages that
|
||||
* should only be received while in the paused state.
|
||||
*
|
||||
* @param aMethod Function
|
||||
* The function we are decorating.
|
||||
*/
|
||||
PauseScopedActor.withPaused = function PSA_withPaused(aMethod) {
|
||||
return function () {
|
||||
if (this.isPaused()) {
|
||||
return aMethod.apply(this, arguments);
|
||||
} else {
|
||||
return this._wrongState();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
PauseScopedActor.prototype = {
|
||||
|
||||
/**
|
||||
* Returns true if we are in the paused state.
|
||||
*/
|
||||
isPaused: function PSA_isPaused() {
|
||||
// When there is not a ThreadActor available (like in the webconsole) we
|
||||
// have to be optimistic and assume that we are paused so that we can
|
||||
// respond to requests.
|
||||
return this.threadActor ? this.threadActor.state === "paused" : true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the wrongState response packet for this actor.
|
||||
*/
|
||||
_wrongState: function PSA_wrongState() {
|
||||
return {
|
||||
error: "wrongState",
|
||||
message: this.constructor.name +
|
||||
" actors can only be accessed while the thread is paused."
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Utility function for updating an object with the properties of another
|
||||
* object.
|
||||
*
|
||||
* @param aTarget Object
|
||||
* The object being updated.
|
||||
* @param aNewAttrs Object
|
||||
* The new attributes being set on the target.
|
||||
*/
|
||||
function update(aTarget, aNewAttrs) {
|
||||
for (let key in aNewAttrs) {
|
||||
aTarget[key] = aNewAttrs[key];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an actor for the specified object.
|
||||
*
|
||||
|
@ -1034,13 +1145,11 @@ function ObjectActor(aObj, aThreadActor)
|
|||
this.threadActor = aThreadActor;
|
||||
}
|
||||
|
||||
ObjectActor.prototype = {
|
||||
actorPrefix: "obj",
|
||||
ObjectActor.prototype = Object.create(PauseScopedActor.prototype);
|
||||
|
||||
WRONG_STATE_RESPONSE: {
|
||||
error: "wrongState",
|
||||
message: "Object actors can only be accessed while the thread is paused."
|
||||
},
|
||||
update(ObjectActor.prototype, {
|
||||
constructor: ObjectActor,
|
||||
actorPrefix: "obj",
|
||||
|
||||
/**
|
||||
* Returns a grip for this actor for returning in a protocol message.
|
||||
|
@ -1066,14 +1175,11 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onOwnPropertyNames: function OA_onOwnPropertyNames(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onOwnPropertyNames:
|
||||
PauseScopedActor.withPaused(function OA_onOwnPropertyNames(aRequest) {
|
||||
return { from: this.actorID,
|
||||
ownPropertyNames: this.obj.getOwnPropertyNames() };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to provide the prototype and own properties of
|
||||
|
@ -1082,11 +1188,8 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onPrototypeAndProperties: function OA_onPrototypeAndProperties(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onPrototypeAndProperties:
|
||||
PauseScopedActor.withPaused(function OA_onPrototypeAndProperties(aRequest) {
|
||||
let ownProperties = {};
|
||||
for each (let name in this.obj.getOwnPropertyNames()) {
|
||||
try {
|
||||
|
@ -1102,7 +1205,7 @@ ObjectActor.prototype = {
|
|||
return { from: this.actorID,
|
||||
prototype: this.threadActor.createValueGrip(this.obj.proto),
|
||||
ownProperties: ownProperties };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to provide the prototype of the object.
|
||||
|
@ -1110,14 +1213,10 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onPrototype: function OA_onPrototype(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onPrototype: PauseScopedActor.withPaused(function OA_onPrototype(aRequest) {
|
||||
return { from: this.actorID,
|
||||
prototype: this.threadActor.createValueGrip(this.obj.proto) };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to provide the property descriptor of the
|
||||
|
@ -1126,10 +1225,7 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onProperty: function OA_onProperty(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
onProperty: PauseScopedActor.withPaused(function OA_onProperty(aRequest) {
|
||||
if (!aRequest.name) {
|
||||
return { error: "missingParameter",
|
||||
message: "no property name was specified" };
|
||||
|
@ -1138,7 +1234,7 @@ ObjectActor.prototype = {
|
|||
let desc = this.obj.getOwnPropertyDescriptor(aRequest.name);
|
||||
return { from: this.actorID,
|
||||
descriptor: this._propertyDescriptor(desc) };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* A helper method that creates a property descriptor for the provided object,
|
||||
|
@ -1167,11 +1263,7 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onDecompile: function OA_onDecompile(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onDecompile: PauseScopedActor.withPaused(function OA_onDecompile(aRequest) {
|
||||
if (this.obj.class !== "Function") {
|
||||
return { error: "objectNotFunction",
|
||||
message: "decompile request is only valid for object grips " +
|
||||
|
@ -1180,7 +1272,7 @@ ObjectActor.prototype = {
|
|||
|
||||
return { from: this.actorID,
|
||||
decompiledCode: this.obj.decompile(!!aRequest.pretty) };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to provide the lexical scope of a function.
|
||||
|
@ -1188,11 +1280,7 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onScope: function OA_onScope(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onScope: PauseScopedActor.withPaused(function OA_onScope(aRequest) {
|
||||
if (this.obj.class !== "Function") {
|
||||
return { error: "objectNotFunction",
|
||||
message: "scope request is only valid for object grips with a" +
|
||||
|
@ -1212,7 +1300,7 @@ ObjectActor.prototype = {
|
|||
// use the 'scope' request in the debugger frontend.
|
||||
return { name: this.obj.name || null,
|
||||
scope: envActor.form(this.obj) };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to provide the name and parameters of a function.
|
||||
|
@ -1220,11 +1308,7 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onNameAndParameters: function OA_onNameAndParameters(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onNameAndParameters: PauseScopedActor.withPaused(function OA_onNameAndParameters(aRequest) {
|
||||
if (this.obj.class !== "Function") {
|
||||
return { error: "objectNotFunction",
|
||||
message: "nameAndParameters request is only valid for object " +
|
||||
|
@ -1233,7 +1317,7 @@ ObjectActor.prototype = {
|
|||
|
||||
return { name: this.obj.name || null,
|
||||
parameters: this.obj.parameterNames };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to promote a pause-lifetime grip to a
|
||||
|
@ -1242,13 +1326,9 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onThreadGrip: function OA_onThreadGrip(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
|
||||
onThreadGrip: PauseScopedActor.withPaused(function OA_onThreadGrip(aRequest) {
|
||||
return { threadGrip: this.threadActor.threadObjectGrip(this.obj) };
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Handle a protocol request to release a thread-lifetime grip.
|
||||
|
@ -1256,10 +1336,7 @@ ObjectActor.prototype = {
|
|||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onRelease: function OA_onRelease(aRequest) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
return this.WRONG_STATE_RESPONSE;
|
||||
}
|
||||
onRelease: PauseScopedActor.withPaused(function OA_onRelease(aRequest) {
|
||||
if (this.registeredPool !== this.threadActor.threadLifetimePool) {
|
||||
return { error: "notReleasable",
|
||||
message: "only thread-lifetime actors can be released." };
|
||||
|
@ -1267,8 +1344,8 @@ ObjectActor.prototype = {
|
|||
|
||||
this.release();
|
||||
return {};
|
||||
},
|
||||
};
|
||||
}),
|
||||
});
|
||||
|
||||
ObjectActor.prototype.requestTypes = {
|
||||
"nameAndParameters": ObjectActor.prototype.onNameAndParameters,
|
||||
|
@ -1283,6 +1360,65 @@ ObjectActor.prototype.requestTypes = {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an actor for the specied "very long" string. "Very long" is specified
|
||||
* at the server's discretion.
|
||||
*
|
||||
* @param aString String
|
||||
* The string.
|
||||
*/
|
||||
function LongStringActor(aString)
|
||||
{
|
||||
this.string = aString;
|
||||
this.stringLength = aString.length;
|
||||
}
|
||||
|
||||
LongStringActor.prototype = {
|
||||
|
||||
actorPrefix: "longString",
|
||||
|
||||
disconnect: function LSA_disconnect() {
|
||||
// Because longStringActors is not a weak map, we won't automatically leave
|
||||
// it so we need to manually leave on disconnect so that we don't leak
|
||||
// memory.
|
||||
if (this.registeredPool && this.registeredPool.longStringActors) {
|
||||
delete this.registeredPool.longStringActors[this.actorID];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a grip for this actor for returning in a protocol message.
|
||||
*/
|
||||
grip: function LSA_grip() {
|
||||
return {
|
||||
"type": "longString",
|
||||
"initial": this.string.substring(
|
||||
0, DebuggerServer.LONG_STRING_INITIAL_LENGTH),
|
||||
"length": this.stringLength,
|
||||
"actor": this.actorID
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle a request to extract part of this actor's string.
|
||||
*
|
||||
* @param aRequest object
|
||||
* The protocol request object.
|
||||
*/
|
||||
onSubstring: function LSA_onSubString(aRequest) {
|
||||
return {
|
||||
"from": this.actorID,
|
||||
"substring": this.string.substring(aRequest.start, aRequest.end)
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
LongStringActor.prototype.requestTypes = {
|
||||
"substring": LongStringActor.prototype.onSubstring
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an actor for the specified stack frame.
|
||||
*
|
||||
|
|
|
@ -61,6 +61,9 @@ var DebuggerServer = {
|
|||
xpcInspector: null,
|
||||
_allowConnection: null,
|
||||
|
||||
LONG_STRING_LENGTH: 10000,
|
||||
LONG_STRING_INITIAL_LENGTH: 1000,
|
||||
|
||||
/**
|
||||
* Initialize the debugger server.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; js-indent-level: 2; -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test()
|
||||
{
|
||||
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Components.interfaces.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript("chrome://global/content/devtools/dbg-script-actors.js");
|
||||
|
||||
test_LSA_disconnect();
|
||||
test_LSA_grip();
|
||||
test_LSA_onSubstring();
|
||||
}
|
||||
|
||||
const TEST_STRING = "This is a very long string!";
|
||||
|
||||
function makeMockLongStringActor()
|
||||
{
|
||||
let string = TEST_STRING;
|
||||
let actor = new LongStringActor(string);
|
||||
actor.actorID = "longString1";
|
||||
actor.registeredPool = {
|
||||
longStringActors: {
|
||||
longString1: actor
|
||||
}
|
||||
};
|
||||
return actor;
|
||||
}
|
||||
|
||||
function test_LSA_disconnect()
|
||||
{
|
||||
let actor = makeMockLongStringActor();
|
||||
do_check_eq(actor.registeredPool.longStringActors[actor.actorID], actor);
|
||||
|
||||
actor.disconnect();
|
||||
do_check_eq(actor.registeredPool.longStringActors[actor.actorID], void 0);
|
||||
}
|
||||
|
||||
function test_LSA_substring()
|
||||
{
|
||||
let actor = makeMockLongStringActor();
|
||||
do_check_eq(actor._substring(0, 4), TEST_STRING.substring(0, 4));
|
||||
do_check_eq(actor._substring(6, 9), TEST_STRING.substring(6, 9));
|
||||
do_check_eq(actor._substring(0, TEST_STRING.length), TEST_STRING);
|
||||
}
|
||||
|
||||
function test_LSA_grip()
|
||||
{
|
||||
let actor = makeMockLongStringActor();
|
||||
|
||||
let grip = actor.grip();
|
||||
do_check_eq(grip.type, "longString");
|
||||
do_check_eq(grip.initial, TEST_STRING.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH));
|
||||
do_check_eq(grip.length, TEST_STRING.length);
|
||||
do_check_eq(grip.actor, actor.actorID);
|
||||
}
|
||||
|
||||
function test_LSA_onSubstring()
|
||||
{
|
||||
let actor = makeMockLongStringActor();
|
||||
let response;
|
||||
|
||||
// From the start
|
||||
response = actor.onSubstring({
|
||||
start: 0,
|
||||
end: 4
|
||||
});
|
||||
do_check_eq(response.from, actor.actorID);
|
||||
do_check_eq(response.substring, TEST_STRING.substring(0, 4));
|
||||
|
||||
// In the middle
|
||||
response = actor.onSubstring({
|
||||
start: 5,
|
||||
end: 8
|
||||
});
|
||||
do_check_eq(response.from, actor.actorID);
|
||||
do_check_eq(response.substring, TEST_STRING.substring(5, 8));
|
||||
|
||||
// Whole string
|
||||
response = actor.onSubstring({
|
||||
start: 0,
|
||||
end: TEST_STRING.length
|
||||
});
|
||||
do_check_eq(response.from, actor.actorID);
|
||||
do_check_eq(response.substring, TEST_STRING);
|
||||
|
||||
// Negative index
|
||||
response = actor.onSubstring({
|
||||
start: -5,
|
||||
end: TEST_STRING.length
|
||||
});
|
||||
do_check_eq(response.from, actor.actorID);
|
||||
do_check_eq(response.substring,
|
||||
TEST_STRING.substring(-5, TEST_STRING.length));
|
||||
|
||||
// Past the end
|
||||
response = actor.onSubstring({
|
||||
start: TEST_STRING.length - 5,
|
||||
end: 100
|
||||
});
|
||||
do_check_eq(response.from, actor.actorID);
|
||||
do_check_eq(response.substring,
|
||||
TEST_STRING.substring(TEST_STRING.length - 5, 100));
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* 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(function() {
|
||||
attachTestGlobalClientAndResume(gClient, "test-grips", function(aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_longstring_grip();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_longstring_grip()
|
||||
{
|
||||
let longString = "All I want is to be a monkey of moderate intelligence who"
|
||||
+ " wears a suit... that's why I'm transferring to business school! Maybe I"
|
||||
+ " love you so much, I love you no matter who you are pretending to be."
|
||||
+ " Enough about your promiscuous mother, Hermes! We have bigger problems."
|
||||
+ " For example, if you killed your grandfather, you'd cease to exist! What"
|
||||
+ " kind of a father would I be if I said no? Yep, I remember. They came in"
|
||||
+ " last at the Olympics, then retired to promote alcoholic beverages! And"
|
||||
+ " remember, don't do anything that affects anything, unless it turns out"
|
||||
+ " you were supposed to, in which case, for the love of God, don't not do"
|
||||
+ " it!";
|
||||
|
||||
DebuggerServer.LONG_STRING_LENGTH = 200;
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
let args = aPacket.frame.arguments;
|
||||
do_check_eq(args.length, 1);
|
||||
let grip = args[0];
|
||||
|
||||
try {
|
||||
do_check_eq(grip.type, "longString");
|
||||
do_check_eq(grip.length, longString.length);
|
||||
do_check_eq(grip.initial, longString.substr(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH));
|
||||
|
||||
let longStringClient = gThreadClient.longString(grip);
|
||||
longStringClient.substring(22, 28, function (aResponse) {
|
||||
try {
|
||||
do_check_eq(aResponse.substring, "monkey");
|
||||
} finally {
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch(error) {
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
do_throw(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
gDebuggee.eval('stopMe("' + longString + '")');
|
||||
}
|
||||
|
|
@ -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");
|
||||
gDebuggee.eval(function stopMe(arg1) {
|
||||
debugger;
|
||||
}.toString());
|
||||
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function() {
|
||||
attachTestGlobalClientAndResume(
|
||||
gClient, "test-grips", function(aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_longstring_grip();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_longstring_grip()
|
||||
{
|
||||
DebuggerServer.LONG_STRING_LENGTH = 200;
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
|
||||
try {
|
||||
let fakeLongStringGrip = {
|
||||
type: "longString",
|
||||
length: 1000000,
|
||||
actor: "123fakeActor123",
|
||||
initial: ""
|
||||
};
|
||||
let longStringClient = gThreadClient.longString(fakeLongStringGrip);
|
||||
longStringClient.substring(22, 28, function (aResponse) {
|
||||
try {
|
||||
do_check_true(!!aResponse.error,
|
||||
"We should not get a response, but an error.");
|
||||
} finally {
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch(error) {
|
||||
gThreadClient.resume(function() {
|
||||
finishClient(gClient);
|
||||
do_throw(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
gDebuggee.eval('stopMe()');
|
||||
}
|
||||
|
|
@ -60,4 +60,7 @@ tail =
|
|||
[test_framebindings-05.js]
|
||||
[test_pause_exceptions-01.js]
|
||||
[test_pause_exceptions-02.js]
|
||||
[test_longstringactor.js]
|
||||
[test_longstringgrips-01.js]
|
||||
[test_longstringgrips-02.js]
|
||||
[test_breakpointstore.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче