Bug 1179820 - Remove source map handling from stylesheets actor; r?gl draft
authorTom Tromey <tom@tromey.com>
Fri, 29 Sep 2017 10:00:36 -0600
changeset 680886 567c1fb3e861bffbd9a48b9026afb1d457a07328
parent 680885 ad6cfa8e25b6cee04002d60d1482d6083c3f2eb0
child 735999 6007c72504ff93bdbf7ed538101457606ba65f5e
push id84661
push userbmo:ttromey@mozilla.com
push dateMon, 16 Oct 2017 14:19:39 +0000
reviewersgl
bugs1179820
milestone58.0a1
Bug 1179820 - Remove source map handling from stylesheets actor; r?gl MozReview-Commit-ID: 88Sw3TSx5yL
devtools/server/actors/stylesheets.js
devtools/shared/fronts/stylesheets.js
devtools/shared/specs/index.js
devtools/shared/specs/stylesheets.js
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -7,19 +7,18 @@
 const {Ci} = require("chrome");
 const Services = require("Services");
 const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const {Task} = require("devtools/shared/task");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {fetch} = require("devtools/shared/DevToolsUtils");
-const {originalSourceSpec, mediaRuleSpec, styleSheetSpec,
+const {mediaRuleSpec, styleSheetSpec,
        styleSheetsSpec} = require("devtools/shared/specs/stylesheets");
-const {SourceMapConsumer} = require("source-map");
 const {
   addPseudoClassLock, removePseudoClassLock } = require("devtools/server/actors/highlighters/utils/markup");
 
 loader.lazyRequireGetter(this, "CssLogic", "devtools/shared/inspector/css-logic");
 loader.lazyRequireGetter(this, "addPseudoClassLock",
   "devtools/server/actors/highlighters/utils/markup", true);
 loader.lazyRequireGetter(this, "removePseudoClassLock",
   "devtools/server/actors/highlighters/utils/markup", true);
@@ -54,74 +53,16 @@ exports.UPDATE_GENERAL = UPDATE_GENERAL;
 // If the user edits a style sheet, we stash a copy of the edited text
 // here, keyed by the style sheet.  This way, if the tools are closed
 // and then reopened, the edited text will be available.  A weak map
 // is used so that navigation by the user will eventually cause the
 // edited text to be collected.
 let modifiedStyleSheets = new WeakMap();
 
 /**
- * Actor representing an original source of a style sheet that was specified
- * in a source map.
- */
-var OriginalSourceActor = protocol.ActorClassWithSpec(originalSourceSpec, {
-  initialize: function (url, sourceMap, parentActor) {
-    protocol.Actor.prototype.initialize.call(this, null);
-
-    this.url = url;
-    this.sourceMap = sourceMap;
-    this.parentActor = parentActor;
-    this.conn = this.parentActor.conn;
-
-    this.text = null;
-  },
-
-  form: function () {
-    return {
-      actor: this.actorID, // actorID is set when it's added to a pool
-      url: this.url,
-      relatedStyleSheet: this.parentActor.form()
-    };
-  },
-
-  _getText: function () {
-    if (this.text) {
-      return promise.resolve(this.text);
-    }
-    let content = this.sourceMap.sourceContentFor(this.url);
-    if (content) {
-      this.text = content;
-      return promise.resolve(content);
-    }
-    let options = {
-      // Make sure to use TYPE_OTHER - we are not fetching necessarily
-      // even fetching a style sheet, and anyway we're not planning to
-      // use it as a style sheet per se but rather just for its text;
-      // and this avoids problems with X-Content-Type-Options:
-      // nosniff.  See bug 1330383.
-      policy: Ci.nsIContentPolicy.TYPE_OTHER,
-      window: this.window
-    };
-    return fetch(this.url, options).then(({content: text}) => {
-      this.text = text;
-      return text;
-    });
-  },
-
-  /**
-   * Protocol method to get the text of this source.
-   */
-  getText: function () {
-    return this._getText().then((text) => {
-      return new LongStringActor(this.conn, text || "");
-    });
-  }
-});
-
-/**
  * A MediaRuleActor lives on the server and provides access to properties
  * of a DOM @media rule and emits events when it changes.
  */
 var MediaRuleActor = protocol.ActorClassWithSpec(mediaRuleSpec, {
   get window() {
     return this.parentActor.window;
   },
 
@@ -186,19 +127,16 @@ var MediaRuleActor = protocol.ActorClass
     this.emit("matches-change", this.matches);
   }
 });
 
 /**
  * A StyleSheetActor represents a stylesheet on the server.
  */
 var StyleSheetActor = protocol.ActorClassWithSpec(styleSheetSpec, {
-  /* List of original sources that generated this stylesheet */
-  _originalSources: null,
-
   toString: function () {
     return "[StyleSheetActor " + this.actorID + "]";
   },
 
   /**
    * Window of target
    */
   get window() {
@@ -495,155 +433,16 @@ var StyleSheetActor = protocol.ActorClas
       options.principal = undefined;
       result = yield fetch(this.href, options);
     }
 
     return result;
   }),
 
   /**
-   * Protocol method to get the original source (actors) for this
-   * stylesheet if it has uses source maps.
-   */
-  getOriginalSources: function () {
-    if (this._originalSources) {
-      return promise.resolve(this._originalSources);
-    }
-    return this._fetchOriginalSources();
-  },
-
-  /**
-   * Fetch the original sources (actors) for this style sheet using its
-   * source map. If they've already been fetched, returns cached array.
-   *
-   * @return {Promise}
-   *         Promise that resolves with an array of OriginalSourceActors
-   */
-  _fetchOriginalSources: function () {
-    this._clearOriginalSources();
-    this._originalSources = [];
-
-    return this.getSourceMap().then((sourceMap) => {
-      if (!sourceMap) {
-        return null;
-      }
-      for (let url of sourceMap.sources) {
-        let actor = new OriginalSourceActor(url, sourceMap, this);
-
-        this.manage(actor);
-        this._originalSources.push(actor);
-      }
-      return this._originalSources;
-    });
-  },
-
-  /**
-   * Get the SourceMapConsumer for this stylesheet's source map, if
-   * it exists. Saves the consumer for later queries.
-   *
-   * @return {Promise}
-   *         A promise that resolves with a SourceMapConsumer, or null.
-   */
-  getSourceMap: function () {
-    if (this._sourceMap) {
-      return this._sourceMap;
-    }
-    return this._fetchSourceMap();
-  },
-
-  /**
-   * Fetch the source map for this stylesheet.
-   *
-   * @return {Promise}
-   *         A promise that resolves with a SourceMapConsumer, or null.
-   */
-  _fetchSourceMap: function () {
-    let deferred = defer();
-
-    let url = this.rawSheet.sourceMapURL;
-    if (!url) {
-      // no source map for this stylesheet
-      deferred.resolve(null);
-      return deferred.promise;
-    }
-
-    url = normalize(url, this.safeHref);
-    let options = {
-      loadFromCache: false,
-      policy: Ci.nsIContentPolicy.TYPE_INTERNAL_STYLESHEET,
-      window: this.window
-    };
-
-    let map = fetch(url, options).then(({content}) => {
-      // Fetching the source map might have failed with a 404 or other. When
-      // this happens, SourceMapConsumer may fail with a JSON.parse error.
-      let consumer;
-      try {
-        consumer = new SourceMapConsumer(content,
-                                         this._getSourceMapRoot(url, this.safeHref));
-      } catch (e) {
-        deferred.reject(new Error(
-          `Source map at ${url} not found or invalid`));
-        return null;
-      }
-      this._sourceMap = promise.resolve(consumer);
-
-      deferred.resolve(consumer);
-      return consumer;
-    }, deferred.reject);
-
-    this._sourceMap = map;
-
-    return deferred.promise;
-  },
-
-  /**
-   * Clear and unmanage the original source actors for this stylesheet.
-   */
-  _clearOriginalSources: function () {
-    for (let actor in this._originalSources) {
-      this.unmanage(actor);
-    }
-    this._originalSources = null;
-  },
-
-  /**
-   * Compute the URL to pass to the SourceMapConsumer constructor as
-   * the "source map's URL".
-   */
-  _getSourceMapRoot: function (absSourceMapURL, scriptURL) {
-    // Pass in the source map URL; except if it is a data: or blob:
-    // URL, fall back to using the source's URL, if possible.
-    if (scriptURL && (absSourceMapURL.startsWith("data:") ||
-                      absSourceMapURL.startsWith("blob:"))) {
-      return scriptURL;
-    }
-    return absSourceMapURL;
-  },
-
-  /**
-   * Protocol method that gets the location in the original source of a
-   * line, column pair in this stylesheet, if its source mapped, otherwise
-   * a promise of the same location.
-   */
-  getOriginalLocation: function (line, column) {
-    return this.getSourceMap().then((sourceMap) => {
-      if (sourceMap) {
-        return sourceMap.originalPositionFor({ line: line, column: column });
-      }
-      return {
-        fromSourceMap: false,
-        source: this.href,
-        line: line,
-        column: column
-      };
-    });
-  },
-
-  /**
    * Protocol method to get the media rules for the stylesheet.
    */
   getMediaRules: function () {
     return this._getMediaRules();
   },
 
   /**
    * Get all the @media rules in this stylesheet.
@@ -1038,20 +837,8 @@ var StyleSheetsActor = protocol.ActorCla
     parent.appendChild(style);
 
     let actor = this.parentActor.createStyleSheetActor(style.sheet);
     return actor;
   }
 });
 
 exports.StyleSheetsActor = StyleSheetsActor;
-
-/**
- * Normalize multiple relative paths towards the base paths on the right.
- */
-function normalize(...urls) {
-  let base = Services.io.newURI(urls.pop());
-  let url;
-  while ((url = urls.pop())) {
-    base = Services.io.newURI(url, null, base);
-  }
-  return base.spec;
-}
--- a/devtools/shared/fronts/stylesheets.js
+++ b/devtools/shared/fronts/stylesheets.js
@@ -1,58 +1,28 @@
 /* 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 { Front, FrontClassWithSpec } = require("devtools/shared/protocol");
 const {
-  originalSourceSpec,
   mediaRuleSpec,
   styleSheetSpec,
   styleSheetsSpec
 } = require("devtools/shared/specs/stylesheets");
 const promise = require("promise");
 const { Task } = require("devtools/shared/task");
 
 loader.lazyRequireGetter(this, "getIndentationFromPrefs",
   "devtools/shared/indentation", true);
 loader.lazyRequireGetter(this, "getIndentationFromString",
   "devtools/shared/indentation", true);
 
 /**
- * The client-side counterpart for an OriginalSourceActor.
- */
-const OriginalSourceFront = FrontClassWithSpec(originalSourceSpec, {
-  initialize: function (client, form) {
-    Front.prototype.initialize.call(this, client, form);
-
-    this.isOriginalSource = true;
-  },
-
-  form: function (form, detail) {
-    if (detail === "actorid") {
-      this.actorID = form;
-      return;
-    }
-    this.actorID = form.actor;
-    this._form = form;
-  },
-
-  get href() {
-    return this._form.url;
-  },
-  get url() {
-    return this._form.url;
-  }
-});
-
-exports.OriginalSourceFront = OriginalSourceFront;
-
-/**
  * Corresponding client-side front for a MediaRuleActor.
  */
 const MediaRuleFront = FrontClassWithSpec(mediaRuleSpec, {
   initialize: function (client, form) {
     Front.prototype.initialize.call(this, client, form);
 
     this._onMatchesChange = this._onMatchesChange.bind(this);
     this.on("matches-change", this._onMatchesChange);
--- a/devtools/shared/specs/index.js
+++ b/devtools/shared/specs/index.js
@@ -185,17 +185,17 @@ const Types = exports.__TypesForTests = 
     front: "devtools/shared/fronts/string",
   },
   {
     types: ["pagestyle", "domstylerule"],
     spec: "devtools/shared/specs/styles",
     front: "devtools/shared/fronts/styles",
   },
   {
-    types: ["originalsource", "mediarule", "stylesheet", "stylesheets"],
+    types: ["mediarule", "stylesheet", "stylesheets"],
     spec: "devtools/shared/specs/stylesheets",
     front: "devtools/shared/fronts/stylesheets",
   },
   {
     types: ["timeline"],
     spec: "devtools/shared/specs/timeline",
     front: "devtools/shared/fronts/timeline",
   },
--- a/devtools/shared/specs/stylesheets.js
+++ b/devtools/shared/specs/stylesheets.js
@@ -5,30 +5,16 @@
 
 const {
   Arg,
   RetVal,
   generateActorSpec,
   types
 } = require("devtools/shared/protocol");
 
-const originalSourceSpec = generateActorSpec({
-  typeName: "originalsource",
-
-  methods: {
-    getText: {
-      response: {
-        text: RetVal("longstring")
-      }
-    }
-  }
-});
-
-exports.originalSourceSpec = originalSourceSpec;
-
 const mediaRuleSpec = generateActorSpec({
   typeName: "mediarule",
 
   events: {
     "matches-change": {
       type: "matchesChange",
       matches: Arg(0, "boolean"),
     }
@@ -63,33 +49,16 @@ const styleSheetSpec = generateActorSpec
     toggleDisabled: {
       response: { disabled: RetVal("boolean")}
     },
     getText: {
       response: {
         text: RetVal("longstring")
       }
     },
-    getOriginalSources: {
-      request: {},
-      response: {
-        originalSources: RetVal("nullable:array:originalsource")
-      }
-    },
-    getOriginalLocation: {
-      request: {
-        line: Arg(0, "number"),
-        column: Arg(1, "number")
-      },
-      response: RetVal(types.addDictType("originallocationresponse", {
-        source: "string",
-        line: "number",
-        column: "number"
-      }))
-    },
     getMediaRules: {
       request: {},
       response: {
         mediaRules: RetVal("nullable:array:mediarule")
       }
     },
     update: {
       request: {