Bug 1378856 - Stop using sdk/core/heritage in DevTools performance server; r=zer0 draft
authorJan Odvarko <odvarko@gmail.com>
Thu, 24 Aug 2017 08:50:05 +0200
changeset 651914 6f335a20aa7e9a27312205f0f1a8eab607bda0d0
parent 650941 7c50f0c999c5bf8ee915261997597a5a9b8fb2ae
child 727912 530d7cf32ad9ff9a3df66121b87544f5d804bd50
push id75865
push userjodvarko@mozilla.com
push dateThu, 24 Aug 2017 06:50:42 +0000
reviewerszer0
bugs1378856
milestone57.0a1
Bug 1378856 - Stop using sdk/core/heritage in DevTools performance server; r=zer0 MozReview-Commit-ID: DCECaZzAEDU
devtools/server/performance/framerate.js
devtools/server/performance/memory.js
devtools/server/performance/profiler.js
devtools/server/performance/recorder.js
devtools/server/performance/timeline.js
--- a/devtools/server/performance/framerate.js
+++ b/devtools/server/performance/framerate.js
@@ -1,99 +1,102 @@
 /* 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 { on, off } = require("devtools/shared/event-emitter");
-const { Class } = require("sdk/core/heritage");
 
 /**
  * A very simple utility for monitoring framerate. Takes a `tabActor`
  * and monitors framerate over time. The actor wrapper around this
  * can be found at devtools/server/actors/framerate.js
  */
-exports.Framerate = Class({
-  initialize: function (tabActor) {
+class Framerate {
+  constructor(tabActor) {
     this.tabActor = tabActor;
     this._contentWin = tabActor.window;
     this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this);
     this._onGlobalCreated = this._onGlobalCreated.bind(this);
+
     on(this.tabActor, "window-ready", this._onGlobalCreated);
-  },
-  destroy: function (conn) {
+  }
+
+  destroy(conn) {
     off(this.tabActor, "window-ready", this._onGlobalCreated);
     this.stopRecording();
-  },
+  }
 
   /**
    * Starts monitoring framerate, storing the frames per second.
    */
-  startRecording: function () {
+  startRecording() {
     if (this._recording) {
       return;
     }
     this._recording = true;
     this._ticks = [];
     this._startTime = this.tabActor.docShell.now();
     this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
-  },
+  }
 
   /**
    * Stops monitoring framerate, returning the recorded values.
    */
-  stopRecording: function (beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
+  stopRecording(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
     if (!this._recording) {
       return [];
     }
     let ticks = this.getPendingTicks(beginAt, endAt);
     this.cancelRecording();
     return ticks;
-  },
+  }
 
   /**
    * Stops monitoring framerate, without returning the recorded values.
    */
-  cancelRecording: function () {
+  cancelRecording() {
     this._contentWin.cancelAnimationFrame(this._rafID);
     this._recording = false;
     this._ticks = null;
     this._rafID = -1;
-  },
+  }
 
   /**
    * Returns whether this instance is currently recording.
    */
-  isRecording: function () {
+  isRecording() {
     return !!this._recording;
-  },
+  }
 
   /**
    * Gets the refresh driver ticks recorded so far.
    */
-  getPendingTicks: function (beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
+  getPendingTicks(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
     if (!this._ticks) {
       return [];
     }
     return this._ticks.filter(e => e >= beginAt && e <= endAt);
-  },
+  }
 
   /**
    * Function invoked along with the refresh driver.
    */
-  _onRefreshDriverTick: function () {
+  _onRefreshDriverTick() {
     if (!this._recording) {
       return;
     }
     this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
     this._ticks.push(this.tabActor.docShell.now() - this._startTime);
-  },
+  }
 
   /**
    * When the content window for the tab actor is created.
    */
-  _onGlobalCreated: function (win) {
+  _onGlobalCreated(win) {
     if (this._recording) {
       this._contentWin.cancelAnimationFrame(this._rafID);
       this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
     }
   }
-});
+}
+
+exports.Framerate = Framerate;
--- a/devtools/server/performance/memory.js
+++ b/devtools/server/performance/memory.js
@@ -1,18 +1,18 @@
 /* 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 { Cc, Ci, Cu } = require("chrome");
 const { reportException } = require("devtools/shared/DevToolsUtils");
-const { Class } = require("sdk/core/heritage");
 const { expectState } = require("devtools/server/actors/common");
+
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 loader.lazyRequireGetter(this, "DeferredTask",
   "resource://gre/modules/DeferredTask.jsm", true);
 loader.lazyRequireGetter(this, "StackFrameCache",
   "devtools/server/actors/utils/stack", true);
 loader.lazyRequireGetter(this, "ThreadSafeChromeUtils");
 loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
   "devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
@@ -26,37 +26,34 @@ loader.lazyRequireGetter(this, "ChildPro
  * Using a tab-scoped actor with this instance will measure the memory footprint of its
  * parent tab. Using a global-scoped actor instance however, will measure the memory
  * footprint of the chrome window referenced by its root actor.
  *
  * To be consumed by actor's, like MemoryActor using this module to
  * send information over RDP, and TimelineActor for using more light-weight
  * utilities like GC events and measuring memory consumption.
  */
