Bug 1548256 - Blank debugger when hovering variables. r=davidwalsh
authorJason Laster <jlaster@mozilla.com>
Wed, 08 May 2019 13:08:24 +0000
changeset 473061 72f1173462423fe2959e08bc1788e902a3a8d7c8
parent 473060 0ad4726584ec4bdb1786371815c814b3c7b66559
child 473062 071e3e7156387b323d52ae3231a8bbffd408d87a
push id113065
push useropoprus@mozilla.com
push dateThu, 09 May 2019 03:46:59 +0000
treeherdermozilla-inbound@34a824c75b7b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidwalsh
bugs1548256
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1548256 - Blank debugger when hovering variables. r=davidwalsh Differential Revision: https://phabricator.services.mozilla.com/D30246
devtools/client/debugger/src/actions/preview.js
devtools/client/debugger/src/client/firefox/commands.js
devtools/client/debugger/src/client/firefox/tests/commands.spec.js
devtools/client/debugger/src/client/firefox/types.js
--- a/devtools/client/debugger/src/actions/preview.js
+++ b/devtools/client/debugger/src/actions/preview.js
@@ -113,16 +113,22 @@ export function setPreview(
         // Error case occurs for a token that follows an errored evaluation
         // https://github.com/firefox-devtools/debugger/pull/8056
         // Accommodating for null allows us to show preview for falsy values
         // line "", false, null, Nan, and more
         if (result === null) {
           return;
         }
 
+        // Handle cases where the result is invisible to the debugger
+        // and not possible to preview. Bug 1548256
+        if (result.class && result.class.includes("InvisibleToDebugger")) {
+          return;
+        }
+
         const root = {
           name: expression,
           path: expression,
           contents: { value: result }
         };
         const properties = await client.loadObjectProperties(root);
 
         return {
--- a/devtools/client/debugger/src/client/firefox/commands.js
+++ b/devtools/client/debugger/src/client/firefox/commands.js
@@ -259,17 +259,17 @@ async function evaluateExpressions(scrip
   return Promise.all(scripts.map(script => evaluate(script, options)));
 }
 
 type EvaluateParam = { thread: string, frameId: ?FrameId };
 
 function evaluate(
   script: ?Script,
   { thread, frameId }: EvaluateParam = {}
-): Promise<{ result: ?Object }> {
+): Promise<{ result: Grip | null }> {
   const params = { thread, frameActor: frameId };
   if (!tabTarget || !script) {
     return Promise.resolve({ result: null });
   }
 
   const console = thread
     ? lookupConsoleClient(thread)
     : tabTarget.activeConsole;
--- a/devtools/client/debugger/src/client/firefox/tests/commands.spec.js
+++ b/devtools/client/debugger/src/client/firefox/tests/commands.spec.js
@@ -19,71 +19,92 @@ function makeThreadCLient(resp) {
 function makeDependencies() {
   return {
     debuggerClient: (null: any),
     supportsWasm: true,
     tabTarget: (null: any)
   };
 }
 
+function makeGrip(actor = "") {
+  return {
+    actor,
+    class: "",
+    displayClass: "",
+    name: "",
+    extensible: true,
+    location: {
+      url: "",
+      line: 2,
+      column: 34
+    },
+    frozen: false,
+    ownPropertyLength: 1,
+    preview: {},
+    sealed: false,
+    optimizedOut: false,
+    type: ""
+  };
+}
+
 describe("firefox commands", () => {
   describe("getProperties", () => {
     it("empty response", async () => {
       const { getProperties } = clientCommands;
       const threadClient = makeThreadCLient({
         ownProperties: {},
         safeGetterValues: {}
       });
 
       setupCommands({ ...makeDependencies(), threadClient });
-      const props = await getProperties("", { actor: "" });
+      const props = await getProperties("", makeGrip());
       expect(props).toMatchSnapshot();
     });
 
     it("simple properties", async () => {
       const { getProperties } = clientCommands;
       const threadClient = makeThreadCLient({
         ownProperties: {
           obj: { value: "obj" },
           foo: { value: "foo" }
         },
         safeGetterValues: {}
       });
 
       setupCommands({ ...makeDependencies(), threadClient });
-      const props = await getProperties("", { actor: "" });
+      const props = await getProperties("", makeGrip());
       expect(props).toMatchSnapshot();
     });
 
     it("getter values", async () => {
       const { getProperties } = clientCommands;
       const threadClient = makeThreadCLient({
         ownProperties: {
           obj: { value: "obj" },
           foo: { value: "foo" }
         },
         safeGetterValues: {
           obj: { getterValue: "getter", enumerable: true, writable: false }
         }
       });
 
       setupCommands({ ...makeDependencies(), threadClient });
-      const props = await getProperties("", { actor: "" });
+      const props = await getProperties("", makeGrip());
       expect(props).toMatchSnapshot();
     });
 
     it("new getter values", async () => {
       const { getProperties } = clientCommands;
       const threadClient = makeThreadCLient({
         ownProperties: {
           foo: { value: "foo" }
         },
         safeGetterValues: {
           obj: { getterValue: "getter", enumerable: true, writable: false }
         }
       });
 
       setupCommands({ ...makeDependencies(), threadClient });
-      const props = await getProperties("", { actor: "" });
+      const props = await getProperties("", makeGrip());
       expect(props).toMatchSnapshot();
     });
   });
 });
--- a/devtools/client/debugger/src/client/firefox/types.js
+++ b/devtools/client/debugger/src/client/firefox/types.js
@@ -204,17 +204,17 @@ export type TabTarget = {
       script: Script,
       func: Function,
       params?: { frameActor: ?FrameId }
     ) => void,
     evaluateJSAsync: (
       script: Script,
       func: Function,
       params?: { frameActor: ?FrameId }
-    ) => Promise<{ result: ?Object }>,
+    ) => Promise<{ result: Grip | null }>,
     autocomplete: (
       input: string,
       cursor: number,
       func: Function,
       frameId: ?string
     ) => void,
     emit: (string, any) => void
   },
@@ -272,19 +272,36 @@ export type TabClient = {
  * value's current state to the client. They also act as references to the
  * original value, by including an actor to which the client can send messages
  * to modify the value in the debuggee.
  *
  * @see https://wiki.mozilla.org/Remote_Debugging_Protocol#Grips
  * @memberof firefox
  * @static
  */
-// FIXME: need Grip definition
 export type Grip = {
-  actor: string
+  actor: string,
+  class: string,
+  displayClass: string,
+  displayName?: string,
+  parameterNames?: string[],
+  userDisplayName?: string,
+  name: string,
+  extensible: boolean,
+  location: {
+    url: string,
+    line: number,
+    column: number
+  },
+  frozen: boolean,
+  ownPropertyLength: number,
+  preview: Object,
+  sealed: boolean,
+  optimizedOut: boolean,
+  type: string
 };
 
 export type FunctionGrip = {|
   class: "Function",
   name: string,
   parameterNames: string[],
   displayName: string,
   userDisplayName: string,