Bug 1544697 - use LongStringFront in SourceFront; r=ochameau,jdescottes
authoryulia <ystartsev@mozilla.com>
Tue, 30 Apr 2019 08:04:33 +0000
changeset 530792 542c3b51efa1deda9a07a1081d635150a0d8d45f
parent 530791 e296ba825656e009010819ee22c31f402abfa312
child 530793 78df5dc92c3f9a0c58043d625a3c93352135948f
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau, jdescottes
bugs1544697
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 1544697 - use LongStringFront in SourceFront; r=ochameau,jdescottes This change does two things: it starts returning the longstring actor directly from the server. It also introduces a new type in the spec — sourcedata. This sourcedata can handle either a plain form (for array buffer) or it writes to and from a front. This is the major change. It could be the basis for writing a union type for protocol.js, which would do the same thing based on a list (ie — RetVal(“nullable:arraybuffer|nullable:longstring”)) This could be useful for getting handling the return value of createValueGrip (https://searchfox.org/mozilla-central/rev/f46e2bf881d522a440b30cbf5cf8d76fc212eaf4/devtools/server/actors/object/utils.js#75) This requires that this stack lands first: https://phabricator.services.mozilla.com/D27709 Differential Revision: https://phabricator.services.mozilla.com/D27877
devtools/server/actors/source.js
devtools/shared/fronts/source.js
devtools/shared/specs/source.js
--- a/devtools/server/actors/source.js
+++ b/devtools/server/actors/source.js
@@ -3,24 +3,24 @@
 /* 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/. */
 
 "use strict";
 
 const { Ci } = require("chrome");
 const { setBreakpointAtEntryPoints } = require("devtools/server/actors/breakpoint");
-const { createValueGrip } = require("devtools/server/actors/object/utils");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { assert, fetch } = DevToolsUtils;
 const { joinURI } = require("devtools/shared/path");
 const { sourceSpec } = require("devtools/shared/specs/source");
 
 loader.lazyRequireGetter(this, "arrayBufferGrip", "devtools/server/actors/array-buffer", true);
+loader.lazyRequireGetter(this, "LongStringActor", "devtools/server/actors/string", true);
 
 function isEvalSource(source) {
   const introType = source.introductionType;
 
   // Script elements that are dynamically created are treated as eval sources.
   // We detect these by looking at whether there was another script on the stack
   // when the source was created.
   if (introType == "scriptElement" && source.introductionScript) {
@@ -322,34 +322,34 @@ const SourceActor = ActorClassWithSpec(s
     }
     return compressed;
   },
 
   /**
    * Handler for the "onSource" packet.
    * @return Object
    *         The return of this function contains a field `contentType`, and
-   *         a field `source`. `source` can either be an arrayBufferActor grip,
-   *         or a LongStringActor grip.
+   *         a field `source`. `source` can either be an ArrayBuffer or
+   *         a LongString.
    */
   onSource: function() {
     return Promise.resolve(this._init)
       .then(this._getSourceText)
       .then(({ content, contentType }) => {
         if (typeof content === "object" && content && content.constructor &&
             content.constructor.name === "ArrayBuffer") {
           return {
             source: arrayBufferGrip(content, this.threadActor.threadLifetimePool),
             contentType,
           };
         }
+
         return {
-          source: createValueGrip(content, this.threadActor.threadLifetimePool,
-            this.threadActor.objectGrip),
-          contentType: contentType,
+          source: new LongStringActor(this.threadActor.conn, content),
+          contentType,
         };
       })
       .catch(error => {
         reportError(error, "Got an exception during SA_onSource: ");
         throw new Error("Could not load the source for " + this.url + ".\n" +
                         DevToolsUtils.safeErrorString(error));
       });
   },
--- a/devtools/shared/fronts/source.js
+++ b/devtools/shared/fronts/source.js
@@ -58,17 +58,17 @@ class SourceFront extends FrontClassWith
   _onSourceResponse(response) {
     if (typeof response.source === "string") {
       return response;
     }
 
     const { contentType, source } = response;
     if (source.type === "arrayBuffer") {
       const arrayBuffer = this._activeThread.threadArrayBuffer(source);
-      return arrayBuffer.slice(0, arrayBuffer.length).then(function(resp) {
+      return arrayBuffer.slice(0, source.length).then(function(resp) {
         if (resp.error) {
           return resp;
         }
         // Keeping str as a string, ArrayBuffer/Uint8Array will not survive
         // setIn/mergeIn operations.
         const str = atob(resp.encoded);
         const newResponse = {
           source: {
@@ -76,24 +76,23 @@ class SourceFront extends FrontClassWith
             toString: () => "[wasm]",
           },
           contentType,
         };
         return newResponse;
       });
     }
 
-    const longString = this._activeThread.threadLongString(source);
-    return longString.substring(0, longString.length).then(function(resp) {
+    return source.substring(0, source.length).then(function(resp) {
       if (resp.error) {
         return resp;
       }
 
       const newResponse = {
-        source: resp.substring,
+        source: resp,
         contentType: contentType,
       };
       return newResponse;
     });
   }
 }
 
 exports.SourceFront = SourceFront;
--- a/devtools/shared/specs/source.js
+++ b/devtools/shared/specs/source.js
@@ -1,28 +1,51 @@
 /* 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/. */
 "use strict";
 
 const {Arg, RetVal, generateActorSpec, types} = require("devtools/shared/protocol");
 
+const longstringType = types.getType("longstring");
+// The sourcedata type needs some custom marshalling, because it is sometimes
+// returned as an arraybuffer and sometimes as a longstring.
+types.addType("sourcedata", {
+  write: (value, context, detail) => {
+    if (value.type === "arrayBuffer") {
+      return value;
+    }
+    return longstringType.write(value, context, detail);
+  },
+  read: (value, context, detail) => {
+    if (value.type === "arrayBuffer") {
+      return value;
+    }
+    return longstringType.read(value, context, detail);
+  },
+});
+
 types.addDictType("sourceposition", {
   line: "number",
   column: "number",
 });
 types.addDictType("nullablesourceposition", {
   line: "nullable:number",
   column: "nullable:number",
 });
 types.addDictType("breakpointquery", {
   start: "nullable:nullablesourceposition",
   end: "nullable:nullablesourceposition",
 });
 
+types.addDictType("source.onsource", {
+  contentType: "nullable:string",
+  source: "nullable:sourcedata",
+});
+
 const sourceSpec = generateActorSpec({
   typeName: "source",
 
   methods: {
     getBreakpointPositions: {
       request: {
         query: Arg(0, "nullable:breakpointquery"),
       },
@@ -37,17 +60,17 @@ const sourceSpec = generateActorSpec({
       response: {
         positions: RetVal("json"),
       },
     },
     onSource: {
       // we are sending the type "source" to be compatible
       // with FF67 and older
       request: { type: "source" },
-      response: RetVal("json"),
+      response: RetVal("source.onsource"),
     },
     setPausePoints: {
       request: {
         pausePoints: Arg(0, "json"),
       },
     },
     blackbox: {
       request: { range: Arg(0, "nullable:json") },