From e83c084fcda532ca8a8c04bd58ae09f463a6b4c2 Mon Sep 17 00:00:00 2001 From: Brandon Benvie Date: Mon, 12 Aug 2013 10:15:22 -0700 Subject: [PATCH] Bug 897256 - Add Debugger Protocol support for NaN, Infinity, and -Infinity. r=dcamp --- .../test/browser_dbg_propertyview-06.js | 108 +++++++++++------ .../devtools/shared/widgets/VariablesView.jsm | 113 ++++++++++++------ toolkit/devtools/server/actors/script.js | 51 ++++---- toolkit/devtools/server/actors/tracer.js | 62 +++++----- .../server/tests/unit/test_objectgrips-08.js | 63 ++++++++++ .../server/tests/unit/test_trace_actor-06.js | 26 +++- .../devtools/server/tests/unit/xpcshell.ini | 1 + toolkit/devtools/webconsole/utils.js | 39 +++--- 8 files changed, 326 insertions(+), 137 deletions(-) create mode 100644 toolkit/devtools/server/tests/unit/test_objectgrips-08.js diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-06.js b/browser/devtools/debugger/test/browser_dbg_propertyview-06.js index 5abfed0ce4f4..3ffd61cc1a64 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-06.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-06.js @@ -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(); diff --git a/browser/devtools/shared/widgets/VariablesView.jsm b/browser/devtools/shared/widgets/VariablesView.jsm index c4e90c0c6707..664579dc6eac 100644 --- a/browser/devtools/shared/widgets/VariablesView.jsm +++ b/browser/devtools/shared/widgets/VariablesView.jsm @@ -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"; + } }; /** diff --git a/toolkit/devtools/server/actors/script.js b/toolkit/devtools/server/actors/script.js index bc66eaae760f..ea733b20ede7 100644 --- a/toolkit/devtools/server/actors/script.js +++ b/toolkit/devtools/server/actors/script.js @@ -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; }, /** diff --git a/toolkit/devtools/server/actors/tracer.js b/toolkit/devtools/server/actors/tracer.js index 8885515dde77..f01f326995a9 100644 --- a/toolkit/devtools/server/actors/tracer.js +++ b/toolkit/devtools/server/actors/tracer.js @@ -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; } /** diff --git a/toolkit/devtools/server/tests/unit/test_objectgrips-08.js b/toolkit/devtools/server/tests/unit/test_objectgrips-08.js new file mode 100644 index 000000000000..b0044f5ae04b --- /dev/null +++ b/toolkit/devtools/server/tests/unit/test_objectgrips-08.js @@ -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 })"); +} + diff --git a/toolkit/devtools/server/tests/unit/test_trace_actor-06.js b/toolkit/devtools/server/tests/unit/test_trace_actor-06.js index 3df0372e82db..2dd965809fa4 100644 --- a/toolkit/devtools/server/tests/unit/test_trace_actor-06.js +++ b/toolkit/devtools/server/tests/unit/test_trace_actor-06.js @@ -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(); diff --git a/toolkit/devtools/server/tests/unit/xpcshell.ini b/toolkit/devtools/server/tests/unit/xpcshell.ini index be4b67a58be8..5197d453acdf 100644 --- a/toolkit/devtools/server/tests/unit/xpcshell.ini +++ b/toolkit/devtools/server/tests/unit/xpcshell.ini @@ -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] diff --git a/toolkit/devtools/webconsole/utils.js b/toolkit/devtools/webconsole/utils.js index 2df725bc16c6..5dcd8089b78d 100644 --- a/toolkit/devtools/webconsole/utils.js +++ b/toolkit/devtools/webconsole/utils.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; } },