mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1201949 - Initial redux-style controllers for front end memory tool heap snapshot. r=jlongster
This commit is contained in:
parent
e5c975bf46
commit
72dea1ba99
@ -111,7 +111,7 @@ devtools.jar:
|
||||
content/performance/views/optimizations-list.js (performance/views/optimizations-list.js)
|
||||
content/performance/views/recordings.js (performance/views/recordings.js)
|
||||
content/memory/memory.xhtml (memory/memory.xhtml)
|
||||
content/memory/controller.js (memory/controller.js)
|
||||
content/memory/initializer.js (memory/initializer.js)
|
||||
content/promisedebugger/promise-controller.js (promisedebugger/promise-controller.js)
|
||||
content/promisedebugger/promise-panel.js (promisedebugger/promise-panel.js)
|
||||
content/promisedebugger/promise-debugger.xhtml (promisedebugger/promise-debugger.xhtml)
|
||||
|
8
devtools/client/memory/actions/moz.build
Normal file
8
devtools/client/memory/actions/moz.build
Normal file
@ -0,0 +1,8 @@
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'snapshot.js',
|
||||
)
|
14
devtools/client/memory/actions/snapshot.js
Normal file
14
devtools/client/memory/actions/snapshot.js
Normal file
@ -0,0 +1,14 @@
|
||||
/* 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 { PROMISE } = require("devtools/client/shared/redux/middleware/promise");
|
||||
const { actions } = require("../constants");
|
||||
|
||||
const takeSnapshot = exports.takeSnapshot = function takeSnapshot (front) {
|
||||
return {
|
||||
type: actions.TAKE_SNAPSHOT,
|
||||
[PROMISE]: front.saveHeapSnapshot()
|
||||
};
|
||||
};
|
9
devtools/client/memory/constants.js
Normal file
9
devtools/client/memory/constants.js
Normal file
@ -0,0 +1,9 @@
|
||||
/* 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 actions = exports.actions = {};
|
||||
|
||||
// Fired by UI to request a snapshot from the actor.
|
||||
actions.TAKE_SNAPSHOT = "take-snapshot";
|
@ -3,26 +3,26 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
const { loader, require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
const { Heritage, ViewHelpers, WidgetMethods } = require("resource:///modules/devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
const Store = require("./store");
|
||||
|
||||
/**
|
||||
* The current target, toolbox and MemoryFront, set by this tool's host.
|
||||
*/
|
||||
var gToolbox, gTarget, gFront;
|
||||
|
||||
/**
|
||||
* Initializes the profiler controller and views.
|
||||
*/
|
||||
const MemoryController = {
|
||||
initialize: Task.async(function *() {
|
||||
yield gFront.attach();
|
||||
}),
|
||||
const REDUX_METHODS_TO_PIPE = ["dispatch", "subscribe", "getState"];
|
||||
|
||||
destroy: Task.async(function *() {
|
||||
yield gFront.detach();
|
||||
})
|
||||
const MemoryController = exports.MemoryController = function ({ toolbox, target, front }) {
|
||||
this.store = Store();
|
||||
this.toolbox = toolbox;
|
||||
this.target = target;
|
||||
this.front = front;
|
||||
};
|
||||
|
||||
REDUX_METHODS_TO_PIPE.map(m =>
|
||||
MemoryController.prototype[m] = function (...args) { return this.store[m](...args); });
|
||||
|
||||
MemoryController.prototype.destroy = function () {
|
||||
this.store = this.toolbox = this.target = this.front = null;
|
||||
};
|
||||
|
30
devtools/client/memory/initializer.js
Normal file
30
devtools/client/memory/initializer.js
Normal file
@ -0,0 +1,30 @@
|
||||
/* 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 { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
const { require } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
const { MemoryController } = require("devtools/client/memory/controller");
|
||||
|
||||
/**
|
||||
* The current target, toolbox and MemoryFront, set by this tool's host.
|
||||
*/
|
||||
let gToolbox, gTarget, gFront;
|
||||
|
||||
/**
|
||||
* Initializes the profiler controller and views.
|
||||
*/
|
||||
var controller = null;
|
||||
function initialize () {
|
||||
return Task.spawn(function *() {
|
||||
controller = new MemoryController({ toolbox: gToolbox, target: gTarget, front: gFront });
|
||||
});
|
||||
}
|
||||
|
||||
function destroy () {
|
||||
return Task.spawn(function *() {
|
||||
controller.destroy();
|
||||
});
|
||||
}
|
@ -12,23 +12,21 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/themes/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/themes/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/themes/memory.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/content/devtools/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/memory.css" type="text/css"/>
|
||||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="controller.js"></script>
|
||||
src="initializer.js"></script>
|
||||
</head>
|
||||
<body class="theme-body">
|
||||
<toolbar class="devtools-toolbar">
|
||||
<toolbarbutton id="snapshot-button" class="devtools-toolbarbutton"
|
||||
tabindex="0"/>
|
||||
<spacer flex="1"></spacer>
|
||||
</toolbar>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<div class="devtools-toolbar">
|
||||
<div id="snapshot-button" class="devtools-toolbarbutton" />
|
||||
</div>
|
||||
<div class="devtools-horizontal-splitter"></div>
|
||||
<div id="memory-content"
|
||||
class="devtools-responsive-container"
|
||||
flex="1">
|
||||
|
@ -9,7 +9,6 @@
|
||||
*/
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const { L10N } = require("devtools/client/performance/modules/global");
|
||||
const { Heritage } = require("resource:///modules/devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
const { AbstractTreeItem } = require("resource:///modules/devtools/client/shared/widgets/AbstractTreeItem.jsm");
|
||||
|
||||
|
@ -4,12 +4,19 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'actions',
|
||||
'modules',
|
||||
'reducers',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'constants.js',
|
||||
'controller.js',
|
||||
'initializer.js',
|
||||
'panel.js',
|
||||
'reducers.js',
|
||||
'store.js',
|
||||
)
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
|
@ -32,8 +32,8 @@ MemoryPanel.prototype = {
|
||||
this.target.form,
|
||||
rootForm);
|
||||
|
||||
console.log(this.panelWin, this.panelWin.MemoryController);
|
||||
this._opening = this.panelWin.MemoryController.initialize().then(() => {
|
||||
yield this.panelWin.gFront.attach();
|
||||
return this._opening = this.panelWin.initialize().then(() => {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
@ -47,21 +47,21 @@ MemoryPanel.prototype = {
|
||||
return this._toolbox.target;
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
destroy: Task.async(function *() {
|
||||
// Make sure this panel is not already destroyed.
|
||||
if (this._destroyer) {
|
||||
return this._destroyer;
|
||||
}
|
||||
|
||||
this._destroyer = this.panelWin.MemoryController.destroy().then(() => {
|
||||
yield this.panelWin.gFront.detach();
|
||||
return this._destroyer = this.panelWin.destroy().then(() => {
|
||||
// Destroy front to ensure packet handler is removed from client
|
||||
this.panelWin.gFront.destroy();
|
||||
this.panelWin = null;
|
||||
this.emit("destroyed");
|
||||
return this;
|
||||
});
|
||||
return this._destroyer;
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
exports.MemoryPanel = MemoryPanel;
|
||||
|
1
devtools/client/memory/reducers.js
Normal file
1
devtools/client/memory/reducers.js
Normal file
@ -0,0 +1 @@
|
||||
exports.snapshots = require("./reducers/snapshot");
|
8
devtools/client/memory/reducers/moz.build
Normal file
8
devtools/client/memory/reducers/moz.build
Normal file
@ -0,0 +1,8 @@
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'snapshot.js',
|
||||
)
|
37
devtools/client/memory/reducers/snapshot.js
Normal file
37
devtools/client/memory/reducers/snapshot.js
Normal file
@ -0,0 +1,37 @@
|
||||
const { actions } = require("../constants");
|
||||
const { PROMISE } = require("devtools/client/shared/redux/middleware/promise");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
function handleTakeSnapshot (state, action) {
|
||||
switch (action.status) {
|
||||
|
||||
case "start":
|
||||
return [...state, {
|
||||
id: action.seqId,
|
||||
status: action.status
|
||||
}];
|
||||
|
||||
case "done":
|
||||
let snapshot = state.find(s => s.id === action.seqId);
|
||||
if (!snapshot) {
|
||||
DevToolsUtils.reportException(`No snapshot with id "${action.seqId}" for TAKE_SNAPSHOT`);
|
||||
break;
|
||||
}
|
||||
snapshot.status = "done";
|
||||
snapshot.snapshotId = action.value;
|
||||
return [...state];
|
||||
|
||||
case "error":
|
||||
DevToolsUtils.reportException(`No async state found for ${action.type}`);
|
||||
}
|
||||
return [...state];
|
||||
}
|
||||
|
||||
module.exports = function (state=[], action) {
|
||||
switch (action.type) {
|
||||
case actions.TAKE_SNAPSHOT:
|
||||
return handleTakeSnapshot(state, action);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
8
devtools/client/memory/store.js
Normal file
8
devtools/client/memory/store.js
Normal file
@ -0,0 +1,8 @@
|
||||
const { combineReducers } = require("../shared/vendor/redux");
|
||||
const createStore = require("../shared/redux/create-store");
|
||||
const reducers = require("./reducers");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
module.exports = function () {
|
||||
return createStore({ log: DevToolsUtils.testing })(combineReducers(reducers), {});
|
||||
};
|
@ -9,4 +9,4 @@ const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
const { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
const { require } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
|
@ -7,11 +7,11 @@ Bug 1067491 - Test taking a census over the RDP.
|
||||
<meta charset="utf-8">
|
||||
<title>Census Tree 01</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/light-theme.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/common.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/widgets.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/memory.css" type="text/css" />
|
||||
<link href="chrome://browser/content/devtools/widgets.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/light-theme.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/common.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/widgets.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/memory.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<ul id="container" style="width:100%;height:300px;"></ul>
|
||||
|
56
devtools/client/memory/test/unit/head.js
Normal file
56
devtools/client/memory/test/unit/head.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
var { gDevTools } = Cu.import("resource:///modules/devtools/client/framework/gDevTools.jsm", {});
|
||||
var { console } = Cu.import("resource://gre/modules/devtools/shared/Console.jsm", {});
|
||||
var { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
var { TargetFactory } = require("devtools/client/framework/target");
|
||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
var promise = require("promise");
|
||||
var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
var { MemoryController } = require("devtools/client/memory/controller");
|
||||
var { expectState } = require("devtools/server/actors/common");
|
||||
var HeapSnapshotFileUtils = require("devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
var { addDebuggerToGlobal } = require("resource://gre/modules/jsdebugger.jsm");
|
||||
var SYSTEM_PRINCIPAL = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
|
||||
var { setTimeout } = require("sdk/timers");
|
||||
|
||||
DevToolsUtils.testing = true;
|
||||
|
||||
function initDebugger () {
|
||||
let global = new Cu.Sandbox(SYSTEM_PRINCIPAL, { freshZone: true });
|
||||
addDebuggerToGlobal(global);
|
||||
return new global.Debugger();
|
||||
}
|
||||
|
||||
function StubbedMemoryFront () {
|
||||
this.dbg = initDebugger();
|
||||
}
|
||||
|
||||
StubbedMemoryFront.prototype.attach = Task.async(function *() {
|
||||
this.state = "attached";
|
||||
});
|
||||
|
||||
StubbedMemoryFront.prototype.detach = Task.async(function *() {
|
||||
this.state = "detached";
|
||||
});
|
||||
|
||||
StubbedMemoryFront.prototype.saveHeapSnapshot = expectState("attached", Task.async(function *() {
|
||||
let path = ThreadSafeChromeUtils.saveHeapSnapshot({ debugger: this.dbg });
|
||||
return HeapSnapshotFileUtils.getSnapshotIdFromPath(path);
|
||||
}), "saveHeapSnapshot");
|
||||
|
||||
function waitUntilState (store, predicate) {
|
||||
let deferred = promise.defer();
|
||||
let unsubscribe = store.subscribe(() => {
|
||||
if (predicate(store.getState())) {
|
||||
unsubscribe();
|
||||
deferred.resolve()
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests the async action creator `takeSnapshot(front)`
|
||||
*/
|
||||
|
||||
let actions = require("devtools/client/memory/actions/snapshot");
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function *() {
|
||||
let front = new StubbedMemoryFront();
|
||||
yield front.attach();
|
||||
let controller = new MemoryController({ toolbox: {}, target: {}, front });
|
||||
|
||||
let unsubscribe = controller.subscribe(checkState);
|
||||
|
||||
let foundPendingState = false;
|
||||
let foundDoneState = false;
|
||||
|
||||
function checkState () {
|
||||
let state = controller.getState();
|
||||
if (state.snapshots.length === 1 && state.snapshots[0].status === "start") {
|
||||
foundPendingState = true;
|
||||
ok(foundPendingState, "Got state change for pending heap snapshot request");
|
||||
ok(!(state.snapshots[0].snapshotId), "Snapshot does not yet have a snapshotId");
|
||||
}
|
||||
if (state.snapshots.length === 1 && state.snapshots[0].status === "done") {
|
||||
foundDoneState = true;
|
||||
ok(foundDoneState, "Got state change for completed heap snapshot request");
|
||||
ok(state.snapshots[0].snapshotId, "Snapshot fetched with a snapshotId");
|
||||
}
|
||||
if (state.snapshots.lenght === 1 && state.snapshots[0].status === "error") {
|
||||
ok(false, "takeSnapshot's promise returned with an error");
|
||||
}
|
||||
}
|
||||
|
||||
controller.dispatch(actions.takeSnapshot(front));
|
||||
yield waitUntilState(controller, () => foundPendingState && foundDoneState);
|
||||
|
||||
unsubscribe();
|
||||
});
|
8
devtools/client/memory/test/unit/xpcshell.ini
Normal file
8
devtools/client/memory/test/unit/xpcshell.ini
Normal file
@ -0,0 +1,8 @@
|
||||
[DEFAULT]
|
||||
tags = devtools
|
||||
head = head.js
|
||||
tail =
|
||||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||
|
||||
[test_action-take-snapshot.js]
|
@ -7,6 +7,7 @@ const { createStore, applyMiddleware } = require("devtools/client/shared/vendor/
|
||||
const { thunk } = require("./middleware/thunk");
|
||||
const { waitUntilService } = require("./middleware/wait-service");
|
||||
const { log } = require("./middleware/log");
|
||||
const { promise } = require("./middleware/promise");
|
||||
|
||||
/**
|
||||
* This creates a dispatcher with all the standard middleware in place
|
||||
@ -20,7 +21,8 @@ const { log } = require("./middleware/log");
|
||||
module.exports = (opts={}) => {
|
||||
const middleware = [
|
||||
thunk,
|
||||
waitUntilService
|
||||
waitUntilService,
|
||||
promise,
|
||||
];
|
||||
|
||||
if (opts.log) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
DevToolsModules(
|
||||
'log.js',
|
||||
'promise.js',
|
||||
'thunk.js',
|
||||
'wait-service.js',
|
||||
)
|
||||
|
52
devtools/client/shared/redux/middleware/promise.js
Normal file
52
devtools/client/shared/redux/middleware/promise.js
Normal file
@ -0,0 +1,52 @@
|
||||
/* 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 uuidgen = require("sdk/util/uuid").uuid;
|
||||
const {
|
||||
entries, toObject, reportException, executeSoon
|
||||
} = require("devtools/shared/DevToolsUtils");
|
||||
const PROMISE = exports.PROMISE = "@@dispatch/promise";
|
||||
|
||||
function promiseMiddleware ({ dispatch, getState }) {
|
||||
return next => action => {
|
||||
if (!(PROMISE in action)) {
|
||||
return next(action);
|
||||
}
|
||||
|
||||
const promise = action[PROMISE];
|
||||
const seqId = uuidgen().toString();
|
||||
|
||||
// Create a new action that doesn't have the promise field and has
|
||||
// the `seqId` field that represents the sequence id
|
||||
action = Object.assign(
|
||||
toObject(entries(action).filter(pair => pair[0] !== PROMISE)), { seqId }
|
||||
);
|
||||
|
||||
dispatch(Object.assign({}, action, { status: "start" }));
|
||||
|
||||
promise.then(value => {
|
||||
executeSoon(() => {
|
||||
dispatch(Object.assign({}, action, {
|
||||
status: "done",
|
||||
value: value
|
||||
}));
|
||||
});
|
||||
}).catch(error => {
|
||||
executeSoon(() => {
|
||||
dispatch(Object.assign({}, action, {
|
||||
status: "error",
|
||||
error
|
||||
}));
|
||||
});
|
||||
reportException(`@@redux/middleware/promise#${action.type}`, error);
|
||||
});
|
||||
|
||||
// Return the promise so action creators can still compose if they
|
||||
// want to.
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
exports.promise = promiseMiddleware;
|
@ -12,6 +12,7 @@ var promise = require("promise");
|
||||
|
||||
loader.lazyRequireGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(this, "setTimeout", "Timer", true);
|
||||
|
||||
/**
|
||||
* Turn the error |aError| into a string, without fail.
|
||||
@ -132,6 +133,18 @@ exports.entries = function entries(obj) {
|
||||
return Object.keys(obj).map(k => [k, obj[k]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array of 2-element arrays as key/values pairs and
|
||||
* constructs an object using them.
|
||||
*/
|
||||
exports.toObject = function(arr) {
|
||||
const obj = {};
|
||||
for(let pair of arr) {
|
||||
obj[pair[0]] = pair[1];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes the given functions into a single function, which will
|
||||
* apply the results of each function right-to-left, starting with
|
||||
@ -186,7 +199,7 @@ exports.waitForTick = function waitForTick() {
|
||||
*/
|
||||
exports.waitForTime = function waitForTime(aDelay) {
|
||||
let deferred = promise.defer();
|
||||
require("Timer").setTimeout(deferred.resolve, aDelay);
|
||||
setTimeout(deferred.resolve, aDelay);
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user