Bug 897256 - Add Debugger Protocol support for NaN, Infinity, and -Infinity. r=dcamp

This commit is contained in:
Brandon Benvie 2013-08-12 10:15:22 -07:00
Родитель 0b5e997c41
Коммит e83c084fcd
8 изменённых файлов: 326 добавлений и 137 удалений

Просмотреть файл

@ -35,6 +35,10 @@ function testSimpleCall() {
let localVar3 = localScope.addItem("localVar3");
let localVar4 = localScope.addItem("localVar4");
let localVar5 = localScope.addItem("localVar5");
let localVar6 = localScope.addItem("localVar6");
let localVar7 = localScope.addItem("localVar7");
let localVar8 = localScope.addItem("localVar8");
let localVar9 = localScope.addItem("localVar9");
localVar0.setGrip(42);
localVar1.setGrip(true);
@ -43,6 +47,10 @@ function testSimpleCall() {
localVar3.setGrip({ "type": "undefined" });
localVar4.setGrip({ "type": "null" });
localVar5.setGrip({ "type": "object", "class": "Object" });
localVar6.setGrip({ "type": "Infinity" });
localVar7.setGrip({ "type": "-Infinity" });
localVar8.setGrip({ "type": "NaN" });
localVar9.setGrip({ "type": "-0" });
localVar5.addItems({
"someProp0": { "value": 42, "enumerable": true },
@ -54,15 +62,16 @@ function testSimpleCall() {
"value": { "type": "object", "class": "Object" },
"enumerable": true
},
"someUndefined": {
"value": { "type": "undefined" },
"enumerable": true
},
"someAccessor": {
"someProp6": { "value": { "type": "Infinity" }, "enumerable": true },
"someProp7": { "value": { "type": "-Infinity" }, "enumerable": true },
"someProp8": { "value": { "type": "NaN" }, "enumerable": true },
"someProp9": { "value": { "type": "undefined" }, "enumerable": true },
"someProp10": { "value": { "type": "-0" }, "enumerable": true },
"someProp11": {
"get": { "type": "object", "class": "Function" },
"set": { "type": "undefined" },
"enumerable": true
}
},
});
localVar5.get("someProp5").addItems({
@ -75,15 +84,16 @@ function testSimpleCall() {
"value": { "type": "object", "class": "Object" },
"enumerable": true
},
"someUndefined": {
"value": { "type": "undefined" },
"enumerable": true
},
"someAccessor": {
"someProp6": { "value": { "type": "Infinity" }, "enumerable": true },
"someProp7": { "value": { "type": "-Infinity" }, "enumerable": true },
"someProp8": { "value": { "type": "NaN" }, "enumerable": true },
"someProp9": { "value": { "type": "undefined" }, "enumerable": true },
"someProp10": { "value": { "type": "-0" }, "enumerable": true },
"someProp11": {
"get": { "type": "object", "class": "Function" },
"set": { "type": "undefined" },
"enumerable": true
}
},
});
windowVar.setGrip({ "type": "object", "class": "Window" });
@ -110,6 +120,10 @@ function testSimpleCall() {
ok(localVar3, "The localVar3 hasn't been created correctly.");
ok(localVar4, "The localVar4 hasn't been created correctly.");
ok(localVar5, "The localVar5 hasn't been created correctly.");
ok(localVar6, "The localVar6 hasn't been created correctly.");
ok(localVar7, "The localVar7 hasn't been created correctly.");
ok(localVar8, "The localVar8 hasn't been created correctly.");
ok(localVar9, "The localVar8 hasn't been created correctly.");
for each (let elt in globalScope.target.querySelector(".nonenum").childNodes) {
info("globalScope :: " + { id: elt.id, className: elt.className }.toSource());
@ -120,12 +134,12 @@ function testSimpleCall() {
for each (let elt in localScope.target.querySelector(".nonenum").childNodes) {
info("localScope :: " + { id: elt.id, className: elt.className }.toSource());
}
is(localScope.target.querySelector(".nonenum").childNodes.length, 6,
is(localScope.target.querySelector(".nonenum").childNodes.length, 10,
"The localScope doesn't contain all the created variable elements.");
is(localVar5.target.querySelector(".variables-view-element-details").childNodes.length, 8,
is(localVar5.target.querySelector(".variables-view-element-details").childNodes.length, 12,
"The localVar5 doesn't contain all the created properties.");
is(localVar5.get("someProp5").target.querySelector(".variables-view-element-details").childNodes.length, 8,
is(localVar5.get("someProp5").target.querySelector(".variables-view-element-details").childNodes.length, 12,
"The localVar5.someProp5 doesn't contain all the created properties.");
is(windowVar.target.querySelector(".value").getAttribute("value"), "Window",
@ -145,40 +159,64 @@ function testSimpleCall() {
"The grip information for the localVar4 wasn't set correctly.");
is(localVar5.target.querySelector(".value").getAttribute("value"), "Object",
"The grip information for the localVar5 wasn't set correctly.");
is(localVar6.target.querySelector(".value").getAttribute("value"), "Infinity",
"The grip information for the localVar6 wasn't set correctly.");
is(localVar7.target.querySelector(".value").getAttribute("value"), "-Infinity",
"The grip information for the localVar7 wasn't set correctly.");
is(localVar8.target.querySelector(".value").getAttribute("value"), "NaN",
"The grip information for the localVar8 wasn't set correctly.");
is(localVar9.target.querySelector(".value").getAttribute("value"), "-0",
"The grip information for the localVar9 wasn't set correctly.");
is(localVar5.get("someProp0").target.querySelector(".value").getAttribute("value"), "42",
"The grip information for the localVar0 wasn't set correctly.");
"The grip information for the someProp0 wasn't set correctly.");
is(localVar5.get("someProp1").target.querySelector(".value").getAttribute("value"), "true",
"The grip information for the localVar1 wasn't set correctly.");
"The grip information for the someProp1 wasn't set correctly.");
is(localVar5.get("someProp2").target.querySelector(".value").getAttribute("value"), "\"nasu\"",
"The grip information for the localVar2 wasn't set correctly.");
"The grip information for the someProp2 wasn't set correctly.");
is(localVar5.get("someProp3").target.querySelector(".value").getAttribute("value"), "undefined",
"The grip information for the localVar3 wasn't set correctly.");
"The grip information for the someProp3 wasn't set correctly.");
is(localVar5.get("someProp4").target.querySelector(".value").getAttribute("value"), "null",
"The grip information for the localVar4 wasn't set correctly.");
"The grip information for the someProp4 wasn't set correctly.");
is(localVar5.get("someProp5").target.querySelector(".value").getAttribute("value"), "Object",
"The grip information for the localVar5 wasn't set correctly.");
is(localVar5.get("someUndefined").target.querySelector(".value").getAttribute("value"), "undefined",
"The grip information for the someUndefined wasn't set correctly.");
is(localVar5.get("someAccessor").target.querySelector(".value").getAttribute("value"), "",
"The grip information for the someAccessor wasn't set correctly.");
"The grip information for the someProp5 wasn't set correctly.");
is(localVar5.get("someProp6").target.querySelector(".value").getAttribute("value"), "Infinity",
"The grip information for the someProp6 wasn't set correctly.");
is(localVar5.get("someProp7").target.querySelector(".value").getAttribute("value"), "-Infinity",
"The grip information for the someProp7 wasn't set correctly.");
is(localVar5.get("someProp8").target.querySelector(".value").getAttribute("value"), "NaN",
"The grip information for the someProp8 wasn't set correctly.");
is(localVar5.get("someProp9").target.querySelector(".value").getAttribute("value"), "undefined",
"The grip information for the someProp9 wasn't set correctly.");
is(localVar5.get("someProp10").target.querySelector(".value").getAttribute("value"), "-0",
"The grip information for the someProp10 wasn't set correctly.");
is(localVar5.get("someProp11").target.querySelector(".value").getAttribute("value"), "",
"The grip information for the someProp11 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp0").target.querySelector(".value").getAttribute("value"), "42",
"The grip information for the sub-localVar0 wasn't set correctly.");
"The grip information for the sub-someProp0 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp1").target.querySelector(".value").getAttribute("value"), "true",
"The grip information for the sub-localVar1 wasn't set correctly.");
"The grip information for the sub-someProp1 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp2").target.querySelector(".value").getAttribute("value"), "\"nasu\"",
"The grip information for the sub-localVar2 wasn't set correctly.");
"The grip information for the sub-someProp2 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp3").target.querySelector(".value").getAttribute("value"), "undefined",
"The grip information for the sub-localVar3 wasn't set correctly.");
"The grip information for the sub-someProp3 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp4").target.querySelector(".value").getAttribute("value"), "null",
"The grip information for the sub-localVar4 wasn't set correctly.");
"The grip information for the sub-someProp4 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp5").target.querySelector(".value").getAttribute("value"), "Object",
"The grip information for the sub-localVar5 wasn't set correctly.");
is(localVar5.get("someProp5").get("someUndefined").target.querySelector(".value").getAttribute("value"), "undefined",
"The grip information for the sub-someUndefined wasn't set correctly.");
is(localVar5.get("someProp5").get("someAccessor").target.querySelector(".value").getAttribute("value"), "",
"The grip information for the sub-someAccessor wasn't set correctly.");
"The grip information for the sub-someProp5 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp6").target.querySelector(".value").getAttribute("value"), "Infinity",
"The grip information for the sub-someProp6 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp7").target.querySelector(".value").getAttribute("value"), "-Infinity",
"The grip information for the sub-someProp7 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp8").target.querySelector(".value").getAttribute("value"), "NaN",
"The grip information for the sub-someProp8 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp9").target.querySelector(".value").getAttribute("value"), "undefined",
"The grip information for the sub-someProp9 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp10").target.querySelector(".value").getAttribute("value"), "-0",
"The grip information for the sub-someProp10 wasn't set correctly.");
is(localVar5.get("someProp5").get("someProp11").target.querySelector(".value").getAttribute("value"), "",
"The grip information for the sub-someProp11 wasn't set correctly.");
gDebugger.DebuggerController.activeThread.resume(function() {
closeDebuggerAndFinish();

Просмотреть файл

@ -3005,9 +3005,16 @@ VariablesView.isPrimitive = function(aDescriptor) {
return true;
}
// For convenience, undefined, null and long strings are considered types.
// For convenience, undefined, null, Infinity, -Infinity, NaN, -0, and long
// strings are considered types.
let type = grip.type;
if (type == "undefined" || type == "null" || type == "longString") {
if (type == "undefined" ||
type == "null" ||
type == "Infinity" ||
type == "-Infinity" ||
type == "NaN" ||
type == "-0" ||
type == "longString") {
return true;
}
@ -3054,9 +3061,12 @@ VariablesView.isFalsy = function(aDescriptor) {
return !grip;
}
// For convenience, undefined and null are both considered types.
// For convenience, undefined, null, NaN, and -0 are all considered types.
let type = grip.type;
if (type == "undefined" || type == "null") {
if (type == "undefined" ||
type == "null" ||
type == "NaN" ||
type == "-0") {
return true;
}
@ -3082,16 +3092,38 @@ VariablesView.isVariable = function(aValue) {
* The value's grip.
*/
VariablesView.getGrip = function(aValue) {
if (aValue === undefined) {
return { type: "undefined" };
switch (typeof aValue) {
case "boolean":
case "string":
return aValue;
case "number":
if (aValue === Infinity) {
return { type: "Infinity" };
} else if (aValue === -Infinity) {
return { type: "-Infinity" };
} else if (Number.isNaN(aValue)) {
return { type: "NaN" };
} else if (1 / aValue === -Infinity) {
return { type: "-0" };
}
return aValue;
case "undefined":
// document.all is also "undefined"
if (aValue === undefined) {
return { type: "undefined" };
}
case "object":
if (aValue === null) {
return { type: "null" };
}
case "function":
return { type: "object",
class: WebConsoleUtils.getObjectClassName(aValue) };
default:
Cu.reportError("Failed to provide a grip for value of " + typeof value +
": " + aValue);
return null;
}
if (aValue === null) {
return { type: "null" };
}
if (typeof aValue == "object" || typeof aValue == "function") {
return { type: "object", class: WebConsoleUtils.getObjectClassName(aValue) };
}
return aValue;
};
/**
@ -3108,27 +3140,33 @@ VariablesView.getString = function(aGrip, aConciseFlag) {
if (aGrip && typeof aGrip == "object") {
switch (aGrip.type) {
case "undefined":
return "undefined";
case "null":
return "null";
case "NaN":
case "Infinity":
case "-Infinity":
case "-0":
return aGrip.type;
case "longString":
return "\"" + aGrip.initial + "\"";
default:
if (!aConciseFlag) {
return "[" + aGrip.type + " " + aGrip.class + "]";
} else {
return aGrip.class;
}
}
} else {
switch (typeof aGrip) {
case "string":
return "\"" + aGrip + "\"";
case "boolean":
return aGrip ? "true" : "false";
return aGrip.class;
}
}
return aGrip + "";
switch (typeof aGrip) {
case "string":
return "\"" + aGrip + "\"";
case "boolean":
return aGrip ? "true" : "false";
case "number":
if (!aGrip && 1 / aGrip === -Infinity) {
return "-0";
}
default:
return aGrip + "";
}
};
/**
@ -3146,20 +3184,25 @@ VariablesView.getClass = function(aGrip) {
return "token-undefined";
case "null":
return "token-null";
case "Infinity":
case "-Infinity":
case "NaN":
case "-0":
return "token-number";
case "longString":
return "token-string";
}
} else {
switch (typeof aGrip) {
case "string":
return "token-string";
case "boolean":
return "token-boolean";
case "number":
return "token-number";
}
}
return "token-other";
switch (typeof aGrip) {
case "string":
return "token-string";
case "boolean":
return "token-boolean";
case "number":
return "token-number";
default:
return "token-other";
}
};
/**

Просмотреть файл

@ -1544,30 +1544,37 @@ ThreadActor.prototype = {
if (!aPool) {
aPool = this._pausePool;
}
let type = typeof(aValue);
if (type === "string" && this._stringIsLong(aValue)) {
return this.longStringGrip(aValue, aPool);
switch (typeof aValue) {
case "boolean":
return aValue;
case "string":
if (this._stringIsLong(aValue)) {
return this.longStringGrip(aValue, aPool);
}
return aValue;
case "number":
if (aValue === Infinity) {
return { type: "Infinity" };
} else if (aValue === -Infinity) {
return { type: "-Infinity" };
} else if (Number.isNaN(aValue)) {
return { type: "NaN" };
} else if (!aValue && 1 / aValue === -Infinity) {
return { type: "-0" };
}
return aValue;
case "undefined":
return { type: "undefined" };
case "object":
if (aValue === null) {
return { type: "null" };
}
return this.objectGrip(aValue, aPool);
default:
dbg_assert(false, "Failed to provide a grip for: " + aValue);
return null;
}
if (type === "boolean" || type === "string" || type === "number") {
return aValue;
}
if (aValue === null) {
return { type: "null" };
}
if (aValue === undefined) {
return { type: "undefined" }
}
if (typeof(aValue) === "object") {
return this.objectGrip(aValue, aPool);
}
dbg_assert(false, "Failed to provide a grip for: " + aValue);
return null;
},
/**

Просмотреть файл

@ -558,35 +558,41 @@ function serializeCompletionValue(aType, { value }) {
* A primitive value or a grip object.
*/
function createValueGrip(aValue, aUseDescriptor) {
let type = typeof aValue;
if (type === "string" && aValue.length >= DebuggerServer.LONG_STRING_LENGTH) {
return {
type: "longString",
initial: aValue.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH),
length: aValue.length
};
switch (typeof aValue) {
case "boolean":
return aValue;
case "string":
if (aValue.length >= DebuggerServer.LONG_STRING_LENGTH) {
return {
type: "longString",
initial: aValue.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH),
length: aValue.length
};
}
return aValue;
case "number":
if (aValue === Infinity) {
return { type: "Infinity" };
} else if (aValue === -Infinity) {
return { type: "-Infinity" };
} else if (Number.isNaN(aValue)) {
return { type: "NaN" };
} else if (!aValue && 1 / aValue === -Infinity) {
return { type: "-0" };
}
return aValue;
case "undefined":
return { type: "undefined" };
case "object":
if (aValue === null) {
return { type: "null" };
}
return aUseDescriptor ? objectDescriptor(aValue) : objectGrip(aValue);
default:
reportException("TraceActor",
new Error("Failed to provide a grip for: " + aValue));
return null;
}
if (type === "boolean" || type === "string" || type === "number") {
return aValue;
}
if (aValue === null) {
return { type: "null" };
}
if (aValue === undefined) {
return { type: "undefined" };
}
if (typeof(aValue) === "object") {
return aUseDescriptor ? objectDescriptor(aValue) : objectGrip(aValue);
}
reportException("TraceActor",
new Error("Failed to provide a grip for: " + aValue));
return null;
}
/**

Просмотреть файл

@ -0,0 +1,63 @@
/* 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() {
attachTestTabAndResume(gClient, "test-grips", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
test_object_grip();
});
});
do_test_pending();
}
function test_object_grip()
{
gThreadClient.addOneTimeListener("paused", function(aEvent, aPacket) {
let args = aPacket.frame.arguments;
do_check_eq(args[0].class, "Object");
let objClient = gThreadClient.pauseGrip(args[0]);
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.type, "Infinity");
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, "-Infinity");
do_check_eq(aResponse.ownProperties.c.configurable, true);
do_check_eq(aResponse.ownProperties.c.enumerable, true);
do_check_eq(aResponse.ownProperties.c.writable, true);
do_check_eq(aResponse.ownProperties.c.value.type, "NaN");
do_check_eq(aResponse.ownProperties.d.configurable, true);
do_check_eq(aResponse.ownProperties.d.enumerable, true);
do_check_eq(aResponse.ownProperties.d.writable, true);
do_check_eq(aResponse.ownProperties.d.value.type, "-0");
gThreadClient.resume(function() {
finishClient(gClient);
});
});
});
gDebuggee.eval("stopMe({ a: Infinity, b: -Infinity, c: NaN, d: -0 })");
}

Просмотреть файл

@ -64,6 +64,22 @@ function test_enter_exit_frame()
'return value should have property "arr"');
do_check_eq(typeof obj.ownProperties.arr.value, "object",
'return value property "arr" should be a grip');
do_check_eq(typeof obj.ownProperties.inf, "object",
'return value should have property "inf"');
do_check_eq(typeof obj.ownProperties.inf.value, "object",
'return value property "inf" should be a grip');
do_check_eq(typeof obj.ownProperties.ninf, "object",
'return value should have property "ninf"');
do_check_eq(typeof obj.ownProperties.ninf.value, "object",
'return value property "ninf" should be a grip');
do_check_eq(typeof obj.ownProperties.nan, "object",
'return value should have property "nan"');
do_check_eq(typeof obj.ownProperties.nan.value, "object",
'return value property "nan" should be a grip');
do_check_eq(typeof obj.ownProperties.nzero, "object",
'return value should have property "nzero"');
do_check_eq(typeof obj.ownProperties.nzero.value, "object",
'return value property "nzero" should be a grip');
do_check_eq(obj.prototype.type, "object");
do_check_eq(obj.ownProperties.num.value, 25);
@ -75,6 +91,10 @@ function test_enter_exit_frame()
do_check_eq(obj.ownProperties.obj.value.class, "Object");
do_check_eq(obj.ownProperties.arr.value.type, "object");
do_check_eq(obj.ownProperties.arr.value.class, "Array");
do_check_eq(obj.ownProperties.inf.value.type, "Infinity");
do_check_eq(obj.ownProperties.ninf.value.type, "-Infinity");
do_check_eq(obj.ownProperties.nan.value.type, "NaN");
do_check_eq(obj.ownProperties.nzero.value.type, "-0");
}
});
@ -107,7 +127,11 @@ function eval_code()
undef: undefined,
nil: null,
obj: obj,
arr: [1,2,3,4,5]
arr: [1,2,3,4,5],
inf: Infinity,
ninf: -Infinity,
nan: NaN,
nzero: -0
};
}
foo();

Просмотреть файл

@ -120,6 +120,7 @@ reason = bug 820380
[test_objectgrips-05.js]
[test_objectgrips-06.js]
[test_objectgrips-07.js]
[test_objectgrips-08.js]
[test_interrupt.js]
[test_stepping-01.js]
[test_stepping-02.js]

Просмотреть файл

@ -317,29 +317,36 @@ let WebConsoleUtils = {
*/
createValueGrip: function WCU_createValueGrip(aValue, aObjectWrapper)
{
let type = typeof(aValue);
switch (type) {
switch (typeof aValue) {
case "boolean":
case "number":
return aValue;
case "string":
return aObjectWrapper(aValue);
case "object":
case "function":
if (aValue) {
return aObjectWrapper(aValue);
return aObjectWrapper(aValue);
case "number":
if (aValue === Infinity) {
return { type: "Infinity" };
}
default:
else if (aValue === -Infinity) {
return { type: "-Infinity" };
}
else if (Number.isNaN(aValue)) {
return { type: "NaN" };
}
else if (!aValue && 1 / aValue === -Infinity) {
return { type: "-0" };
}
return aValue;
case "undefined":
return { type: "undefined" };
case "object":
if (aValue === null) {
return { type: "null" };
}
if (aValue === undefined) {
return { type: "undefined" };
}
Cu.reportError("Failed to provide a grip for value of " + type + ": " +
aValue);
case "function":
return aObjectWrapper(aValue);
default:
Cu.reportError("Failed to provide a grip for value of " + typeof aValue
+ ": " + aValue);
return null;
}
},