-exports.Memory = Class({
-  extends: EventEmitter,
+function Memory(parent, frameCache = new StackFrameCache()) {
+  EventEmitter.decorate(this);
 
-  /**
-   * Requires a root actor and a StackFrameCache.
-   */
-  initialize: function (parent, frameCache = new StackFrameCache()) {
-    this.parent = parent;
-    this._mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
-                  .getService(Ci.nsIMemoryReporterManager);
-    this.state = "detached";
-    this._dbg = null;
-    this._frameCache = frameCache;
+  this.parent = parent;
+  this._mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
+                .getService(Ci.nsIMemoryReporterManager);
+  this.state = "detached";
+  this._dbg = null;
+  this._frameCache = frameCache;
 
-    this._onGarbageCollection = this._onGarbageCollection.bind(this);
-    this._emitAllocations = this._emitAllocations.bind(this);
-    this._onWindowReady = this._onWindowReady.bind(this);
+  this._onGarbageCollection = this._onGarbageCollection.bind(this);
+  this._emitAllocations = this._emitAllocations.bind(this);
+  this._onWindowReady = this._onWindowReady.bind(this);
 
-    EventEmitter.on(this.parent, "window-ready", this._onWindowReady);
-  },
+  EventEmitter.on(this.parent, "window-ready", this._onWindowReady);
+}
 
+Memory.prototype = {
   destroy: function () {
     EventEmitter.off(this.parent, "window-ready", this._onWindowReady);
 
     this._mgr = null;
     if (this.state === "attached") {
       this.detach();
     }
   },
@@ -421,10 +418,11 @@ exports.Memory = Class({
 
   /**
    * Accesses the docshell to return the current process time.
    */
   _getCurrentTime: function () {
     return (this.parent.isRootActor ? this.parent.docShell :
                                       this.parent.originalDocShell).now();
   },
+};
 
-});
+exports.Memory = Memory;
--- a/devtools/server/performance/profiler.js
+++ b/devtools/server/performance/profiler.js
@@ -1,16 +1,16 @@
 /* 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 { Cc, Ci, Cu } = require("chrome");
 const Services = require("Services");
-const { Class } = require("sdk/core/heritage");
+
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 loader.lazyRequireGetter(this, "DevToolsUtils", "devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm", true);
 loader.lazyRequireGetter(this, "Task", "devtools/shared/task", true);
 
 // Events piped from system observers to Profiler instances.
 const PROFILER_SYSTEM_EVENTS = [
   "console-api-profiler",
@@ -401,147 +401,148 @@ const ProfilerManager = (function () {
       this._poller.arm();
     }
   };
 })();
 
 /**
  * The profiler actor provides remote access to the built-in nsIProfiler module.
  */
-var Profiler = exports.Profiler = Class({
-  extends: EventEmitter,
+class Profiler {
+  constructor() {
+    EventEmitter.decorate(this);
 
-  initialize: function () {
     this.subscribedEvents = new Set();
     ProfilerManager.addInstance(this);
-  },
+  }
 
-  destroy: function () {
+  destroy() {
     this.unregisterEventNotifications({ events: Array.from(this.subscribedEvents) });
     this.subscribedEvents = null;
+
     ProfilerManager.removeInstance(this);
-  },
+  }
 
   /**
    * @see ProfilerManager.start
    */
-  start: function (options) {
+  start(options) {
     return ProfilerManager.start(options);
-  },
+  }
 
   /**
    * @see ProfilerManager.stop
    */
-  stop: function () {
+  stop() {
     return ProfilerManager.stop();
-  },
+  }
 
   /**
    * @see ProfilerManager.getProfile
    */
-  getProfile: function (request = {}) {
+  getProfile(request = {}) {
     return ProfilerManager.getProfile(request);
-  },
+  }
 
   /**
    * @see ProfilerManager.getFeatures
    */
-  getFeatures: function () {
+  getFeatures() {
     return ProfilerManager.getFeatures();
-  },
+  }
 
   /**
    * @see ProfilerManager.getBufferInfo
    */
-  getBufferInfo: function () {
+  getBufferInfo() {
     return ProfilerManager.getBufferInfo();
-  },
+  }
 
   /**
    * @see ProfilerManager.getStartOptions
    */
-  getStartOptions: function () {
+  getStartOptions() {
     return ProfilerManager.getStartOptions();
-  },
+  }
 
   /**
    * @see ProfilerManager.isActive
    */
-  isActive: function () {
+  isActive() {
     return ProfilerManager.isActive();
-  },
+  }
 
   /**
    * @see ProfilerManager.sharedLibraries
    */
-  sharedLibraries: function () {
+  sharedLibraries() {
     return ProfilerManager.sharedLibraries;
-  },
+  }
 
   /**
    * @see ProfilerManager.setProfilerStatusInterval
    */
-  setProfilerStatusInterval: function (interval) {
+  setProfilerStatusInterval(interval) {
     return ProfilerManager.setProfilerStatusInterval(interval);
-  },
+  }
 
   /**
    * Subscribes this instance to one of several events defined in
    * an events array.
    * - "console-api-profiler",
    * - "profiler-started",
    * - "profiler-stopped"
    * - "profiler-status"
    *
    * @param {Array<string>} data.event
    * @return {object}
    */
-  registerEventNotifications: function (data = {}) {
+  registerEventNotifications(data = {}) {
     let response = [];
     (data.events || []).forEach(e => {
       if (!this.subscribedEvents.has(e)) {
         if (e === "profiler-status") {
           ProfilerManager.subscribeToProfilerStatusEvents();
         }
         this.subscribedEvents.add(e);
         response.push(e);
       }
     });
     return { registered: response };
-  },
+  }
 
   /**
    * Unsubscribes this instance to one of several events defined in
    * an events array.
    *
    * @param {Array<string>} data.event
    * @return {object}
    */
-  unregisterEventNotifications: function (data = {}) {
+  unregisterEventNotifications(data = {}) {
     let response = [];
     (data.events || []).forEach(e => {
       if (this.subscribedEvents.has(e)) {
         if (e === "profiler-status") {
           ProfilerManager.unsubscribeToProfilerStatusEvents();
         }
         this.subscribedEvents.delete(e);
         response.push(e);
       }
     });
     return { registered: response };
-  },
-});
+  }
 
-/**
- * Checks whether or not the profiler module can currently run.
- * @return boolean
- */
-Profiler.canProfile = function () {
-  return nsIProfilerModule.CanProfile();
-};
+  /**
+   * Checks whether or not the profiler module can currently run.
+   * @return boolean
+   */
+  static canProfile() {
+    return nsIProfilerModule.CanProfile();
+  }
+}
 
 /**
  * JSON.stringify callback used in Profiler.prototype.observe.
  */
 function cycleBreaker(key, value) {
   if (key == "wrappedJSObject") {
     return undefined;
   }
@@ -567,8 +568,10 @@ function sanitizeHandler(handler, identi
     subject = JSON.parse(JSON.stringify(subject, cycleBreaker));
     data = (data && !Cu.isXrayWrapper(data) && data.wrappedJSObject) || data;
     data = JSON.parse(JSON.stringify(data, cycleBreaker));
 
     // Pass in clean data to the underlying handler
     return handler.call(this, subject, topic, data);
   }, identifier);
 }
+
+exports.Profiler = Profiler;
--- a/devtools/server/performance/recorder.js
+++ b/devtools/server/performance/recorder.js
@@ -42,30 +42,30 @@ const DRAIN_ALLOCATIONS_TIMEOUT = 2000;
 
 /**
  * A connection to underlying actors (profiler, memory, framerate, etc.)
  * shared by all tools in a target.
  *
  * @param Target target
  *        The target owning this connection.
  */
-exports.PerformanceRecorder = Class({
-  extends: EventEmitter,
+function PerformanceRecorder(conn, tabActor) {
+  EventEmitter.decorate(this);
 
-  initialize: function (conn, tabActor) {
-    this.conn = conn;
-    this.tabActor = tabActor;
+  this.conn = conn;
+  this.tabActor = tabActor;
 
-    this._pendingConsoleRecordings = [];
-    this._recordings = [];
+  this._pendingConsoleRecordings = [];
+  this._recordings = [];
 
-    this._onTimelineData = this._onTimelineData.bind(this);
-    this._onProfilerEvent = this._onProfilerEvent.bind(this);
-  },
+  this._onTimelineData = this._onTimelineData.bind(this);
+  this._onProfilerEvent = this._onProfilerEvent.bind(this);
+}
 
+PerformanceRecorder.prototype = {
   /**
    * Initializes a connection to the profiler and other miscellaneous actors.
    * If in the process of opening, or already open, nothing happens.
    *
    * @param {Object} options.systemClient
    *        Metadata about the client's system to attach to the recording models.
    *
    * @return object
@@ -474,17 +474,17 @@ exports.PerformanceRecorder = Class({
     if (this._memory.getState() === "attached") {
       allocationSettings = this._memory.getAllocationsSettings();
     }
 
     return Object.assign({}, allocationSettings, this._profiler.getStartOptions());
   },
 
   toString: () => "[object PerformanceRecorder]"
-});
+};
 
 /**
  * Creates an object of configurations based off of
  * preferences for a PerformanceRecording.
  */
 function getPerformanceRecordingPrefs() {
   return {
     withMarkers: true,
@@ -493,8 +493,10 @@ function getPerformanceRecordingPrefs() 
     withAllocations:
       Services.prefs.getBoolPref("devtools.performance.ui.enable-allocations"),
     allocationsSampleProbability:
       +Services.prefs.getCharPref("devtools.performance.memory.sample-probability"),
     allocationsMaxLogLength:
       Services.prefs.getIntPref("devtools.performance.memory.max-log-length")
   };
 }
+
+exports.PerformanceRecorder = PerformanceRecorder;
--- a/devtools/server/performance/timeline.js
+++ b/devtools/server/performance/timeline.js
@@ -16,52 +16,50 @@
  *   timeline.stop()
  *   timeline.isRecording()
  *
  * When markers are available, an event is emitted:
  *   timeline.on("markers", function(markers) {...})
  */
 
 const { Ci, Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
+
 // Be aggressive about lazy loading, as this will run on every
 // toolbox startup
 loader.lazyRequireGetter(this, "Task", "devtools/shared/task", true);
 loader.lazyRequireGetter(this, "Memory", "devtools/server/performance/memory", true);
 loader.lazyRequireGetter(this, "Framerate", "devtools/server/performance/framerate", true);
 loader.lazyRequireGetter(this, "StackFrameCache", "devtools/server/actors/utils/stack", true);
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 
 // How often do we pull markers from the docShells, and therefore, how often do
 // we send events to the front (knowing that when there are no markers in the
 // docShell, no event is sent). In milliseconds.
 const DEFAULT_TIMELINE_DATA_PULL_TIMEOUT = 200;
 
 /**
  * The timeline actor pops and forwards timeline markers registered in docshells.
  */
-exports.Timeline = Class({
-  extends: EventEmitter,
-  /**
-   * Initializes this actor with the provided connection and tab actor.
-   */
-  initialize: function (tabActor) {
-    this.tabActor = tabActor;
+function Timeline(tabActor) {
+  EventEmitter.decorate(this);
+
+  this.tabActor = tabActor;
 
-    this._isRecording = false;
-    this._stackFrames = null;
-    this._memory = null;
-    this._framerate = null;
+  this._isRecording = false;
+  this._stackFrames = null;
+  this._memory = null;
+  this._framerate = null;
 
-    // Make sure to get markers from new windows as they become available
-    this._onWindowReady = this._onWindowReady.bind(this);
-    this._onGarbageCollection = this._onGarbageCollection.bind(this);
-    EventEmitter.on(this.tabActor, "window-ready", this._onWindowReady);
-  },
+  // Make sure to get markers from new windows as they become available
+  this._onWindowReady = this._onWindowReady.bind(this);
+  this._onGarbageCollection = this._onGarbageCollection.bind(this);
+  EventEmitter.on(this.tabActor, "window-ready", this._onWindowReady);
+}
 
+Timeline.prototype = {
   /**
    * Destroys this actor, stopping recording first.
    */
   destroy: function () {
     this.stop();
 
     EventEmitter.off(this.tabActor, "window-ready", this._onWindowReady);
     this.tabActor = null;
@@ -352,9 +350,11 @@ exports.Timeline = Class({
         causeName: reason,
         nonincrementalReason: nonincrementalReason,
         cycle: gcCycleNumber,
         start,
         end,
       };
     }), endTime);
   },
-});
+};
+
+exports.Timeline = Timeline;