diff --git a/.cron.yml b/.cron.yml index 1a6929d59b10..758fb3f04bdc 100644 --- a/.cron.yml +++ b/.cron.yml @@ -59,14 +59,3 @@ jobs: - mozilla-central when: - {hour: 18, minute: 0} - - - name: nightly-stylo-talos - job: - type: decision-task - treeherder-symbol: T - target-tasks-method: stylo_talos - run-on-projects: - - mozilla-central - when: - - {hour: 4, minute: 0} - diff --git a/.eslintignore b/.eslintignore index 3ed9aa149d47..44a937a19187 100644 --- a/.eslintignore +++ b/.eslintignore @@ -131,7 +131,7 @@ devtools/server/actors/stylesheets.js devtools/server/tests/browser/storage-*.html !devtools/server/tests/browser/storage-unsecured-iframe.html devtools/server/tests/browser/stylesheets-nested-iframes.html -devtools/server/tests/unit/** +devtools/server/tests/unit/xpcshell_debugging_script.js devtools/shared/platform/content/test/test_clipboard.html devtools/shared/qrcode/tests/mochitest/test_decode.html devtools/shared/tests/mochitest/*.html @@ -174,6 +174,7 @@ devtools/client/debugger/test/mochitest/code_worker-source-map.js devtools/client/framework/test/code_ugly* devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js devtools/server/tests/unit/setBreakpoint* +devtools/server/tests/unit/sourcemapped.js # dom/ exclusions dom/animation/** diff --git a/accessible/base/NotificationController.cpp b/accessible/base/NotificationController.cpp index 0bf82570cc3e..14ff88485baa 100644 --- a/accessible/base/NotificationController.cpp +++ b/accessible/base/NotificationController.cpp @@ -755,8 +755,11 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime) childDoc->Shutdown(); } } - mHangingChildDocuments.Clear(); + MOZ_ASSERT(mDocument, "Illicit document shutdown"); + if (!mDocument) { + return; + } // If the document is ready and all its subdocuments are completely loaded // then process the document load. diff --git a/browser/base/content/browser-ctrlTab.js b/browser/base/content/browser-ctrlTab.js index 74c073ef872b..ce0694eee001 100644 --- a/browser/base/content/browser-ctrlTab.js +++ b/browser/base/content/browser-ctrlTab.js @@ -204,16 +204,17 @@ var ctrlTab = { }, uninit: function ctrlTab_uninit() { - this._recentlyUsedTabs = null; - this._init(false); + if (this._recentlyUsedTabs) { + this._recentlyUsedTabs = null; + this._init(false); + } }, prefName: "browser.ctrlTab.previews", readPref: function ctrlTab_readPref() { var enable = gPrefService.getBoolPref(this.prefName) && - (!gPrefService.prefHasUserValue("browser.ctrlTab.disallowForScreenReaders") || - !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders")); + !gPrefService.getBoolPref("browser.ctrlTab.disallowForScreenReaders", false); if (enable) this.init(); @@ -535,15 +536,15 @@ var ctrlTab = { _init: function ctrlTab__init(enable) { var toggleEventListener = enable ? "addEventListener" : "removeEventListener"; - window[toggleEventListener]("SSWindowRestored", this, false); + window[toggleEventListener]("SSWindowRestored", this); var tabContainer = gBrowser.tabContainer; - tabContainer[toggleEventListener]("TabOpen", this, false); - tabContainer[toggleEventListener]("TabAttrModified", this, false); - tabContainer[toggleEventListener]("TabSelect", this, false); - tabContainer[toggleEventListener]("TabClose", this, false); + tabContainer[toggleEventListener]("TabOpen", this); + tabContainer[toggleEventListener]("TabAttrModified", this); + tabContainer[toggleEventListener]("TabSelect", this); + tabContainer[toggleEventListener]("TabClose", this); - document[toggleEventListener]("keypress", this, false); + document[toggleEventListener]("keypress", this); gBrowser.mTabBox.handleCtrlTab = !enable; if (enable) diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc index 21c9fc200f66..01b5bdae2c14 100644 --- a/browser/base/content/browser-sets.inc +++ b/browser/base/content/browser-sets.inc @@ -338,7 +338,7 @@ - + diff --git a/devtools/server/tests/unit/.eslintrc.js b/devtools/server/tests/unit/.eslintrc.js index 0124280192b7..8342de80c309 100644 --- a/devtools/server/tests/unit/.eslintrc.js +++ b/devtools/server/tests/unit/.eslintrc.js @@ -2,5 +2,8 @@ module.exports = { // Extend from the common devtools xpcshell eslintrc config. - "extends": "../../../.eslintrc.xpcshell.js" + "extends": "../../../.eslintrc.xpcshell.js", + "rules": { + "no-debugger": 0, + } }; diff --git a/devtools/server/tests/unit/head_dbg.js b/devtools/server/tests/unit/head_dbg.js index 57d0eb8ffc3e..9d58b1f75756 100644 --- a/devtools/server/tests/unit/head_dbg.js +++ b/devtools/server/tests/unit/head_dbg.js @@ -1,5 +1,7 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint no-unused-vars: ["error", {"vars": "local"}] */ +/* eslint-disable no-shadow */ "use strict"; var Cc = Components.classes; @@ -42,11 +44,11 @@ const { MemoryFront } = require("devtools/shared/fronts/memory"); const { addDebuggerToGlobal } = Cu.import("resource://gre/modules/jsdebugger.jsm", {}); -const systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal); +const systemPrincipal = Cc["@mozilla.org/systemprincipal;1"] + .createInstance(Ci.nsIPrincipal); -var loadSubScript = Cc[ - "@mozilla.org/moz/jssubscript-loader;1" -].getService(Ci.mozIJSSubScriptLoader).loadSubScript; +var { loadSubScript } = Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader); /** * Initializes any test that needs to work with add-ons. @@ -150,9 +152,8 @@ function makeFullRuntimeMemoryActorTest(testGeneratorFunction) { } function createTestGlobal(name) { - let sandbox = Cu.Sandbox( - Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal) - ); + let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"] + .createInstance(Ci.nsIPrincipal)); sandbox.__name = name; return sandbox; } @@ -236,24 +237,27 @@ function dumpn(msg) { function testExceptionHook(ex) { try { do_report_unexpected_exception(ex); - } catch (ex) { - return {throw: ex}; + } catch (e) { + return {throw: e}; } return undefined; } -// Convert an nsIScriptError 'aFlags' value into an appropriate string. -function scriptErrorFlagsToKind(aFlags) { - var kind; - if (aFlags & Ci.nsIScriptError.warningFlag) +// Convert an nsIScriptError 'flags' value into an appropriate string. +function scriptErrorFlagsToKind(flags) { + let kind; + if (flags & Ci.nsIScriptError.warningFlag) { kind = "warning"; - if (aFlags & Ci.nsIScriptError.exceptionFlag) + } + if (flags & Ci.nsIScriptError.exceptionFlag) { kind = "exception"; - else + } else { kind = "error"; + } - if (aFlags & Ci.nsIScriptError.strictFlag) + if (flags & Ci.nsIScriptError.strictFlag) { kind = "strict " + kind; + } return kind; } @@ -262,24 +266,25 @@ function scriptErrorFlagsToKind(aFlags) { // into the ether. var errorCount = 0; var listener = { - observe: function (aMessage) { + observe: function (message) { try { + let string; errorCount++; try { // If we've been given an nsIScriptError, then we can print out // something nicely formatted, for tools like Emacs to pick up. - var scriptError = aMessage.QueryInterface(Ci.nsIScriptError); - dumpn(aMessage.sourceName + ":" + aMessage.lineNumber + ": " + - scriptErrorFlagsToKind(aMessage.flags) + ": " + - aMessage.errorMessage); - var string = aMessage.errorMessage; - } catch (x) { + message.QueryInterface(Ci.nsIScriptError); + dumpn(message.sourceName + ":" + message.lineNumber + ": " + + scriptErrorFlagsToKind(message.flags) + ": " + + message.errorMessage); + string = message.errorMessage; + } catch (e1) { // Be a little paranoid with message, as the whole goal here is to lose // no information. try { - var string = "" + aMessage.message; - } catch (x) { - var string = ""; + string = "" + message.message; + } catch (e2) { + string = ""; } } @@ -310,8 +315,7 @@ var listener = { var consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService); consoleService.registerListener(listener); -function check_except(func) -{ +function check_except(func) { try { func(); } catch (e) { @@ -322,70 +326,67 @@ function check_except(func) do_check_true(false); } -function testGlobal(aName) { - let systemPrincipal = Cc["@mozilla.org/systemprincipal;1"] - .createInstance(Ci.nsIPrincipal); - - let sandbox = Cu.Sandbox(systemPrincipal); - sandbox.__name = aName; +function testGlobal(name) { + let sandbox = Cu.Sandbox(Cc["@mozilla.org/systemprincipal;1"] + .createInstance(Ci.nsIPrincipal)); + sandbox.__name = name; return sandbox; } -function addTestGlobal(aName, aServer = DebuggerServer) -{ - let global = testGlobal(aName); - aServer.addTestGlobal(global); +function addTestGlobal(name, server = DebuggerServer) { + let global = testGlobal(name); + server.addTestGlobal(global); return global; } -// List the DebuggerClient |aClient|'s tabs, look for one whose title is -// |aTitle|, and apply |aCallback| to the packet's entry for that tab. -function getTestTab(aClient, aTitle, aCallback) { - aClient.listTabs(function (aResponse) { - for (let tab of aResponse.tabs) { - if (tab.title === aTitle) { - aCallback(tab, aResponse); +// List the DebuggerClient |client|'s tabs, look for one whose title is +// |title|, and apply |callback| to the packet's entry for that tab. +function getTestTab(client, title, callback) { + client.listTabs(function (response) { + for (let tab of response.tabs) { + if (tab.title === title) { + callback(tab, response); return; } } - aCallback(null); + callback(null); }); } -// Attach to |aClient|'s tab whose title is |aTitle|; pass |aCallback| the +// Attach to |client|'s tab whose title is |title|; pass |callback| the // response packet and a TabClient instance referring to that tab. -function attachTestTab(aClient, aTitle, aCallback) { - getTestTab(aClient, aTitle, function (aTab) { - aClient.attachTab(aTab.actor, aCallback); +function attachTestTab(client, title, callback) { + getTestTab(client, title, function (tab) { + client.attachTab(tab.actor, callback); }); } -// Attach to |aClient|'s tab whose title is |aTitle|, and then attach to -// that tab's thread. Pass |aCallback| the thread attach response packet, a +// Attach to |client|'s tab whose title is |title|, and then attach to +// that tab's thread. Pass |callback| the thread attach response packet, a // TabClient referring to the tab, and a ThreadClient referring to the // thread. -function attachTestThread(aClient, aTitle, aCallback) { - attachTestTab(aClient, aTitle, function (aTabResponse, aTabClient) { - function onAttach(aResponse, aThreadClient) { - aCallback(aResponse, aTabClient, aThreadClient, aTabResponse); +function attachTestThread(client, title, callback) { + attachTestTab(client, title, function (tabResponse, tabClient) { + function onAttach(response, threadClient) { + callback(response, tabClient, threadClient, tabResponse); } - aTabClient.attachThread({ + tabClient.attachThread({ useSourceMaps: true, autoBlackBox: true }, onAttach); }); } -// Attach to |aClient|'s tab whose title is |aTitle|, attach to the tab's -// thread, and then resume it. Pass |aCallback| the thread's response to +// Attach to |client|'s tab whose title is |title|, attach to the tab's +// thread, and then resume it. Pass |callback| the thread's response to // the 'resume' packet, a TabClient for the tab, and a ThreadClient for the // thread. -function attachTestTabAndResume(aClient, aTitle, aCallback = () => {}) { - return new Promise((resolve, reject) => { - attachTestThread(aClient, aTitle, function (aResponse, aTabClient, aThreadClient) { - aThreadClient.resume(function (aResponse) { - aCallback(aResponse, aTabClient, aThreadClient); - resolve([aResponse, aTabClient, aThreadClient]); +function attachTestTabAndResume(client, title, callback = () => {}) { + return new Promise((resolve) => { + attachTestThread(client, title, function (response, tabClient, threadClient) { + threadClient.resume(function (response) { + callback(response, tabClient, threadClient); + resolve([response, tabClient, threadClient]); }); }); }); @@ -394,11 +395,12 @@ function attachTestTabAndResume(aClient, aTitle, aCallback = () => {}) { /** * Initialize the testing debugger server. */ -function initTestDebuggerServer(aServer = DebuggerServer) -{ - aServer.registerModule("xpcshell-test/testactors"); +function initTestDebuggerServer(server = DebuggerServer) { + server.registerModule("xpcshell-test/testactors"); // Allow incoming connections. - aServer.init(function () { return true; }); + server.init(function () { + return true; + }); } /** @@ -415,18 +417,16 @@ function startTestDebuggerServer(title, server = DebuggerServer) { return connect(client).then(() => client); } -function finishClient(aClient) -{ - aClient.close(function () { +function finishClient(client) { + client.close(function () { DebuggerServer.destroy(); do_test_finished(); }); } // Create a server, connect to it and fetch tab actors for the parent process; -// pass |aCallback| the debugger client and tab actor form with all actor IDs. -function get_chrome_actors(callback) -{ +// pass |callback| the debugger client and tab actor form with all actor IDs. +function get_chrome_actors(callback) { if (!DebuggerServer.initialized) { DebuggerServer.init(); DebuggerServer.addBrowserActors(); @@ -449,8 +449,8 @@ function getChromeActors(client, server = DebuggerServer) { /** * Takes a relative file path and returns the absolute file url for it. */ -function getFileUrl(aName, aAllowMissing = false) { - let file = do_get_file(aName, aAllowMissing); +function getFileUrl(name, allowMissing = false) { + let file = do_get_file(name, allowMissing); return Services.io.newFileURI(file).spec; } @@ -458,9 +458,8 @@ function getFileUrl(aName, aAllowMissing = false) { * Returns the full path of the file with the specified name in a * platform-independent and URL-like form. */ -function getFilePath(aName, aAllowMissing = false, aUsePlatformPathSeparator = false) -{ - let file = do_get_file(aName, aAllowMissing); +function getFilePath(name, allowMissing = false, usePlatformPathSeparator = false) { + let file = do_get_file(name, allowMissing); let path = Services.io.newFileURI(file).spec; let filePrePath = "file://"; if ("nsILocalFileWin" in Ci && @@ -470,7 +469,7 @@ function getFilePath(aName, aAllowMissing = false, aUsePlatformPathSeparator = f path = path.slice(filePrePath.length); - if (aUsePlatformPathSeparator && path.match(/^\w:/)) { + if (usePlatformPathSeparator && path.match(/^\w:/)) { path = path.replace(/\//g, "\\"); } @@ -480,8 +479,8 @@ function getFilePath(aName, aAllowMissing = false, aUsePlatformPathSeparator = f /** * Returns the full text contents of the given file. */ -function readFile(aFileName) { - let f = do_get_file(aFileName); +function readFile(fileName) { + let f = do_get_file(fileName); let s = Cc["@mozilla.org/network/file-input-stream;1"] .createInstance(Ci.nsIFileInputStream); s.init(f, -1, -1, false); @@ -492,16 +491,16 @@ function readFile(aFileName) { } } -function writeFile(aFileName, aContent) { - let file = do_get_file(aFileName, true); +function writeFile(fileName, content) { + let file = do_get_file(fileName, true); let stream = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); stream.init(file, -1, -1, 0); try { do { - let numWritten = stream.write(aContent, aContent.length); - aContent = aContent.slice(numWritten); - } while (aContent.length > 0); + let numWritten = stream.write(content, content.length); + content = content.slice(numWritten); + } while (content.length > 0); } finally { stream.close(); } @@ -585,9 +584,9 @@ StubTransport.prototype.ready = function () {}; StubTransport.prototype.send = function () {}; StubTransport.prototype.close = function () {}; -function executeSoon(aFunc) { +function executeSoon(func) { Services.tm.mainThread.dispatch({ - run: DevToolsUtils.makeInfallible(aFunc) + run: DevToolsUtils.makeInfallible(func) }, Ci.nsIThread.DISPATCH_NORMAL); } @@ -810,8 +809,7 @@ function getSource(threadClient, url) { }); if (source.length) { deferred.resolve(threadClient.source(source[0])); - } - else { + } else { deferred.reject(new Error("source not found")); } }); diff --git a/devtools/server/tests/unit/hello-actor.js b/devtools/server/tests/unit/hello-actor.js index 6d7427f63cc6..f7e4819dc4f2 100644 --- a/devtools/server/tests/unit/hello-actor.js +++ b/devtools/server/tests/unit/hello-actor.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint no-unused-vars: ["error", {"vars": "local"}] */ + +"use strict"; const protocol = require("devtools/shared/protocol"); @@ -12,7 +15,5 @@ const helloSpec = protocol.generateActorSpec({ }); var HelloActor = protocol.ActorClassWithSpec(helloSpec, { - hello: function () { - return; - } + hello: function () {} }); diff --git a/devtools/server/tests/unit/post_init_global_actors.js b/devtools/server/tests/unit/post_init_global_actors.js index 0035e8914f7f..748f93cbf248 100644 --- a/devtools/server/tests/unit/post_init_global_actors.js +++ b/devtools/server/tests/unit/post_init_global_actors.js @@ -1,11 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function PostInitGlobalActor(aConnection) {} +"use strict"; + +function PostInitGlobalActor(connection) {} PostInitGlobalActor.prototype = { actorPrefix: "postInitGlobal", - onPing: function onPing(aRequest) { + onPing(request) { return { message: "pong" }; }, }; diff --git a/devtools/server/tests/unit/post_init_tab_actors.js b/devtools/server/tests/unit/post_init_tab_actors.js index 9b9ddf111d85..b20f2a63457e 100644 --- a/devtools/server/tests/unit/post_init_tab_actors.js +++ b/devtools/server/tests/unit/post_init_tab_actors.js @@ -1,11 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function PostInitTabActor(aConnection) {} +"use strict"; + +function PostInitTabActor(connection) {} PostInitTabActor.prototype = { actorPostfix: "postInitTab", - onPing: function onPing(aRequest) { + onPing(request) { return { message: "pong" }; }, }; diff --git a/devtools/server/tests/unit/pre_init_global_actors.js b/devtools/server/tests/unit/pre_init_global_actors.js index bd4284a70a31..e0c03514b2bd 100644 --- a/devtools/server/tests/unit/pre_init_global_actors.js +++ b/devtools/server/tests/unit/pre_init_global_actors.js @@ -1,11 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function PreInitGlobalActor(aConnection) {} +"use strict"; + +function PreInitGlobalActor(connection) {} PreInitGlobalActor.prototype = { actorPrefix: "preInitGlobal", - onPing: function onPing(aRequest) { + onPing(request) { return { message: "pong" }; }, }; diff --git a/devtools/server/tests/unit/pre_init_tab_actors.js b/devtools/server/tests/unit/pre_init_tab_actors.js index 628f0fb2fe79..b3eda97c2657 100644 --- a/devtools/server/tests/unit/pre_init_tab_actors.js +++ b/devtools/server/tests/unit/pre_init_tab_actors.js @@ -1,11 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function PreInitTabActor(aConnection) {} +"use strict"; + +function PreInitTabActor(connection) {} PreInitTabActor.prototype = { actorPrefix: "preInitTab", - onPing: function onPing(aRequest) { + onPing(request) { return { message: "pong" }; }, }; diff --git a/devtools/server/tests/unit/registertestactors-01.js b/devtools/server/tests/unit/registertestactors-01.js index 92f511225b67..e771314f528b 100644 --- a/devtools/server/tests/unit/registertestactors-01.js +++ b/devtools/server/tests/unit/registertestactors-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + function Actor() {} exports.register = function (handle) { diff --git a/devtools/server/tests/unit/registertestactors-02.js b/devtools/server/tests/unit/registertestactors-02.js index 54f78e508689..35b43236c59f 100644 --- a/devtools/server/tests/unit/registertestactors-02.js +++ b/devtools/server/tests/unit/registertestactors-02.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + function Actor() {} exports.register = function (handle) { diff --git a/devtools/server/tests/unit/registertestactors-03.js b/devtools/server/tests/unit/registertestactors-03.js index 8d42fdbd80dd..f3d9bd66af64 100644 --- a/devtools/server/tests/unit/registertestactors-03.js +++ b/devtools/server/tests/unit/registertestactors-03.js @@ -1,7 +1,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -var {method, RetVal, Actor, ActorClassWithSpec, Front, FrontClassWithSpec, +"use strict"; + +var {RetVal, Actor, ActorClassWithSpec, Front, FrontClassWithSpec, generateActorSpec} = require("devtools/shared/protocol"); var Services = require("Services"); diff --git a/devtools/server/tests/unit/test_actor-registry-actor.js b/devtools/server/tests/unit/test_actor-registry-actor.js index 8b0abfbbb886..1d704d0f9aa9 100644 --- a/devtools/server/tests/unit/test_actor-registry-actor.js +++ b/devtools/server/tests/unit/test_actor-registry-actor.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that you can register new actors via the ActorRegistrationActor. */ @@ -12,8 +14,7 @@ var gOldPref; const { ActorRegistryFront } = require("devtools/shared/fronts/actor-registry"); -function run_test() -{ +function run_test() { gOldPref = Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps"); Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", false); initTestDebuggerServer(); @@ -39,7 +40,7 @@ function registerNewActor() { gRegistryFront .registerActor("resource://test/hello-actor.js", options) - .then(actorFront => gActorFront = actorFront) + .then(actorFront => (gActorFront = actorFront)) .then(talkToNewActor) .then(null, e => { DevToolsUtils.reportException("registerNewActor", e); diff --git a/devtools/server/tests/unit/test_add_actors.js b/devtools/server/tests/unit/test_add_actors.js index 9b90da72437c..643b9e2e5ce3 100644 --- a/devtools/server/tests/unit/test_add_actors.js +++ b/devtools/server/tests/unit/test_add_actors.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gClient; var gActors; @@ -11,8 +13,7 @@ var gActors; * in order to add actors after initialization but rather can add actors anytime * regardless of the object's state. */ -function run_test() -{ +function run_test() { DebuggerServer.addActors("resource://test/pre_init_global_actors.js"); DebuggerServer.addActors("resource://test/pre_init_tab_actors.js"); @@ -32,52 +33,47 @@ function run_test() run_next_test(); } -function init() -{ +function init() { gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect() .then(() => gClient.listTabs()) - .then(aResponse => { - gActors = aResponse; + .then(response => { + gActors = response; run_next_test(); }); } -function test_pre_init_global_actor() -{ +function test_pre_init_global_actor() { gClient.request({ to: gActors.preInitGlobalActor, type: "ping" }, - function onResponse(aResponse) { - do_check_eq(aResponse.message, "pong"); + function onResponse(response) { + do_check_eq(response.message, "pong"); run_next_test(); } ); } -function test_pre_init_tab_actor() -{ +function test_pre_init_tab_actor() { gClient.request({ to: gActors.preInitTabActor, type: "ping" }, - function onResponse(aResponse) { - do_check_eq(aResponse.message, "pong"); + function onResponse(response) { + do_check_eq(response.message, "pong"); run_next_test(); } ); } -function test_post_init_global_actor() -{ +function test_post_init_global_actor() { gClient.request({ to: gActors.postInitGlobalActor, type: "ping" }, - function onResponse(aResponse) { - do_check_eq(aResponse.message, "pong"); + function onResponse(response) { + do_check_eq(response.message, "pong"); run_next_test(); } ); } -function test_post_init_tab_actor() -{ +function test_post_init_tab_actor() { gClient.request({ to: gActors.postInitTabActor, type: "ping" }, - function onResponse(aResponse) { - do_check_eq(aResponse.message, "pong"); + function onResponse(response) { + do_check_eq(response.message, "pong"); run_next_test(); } ); @@ -88,16 +84,17 @@ function getActorInstance(connID, actorID) { return DebuggerServer._connections[connID].getActor(actorID); } -function test_stable_global_actor_instances() -{ +function test_stable_global_actor_instances() { // Consider that there is only one connection, // and the first one is ours let connID = Object.keys(DebuggerServer._connections)[0]; let postInitGlobalActor = getActorInstance(connID, gActors.postInitGlobalActor); let preInitGlobalActor = getActorInstance(connID, gActors.preInitGlobalActor); - gClient.listTabs(function onListTabs(aResponse) { - do_check_eq(postInitGlobalActor, getActorInstance(connID, aResponse.postInitGlobalActor)); - do_check_eq(preInitGlobalActor, getActorInstance(connID, aResponse.preInitGlobalActor)); + gClient.listTabs(function onListTabs(response) { + do_check_eq(postInitGlobalActor, + getActorInstance(connID, response.postInitGlobalActor)); + do_check_eq(preInitGlobalActor, + getActorInstance(connID, response.preInitGlobalActor)); run_next_test(); }); } diff --git a/devtools/server/tests/unit/test_addon_reload.js b/devtools/server/tests/unit/test_addon_reload.js index 5fbd75ff8ee1..e72988e6d00a 100644 --- a/devtools/server/tests/unit/test_addon_reload.js +++ b/devtools/server/tests/unit/test_addon_reload.js @@ -1,7 +1,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; -const protocol = require("devtools/shared/protocol"); const {AddonManager} = require("resource://gre/modules/AddonManager.jsm"); startupAddonsManager(); @@ -80,7 +82,7 @@ add_task(function* testReloadExitedAddon() { // Uninstall the decoy add-on, which should cause its actor to exit. const onUninstalled = promiseAddonEvent("onUninstalled"); installedAddon2.uninstall(); - const [uninstalledAddon] = yield onUninstalled; + yield onUninstalled; // Try to re-list all add-ons after a reload. // This was throwing an exception because of the exited actor. diff --git a/devtools/server/tests/unit/test_addons_actor.js b/devtools/server/tests/unit/test_addons_actor.js index 1815d43c6ad5..448b7b7afaae 100644 --- a/devtools/server/tests/unit/test_addons_actor.js +++ b/devtools/server/tests/unit/test_addons_actor.js @@ -1,8 +1,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; -const protocol = require("devtools/shared/protocol"); -const {AddonsActor} = require("devtools/server/actors/addons"); const {AddonsFront} = require("devtools/shared/fronts/addons"); startupAddonsManager(); diff --git a/devtools/server/tests/unit/test_animation_name.js b/devtools/server/tests/unit/test_animation_name.js index 4cd708fc4d89..3b9bc0589c7f 100644 --- a/devtools/server/tests/unit/test_animation_name.js +++ b/devtools/server/tests/unit/test_animation_name.js @@ -1,87 +1,87 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -"use strict"; - -// Test that AnimationPlayerActor.getName returns the right name depending on -// the type of an animation and the various properties available on it. - -const { AnimationPlayerActor } = require("devtools/server/actors/animation"); - -function run_test() { - // Mock a window with just the properties the AnimationPlayerActor uses. - let window = { - MutationObserver: function () { - this.observe = () => {}; - }, - Animation: function () { - this.effect = {target: getMockNode()}; - }, - CSSAnimation: function () { - this.effect = {target: getMockNode()}; - }, - CSSTransition: function () { - this.effect = {target: getMockNode()}; - } - }; - - window.CSSAnimation.prototype = Object.create(window.Animation.prototype); - window.CSSTransition.prototype = Object.create(window.Animation.prototype); - - // Helper to get a mock DOM node. - function getMockNode() { - return { - ownerDocument: { - defaultView: window - } - }; - } - - // Objects in this array should contain the following properties: - // - desc {String} For logging - // - animation {Object} An animation object instantiated from one of the mock - // window animation constructors. - // - props {Objet} Properties of this object will be added to the animation - // object. - // - expectedName {String} The expected name returned by - // AnimationPlayerActor.getName. - const TEST_DATA = [{ - desc: "Animation with an id", - animation: new window.Animation(), - props: { id: "animation-id" }, - expectedName: "animation-id" - }, { - desc: "Animation without an id", - animation: new window.Animation(), - props: {}, - expectedName: "" - }, { - desc: "CSSTransition with an id", - animation: new window.CSSTransition(), - props: { id: "transition-with-id", transitionProperty: "width" }, - expectedName: "transition-with-id" - }, { - desc: "CSSAnimation with an id", - animation: new window.CSSAnimation(), - props: { id: "animation-with-id", animationName: "move" }, - expectedName: "animation-with-id" - }, { - desc: "CSSTransition without an id", - animation: new window.CSSTransition(), - props: { transitionProperty: "width" }, - expectedName: "width" - }, { - desc: "CSSAnimation without an id", - animation: new window.CSSAnimation(), - props: { animationName: "move" }, - expectedName: "move" - }]; - - for (let { desc, animation, props, expectedName } of TEST_DATA) { - do_print(desc); - for (let key in props) { - animation[key] = props[key]; - } - let actor = AnimationPlayerActor({}, animation); - do_check_eq(actor.getName(), expectedName); - } -} +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// Test that AnimationPlayerActor.getName returns the right name depending on +// the type of an animation and the various properties available on it. + +const { AnimationPlayerActor } = require("devtools/server/actors/animation"); + +function run_test() { + // Mock a window with just the properties the AnimationPlayerActor uses. + let window = { + MutationObserver: function () { + this.observe = () => {}; + }, + Animation: function () { + this.effect = {target: getMockNode()}; + }, + CSSAnimation: function () { + this.effect = {target: getMockNode()}; + }, + CSSTransition: function () { + this.effect = {target: getMockNode()}; + } + }; + + window.CSSAnimation.prototype = Object.create(window.Animation.prototype); + window.CSSTransition.prototype = Object.create(window.Animation.prototype); + + // Helper to get a mock DOM node. + function getMockNode() { + return { + ownerDocument: { + defaultView: window + } + }; + } + + // Objects in this array should contain the following properties: + // - desc {String} For logging + // - animation {Object} An animation object instantiated from one of the mock + // window animation constructors. + // - props {Objet} Properties of this object will be added to the animation + // object. + // - expectedName {String} The expected name returned by + // AnimationPlayerActor.getName. + const TEST_DATA = [{ + desc: "Animation with an id", + animation: new window.Animation(), + props: { id: "animation-id" }, + expectedName: "animation-id" + }, { + desc: "Animation without an id", + animation: new window.Animation(), + props: {}, + expectedName: "" + }, { + desc: "CSSTransition with an id", + animation: new window.CSSTransition(), + props: { id: "transition-with-id", transitionProperty: "width" }, + expectedName: "transition-with-id" + }, { + desc: "CSSAnimation with an id", + animation: new window.CSSAnimation(), + props: { id: "animation-with-id", animationName: "move" }, + expectedName: "animation-with-id" + }, { + desc: "CSSTransition without an id", + animation: new window.CSSTransition(), + props: { transitionProperty: "width" }, + expectedName: "width" + }, { + desc: "CSSAnimation without an id", + animation: new window.CSSAnimation(), + props: { animationName: "move" }, + expectedName: "move" + }]; + + for (let { desc, animation, props, expectedName } of TEST_DATA) { + do_print(desc); + for (let key in props) { + animation[key] = props[key]; + } + let actor = AnimationPlayerActor({}, animation); + do_check_eq(actor.getName(), expectedName); + } +} diff --git a/devtools/server/tests/unit/test_animation_type.js b/devtools/server/tests/unit/test_animation_type.js index 0f37755a4ee0..c4e842afe67c 100644 --- a/devtools/server/tests/unit/test_animation_type.js +++ b/devtools/server/tests/unit/test_animation_type.js @@ -1,68 +1,68 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -"use strict"; - -// Test the output of AnimationPlayerActor.getType(). - -const { ANIMATION_TYPES, AnimationPlayerActor } = - require("devtools/server/actors/animation"); - -function run_test() { - // Mock a window with just the properties the AnimationPlayerActor uses. - let window = { - MutationObserver: function () { - this.observe = () => {}; - }, - Animation: function () { - this.effect = {target: getMockNode()}; - }, - CSSAnimation: function () { - this.effect = {target: getMockNode()}; - }, - CSSTransition: function () { - this.effect = {target: getMockNode()}; - } - }; - - window.CSSAnimation.prototype = Object.create(window.Animation.prototype); - window.CSSTransition.prototype = Object.create(window.Animation.prototype); - - // Helper to get a mock DOM node. - function getMockNode() { - return { - ownerDocument: { - defaultView: window - } - }; - } - - // Objects in this array should contain the following properties: - // - desc {String} For logging - // - animation {Object} An animation object instantiated from one of the mock - // window animation constructors. - // - expectedType {String} The expected type returned by - // AnimationPlayerActor.getType. - const TEST_DATA = [{ - desc: "Test CSSAnimation type", - animation: new window.CSSAnimation(), - expectedType: ANIMATION_TYPES.CSS_ANIMATION - }, { - desc: "Test CSSTransition type", - animation: new window.CSSTransition(), - expectedType: ANIMATION_TYPES.CSS_TRANSITION - }, { - desc: "Test ScriptAnimation type", - animation: new window.Animation(), - expectedType: ANIMATION_TYPES.SCRIPT_ANIMATION - }, { - desc: "Test unknown type", - animation: {effect: {target: getMockNode()}}, - expectedType: ANIMATION_TYPES.UNKNOWN - }]; - - for (let { desc, animation, expectedType } of TEST_DATA) { - do_print(desc); - let actor = AnimationPlayerActor({}, animation); - do_check_eq(actor.getType(), expectedType); - } -} +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// Test the output of AnimationPlayerActor.getType(). + +const { ANIMATION_TYPES, AnimationPlayerActor } = + require("devtools/server/actors/animation"); + +function run_test() { + // Mock a window with just the properties the AnimationPlayerActor uses. + let window = { + MutationObserver: function () { + this.observe = () => {}; + }, + Animation: function () { + this.effect = {target: getMockNode()}; + }, + CSSAnimation: function () { + this.effect = {target: getMockNode()}; + }, + CSSTransition: function () { + this.effect = {target: getMockNode()}; + } + }; + + window.CSSAnimation.prototype = Object.create(window.Animation.prototype); + window.CSSTransition.prototype = Object.create(window.Animation.prototype); + + // Helper to get a mock DOM node. + function getMockNode() { + return { + ownerDocument: { + defaultView: window + } + }; + } + + // Objects in this array should contain the following properties: + // - desc {String} For logging + // - animation {Object} An animation object instantiated from one of the mock + // window animation constructors. + // - expectedType {String} The expected type returned by + // AnimationPlayerActor.getType. + const TEST_DATA = [{ + desc: "Test CSSAnimation type", + animation: new window.CSSAnimation(), + expectedType: ANIMATION_TYPES.CSS_ANIMATION + }, { + desc: "Test CSSTransition type", + animation: new window.CSSTransition(), + expectedType: ANIMATION_TYPES.CSS_TRANSITION + }, { + desc: "Test ScriptAnimation type", + animation: new window.Animation(), + expectedType: ANIMATION_TYPES.SCRIPT_ANIMATION + }, { + desc: "Test unknown type", + animation: {effect: {target: getMockNode()}}, + expectedType: ANIMATION_TYPES.UNKNOWN + }]; + + for (let { desc, animation, expectedType } of TEST_DATA) { + do_print(desc); + let actor = AnimationPlayerActor({}, animation); + do_check_eq(actor.getType(), expectedType); + } +} diff --git a/devtools/server/tests/unit/test_attach.js b/devtools/server/tests/unit/test_attach.js index a69db2c2ba05..3efbb596160a 100644 --- a/devtools/server/tests/unit/test_attach.js +++ b/devtools/server/tests/unit/test_attach.js @@ -1,36 +1,35 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gClient; var gDebuggee; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = testGlobal("test-1"); DebuggerServer.addTestGlobal(gDebuggee); let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); - gClient.connect().then(function ([aType, aTraits]) { - attachTestTab(gClient, "test-1", function (aReply, aTabClient) { - test_attach(aTabClient); + gClient.connect().then(function ([type, traits]) { + attachTestTab(gClient, "test-1", function (reply, tabClient) { + test_attach(tabClient); }); }); do_test_pending(); } -function test_attach(aTabClient) -{ - aTabClient.attachThread({}, function (aResponse, aThreadClient) { - do_check_eq(aThreadClient.state, "paused"); - aThreadClient.resume(cleanup); +function test_attach(tabClient) { + tabClient.attachThread({}, function (response, threadClient) { + do_check_eq(threadClient.state, "paused"); + threadClient.resume(cleanup); }); } -function cleanup() -{ - gClient.addListener("closed", function (aEvent) { +function cleanup() { + gClient.addListener("closed", function (event) { do_test_finished(); }); gClient.close(); diff --git a/devtools/server/tests/unit/test_blackboxing-01.js b/devtools/server/tests/unit/test_blackboxing-01.js index d5356c39035d..9e9d0a70244c 100644 --- a/devtools/server/tests/unit/test_blackboxing-01.js +++ b/devtools/server/tests/unit/test_blackboxing-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test basic black boxing. */ @@ -9,16 +11,16 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - testBlackBox(); - }); + attachTestTabAndResume(gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + testBlackBox(); + }); }); do_test_pending(); } @@ -43,27 +45,27 @@ const testBlackBox = Task.async(function* () { // Test that we can step into `doStuff` when we are not black boxed. yield runTest( - function onSteppedLocation(aLocation) { - do_check_eq(aLocation.source.url, BLACK_BOXED_URL); - do_check_eq(aLocation.line, 2); + function onSteppedLocation(location) { + do_check_eq(location.source.url, BLACK_BOXED_URL); + do_check_eq(location.line, 2); }, - function onDebuggerStatementFrames(aFrames) { - do_check_true(!aFrames.some(f => f.where.source.isBlackBoxed)); + function onDebuggerStatementFrames(frames) { + do_check_true(!frames.some(f => f.where.source.isBlackBoxed)); } ); - let blackBoxResponse = yield blackBox(sourceClient); + yield blackBox(sourceClient); do_check_true(sourceClient.isBlackBoxed); // Test that we step through `doStuff` when we are black boxed and its frame // doesn't show up. yield runTest( - function onSteppedLocation(aLocation) { - do_check_eq(aLocation.source.url, SOURCE_URL); - do_check_eq(aLocation.line, 4); + function onSteppedLocation(location) { + do_check_eq(location.source.url, SOURCE_URL); + do_check_eq(location.line, 4); }, - function onDebuggerStatementFrames(aFrames) { - for (let f of aFrames) { + function onDebuggerStatementFrames(frames) { + for (let f of frames) { if (f.where.source.url == BLACK_BOXED_URL) { do_check_true(f.where.source.isBlackBoxed); } else { @@ -73,17 +75,17 @@ const testBlackBox = Task.async(function* () { } ); - let unBlackBoxResponse = yield unBlackBox(sourceClient); + yield unBlackBox(sourceClient); do_check_true(!sourceClient.isBlackBoxed); // Test that we can step into `doStuff` again. yield runTest( - function onSteppedLocation(aLocation) { - do_check_eq(aLocation.source.url, BLACK_BOXED_URL); - do_check_eq(aLocation.line, 2); + function onSteppedLocation(location) { + do_check_eq(location.source.url, BLACK_BOXED_URL); + do_check_eq(location.line, 2); }, - function onDebuggerStatementFrames(aFrames) { - do_check_true(!aFrames.some(f => f.where.source.isBlackBoxed)); + function onDebuggerStatementFrames(frames) { + do_check_true(!frames.some(f => f.where.source.isBlackBoxed)); } ); @@ -91,6 +93,7 @@ const testBlackBox = Task.async(function* () { }); function evalCode() { + /* eslint-disable */ Components.utils.evalInSandbox( "" + function doStuff(k) { // line 1 let arg = 15; // line 2 - Step in here @@ -116,6 +119,7 @@ function evalCode() { SOURCE_URL, 1 ); + /* eslint-enable */ } const runTest = Task.async(function* (onSteppedLocation, onDebuggerStatementFrames) { diff --git a/devtools/server/tests/unit/test_blackboxing-02.js b/devtools/server/tests/unit/test_blackboxing-02.js index 5bfb3641a7b8..66bf08257a5a 100644 --- a/devtools/server/tests/unit/test_blackboxing-02.js +++ b/devtools/server/tests/unit/test_blackboxing-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that we don't hit breakpoints in black boxed sources, and that when we @@ -11,16 +14,16 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_black_box(); - }); + attachTestTabAndResume(gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_black_box(); + }); }); do_test_pending(); } @@ -28,27 +31,27 @@ function run_test() const BLACK_BOXED_URL = "http://example.com/blackboxme.js"; const SOURCE_URL = "http://example.com/source.js"; -function test_black_box() -{ - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.eval(aPacket.frame.actor, "doStuff", function (aResponse) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let obj = gThreadClient.pauseGrip(aPacket.why.frameFinished.return); +function test_black_box() { + gClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.eval(packet.frame.actor, "doStuff", function (response) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let obj = gThreadClient.pauseGrip(packet.why.frameFinished.return); obj.getDefinitionSite(runWithSource); }); }); - function runWithSource(aPacket) { - let source = gThreadClient.source(aPacket.source); + function runWithSource(packet) { + let source = gThreadClient.source(packet.source); source.setBreakpoint({ line: 2 - }, function (aResponse) { - do_check_true(!aResponse.error, "Should be able to set breakpoint."); + }, function (response) { + do_check_true(!response.error, "Should be able to set breakpoint."); gThreadClient.resume(test_black_box_breakpoint); }); } }); + /* eslint-disable */ Components.utils.evalInSandbox( "" + function doStuff(k) { // line 1 let arg = 15; // line 2 - Break here @@ -74,18 +77,22 @@ function test_black_box() SOURCE_URL, 1 ); + /* eslint-enable */ } function test_black_box_breakpoint() { gThreadClient.getSources(function ({error, sources}) { do_check_true(!error, "Should not get an error: " + error); - let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]); + let sourceClient = gThreadClient.source( + sources.filter(s => s.url == BLACK_BOXED_URL)[0] + ); sourceClient.blackBox(function ({error}) { do_check_true(!error, "Should not get an error: " + error); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "debuggerStatement", - "We should pass over the breakpoint since the source is black boxed."); + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq( + packet.why.type, "debuggerStatement", + "We should pass over the breakpoint since the source is black boxed."); gThreadClient.resume(test_unblack_box_breakpoint.bind(null, sourceClient)); }); gDebuggee.runTest(); @@ -93,14 +100,15 @@ function test_black_box_breakpoint() { }); } -function test_unblack_box_breakpoint(aSourceClient) { - aSourceClient.unblackBox(function ({error}) { +function test_unblack_box_breakpoint(sourceClient) { + sourceClient.unblackBox(function ({error}) { do_check_true(!error, "Should not get an error: " + error); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "breakpoint", + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "breakpoint", "We should hit the breakpoint again"); - // We will hit the debugger statement on resume, so do this nastiness to skip over it. + // We will hit the debugger statement on resume, so do this + // nastiness to skip over it. gClient.addOneTimeListener( "paused", gThreadClient.resume.bind( diff --git a/devtools/server/tests/unit/test_blackboxing-03.js b/devtools/server/tests/unit/test_blackboxing-03.js index 48f1787772aa..78e1d85fcbd0 100644 --- a/devtools/server/tests/unit/test_blackboxing-03.js +++ b/devtools/server/tests/unit/test_blackboxing-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Test that we don't stop at debugger statements inside black boxed sources. @@ -10,16 +13,16 @@ var gClient; var gThreadClient; var gBpClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_black_box(); - }); + attachTestTabAndResume(gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_black_box(); + }); }); do_test_pending(); } @@ -27,10 +30,9 @@ function run_test() const BLACK_BOXED_URL = "http://example.com/blackboxme.js"; const SOURCE_URL = "http://example.com/source.js"; -function test_black_box() -{ - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_black_box() { + gClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); source.setBreakpoint({ line: 4 }, function ({error}, bpClient) { @@ -40,6 +42,7 @@ function test_black_box() }); }); + /* eslint-disable */ Components.utils.evalInSandbox( "" + function doStuff(k) { // line 1 debugger; // line 2 - Break here @@ -65,18 +68,21 @@ function test_black_box() SOURCE_URL, 1 ); + /* eslint-enable */ } function test_black_box_dbg_statement() { gThreadClient.getSources(function ({error, sources}) { do_check_true(!error, "Should not get an error: " + error); - let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]); + let sourceClient = gThreadClient.source( + sources.filter(s => s.url == BLACK_BOXED_URL)[0] + ); sourceClient.blackBox(function ({error}) { do_check_true(!error, "Should not get an error: " + error); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "breakpoint", + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "breakpoint", "We should pass over the debugger statement."); gBpClient.remove(function ({error}) { do_check_true(!error, "Should not get an error: " + error); @@ -88,12 +94,12 @@ function test_black_box_dbg_statement() { }); } -function test_unblack_box_dbg_statement(aSourceClient) { - aSourceClient.unblackBox(function ({error}) { +function test_unblack_box_dbg_statement(sourceClient) { + sourceClient.unblackBox(function ({error}) { do_check_true(!error, "Should not get an error: " + error); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "debuggerStatement", + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "debuggerStatement", "We should stop at the debugger statement again"); finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_blackboxing-04.js b/devtools/server/tests/unit/test_blackboxing-04.js index fbfaf288177e..9952ff302fcb 100644 --- a/devtools/server/tests/unit/test_blackboxing-04.js +++ b/devtools/server/tests/unit/test_blackboxing-04.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test behavior of blackboxing sources we are currently paused in. @@ -9,16 +12,16 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_black_box(); - }); + attachTestTabAndResume(gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_black_box(); + }); }); do_test_pending(); } @@ -26,27 +29,27 @@ function run_test() const BLACK_BOXED_URL = "http://example.com/blackboxme.js"; const SOURCE_URL = "http://example.com/source.js"; -function test_black_box() -{ - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.eval(aPacket.frame.actor, "doStuff", function (aResponse) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let obj = gThreadClient.pauseGrip(aPacket.why.frameFinished.return); +function test_black_box() { + gClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.eval(packet.frame.actor, "doStuff", function (response) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let obj = gThreadClient.pauseGrip(packet.why.frameFinished.return); obj.getDefinitionSite(runWithSource); }); }); - function runWithSource(aPacket) { - let source = gThreadClient.source(aPacket.source); + function runWithSource(packet) { + let source = gThreadClient.source(packet.source); source.setBreakpoint({ line: 2 - }, function (aResponse) { - do_check_true(!aResponse.error, "Should be able to set breakpoint."); + }, function (response) { + do_check_true(!response.error, "Should be able to set breakpoint."); test_black_box_paused(); }); } }); + /* eslint-disable */ Components.utils.evalInSandbox( "" + function doStuff(k) { // line 1 debugger; // line 2 @@ -72,16 +75,20 @@ function test_black_box() SOURCE_URL, 1 ); + /* eslint-enable */ } function test_black_box_paused() { gThreadClient.getSources(function ({error, sources}) { do_check_true(!error, "Should not get an error: " + error); - let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]); + let sourceClient = gThreadClient.source( + sources.filter(s => s.url == BLACK_BOXED_URL)[0] + ); sourceClient.blackBox(function ({error, pausedInSource}) { do_check_true(!error, "Should not get an error: " + error); - do_check_true(pausedInSource, "We should be notified that we are currently paused in this source"); + do_check_true(pausedInSource, + "We should be notified that we are currently paused in this source"); finishClient(gClient); }); }); diff --git a/devtools/server/tests/unit/test_blackboxing-05.js b/devtools/server/tests/unit/test_blackboxing-05.js index fa8142e870e3..1835070ac44b 100644 --- a/devtools/server/tests/unit/test_blackboxing-05.js +++ b/devtools/server/tests/unit/test_blackboxing-05.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test exceptions inside black boxed sources. @@ -9,21 +12,22 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - // XXX: We have to do an executeSoon so that the error isn't caught and - // reported by DebuggerClient.requester (because we are using the local - // transport and share a stack) which causes the test to fail. - Services.tm.mainThread.dispatch({ - run: test_black_box - }, Ci.nsIThread.DISPATCH_NORMAL); - }); + attachTestTabAndResume( + gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + // XXX: We have to do an executeSoon so that the error isn't caught and + // reported by DebuggerClient.requester (because we are using the local + // transport and share a stack) which causes the test to fail. + Services.tm.mainThread.dispatch({ + run: test_black_box + }, Ci.nsIThread.DISPATCH_NORMAL); + }); }); do_test_pending(); } @@ -31,10 +35,10 @@ function run_test() const BLACK_BOXED_URL = "http://example.com/blackboxme.js"; const SOURCE_URL = "http://example.com/source.js"; -function test_black_box() -{ +function test_black_box() { gClient.addOneTimeListener("paused", test_black_box_exception); + /* eslint-disable */ Components.utils.evalInSandbox( "" + function doStuff(k) { // line 1 throw new Error("wu tang clan ain't nuthin' ta fuck wit"); // line 2 @@ -61,19 +65,22 @@ function test_black_box() SOURCE_URL, 1 ); + /* eslint-enable */ } function test_black_box_exception() { gThreadClient.getSources(function ({error, sources}) { do_check_true(!error, "Should not get an error: " + error); - let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]); + let sourceClient = gThreadClient.source( + sources.filter(s => s.url == BLACK_BOXED_URL)[0] + ); sourceClient.blackBox(function ({error}) { do_check_true(!error, "Should not get an error: " + error); gThreadClient.pauseOnExceptions(true); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.frame.where.source.url, SOURCE_URL, + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.frame.where.source.url, SOURCE_URL, "We shouldn't pause while in the black boxed source."); finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_blackboxing-06.js b/devtools/server/tests/unit/test_blackboxing-06.js index 9384f2cc25f1..2f6bfcc4e3a0 100644 --- a/devtools/server/tests/unit/test_blackboxing-06.js +++ b/devtools/server/tests/unit/test_blackboxing-06.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that we can black box source mapped sources. @@ -11,31 +14,33 @@ var gThreadClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + attachTestTabAndResume( + gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; - promise.resolve(setup_code()) - .then(black_box_code) - .then(run_code) - .then(test_correct_location) - .then(null, function (error) { - do_check_true(false, "Should not get an error, got " + error); - }) - .then(function () { - finishClient(gClient); - }); - }); + promise.resolve(setup_code()) + .then(black_box_code) + .then(run_code) + .then(test_correct_location) + .then(null, function (error) { + do_check_true(false, "Should not get an error, got " + error); + }) + .then(function () { + finishClient(gClient); + }); + }); }); do_test_pending(); } function setup_code() { + /* eslint-disable */ let { code, map } = (new SourceNode(null, null, null, [ new SourceNode(1, 0, "a.js", "" + function a() { return b(); @@ -54,6 +59,7 @@ function setup_code() { file: "abc.js", sourceRoot: "http://example.com/" }); + /* eslint-enable */ code += "//# sourceMappingURL=data:text/json," + map.toString(); @@ -85,8 +91,8 @@ function black_box_code() { function run_code() { const d = promise.defer(); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - d.resolve(aPacket); + gClient.addOneTimeListener("paused", function (event, packet) { + d.resolve(packet); gThreadClient.resume(); }); gDebuggee.a(); @@ -94,9 +100,10 @@ function run_code() { return d.promise; } -function test_correct_location(aPacket) { - do_check_eq(aPacket.why.type, "debuggerStatement", +function test_correct_location(packet) { + do_check_eq(packet.why.type, "debuggerStatement", "Should hit a debugger statement."); - do_check_eq(aPacket.frame.where.source.url, "http://example.com/c.js", - "Should have skipped over the debugger statement in the black boxed source"); + do_check_eq(packet.frame.where.source.url, "http://example.com/c.js", + "Should have skipped over the debugger statement in the" + + " black boxed source"); } diff --git a/devtools/server/tests/unit/test_blackboxing-07.js b/devtools/server/tests/unit/test_blackboxing-07.js index da31470210ab..edb65b53b0f0 100644 --- a/devtools/server/tests/unit/test_blackboxing-07.js +++ b/devtools/server/tests/unit/test_blackboxing-07.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that sources whose URL ends with ".min.js" automatically get black * boxed. @@ -10,16 +12,16 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-black-box"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-black-box", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - testBlackBox(); - }); + attachTestTabAndResume(gClient, "test-black-box", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + testBlackBox(); + }); }); do_test_pending(); } diff --git a/devtools/server/tests/unit/test_breakpoint-01.js b/devtools/server/tests/unit/test_breakpoint-01.js index 9a20257a3ef0..63e678be3c46 100644 --- a/devtools/server/tests/unit/test_breakpoint-01.js +++ b/devtools/server/tests/unit/test_breakpoint-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check basic breakpoint functionality. @@ -9,55 +12,52 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_breakpoint(); + }); }); } -function test_simple_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_simple_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 3 }; - source.setBreakpoint(location, function (aResponse, bpClient) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + source.setBreakpoint(location, function (response, bpClient) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); }); - }); // Continue until the breakpoint is hit. @@ -65,6 +65,7 @@ function test_simple_breakpoint() }); }); + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 @@ -72,4 +73,5 @@ function test_simple_breakpoint() "var b = 2;\n", // line0 + 3 gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-02.js b/devtools/server/tests/unit/test_breakpoint-02.js index d2b220d8303f..185b9fcc1e1c 100644 --- a/devtools/server/tests/unit/test_breakpoint-02.js +++ b/devtools/server/tests/unit/test_breakpoint-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Check that setting breakpoints when the debuggee is running works. @@ -10,46 +13,44 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_breakpoint_running(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_breakpoint_running(); + }); }); } -function test_breakpoint_running() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_breakpoint_running() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { let location = { line: gDebuggee.line0 + 3 }; gThreadClient.resume(); // Setting the breakpoint later should interrupt the debuggee. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "interrupted"); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "interrupted"); }); - let source = gThreadClient.source(aPacket.frame.where.source); - source.setBreakpoint(location, function (aResponse) { + let source = gThreadClient.source(packet.frame.where.source); + source.setBreakpoint(location, function (response) { // Eval scripts don't stick around long enough for the breakpoint to be set, // so just make sure we got the expected response from the actor. - do_check_neq(aResponse.error, "noScript"); + do_check_neq(response.error, "noScript"); do_execute_soon(function () { gClient.close().then(gCallback); @@ -57,6 +58,7 @@ function test_breakpoint_running() }); }); + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "debugger;\n" + @@ -64,4 +66,5 @@ function test_breakpoint_running() "var b = 2;\n", // line0 + 3 gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-03.js b/devtools/server/tests/unit/test_breakpoint-03.js index b1792866b61b..652ecbee67ea 100644 --- a/devtools/server/tests/unit/test_breakpoint-03.js +++ b/devtools/server/tests/unit/test_breakpoint-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint on a line without code will skip @@ -12,68 +15,66 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume(gClient, "test-stack", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; test_skip_breakpoint(); }); }); } -var test_no_skip_breakpoint = Task.async(function*(source, location) { - let [aResponse, bpClient] = yield source.setBreakpoint( +var test_no_skip_breakpoint = Task.async(function* (source, location) { + let [response, bpClient] = yield source.setBreakpoint( Object.assign({}, location, { noSliding: true }) ); - do_check_true(!aResponse.actualLocation); + do_check_true(!response.actualLocation); do_check_eq(bpClient.location.line, gDebuggee.line0 + 3); yield bpClient.remove(); }); -var test_skip_breakpoint = function() { - gThreadClient.addOneTimeListener("paused", Task.async(function *(aEvent, aPacket) { +var test_skip_breakpoint = function () { + gThreadClient.addOneTimeListener("paused", Task.async(function* (event, packet) { let location = { line: gDebuggee.line0 + 3 }; - let source = gThreadClient.source(aPacket.frame.where.source); + let source = gThreadClient.source(packet.frame.where.source); // First, make sure that we can disable sliding with the // `noSliding` option. yield test_no_skip_breakpoint(source, location); // Now make sure that the breakpoint properly slides forward one line. - const [aResponse, bpClient] = yield source.setBreakpoint(location); - do_check_true(!!aResponse.actualLocation); - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); + const [response, bpClient] = yield source.setBreakpoint(location); + do_check_true(!!response.actualLocation); + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line + 1); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line + 1); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -85,6 +86,7 @@ var test_skip_breakpoint = function() { // Use `evalInSandbox` to make the debugger treat it as normal // globally-scoped code, where breakpoint sliding rules apply. + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 @@ -93,4 +95,5 @@ var test_skip_breakpoint = function() { "var b = 2;", // line0 + 4 gDebuggee ); -} + /* eslint-enable */ +}; diff --git a/devtools/server/tests/unit/test_breakpoint-04.js b/devtools/server/tests/unit/test_breakpoint-04.js index 9004c092b285..896dfd50c631 100644 --- a/devtools/server/tests/unit/test_breakpoint-04.js +++ b/devtools/server/tests/unit/test_breakpoint-04.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint in a line in a child script works. @@ -10,51 +13,49 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_child_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_child_breakpoint(); + }); }); } -function test_child_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_child_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 3 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // actualLocation is not returned when breakpoints don't skip forward. - do_check_eq(aResponse.actualLocation, undefined); + do_check_eq(response.actualLocation, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -64,9 +65,9 @@ function test_child_breakpoint() // Continue until the breakpoint is hit. gThreadClient.resume(); }); - }); + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 @@ -77,4 +78,5 @@ function test_child_breakpoint() "foo();\n", // line0 + 6 gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-05.js b/devtools/server/tests/unit/test_breakpoint-05.js index 9e04d0271578..3d2183b73dd5 100644 --- a/devtools/server/tests/unit/test_breakpoint-05.js +++ b/devtools/server/tests/unit/test_breakpoint-05.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint in a line without code in a child script @@ -11,52 +14,50 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_child_skip_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_child_skip_breakpoint(); + }); }); } -function test_child_skip_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_child_skip_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 3 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // Check that the breakpoint has properly skipped forward one line. - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line + 1); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line + 1); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -68,6 +69,7 @@ function test_child_skip_breakpoint() }); }); + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 @@ -79,4 +81,5 @@ function test_child_skip_breakpoint() "foo();\n", // line0 + 7 gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-06.js b/devtools/server/tests/unit/test_breakpoint-06.js index aa92b1a5f38d..80f7ae6c214b 100644 --- a/devtools/server/tests/unit/test_breakpoint-06.js +++ b/devtools/server/tests/unit/test_breakpoint-06.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint in a line without code in a deeply-nested @@ -11,52 +14,50 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_nested_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_nested_breakpoint(); + }); }); } -function test_nested_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_nested_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 5 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // Check that the breakpoint has properly skipped forward one line. - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line + 1); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line + 1); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -66,9 +67,9 @@ function test_nested_breakpoint() // Continue until the breakpoint is hit. gThreadClient.resume(); }); - }); + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 @@ -86,4 +87,5 @@ function test_nested_breakpoint() "foo();\n", // line0 + 13 gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-07.js b/devtools/server/tests/unit/test_breakpoint-07.js index 008f1424d0f0..84c1c46e86c7 100644 --- a/devtools/server/tests/unit/test_breakpoint-07.js +++ b/devtools/server/tests/unit/test_breakpoint-07.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint in a line without code in the second child @@ -11,52 +14,50 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_second_child_skip_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_second_child_skip_breakpoint(); + }); }); } -function test_second_child_skip_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_second_child_skip_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 6 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // Check that the breakpoint has properly skipped forward one line. - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line + 1); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line + 1); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -68,6 +69,7 @@ function test_second_child_skip_breakpoint() }); }); + /* eslint-disable */ Cu.evalInSandbox( "var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 @@ -82,4 +84,5 @@ function test_second_child_skip_breakpoint() "foo();\n", // line0 + 10 gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-08.js b/devtools/server/tests/unit/test_breakpoint-08.js index 6215a61ac685..62bc31763597 100644 --- a/devtools/server/tests/unit/test_breakpoint-08.js +++ b/devtools/server/tests/unit/test_breakpoint-08.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint in a line without code in a child script @@ -11,60 +14,58 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_child_skip_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_child_skip_breakpoint(); + }); }); } -function test_child_skip_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.eval(aPacket.frame.actor, "foo", function (aResponse) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let obj = gThreadClient.pauseGrip(aPacket.why.frameFinished.return); +function test_child_skip_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.eval(packet.frame.actor, "foo", function (response) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let obj = gThreadClient.pauseGrip(packet.why.frameFinished.return); obj.getDefinitionSite(runWithBreakpoint); }); }); - function runWithBreakpoint(aPacket) { - let source = gThreadClient.source(aPacket.source); + function runWithBreakpoint(packet) { + let source = gThreadClient.source(packet.source); let location = { line: gDebuggee.line0 + 3 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // Check that the breakpoint has properly skipped forward one line. - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line + 1); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line + 1); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -77,6 +78,7 @@ function test_child_skip_breakpoint() } }); + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 " this.a = 1;\n" + // line0 + 2 @@ -93,4 +95,5 @@ function test_child_skip_breakpoint() gDebuggee, "1.7", "script2.js"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-09.js b/devtools/server/tests/unit/test_breakpoint-09.js index 8bea375b98e5..888f1105a9f0 100644 --- a/devtools/server/tests/unit/test_breakpoint-09.js +++ b/devtools/server/tests/unit/test_breakpoint-09.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that removing a breakpoint works. @@ -10,51 +13,49 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_remove_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_remove_breakpoint(); + }); }); } -function test_remove_breakpoint() -{ +function test_remove_breakpoint() { let done = false; - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 2 }; - source.setBreakpoint(location, function (aResponse, bpClient) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + source.setBreakpoint(location, function (response, bpClient) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { done = true; gThreadClient.addOneTimeListener("paused", - function (aEvent, aPacket) { + function (event, packet) { // The breakpoint should not be hit again. gThreadClient.resume(function () { do_check_true(false); @@ -62,15 +63,13 @@ function test_remove_breakpoint() }); gThreadClient.resume(); }); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); - }); - }); + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "function foo(stop) {\n" + // line0 + 1 " this.a = 1;\n" + // line0 + 2 @@ -81,6 +80,7 @@ function test_remove_breakpoint() "debugger;\n" + // line1 + 7 "foo();\n", // line1 + 8 gDebuggee); + /* eslint-enable */ if (!done) { do_check_true(false); } diff --git a/devtools/server/tests/unit/test_breakpoint-10.js b/devtools/server/tests/unit/test_breakpoint-10.js index c6957676704a..99106bad3f5b 100644 --- a/devtools/server/tests/unit/test_breakpoint-10.js +++ b/devtools/server/tests/unit/test_breakpoint-10.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that setting a breakpoint in a line with multiple entry points @@ -11,56 +14,54 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_child_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_child_breakpoint(); + }); }); } -function test_child_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_child_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 3 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // actualLocation is not returned when breakpoints don't skip forward. - do_check_eq(aResponse.actualLocation, undefined); + do_check_eq(response.actualLocation, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.i, 0); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.i, 1); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -69,16 +70,13 @@ function test_child_breakpoint() // Continue until the breakpoint is hit again. gThreadClient.resume(); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); - }); - }); - + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 "var a, i = 0;\n" + // line0 + 2 @@ -86,4 +84,5 @@ function test_child_breakpoint() " a = i;\n" + // line0 + 4 "}\n", // line0 + 5 gDebuggee); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-11.js b/devtools/server/tests/unit/test_breakpoint-11.js index 480b95984d24..8b3aba3e4dc0 100644 --- a/devtools/server/tests/unit/test_breakpoint-11.js +++ b/devtools/server/tests/unit/test_breakpoint-11.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Make sure that setting a breakpoint in a line with bytecodes in multiple @@ -11,57 +14,55 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_child_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_child_breakpoint(); + }); }); } -function test_child_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_child_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 2 }; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // actualLocation is not returned when breakpoints don't skip forward. - do_check_eq(aResponse.actualLocation, undefined); + do_check_eq(response.actualLocation, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a.b, 1); do_check_eq(gDebuggee.res, undefined); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { gClient.close().then(gCallback); }); @@ -70,19 +71,17 @@ function test_child_breakpoint() // Continue until the breakpoint is hit again. gThreadClient.resume(); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); - }); - }); - + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 "var a = { b: 1, f: function() { return 2; } };\n" + // line0+2 "var res = a.f();\n", // line0 + 3 gDebuggee); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-12.js b/devtools/server/tests/unit/test_breakpoint-12.js index fb147da9f29f..6e890cff39a6 100644 --- a/devtools/server/tests/unit/test_breakpoint-12.js +++ b/devtools/server/tests/unit/test_breakpoint-12.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Make sure that setting a breakpoint twice in a line without bytecodes works @@ -14,47 +17,45 @@ var gBpActor; var gCount; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; +function run_test_with_server(server, callback) { + gCallback = callback; gCount = 1; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_child_skip_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_child_skip_breakpoint(); + }); }); } -function test_child_skip_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_child_skip_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 3}; - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // Check that the breakpoint has properly skipped forward one line. - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); - gBpActor = aResponse.actor; + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); + gBpActor = response.actor; // Set more breakpoints at the same location. set_breakpoints(source, location); }); - }); + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 " this.a = 1;\n" + // line0 + 2 @@ -64,17 +65,18 @@ function test_child_skip_breakpoint() "debugger;\n" + // line0 + 6 "foo();\n", // line0 + 7 gDebuggee); + /* eslint-enable */ } // Set many breakpoints at the same location. function set_breakpoints(source, location) { do_check_neq(gCount, NUM_BREAKPOINTS); - source.setBreakpoint(location, function (aResponse, bpClient) { + source.setBreakpoint(location, function (response, bpClient) { // Check that the breakpoint has properly skipped forward one line. - do_check_eq(aResponse.actualLocation.source.actor, source.actor); - do_check_eq(aResponse.actualLocation.line, location.line + 1); + do_check_eq(response.actualLocation.source.actor, source.actor); + do_check_eq(response.actualLocation.line, location.line + 1); // Check that the same breakpoint actor was returned. - do_check_eq(aResponse.actor, gBpActor); + do_check_eq(response.actor, gBpActor); if (++gCount < NUM_BREAKPOINTS) { set_breakpoints(source, location); @@ -83,18 +85,18 @@ function set_breakpoints(source, location) { // After setting all the breakpoints, check that only one has effectively // remained. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line + 1); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line + 1); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); // Check that the breakpoint worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // We don't expect any more pauses after the breakpoint was hit once. do_check_true(false); }); @@ -104,10 +106,8 @@ function set_breakpoints(source, location) { gClient.close().then(gCallback); }); }); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); }); - } diff --git a/devtools/server/tests/unit/test_breakpoint-13.js b/devtools/server/tests/unit/test_breakpoint-13.js index cdc4c9091e6a..533466da36d0 100644 --- a/devtools/server/tests/unit/test_breakpoint-13.js +++ b/devtools/server/tests/unit/test_breakpoint-13.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Check that execution doesn't pause twice while stepping, when encountering @@ -11,80 +14,78 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_breakpoint(); + }); }); } -function test_simple_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_simple_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 2 }; - source.setBreakpoint(location, Task.async(function* (aResponse, bpClient) { + source.setBreakpoint(location, Task.async(function* (response, bpClient) { const testCallbacks = [ - function (aPacket) { + function (packet) { // Check that the stepping worked. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // Entered the foo function call frame. - do_check_eq(aPacket.frame.where.line, location.line); - do_check_neq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, location.line); + do_check_neq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // At the end of the foo function call frame. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_neq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_neq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // Check that the breakpoint wasn't the reason for this pause, but // that the frame is about to be popped while stepping. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_neq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.why.frameFinished.return.type, "undefined"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_neq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.why.frameFinished.return.type, "undefined"); }, - function (aPacket) { + function (packet) { // The foo function call frame was just popped from the stack. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.poppedFrames.length, 1); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.poppedFrames.length, 1); }, - function (aPacket) { + function (packet) { // Check that the debugger statement wasn't the reason for this pause. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6); - do_check_neq(aPacket.why.type, "debuggerStatement"); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 6); + do_check_neq(packet.why.type, "debuggerStatement"); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // Check that the debugger statement wasn't the reason for this pause. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7); - do_check_neq(aPacket.why.type, "debuggerStatement"); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 7); + do_check_neq(packet.why.type, "debuggerStatement"); + do_check_eq(packet.why.type, "resumeLimit"); }, ]; @@ -103,6 +104,7 @@ function test_simple_breakpoint() })); }); + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 " this.a = 1;\n" + // line0 + 2 <-- Breakpoint is set here. @@ -112,4 +114,5 @@ function test_simple_breakpoint() "debugger;\n" + // line0 + 6 "var b = 2;\n", // line0 + 7 gDebuggee); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-14.js b/devtools/server/tests/unit/test_breakpoint-14.js index aa86975b66d6..3846e5778c52 100644 --- a/devtools/server/tests/unit/test_breakpoint-14.js +++ b/devtools/server/tests/unit/test_breakpoint-14.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Check that a breakpoint or a debugger statement cause execution to pause even @@ -11,78 +14,76 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_breakpoint(); + }); }); } -function test_simple_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_simple_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 2 }; - source.setBreakpoint(location, Task.async(function* (aResponse, bpClient) { + source.setBreakpoint(location, Task.async(function* (response, bpClient) { const testCallbacks = [ - function (aPacket) { + function (packet) { // Check that the stepping worked. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // Reached the breakpoint. - do_check_eq(aPacket.frame.where.line, location.line); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_neq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, location.line); + do_check_eq(packet.why.type, "breakpoint"); + do_check_neq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // Stepped to the closing brace of the function. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // The frame is about to be popped while stepping. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_neq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.why.frameFinished.return.type, "undefined"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_neq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.why.frameFinished.return.type, "undefined"); }, - function (aPacket) { + function (packet) { // The foo function call frame was just popped from the stack. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.poppedFrames.length, 1); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.poppedFrames.length, 1); }, - function (aPacket) { + function (packet) { // Check that the debugger statement wasn't the reason for this pause. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6); - do_check_neq(aPacket.why.type, "debuggerStatement"); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 6); + do_check_neq(packet.why.type, "debuggerStatement"); + do_check_eq(packet.why.type, "resumeLimit"); }, - function (aPacket) { + function (packet) { // Check that the debugger statement wasn't the reason for this pause. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 7); - do_check_neq(aPacket.why.type, "debuggerStatement"); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 7); + do_check_neq(packet.why.type, "debuggerStatement"); + do_check_eq(packet.why.type, "resumeLimit"); }, ]; @@ -101,6 +102,7 @@ function test_simple_breakpoint() })); }); + /* eslint-disable */ Cu.evalInSandbox("var line0 = Error().lineNumber;\n" + "function foo() {\n" + // line0 + 1 " this.a = 1;\n" + // line0 + 2 <-- Breakpoint is set here. @@ -110,4 +112,5 @@ function test_simple_breakpoint() "debugger;\n" + // line0 + 6 "var b = 2;\n", // line0 + 7 gDebuggee); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-15.js b/devtools/server/tests/unit/test_breakpoint-15.js index 6a3ab7c6f556..57b2d101007b 100644 --- a/devtools/server/tests/unit/test_breakpoint-15.js +++ b/devtools/server/tests/unit/test_breakpoint-15.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that adding a breakpoint in the same place returns the same actor. */ @@ -9,16 +11,16 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - testSameBreakpoint(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + testSameBreakpoint(); + }); }); do_test_pending(); } @@ -34,10 +36,11 @@ const testSameBreakpoint = Task.async(function* () { line: 2 }; - let [firstResponse, firstBpClient] = yield setBreakpoint(source, wholeLineLocation); - let [secondResponse, secondBpClient] = yield setBreakpoint(source, wholeLineLocation); + let [, firstBpClient] = yield setBreakpoint(source, wholeLineLocation); + let [, secondBpClient] = yield setBreakpoint(source, wholeLineLocation); - do_check_eq(firstBpClient.actor, secondBpClient.actor, "Should get the same actor w/ whole line breakpoints"); + do_check_eq(firstBpClient.actor, secondBpClient.actor, + "Should get the same actor w/ whole line breakpoints"); // Specific column @@ -46,15 +49,17 @@ const testSameBreakpoint = Task.async(function* () { column: 6 }; - [firstResponse, firstBpClient] = yield setBreakpoint(source, columnLocation); - [secondResponse, secondBpClient] = yield setBreakpoint(source, columnLocation); + [, firstBpClient] = yield setBreakpoint(source, columnLocation); + [, secondBpClient] = yield setBreakpoint(source, columnLocation); - do_check_eq(secondBpClient.actor, secondBpClient.actor, "Should get the same actor column breakpoints"); + do_check_eq(secondBpClient.actor, secondBpClient.actor, + "Should get the same actor column breakpoints"); finishClient(gClient); }); function evalCode() { + /* eslint-disable */ Components.utils.evalInSandbox( "" + function doStuff(k) { // line 1 let arg = 15; // line 2 - Step in here @@ -66,4 +71,5 @@ function evalCode() { SOURCE_URL, 1 ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-16.js b/devtools/server/tests/unit/test_breakpoint-16.js index 43a9086ecad1..27befc8468d7 100644 --- a/devtools/server/tests/unit/test_breakpoint-16.js +++ b/devtools/server/tests/unit/test_breakpoint-16.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that we can set breakpoints in columns, not just lines. @@ -10,57 +13,54 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-breakpoints", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-breakpoints", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume(gClient, "test-breakpoints", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; test_column_breakpoint(); }); }); } -function test_column_breakpoint() -{ +function test_column_breakpoint() { // Debugger statement - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); + gClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); let location = { line: gDebuggee.line0 + 1, column: 55 }; let timesBreakpointHit = 0; - source.setBreakpoint(location, function (aResponse, bpClient) { - gThreadClient.addListener("paused", function onPaused(aEvent, aPacket) { - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.why.actors[0], bpClient.actor); - do_check_eq(aPacket.frame.where.source.actor, source.actor); - do_check_eq(aPacket.frame.where.line, location.line); - do_check_eq(aPacket.frame.where.column, location.column); + source.setBreakpoint(location, function (response, bpClient) { + gThreadClient.addListener("paused", function onPaused(event, packet) { + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.why.actors[0], bpClient.actor); + do_check_eq(packet.frame.where.source.actor, source.actor); + do_check_eq(packet.frame.where.line, location.line); + do_check_eq(packet.frame.where.column, location.column); do_check_eq(gDebuggee.acc, timesBreakpointHit); - do_check_eq(aPacket.frame.environment.bindings.variables.i.value, + do_check_eq(packet.frame.environment.bindings.variables.i.value, timesBreakpointHit); if (++timesBreakpointHit === 3) { gThreadClient.removeListener("paused", onPaused); - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(() => gClient.close().then(gCallback)); }); } else { @@ -71,13 +71,13 @@ function test_column_breakpoint() // Continue until the breakpoint is hit. gThreadClient.resume(); }); - }); - + /* eslint-disable */ Components.utils.evalInSandbox( "var line0 = Error().lineNumber;\n" + "(function () { debugger; this.acc = 0; for (var i = 0; i < 3; i++) this.acc++; }());", gDebuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_breakpoint-17.js b/devtools/server/tests/unit/test_breakpoint-17.js index 944627e619bc..d5f99a5aed36 100644 --- a/devtools/server/tests/unit/test_breakpoint-17.js +++ b/devtools/server/tests/unit/test_breakpoint-17.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that when we add 2 breakpoints to the same line at different columns and @@ -11,23 +14,22 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, do_test_finished); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-breakpoints", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-breakpoints", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-breakpoints", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_breakpoints_columns(); - }); + attachTestTabAndResume(gClient, "test-breakpoints", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_breakpoints_columns(); + }); }); } @@ -56,44 +58,44 @@ function test_breakpoints_columns() { Components.utils.evalInSandbox(code, gDebuggee, "1.8", "http://example.com/", 1); } -function set_breakpoints(aEvent, aPacket) { +function set_breakpoints(event, packet) { let first, second; - let source = gThreadClient.source(aPacket.frame.where.source); + let source = gThreadClient.source(packet.frame.where.source); source.setBreakpoint(firstLocation, function ({ error, actualLocation }, - aBreakpointClient) { + breakpointClient) { do_check_true(!error, "Should not get an error setting the breakpoint"); do_check_true(!actualLocation, "Should not get an actualLocation"); - first = aBreakpointClient; + first = breakpointClient; source.setBreakpoint(secondLocation, function ({ error, actualLocation }, - aBreakpointClient) { + breakpointClient) { do_check_true(!error, "Should not get an error setting the breakpoint"); do_check_true(!actualLocation, "Should not get an actualLocation"); - second = aBreakpointClient; + second = breakpointClient; test_different_actors(first, second); }); }); } -function test_different_actors(aFirst, aSecond) { - do_check_neq(aFirst.actor, aSecond.actor, +function test_different_actors(first, second) { + do_check_neq(first.actor, second.actor, "Each breakpoint should have a different actor"); - test_remove_one(aFirst, aSecond); + test_remove_one(first, second); } -function test_remove_one(aFirst, aSecond) { - aFirst.remove(function ({error}) { +function test_remove_one(first, second) { + first.remove(function ({error}) { do_check_true(!error, "Should not get an error removing a breakpoint"); let hitSecond; - gClient.addListener("paused", function _onPaused(aEvent, {why, frame}) { + gClient.addListener("paused", function _onPaused(event, {why, frame}) { if (why.type == "breakpoint") { hitSecond = true; do_check_eq(why.actors.length, 1, "Should only be paused because of one breakpoint actor"); - do_check_eq(why.actors[0], aSecond.actor, + do_check_eq(why.actors[0], second.actor, "Should be paused because of the correct breakpoint actor"); do_check_eq(frame.where.line, secondLocation.line, "Should be at the right line"); diff --git a/devtools/server/tests/unit/test_breakpoint-18.js b/devtools/server/tests/unit/test_breakpoint-18.js index d153d3eff8f0..1be1676b345b 100644 --- a/devtools/server/tests/unit/test_breakpoint-18.js +++ b/devtools/server/tests/unit/test_breakpoint-18.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that we only break on offsets that are entry points for the line we are * breaking on. Bug 907278. @@ -11,26 +13,24 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-breakpoints", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-breakpoints", server); gDebuggee.console = { log: x => void x }; - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume(gClient, "test-breakpoints", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; setUpCode(); }); }); @@ -51,8 +51,8 @@ function setUpCode() { ); } -function setBreakpoint(aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function setBreakpoint(event, packet) { + let source = gThreadClient.source(packet.frame.where.source); gClient.addOneTimeListener("resumed", runCode); source.setBreakpoint({ line: 2 }, ({ error }) => { diff --git a/devtools/server/tests/unit/test_breakpoint-19.js b/devtools/server/tests/unit/test_breakpoint-19.js index da04a52681dc..4de09807bff5 100644 --- a/devtools/server/tests/unit/test_breakpoint-19.js +++ b/devtools/server/tests/unit/test_breakpoint-19.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Make sure that setting a breakpoint in a not-yet-existing script doesn't throw * an error (see bug 897567). Also make sure that this breakpoint works. @@ -9,28 +11,24 @@ var gDebuggee; var gClient; var gThreadClient; -var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-breakpoints", aServer); +function run_test_with_server(server, callback) { + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-breakpoints", server); gDebuggee.console = { log: x => void x }; - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume(gClient, "test-breakpoints", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; testBreakpoint(); }); }); @@ -39,6 +37,7 @@ function run_test_with_server(aServer, aCallback) const URL = "test.js"; function setUpCode() { + /* eslint-disable */ Cu.evalInSandbox( "" + function test() { // 1 var a = 1; // 2 @@ -49,11 +48,12 @@ function setUpCode() { "1.8", URL ); + /* eslint-enable */ } const testBreakpoint = Task.async(function* () { let source = yield getSource(gThreadClient, URL); - let [response, bpClient] = yield setBreakpoint(source, {line: 2}); + let [response, ] = yield setBreakpoint(source, {line: 2}); ok(!response.error); let actor = response.actor; diff --git a/devtools/server/tests/unit/test_breakpoint-20.js b/devtools/server/tests/unit/test_breakpoint-20.js index b70282dae45b..322fb204e6cb 100644 --- a/devtools/server/tests/unit/test_breakpoint-20.js +++ b/devtools/server/tests/unit/test_breakpoint-20.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Verify that when two of the "same" source are loaded concurrently (like e10s * frame scripts), breakpoints get hit in scripts defined by all sources. @@ -8,11 +10,8 @@ var gDebuggee; var gClient; -var gTraceClient; -var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-breakpoints"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); @@ -22,7 +21,8 @@ function run_test() do_test_pending(); } -const testBreakpoint = Task.async(function* (threadResponse, tabClient, threadClient, tabResponse) { +const testBreakpoint = Task.async(function* (threadResponse, tabClient, + threadClient, tabResponse) { evalSetupCode(); // Load the test source once. @@ -34,7 +34,7 @@ const testBreakpoint = Task.async(function* (threadResponse, tabClient, threadCl // Set a breakpoint in the test source. const source = yield getSource(threadClient, "test.js"); - const [response, bpClient] = yield setBreakpoint(source, { + const [response, ] = yield setBreakpoint(source, { line: 3 }); ok(!response.error, "Shouldn't get an error setting the BP."); diff --git a/devtools/server/tests/unit/test_breakpoint-21.js b/devtools/server/tests/unit/test_breakpoint-21.js index e5f2e9e4a9e5..e59f9f4e827b 100644 --- a/devtools/server/tests/unit/test_breakpoint-21.js +++ b/devtools/server/tests/unit/test_breakpoint-21.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Bug 1122064 - make sure that scripts introduced via onNewScripts * properly populate the `ScriptStore` with all there nested child @@ -10,27 +12,23 @@ var gDebuggee; var gClient; var gThreadClient; -var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-breakpoints", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-breakpoints", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume(gClient, "test-breakpoints", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; test(); }); }); @@ -62,6 +60,7 @@ const test = Task.async(function* () { finishClient(gClient); }); +/* eslint-disable */ function evalCode() { // Start a new script Components.utils.evalInSandbox( diff --git a/devtools/server/tests/unit/test_breakpoint-22.js b/devtools/server/tests/unit/test_breakpoint-22.js index 75fe8aa5a20a..f167a4a62276 100644 --- a/devtools/server/tests/unit/test_breakpoint-22.js +++ b/devtools/server/tests/unit/test_breakpoint-22.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Bug 1333219 - make that setBreakpoint fails when script is not found * at the specified line. @@ -9,27 +11,23 @@ var gDebuggee; var gClient; var gThreadClient; -var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-breakpoints", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-breakpoints", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume(gClient, "test-breakpoints", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; test(); }); }); @@ -46,7 +44,7 @@ const test = Task.async(function* () { line: gDebuggee.line0 + 2 }; - let [res, bpClient] = yield setBreakpoint(source, location); + let [res, ] = yield setBreakpoint(source, location); ok(!res.error); let location2 = { diff --git a/devtools/server/tests/unit/test_breakpoint-actor-map.js b/devtools/server/tests/unit/test_breakpoint-actor-map.js index d1d149648a23..2c37c9bcc404 100644 --- a/devtools/server/tests/unit/test_breakpoint-actor-map.js +++ b/devtools/server/tests/unit/test_breakpoint-actor-map.js @@ -128,7 +128,9 @@ function test_find_actors() { // Breakpoints by URL - bpSet = new Set(bps.filter(bp => { return bp.originalSourceActor.actorID === "actor1"; })); + bpSet = new Set(bps.filter(bp => { + return bp.originalSourceActor.actorID === "actor1"; + })); for (let bp of bpStore.findActors({ originalSourceActor: { actorID: "actor1" } })) { bpSet.delete(bp); } @@ -137,9 +139,12 @@ function test_find_actors() { // Breakpoints by URL and line - bpSet = new Set(bps.filter(bp => { return bp.originalSourceActor.actorID === "actor1" && bp.originalLine === 10; })); + bpSet = new Set(bps.filter(bp => { + return bp.originalSourceActor.actorID === "actor1" && bp.originalLine === 10; + })); let first = true; - for (let bp of bpStore.findActors({ originalSourceActor: { actorID: "actor1" }, originalLine: 10 })) { + for (let bp of bpStore.findActors({ originalSourceActor: { actorID: "actor1" }, + originalLine: 10 })) { if (first) { do_check_eq(bp.originalColumn, undefined, "Should always get the whole line breakpoint first"); diff --git a/devtools/server/tests/unit/test_client_close.js b/devtools/server/tests/unit/test_client_close.js index 84747e85b8b5..6a6298ec9d3f 100644 --- a/devtools/server/tests/unit/test_client_close.js +++ b/devtools/server/tests/unit/test_client_close.js @@ -1,27 +1,27 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gClient; var gDebuggee; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = testGlobal("test-1"); DebuggerServer.addTestGlobal(gDebuggee); let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); - gClient.connect().then(function (aType, aTraits) { - attachTestTab(gClient, "test-1", function (aReply, aTabClient) { + gClient.connect().then(function (type, traits) { + attachTestTab(gClient, "test-1", function (reply, tabClient) { test_close(transport); }); }); do_test_pending(); } -function test_close(aTransport) -{ +function test_close(transport) { // Check that, if we fake a transport shutdown // (like if a device is unplugged) // the client is automatically closed, @@ -35,5 +35,5 @@ function test_close(aTransport) }); }; gClient.addListener("closed", onClosed); - aTransport.close(); + transport.close(); } diff --git a/devtools/server/tests/unit/test_client_request.js b/devtools/server/tests/unit/test_client_request.js index c0c2c3a92e29..d01be89cac91 100644 --- a/devtools/server/tests/unit/test_client_request.js +++ b/devtools/server/tests/unit/test_client_request.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test the DebuggerClient.request API. var gClient, gActorId; @@ -24,8 +26,7 @@ TestActor.prototype.requestTypes = { "error": TestActor.prototype.error }; -function run_test() -{ +function run_test() { DebuggerServer.addGlobalActor(TestActor); DebuggerServer.init(); @@ -42,13 +43,12 @@ function run_test() run_next_test(); } -function init() -{ +function init() { gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect() .then(() => gClient.listTabs()) - .then(aResponse => { - gActorId = aResponse.test; + .then(response => { + gActorId = response.test; run_next_test(); }); } @@ -72,8 +72,7 @@ function checkStack(expectedName) { ok(false, "Incomplete stack"); } -function test_client_request_callback() -{ +function test_client_request_callback() { // Test that DebuggerClient.request accepts a `onResponse` callback as 2nd argument gClient.request({ to: gActorId, @@ -86,8 +85,7 @@ function test_client_request_callback() }); } -function test_client_request_promise() -{ +function test_client_request_promise() { // Test that DebuggerClient.request returns a promise that resolves on response let request = gClient.request({ to: gActorId, @@ -102,8 +100,7 @@ function test_client_request_promise() }); } -function test_client_request_promise_error() -{ +function test_client_request_promise_error() { // Test that DebuggerClient.request returns a promise that reject when server // returns an explicit error message let request = gClient.request({ @@ -122,8 +119,7 @@ function test_client_request_promise_error() }); } -function test_client_request_event_emitter() -{ +function test_client_request_event_emitter() { // Test that DebuggerClient.request returns also an EventEmitter object let request = gClient.request({ to: gActorId, @@ -156,7 +152,8 @@ function test_close_client_while_sending_requests() { let expectReply = promise.defer(); gClient.expectReply("root", function (response) { do_check_eq(response.error, "connectionClosed"); - do_check_eq(response.message, "server side packet can't be received as the connection just closed."); + do_check_eq(response.message, + "server side packet can't be received as the connection just closed."); expectReply.resolve(); }); @@ -165,22 +162,23 @@ function test_close_client_while_sending_requests() { ok(false, "First request unexpectedly succeed while closing the connection"); }, response => { do_check_eq(response.error, "connectionClosed"); - do_check_eq(response.message, "'hello' active request packet to '" + gActorId + "' can't be sent as the connection just closed."); + do_check_eq(response.message, "'hello' active request packet to '" + + gActorId + "' can't be sent as the connection just closed."); }) .then(() => pendingRequest) .then(() => { ok(false, "Second request unexpectedly succeed while closing the connection"); }, response => { do_check_eq(response.error, "connectionClosed"); - do_check_eq(response.message, "'hello' pending request packet to '" + gActorId + "' can't be sent as the connection just closed."); + do_check_eq(response.message, "'hello' pending request packet to '" + + gActorId + "' can't be sent as the connection just closed."); }) .then(() => expectReply.promise) .then(run_next_test); }); } -function test_client_request_after_close() -{ +function test_client_request_after_close() { // Test that DebuggerClient.request fails after we called client.close() // (with promise API) let request = gClient.request({ @@ -193,22 +191,23 @@ function test_client_request_after_close() }, response => { ok(true, "Request failed after client.close"); do_check_eq(response.error, "connectionClosed"); - ok(response.message.match(/'hello' request packet to '.*' can't be sent as the connection is closed./)); + ok(response.message.match( + /'hello' request packet to '.*' can't be sent as the connection is closed./)); run_next_test(); }); } -function test_client_request_after_close_callback() -{ +function test_client_request_after_close_callback() { // Test that DebuggerClient.request fails after we called client.close() // (with callback API) - let request = gClient.request({ + gClient.request({ to: gActorId, type: "hello" }, response => { ok(true, "Request failed after client.close"); do_check_eq(response.error, "connectionClosed"); - ok(response.message.match(/'hello' request packet to '.*' can't be sent as the connection is closed./)); + ok(response.message.match( + /'hello' request packet to '.*' can't be sent as the connection is closed./)); run_next_test(); }); } diff --git a/devtools/server/tests/unit/test_conditional_breakpoint-01.js b/devtools/server/tests/unit/test_conditional_breakpoint-01.js index 4661bb0c4c2a..7df85e2a7ff6 100644 --- a/devtools/server/tests/unit/test_conditional_breakpoint-01.js +++ b/devtools/server/tests/unit/test_conditional_breakpoint-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check conditional breakpoint when condition evaluates to true. @@ -9,48 +12,45 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-conditional-breakpoint"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-conditional-breakpoint", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_breakpoint(); + }); }); do_test_pending(); } -function test_simple_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_simple_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); source.setBreakpoint({ line: 3, condition: "a === 1" - }, function (aResponse, bpClient) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + }, function (response, bpClient) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.why.type, "breakpoint"); - do_check_eq(aPacket.frame.where.line, 3); + do_check_eq(packet.why.type, "breakpoint"); + do_check_eq(packet.frame.where.line, 3); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { finishClient(gClient); }); }); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); - }); - }); + /* eslint-disable */ Components.utils.evalInSandbox("debugger;\n" + // 1 "var a = 1;\n" + // 2 "var b = 2;\n", // 3 @@ -58,4 +58,5 @@ function test_simple_breakpoint() "1.8", "test.js", 1); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_conditional_breakpoint-02.js b/devtools/server/tests/unit/test_conditional_breakpoint-02.js index 873f761599ba..84c58a836a67 100644 --- a/devtools/server/tests/unit/test_conditional_breakpoint-02.js +++ b/devtools/server/tests/unit/test_conditional_breakpoint-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check conditional breakpoint when condition evaluates to false. @@ -9,46 +12,45 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-conditional-breakpoint"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-conditional-breakpoint", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_breakpoint(); + }); }); do_test_pending(); } -function test_simple_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_simple_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); source.setBreakpoint({ line: 3, condition: "a === 2" - }, function (aResponse, bpClient) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + }, function (response, bpClient) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.why.type, "debuggerStatement"); - do_check_eq(aPacket.frame.where.line, 4); + do_check_eq(packet.why.type, "debuggerStatement"); + do_check_eq(packet.frame.where.line, 4); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { finishClient(gClient); }); }); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); }); }); + /* eslint-disable */ Components.utils.evalInSandbox("debugger;\n" + // 1 "var a = 1;\n" + // 2 "var b = 2;\n" + // 3 @@ -57,4 +59,5 @@ function test_simple_breakpoint() "1.8", "test.js", 1); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_conditional_breakpoint-03.js b/devtools/server/tests/unit/test_conditional_breakpoint-03.js index d9cf13e005da..a0d8ea868902 100644 --- a/devtools/server/tests/unit/test_conditional_breakpoint-03.js +++ b/devtools/server/tests/unit/test_conditional_breakpoint-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check conditional breakpoint when condition throws and make sure it pauses @@ -9,48 +12,45 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-conditional-breakpoint"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-conditional-breakpoint", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_breakpoint(); - }); + attachTestTabAndResume(gClient, "test-conditional-breakpoint", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_breakpoint(); + }); }); do_test_pending(); } -function test_simple_breakpoint() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let source = gThreadClient.source(aPacket.frame.where.source); +function test_simple_breakpoint() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let source = gThreadClient.source(packet.frame.where.source); source.setBreakpoint({ line: 3, condition: "throw new Error()" - }, function (aResponse, bpClient) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + }, function (response, bpClient) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.why.type, "breakpointConditionThrown"); - do_check_eq(aPacket.frame.where.line, 3); + do_check_eq(packet.why.type, "breakpointConditionThrown"); + do_check_eq(packet.frame.where.line, 3); // Remove the breakpoint. - bpClient.remove(function (aResponse) { + bpClient.remove(function (response) { gThreadClient.resume(function () { finishClient(gClient); }); }); - }); // Continue until the breakpoint is hit. gThreadClient.resume(); - }); - }); + /* eslint-disable */ Components.utils.evalInSandbox("debugger;\n" + // 1 "var a = 1;\n" + // 2 "var b = 2;\n", // 3 @@ -58,4 +58,5 @@ function test_simple_breakpoint() "1.8", "test.js", 1); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_dbgactor.js b/devtools/server/tests/unit/test_dbgactor.js index b22b8446ba48..77fa20883159 100644 --- a/devtools/server/tests/unit/test_dbgactor.js +++ b/devtools/server/tests/unit/test_dbgactor.js @@ -1,29 +1,31 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gClient; var gDebuggee; const xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = testGlobal("test-1"); DebuggerServer.addTestGlobal(gDebuggee); let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); - gClient.addListener("connected", function (aEvent, aType, aTraits) { - gClient.listTabs((aResponse) => { - do_check_true("tabs" in aResponse); - for (let tab of aResponse.tabs) { + gClient.addListener("connected", function (event, type, traits) { + gClient.listTabs((response) => { + do_check_true("tabs" in response); + for (let tab of response.tabs) { if (tab.title == "test-1") { test_attach_tab(tab.actor); return false; } } - do_check_true(false); // We should have found our tab in the list. + // We should have found our tab in the list. + do_check_true(false); return undefined; }); }); @@ -33,42 +35,39 @@ function run_test() do_test_pending(); } -// Attach to |aTabActor|, and check the response. -function test_attach_tab(aTabActor) -{ - gClient.request({ to: aTabActor, type: "attach" }, function (aResponse) { - do_check_false("error" in aResponse); - do_check_eq(aResponse.from, aTabActor); - do_check_eq(aResponse.type, "tabAttached"); - do_check_true(typeof aResponse.threadActor === "string"); +// Attach to |tabActor|, and check the response. +function test_attach_tab(tabActor) { + gClient.request({ to: tabActor, type: "attach" }, function (response) { + do_check_false("error" in response); + do_check_eq(response.from, tabActor); + do_check_eq(response.type, "tabAttached"); + do_check_true(typeof response.threadActor === "string"); - test_attach_thread(aResponse.threadActor); + test_attach_thread(response.threadActor); }); } -// Attach to |aThreadActor|, check the response, and resume it. -function test_attach_thread(aThreadActor) -{ - gClient.request({ to: aThreadActor, type: "attach" }, function (aResponse) { - do_check_false("error" in aResponse); - do_check_eq(aResponse.from, aThreadActor); - do_check_eq(aResponse.type, "paused"); - do_check_true("why" in aResponse); - do_check_eq(aResponse.why.type, "attached"); +// Attach to |threadActor|, check the response, and resume it. +function test_attach_thread(threadActor) { + gClient.request({ to: threadActor, type: "attach" }, function (response) { + do_check_false("error" in response); + do_check_eq(response.from, threadActor); + do_check_eq(response.type, "paused"); + do_check_true("why" in response); + do_check_eq(response.why.type, "attached"); - test_resume_thread(aThreadActor); + test_resume_thread(threadActor); }); } -// Resume |aThreadActor|, and see that it stops at the 'debugger' +// Resume |threadActor|, and see that it stops at the 'debugger' // statement. -function test_resume_thread(aThreadActor) -{ +function test_resume_thread(threadActor) { // Allow the client to resume execution. - gClient.request({ to: aThreadActor, type: "resume" }, function (aResponse) { - do_check_false("error" in aResponse); - do_check_eq(aResponse.from, aThreadActor); - do_check_eq(aResponse.type, "resumed"); + gClient.request({ to: threadActor, type: "resume" }, function (response) { + do_check_false("error" in response); + do_check_eq(response.from, threadActor); + do_check_eq(response.type, "resumed"); do_check_eq(xpcInspector.eventLoopNestLevel, 0); @@ -78,14 +77,14 @@ function test_resume_thread(aThreadActor) do_check_true(gDebuggee.b); }); - gClient.addListener("paused", function (aName, aPacket) { - do_check_eq(aName, "paused"); - do_check_false("error" in aPacket); - do_check_eq(aPacket.from, aThreadActor); - do_check_eq(aPacket.type, "paused"); - do_check_true("actor" in aPacket); - do_check_true("why" in aPacket); - do_check_eq(aPacket.why.type, "debuggerStatement"); + gClient.addListener("paused", function (name, packet) { + do_check_eq(name, "paused"); + do_check_false("error" in packet); + do_check_eq(packet.from, threadActor); + do_check_eq(packet.type, "paused"); + do_check_true("actor" in packet); + do_check_true("why" in packet); + do_check_eq(packet.why.type, "debuggerStatement"); // Reach around the protocol to check that the debuggee is in the state // we expect. @@ -95,19 +94,18 @@ function test_resume_thread(aThreadActor) do_check_eq(xpcInspector.eventLoopNestLevel, 1); // Let the debuggee continue execution. - gClient.request({ to: aThreadActor, type: "resume" }, cleanup); + gClient.request({ to: threadActor, type: "resume" }, cleanup); }); } -function cleanup() -{ - gClient.addListener("closed", function (aEvent, aResult) { +function cleanup() { + gClient.addListener("closed", function (event, result) { do_test_finished(); }); try { - let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector); - do_check_eq(xpcInspector.eventLoopNestLevel, 0); + let inspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector); + do_check_eq(inspector.eventLoopNestLevel, 0); } catch (e) { dump(e); } diff --git a/devtools/server/tests/unit/test_dbgclient_debuggerstatement.js b/devtools/server/tests/unit/test_dbgclient_debuggerstatement.js index 40468cb1df49..e3e745031100 100644 --- a/devtools/server/tests/unit/test_dbgclient_debuggerstatement.js +++ b/devtools/server/tests/unit/test_dbgclient_debuggerstatement.js @@ -1,44 +1,43 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gClient; var gTabClient; var gDebuggee; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = testGlobal("test-1"); DebuggerServer.addTestGlobal(gDebuggee); let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); - gClient.connect().then(function ([aType, aTraits]) { - attachTestTab(gClient, "test-1", function (aReply, aTabClient) { - gTabClient = aTabClient; - test_threadAttach(aReply.threadActor); + gClient.connect().then(function ([type, traits]) { + attachTestTab(gClient, "test-1", function (reply, tabClient) { + gTabClient = tabClient; + test_threadAttach(reply.threadActor); }); }); do_test_pending(); } -function test_threadAttach(aThreadActorID) -{ - do_print("Trying to attach to thread " + aThreadActorID); - gTabClient.attachThread({}, function (aResponse, aThreadClient) { - do_check_eq(aThreadClient.state, "paused"); - do_check_eq(aThreadClient.actor, aThreadActorID); - aThreadClient.resume(function () { - do_check_eq(aThreadClient.state, "attached"); - test_debugger_statement(aThreadClient); +function test_threadAttach(threadActorID) { + do_print("Trying to attach to thread " + threadActorID); + gTabClient.attachThread({}, function (response, threadClient) { + do_check_eq(threadClient.state, "paused"); + do_check_eq(threadClient.actor, threadActorID); + threadClient.resume(function () { + do_check_eq(threadClient.state, "attached"); + test_debugger_statement(threadClient); }); }); } -function test_debugger_statement(aThreadClient) -{ - aThreadClient.addListener("paused", function (aEvent, aPacket) { - do_check_eq(aThreadClient.state, "paused"); +function test_debugger_statement(threadClient) { + threadClient.addListener("paused", function (event, packet) { + do_check_eq(threadClient.state, "paused"); // Reach around the protocol to check that the debuggee is in the state // we expect. do_check_true(gDebuggee.a); @@ -47,7 +46,7 @@ function test_debugger_statement(aThreadClient) let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector); do_check_eq(xpcInspector.eventLoopNestLevel, 1); - aThreadClient.resume(cleanup); + threadClient.resume(cleanup); }); Cu.evalInSandbox("var a = true; var b = false; debugger; var b = true;", gDebuggee); @@ -56,9 +55,8 @@ function test_debugger_statement(aThreadClient) do_check_true(gDebuggee.b); } -function cleanup() -{ - gClient.addListener("closed", function (aEvent) { +function cleanup() { + gClient.addListener("closed", function (event) { do_test_finished(); }); diff --git a/devtools/server/tests/unit/test_dbgglobal.js b/devtools/server/tests/unit/test_dbgglobal.js index 09489b9e20b4..d98a09d8c9d0 100644 --- a/devtools/server/tests/unit/test_dbgglobal.js +++ b/devtools/server/tests/unit/test_dbgglobal.js @@ -1,8 +1,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -function run_test() -{ +"use strict"; + +function run_test() { // Should get an exception if we try to interact with DebuggerServer // before we initialize it... check_except(function () { @@ -28,28 +29,28 @@ function run_test() // Make sure we got the test's root actor all set up. let client1 = DebuggerServer.connectPipe(); client1.hooks = { - onPacket: function (aPacket1) { - do_check_eq(aPacket1.from, "root"); - do_check_eq(aPacket1.applicationType, "xpcshell-tests"); + onPacket: function (packet1) { + do_check_eq(packet1.from, "root"); + do_check_eq(packet1.applicationType, "xpcshell-tests"); // Spin up a second connection, make sure it has its own root // actor. let client2 = DebuggerServer.connectPipe(); client2.hooks = { - onPacket: function (aPacket2) { - do_check_eq(aPacket2.from, "root"); - do_check_neq(aPacket1.testConnectionPrefix, - aPacket2.testConnectionPrefix); + onPacket: function (packet2) { + do_check_eq(packet2.from, "root"); + do_check_neq(packet1.testConnectionPrefix, + packet2.testConnectionPrefix); client2.close(); }, - onClosed: function (aResult) { + onClosed: function (result) { client1.close(); }, }; client2.ready(); }, - onClosed: function (aResult) { + onClosed: function (result) { do_test_finished(); }, }; diff --git a/devtools/server/tests/unit/test_eval-01.js b/devtools/server/tests/unit/test_eval-01.js index b11903f8719f..4e0c0668f152 100644 --- a/devtools/server/tests/unit/test_eval-01.js +++ b/devtools/server/tests/unit/test_eval-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check basic eval resume/re-pause @@ -9,50 +12,48 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_eval(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_eval(); + }); }); do_test_pending(); } -function test_simple_eval() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let arg1Actor = aPacket.frame.arguments[0].actor; - gThreadClient.eval(null, "({ obj: true })", function (aResponse) { - do_check_eq(aResponse.type, "resumed"); +function test_simple_eval() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let arg1Actor = packet.frame.arguments[0].actor; + gThreadClient.eval(null, "({ obj: true })", function (response) { + do_check_eq(response.type, "resumed"); // Expect a pause notification immediately. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value... - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "clientEvaluated"); - do_check_eq(aPacket.why.frameFinished.return.type, "object"); - do_check_eq(aPacket.why.frameFinished.return.class, "Object"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "clientEvaluated"); + do_check_eq(packet.why.frameFinished.return.type, "object"); + do_check_eq(packet.why.frameFinished.return.class, "Object"); // Make sure the previous pause lifetime was correctly dropped. - gClient.request({ to: arg1Actor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); + gClient.request({ to: arg1Actor, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "noSuchActor"); gThreadClient.resume(function () { finishClient(gClient); }); }); - }); - }); - }); + /* eslint-disable */ gDebuggee.eval("(" + function () { function stopMe(arg1) { debugger; } stopMe({obj: true}); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_eval-02.js b/devtools/server/tests/unit/test_eval-02.js index 386ea5c98944..b86499e3c59b 100644 --- a/devtools/server/tests/unit/test_eval-02.js +++ b/devtools/server/tests/unit/test_eval-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check eval resume/re-pause with a throw. @@ -9,31 +12,30 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_throw_eval(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_throw_eval(); + }); }); do_test_pending(); } -function test_throw_eval() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.eval(null, "throw 'failure'", function (aResponse) { - do_check_eq(aResponse.type, "resumed"); +function test_throw_eval() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.eval(null, "throw 'failure'", function (response) { + do_check_eq(response.type, "resumed"); // Expect a pause notification immediately. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value... - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "clientEvaluated"); - do_check_eq(aPacket.why.frameFinished.throw, "failure"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "clientEvaluated"); + do_check_eq(packet.why.frameFinished.throw, "failure"); gThreadClient.resume(function () { finishClient(gClient); }); @@ -41,8 +43,10 @@ function test_throw_eval() }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { function stopMe(arg1) { debugger; } stopMe({obj: true}); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_eval-03.js b/devtools/server/tests/unit/test_eval-03.js index 2234259aabc1..f75b0f538d21 100644 --- a/devtools/server/tests/unit/test_eval-03.js +++ b/devtools/server/tests/unit/test_eval-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check syntax errors in an eval. @@ -9,32 +12,31 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_syntax_error_eval(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_syntax_error_eval(); + }); }); do_test_pending(); } -function test_syntax_error_eval() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.eval(null, "%$@!@#", function (aResponse) { - do_check_eq(aResponse.type, "resumed"); +function test_syntax_error_eval() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.eval(null, "%$@!@#", function (response) { + do_check_eq(response.type, "resumed"); // Expect a pause notification immediately. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value... - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "clientEvaluated"); - do_check_eq(aPacket.why.frameFinished.throw.type, "object"); - do_check_eq(aPacket.why.frameFinished.throw.class, "Error"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "clientEvaluated"); + do_check_eq(packet.why.frameFinished.throw.type, "object"); + do_check_eq(packet.why.frameFinished.throw.class, "Error"); gThreadClient.resume(function () { finishClient(gClient); @@ -43,8 +45,10 @@ function test_syntax_error_eval() }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { function stopMe(arg1) { debugger; } stopMe({obj: true}); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_eval-04.js b/devtools/server/tests/unit/test_eval-04.js index 77cb58d97b9f..2fdf1dc33976 100644 --- a/devtools/server/tests/unit/test_eval-04.js +++ b/devtools/server/tests/unit/test_eval-04.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check evals against different frames. @@ -9,43 +12,41 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_syntax_error_eval(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_different_frames_eval(); + }); }); do_test_pending(); } -function test_syntax_error_eval() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - - gThreadClient.getFrames(0, 2, function (aResponse) { - let frame0 = aResponse.frames[0]; - let frame1 = aResponse.frames[1]; +function test_different_frames_eval() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getFrames(0, 2, function (response) { + let frame0 = response.frames[0]; + let frame1 = response.frames[1]; // Eval against the top frame... - gThreadClient.eval(frame0.actor, "arg", function (aResponse) { - do_check_eq(aResponse.type, "resumed"); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.eval(frame0.actor, "arg", function (response) { + do_check_eq(response.type, "resumed"); + gThreadClient.addOneTimeListener("paused", function (event, packet) { // 'arg' should have been evaluated in frame0 - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.type, "clientEvaluated"); - do_check_eq(aPacket.why.frameFinished.return, "arg0"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.type, "clientEvaluated"); + do_check_eq(packet.why.frameFinished.return, "arg0"); // Now eval against the second frame. - gThreadClient.eval(frame1.actor, "arg", function (aResponse) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.eval(frame1.actor, "arg", function (response) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // 'arg' should have been evaluated in frame1 - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.why.frameFinished.return, "arg1"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.why.frameFinished.return, "arg1"); gThreadClient.resume(function () { finishClient(gClient); diff --git a/devtools/server/tests/unit/test_eval-05.js b/devtools/server/tests/unit/test_eval-05.js index b199e4afbec5..30b7731f82e5 100644 --- a/devtools/server/tests/unit/test_eval-05.js +++ b/devtools/server/tests/unit/test_eval-05.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check pauses within evals. @@ -9,34 +12,33 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_syntax_error_eval(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pauses_eval(); + }); }); do_test_pending(); } -function test_syntax_error_eval() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.eval(null, "debugger", function (aResponse) { +function test_pauses_eval() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.eval(null, "debugger", function (response) { // Expect a resume then a debuggerStatement pause. - do_check_eq(aResponse.type, "resumed"); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "debuggerStatement"); + do_check_eq(response.type, "resumed"); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "debuggerStatement"); // Resume from the debugger statement should immediately re-pause // with a clientEvaluated reason. - gThreadClient.resume(function (aPacket) { - do_check_eq(aPacket.type, "resumed"); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "clientEvaluated"); + gThreadClient.resume(function (packet) { + do_check_eq(packet.type, "resumed"); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "clientEvaluated"); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_eventlooplag_actor.js b/devtools/server/tests/unit/test_eventlooplag_actor.js index d2acdd8f8983..5a2fab215bc1 100644 --- a/devtools/server/tests/unit/test_eventlooplag_actor.js +++ b/devtools/server/tests/unit/test_eventlooplag_actor.js @@ -7,8 +7,7 @@ "use strict"; -function run_test() -{ +function run_test() { let {EventLoopLagFront} = require("devtools/shared/fronts/eventlooplag"); DebuggerServer.init(); @@ -18,7 +17,6 @@ function run_test() let threshold = 20; let interval = 10; - let front; let client = new DebuggerClient(DebuggerServer.connectPipe()); diff --git a/devtools/server/tests/unit/test_forwardingprefix.js b/devtools/server/tests/unit/test_forwardingprefix.js index 885a99db897d..d7d15c3f518d 100644 --- a/devtools/server/tests/unit/test_forwardingprefix.js +++ b/devtools/server/tests/unit/test_forwardingprefix.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /* Exercise prefix-based forwarding of packets to other transports. */ const { RootActor } = require("devtools/server/actors/root"); @@ -9,8 +11,7 @@ var gMainConnection, gMainTransport; var gSubconnection1, gSubconnection2; var gClient; -function run_test() -{ +function run_test() { DebuggerServer.init(); add_test(createMainConnection); @@ -31,28 +32,26 @@ function run_test() * (that is, packets sent on |transport| go to the new connection, and * |transport|'s hooks receive replies). * - * |aPrefix| is optional; if present, it's the prefix (minus the '/') for + * |prefix| is optional; if present, it's the prefix (minus the '/') for * actors in the new connection. */ -function newConnection(aPrefix) -{ - var conn; - DebuggerServer.createRootActor = function (aConn) { - conn = aConn; - return new RootActor(aConn, {}); +function newConnection(prefix) { + let conn; + DebuggerServer.createRootActor = function (connection) { + conn = connection; + return new RootActor(connection, {}); }; - var transport = DebuggerServer.connectPipe(aPrefix); + let transport = DebuggerServer.connectPipe(prefix); return { conn: conn, transport: transport }; } /* Create the main connection for these tests. */ -function createMainConnection() -{ +function createMainConnection() { ({ conn: gMainConnection, transport: gMainTransport } = newConnection()); gClient = new DebuggerClient(gMainTransport); - gClient.connect().then(([aType, aTraits]) => run_next_test()); + gClient.connect().then(([type, traits]) => run_next_test()); } /* @@ -63,13 +62,13 @@ function createMainConnection() * - prefix2/root * - prefix2/actor * - * Expect proper echos from those named in |aReachables|, and 'noSuchActor' + * Expect proper echos from those named in |reachables|, and 'noSuchActor' * errors from the others. When we've gotten all our replies (errors or - * otherwise), call |aCompleted|. + * otherwise), call |completed|. * - * To avoid deep stacks, we call aCompleted from the next tick. + * To avoid deep stacks, we call completed from the next tick. */ -function tryActors(aReachables, aCompleted) { +function tryActors(reachables, completed) { let count = 0; let outerActor; @@ -84,16 +83,22 @@ function tryActors(aReachables, aCompleted) { count++; - gClient.request({ to: actor, type: "echo", value: "tango"}, // phone home - (aResponse) => { - if (aReachables.has(actor)) - do_check_matches({ from: actor, to: actor, type: "echo", value: "tango" }, aResponse); - else - do_check_matches({ from: actor, error: "noSuchActor", message: "No such actor for ID: " + actor }, aResponse); + // phone home + gClient.request( + { to: actor, type: "echo", value: "tango"}, + (response) => { + if (reachables.has(actor)) { + do_check_matches({ from: actor, to: actor, + type: "echo", value: "tango" }, response); + } else { + do_check_matches({ from: actor, error: "noSuchActor", + message: "No such actor for ID: " + actor }, response); + } - if (--count == 0) - do_execute_soon(aCompleted, "tryActors callback " + aCompleted.name); - }); + if (--count == 0) { + do_execute_soon(completed, "tryActors callback " + completed.name); + } + }); } } @@ -102,56 +107,50 @@ function tryActors(aReachables, aCompleted) { * but sending messages to prefixed actor names, or anyone else, should get * an error. */ -function TestNoForwardingYet() -{ +function TestNoForwardingYet() { tryActors(new Set(["root"]), run_next_test); } /* * Create a new pipe connection which forwards its reply packets to * gMainConnection's client, and to which gMainConnection forwards packets - * directed to actors whose names begin with |aPrefix + '/'|, and. + * directed to actors whose names begin with |prefix + '/'|, and. * * Return an object { conn, transport }, as for newConnection. */ -function newSubconnection(aPrefix) -{ - let { conn, transport } = newConnection(aPrefix); +function newSubconnection(prefix) { + let { conn, transport } = newConnection(prefix); transport.hooks = { - onPacket: (aPacket) => gMainConnection.send(aPacket), + onPacket: (packet) => gMainConnection.send(packet), onClosed: () => {} }; - gMainConnection.setForwarding(aPrefix, transport); + gMainConnection.setForwarding(prefix, transport); return { conn: conn, transport: transport }; } /* Create a second root actor, to which we can forward things. */ -function createSubconnection1() -{ +function createSubconnection1() { let { conn, transport } = newSubconnection("prefix1"); gSubconnection1 = conn; transport.ready(); - gClient.expectReply("prefix1/root", (aReply) => run_next_test()); + gClient.expectReply("prefix1/root", (reply) => run_next_test()); } // Establish forwarding, but don't put any actors in that server. -function TestForwardPrefix1OnlyRoot() -{ +function TestForwardPrefix1OnlyRoot() { tryActors(new Set(["root", "prefix1/root"]), run_next_test); } /* Create a third root actor, to which we can forward things. */ -function createSubconnection2() -{ +function createSubconnection2() { let { conn, transport } = newSubconnection("prefix2"); gSubconnection2 = conn; transport.ready(); - gClient.expectReply("prefix2/root", (aReply) => run_next_test()); + gClient.expectReply("prefix2/root", (reply) => run_next_test()); } -function TestForwardPrefix12OnlyRoot() -{ +function TestForwardPrefix12OnlyRoot() { tryActors(new Set(["root", "prefix1/root", "prefix2/root"]), run_next_test); } @@ -161,36 +160,39 @@ function TestForwardPrefix12OnlyRoot() // the reply-sending code attaches the replying actor's name to the packet, // so simply matching the 'from' field in the reply ensures that we heard // from the right actor. -function EchoActor(aConnection) -{ - this.conn = aConnection; +function EchoActor(connection) { + this.conn = connection; } EchoActor.prototype.actorPrefix = "EchoActor"; -EchoActor.prototype.onEcho = function (aRequest) { +EchoActor.prototype.onEcho = function (request) { /* - * Request packets are frozen. Copy aRequest, so that + * Request packets are frozen. Copy request, so that * DebuggerServerConnection.onPacket can attach a 'from' property. */ - return JSON.parse(JSON.stringify(aRequest)); + return JSON.parse(JSON.stringify(request)); }; EchoActor.prototype.requestTypes = { "echo": EchoActor.prototype.onEcho }; -function TestForwardPrefix12WithActor1() -{ +function TestForwardPrefix12WithActor1() { let actor = new EchoActor(gSubconnection1); actor.actorID = "prefix1/actor"; gSubconnection1.addActor(actor); - tryActors(new Set(["root", "prefix1/root", "prefix1/actor", "prefix2/root"]), run_next_test); + tryActors( + new Set(["root", "prefix1/root", "prefix1/actor", "prefix2/root"]), + run_next_test + ); } -function TestForwardPrefix12WithActor12() -{ +function TestForwardPrefix12WithActor12() { let actor = new EchoActor(gSubconnection2); actor.actorID = "prefix2/actor"; gSubconnection2.addActor(actor); - tryActors(new Set(["root", "prefix1/root", "prefix1/actor", "prefix2/root", "prefix2/actor"]), run_next_test); + tryActors( + new Set(["root", "prefix1/root", "prefix1/actor", "prefix2/root", "prefix2/actor"]), + run_next_test + ); } diff --git a/devtools/server/tests/unit/test_frameactor-01.js b/devtools/server/tests/unit/test_frameactor-01.js index ad37a8ab5962..051d44118302 100644 --- a/devtools/server/tests/unit/test_frameactor-01.js +++ b/devtools/server/tests/unit/test_frameactor-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Verify that we get a frame actor along with a debugger statement. */ @@ -9,26 +11,25 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_true(!!aPacket.frame); - do_check_true(!!aPacket.frame.actor); - do_check_eq(aPacket.frame.callee.name, "stopMe"); +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_true(!!packet.frame); + do_check_true(!!packet.frame.actor); + do_check_eq(packet.frame.callee.name, "stopMe"); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_frameactor-02.js b/devtools/server/tests/unit/test_frameactor-02.js index f2890adacf58..e1205020bbec 100644 --- a/devtools/server/tests/unit/test_frameactor-02.js +++ b/devtools/server/tests/unit/test_frameactor-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Verify that two pauses in a row will keep the same frame actor. @@ -9,25 +12,24 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket2) { - do_check_eq(aPacket1.frame.actor, aPacket2.frame.actor); +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet1) { + gThreadClient.addOneTimeListener("paused", function (event, packet2) { + do_check_eq(packet1.frame.actor, packet2.frame.actor); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_frameactor-03.js b/devtools/server/tests/unit/test_frameactor-03.js index 0d7739d5ac09..2d81cf474059 100644 --- a/devtools/server/tests/unit/test_frameactor-03.js +++ b/devtools/server/tests/unit/test_frameactor-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Verify that a frame actor is properly expired when the frame goes away. @@ -9,27 +12,26 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket2) { - let poppedFrames = aPacket2.poppedFrames; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet1) { + gThreadClient.addOneTimeListener("paused", function (event, packet2) { + let poppedFrames = packet2.poppedFrames; do_check_eq(typeof (poppedFrames), typeof ([])); - do_check_true(poppedFrames.indexOf(aPacket1.frame.actor) >= 0); + do_check_true(poppedFrames.indexOf(packet1.frame.actor) >= 0); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_frameactor-04.js b/devtools/server/tests/unit/test_frameactor-04.js index b4faa96e039c..6fdb2ab9e177 100644 --- a/devtools/server/tests/unit/test_frameactor-04.js +++ b/devtools/server/tests/unit/test_frameactor-04.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Verify the "frames" request on the thread. */ @@ -9,16 +11,16 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } @@ -46,17 +48,18 @@ var gSliceTests = [ function test_frame_slice() { if (gSliceTests.length == 0) { - gThreadClient.resume(function () { finishClient(gClient); }); + gThreadClient.resume(() => finishClient(gClient)); return; } let test = gSliceTests.shift(); - gThreadClient.getFrames(test.start, test.count, function (aResponse) { - var testFrames = gFrames.slice(test.start, test.count ? test.start + test.count : undefined); - do_check_eq(testFrames.length, aResponse.frames.length); - for (var i = 0; i < testFrames.length; i++) { + gThreadClient.getFrames(test.start, test.count, function (response) { + let testFrames = gFrames.slice(test.start, + test.count ? test.start + test.count : undefined); + do_check_eq(testFrames.length, response.frames.length); + for (let i = 0; i < testFrames.length; i++) { let expected = testFrames[i]; - let actual = aResponse.frames[i]; + let actual = response.frames[i]; if (test.resetActors) { expected.actor = actual.actor; @@ -70,9 +73,8 @@ function test_frame_slice() { }); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) { +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { test_frame_slice(); }); diff --git a/devtools/server/tests/unit/test_frameactor-05.js b/devtools/server/tests/unit/test_frameactor-05.js index feece598ef2d..ed1bf57efc18 100644 --- a/devtools/server/tests/unit/test_frameactor-05.js +++ b/devtools/server/tests/unit/test_frameactor-05.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Verify that frame actors retrieved with the frames request @@ -10,64 +13,37 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_frame_slice() { - if (gSliceTests.length == 0) { - gThreadClient.resume(function () { finishClient(gClient); }); - return; - } - - let test = gSliceTests.shift(); - gThreadClient.getFrames(test.start, test.count, function (aResponse) { - var testFrames = gFrames.slice(test.start, test.count ? test.start + test.count : undefined); - do_check_eq(testFrames.length, aResponse.frames.length); - for (var i = 0; i < testFrames.length; i++) { - let expected = testFrames[i]; - let actual = aResponse.frames[i]; - - if (test.resetActors) { - expected.actor = actual.actor; - } - - for (var key in expected) { - do_check_eq(expected[key], actual[key]); - } - } - test_frame_slice(); - }); -} - -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) { - gThreadClient.getFrames(0, null, function (aFrameResponse) { - do_check_eq(aFrameResponse.frames.length, 5); +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getFrames(0, null, function (frameResponse) { + do_check_eq(frameResponse.frames.length, 5); // Now wait for the next pause, after which the three // youngest actors should be popped.. - let expectPopped = aFrameResponse.frames.slice(0, 3).map(frame => frame.actor); + let expectPopped = frameResponse.frames.slice(0, 3).map(frame => frame.actor); expectPopped.sort(); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPausePacket) { - let popped = aPausePacket.poppedFrames.sort(); + gThreadClient.addOneTimeListener("paused", function (event, pausePacket) { + let popped = pausePacket.poppedFrames.sort(); do_check_eq(popped.length, 3); for (let i = 0; i < 3; i++) { do_check_eq(expectPopped[i], popped[i]); } - gThreadClient.resume(function () { finishClient(gClient); }); + gThreadClient.resume(() => finishClient(gClient)); }); gThreadClient.resume(); }); diff --git a/devtools/server/tests/unit/test_frameactor_wasm-01.js b/devtools/server/tests/unit/test_frameactor_wasm-01.js index bc941b32283a..1e9f7b8326c8 100644 --- a/devtools/server/tests/unit/test_frameactor_wasm-01.js +++ b/devtools/server/tests/unit/test_frameactor_wasm-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Verify that wasm frame(s) can be requested from the client. @@ -9,34 +12,35 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { if (typeof WebAssembly == "undefined") { - return; // wasm is not enabled for this platform + // wasm is not enabled for this platform + return; } initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - gThreadClient.reconfigure({ observeAsmJS: true }, function (aResponse) { - do_check_eq(!!aResponse.error, false); - test_pause_frame(); + attachTestTabAndResume( + gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + gThreadClient.reconfigure({ observeAsmJS: true }, function (response) { + do_check_eq(!!response.error, false); + test_pause_frame(); + }); }); - }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket1) { - gThreadClient.getFrames(0, null, function (aFrameResponse) { - do_check_eq(aFrameResponse.frames.length, 4); +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getFrames(0, null, function (frameResponse) { + do_check_eq(frameResponse.frames.length, 4); - let wasmFrame = aFrameResponse.frames[1]; + let wasmFrame = frameResponse.frames[1]; do_check_eq(wasmFrame.type, "wasmcall"); do_check_eq(wasmFrame.this, undefined); @@ -49,15 +53,16 @@ function test_pause_frame() }); }); + /* eslint-disable comma-spacing, max-len */ gDebuggee.eval("(" + function () { // WebAssembly bytecode was generated by running: // js -e 'print(wasmTextToBinary("(module(import \"a\" \"b\")(func(export \"c\")call 0))"))' - var m = new WebAssembly.Module(new Uint8Array([ + let m = new WebAssembly.Module(new Uint8Array([ 0,97,115,109,1,0,0,0,1,132,128,128,128,0,1,96,0,0,2,135,128,128,128,0,1,1,97,1, 98,0,0,3,130,128,128,128,0,1,0,6,129,128,128,128,0,0,7,133,128,128,128,0,1,1,99, 0,1,10,138,128,128,128,0,1,132,128,128,128,0,0,16,0,11 ])); - var i = new WebAssembly.Instance(m, {a: {b: () => { + let i = new WebAssembly.Instance(m, {a: {b: () => { debugger; }}}); i.exports.c(); diff --git a/devtools/server/tests/unit/test_framearguments-01.js b/devtools/server/tests/unit/test_framearguments-01.js index e075d2c25df2..bae9b52674ee 100644 --- a/devtools/server/tests/unit/test_framearguments-01.js +++ b/devtools/server/tests/unit/test_framearguments-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check a frame actor's arguments property. */ @@ -9,24 +11,23 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame["arguments"]; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args.length, 6); do_check_eq(args[0], 42); do_check_eq(args[1], true); @@ -43,7 +44,7 @@ function test_pause_frame() }); gDebuggee.eval("(" + function () { - function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) { + function stopMe(number, bool, string, null_, undef, object) { debugger; } stopMe(42, true, "nasu", null, undefined, { foo: "bar" }); diff --git a/devtools/server/tests/unit/test_framebindings-01.js b/devtools/server/tests/unit/test_framebindings-01.js index ae62f8ff1007..36a97f4d0d9a 100644 --- a/devtools/server/tests/unit/test_framebindings-01.js +++ b/devtools/server/tests/unit/test_framebindings-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check a frame actor's bindings property. */ @@ -9,36 +11,35 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let bindings = aPacket.frame.environment.bindings; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let bindings = packet.frame.environment.bindings; let args = bindings.arguments; let vars = bindings.variables; do_check_eq(args.length, 6); - do_check_eq(args[0].aNumber.value, 42); - do_check_eq(args[1].aBool.value, true); - do_check_eq(args[2].aString.value, "nasu"); - do_check_eq(args[3].aNull.value.type, "null"); - do_check_eq(args[4].aUndefined.value.type, "undefined"); - do_check_eq(args[5].aObject.value.type, "object"); - do_check_eq(args[5].aObject.value.class, "Object"); - do_check_true(!!args[5].aObject.value.actor); + do_check_eq(args[0].number.value, 42); + do_check_eq(args[1].bool.value, true); + do_check_eq(args[2].string.value, "nasu"); + do_check_eq(args[3].null_.value.type, "null"); + do_check_eq(args[4].undef.value.type, "undefined"); + do_check_eq(args[5].object.value.type, "object"); + do_check_eq(args[5].object.value.class, "Object"); + do_check_true(!!args[5].object.value.actor); do_check_eq(vars.a.value, 1); do_check_eq(vars.b.value, true); @@ -47,17 +48,17 @@ function test_pause_frame() do_check_true(!!vars.c.value.actor); let objClient = gThreadClient.pauseGrip(vars.c.value); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.a.configurable, true); - do_check_eq(aResponse.ownProperties.a.enumerable, true); - do_check_eq(aResponse.ownProperties.a.writable, true); - do_check_eq(aResponse.ownProperties.a.value, "a"); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.a.configurable, true); + do_check_eq(response.ownProperties.a.enumerable, true); + do_check_eq(response.ownProperties.a.writable, true); + do_check_eq(response.ownProperties.a.value, "a"); - do_check_eq(aResponse.ownProperties.b.configurable, true); - do_check_eq(aResponse.ownProperties.b.enumerable, true); - do_check_eq(aResponse.ownProperties.b.writable, true); - do_check_eq(aResponse.ownProperties.b.value.type, "undefined"); - do_check_false("class" in aResponse.ownProperties.b.value); + do_check_eq(response.ownProperties.b.configurable, true); + do_check_eq(response.ownProperties.b.enumerable, true); + do_check_eq(response.ownProperties.b.writable, true); + do_check_eq(response.ownProperties.b.value.type, "undefined"); + do_check_false("class" in response.ownProperties.b.value); gThreadClient.resume(function () { finishClient(gClient); @@ -65,8 +66,9 @@ function test_pause_frame() }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { - function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) { + function stopMe(number, bool, string, null_, undef, object) { var a = 1; var b = true; var c = { a: "a", b: undefined }; @@ -74,4 +76,5 @@ function test_pause_frame() } stopMe(42, true, "nasu", null, undefined, { foo: "bar" }); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_framebindings-02.js b/devtools/server/tests/unit/test_framebindings-02.js index 552670349cbc..606383b30580 100644 --- a/devtools/server/tests/unit/test_framebindings-02.js +++ b/devtools/server/tests/unit/test_framebindings-02.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check a frame actor's parent bindings. */ @@ -9,24 +11,23 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let parentEnv = aPacket.frame.environment.parent; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let parentEnv = packet.frame.environment.parent; let bindings = parentEnv.bindings; let args = bindings.arguments; let vars = bindings.variables; @@ -40,10 +41,10 @@ function test_pause_frame() parentEnv = parentEnv.parent.parent; do_check_neq(parentEnv, undefined); let objClient = gThreadClient.pauseGrip(parentEnv.object); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.Object.value.type, "object"); - do_check_eq(aResponse.ownProperties.Object.value.class, "Function"); - do_check_true(!!aResponse.ownProperties.Object.value.actor); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.Object.value.type, "object"); + do_check_eq(response.ownProperties.Object.value.class, "Function"); + do_check_true(!!response.ownProperties.Object.value.actor); gThreadClient.resume(function () { finishClient(gClient); @@ -51,8 +52,9 @@ function test_pause_frame() }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { - function stopMe(aNumber, aBool, aString, aNull, aUndefined, aObject) { + function stopMe(number, bool, string, null_, undef, object) { var a = 1; var b = true; var c = { a: "a" }; diff --git a/devtools/server/tests/unit/test_framebindings-03.js b/devtools/server/tests/unit/test_framebindings-03.js index 1ec51570d84c..f32bdf39649f 100644 --- a/devtools/server/tests/unit/test_framebindings-03.js +++ b/devtools/server/tests/unit/test_framebindings-03.js @@ -1,6 +1,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* strict mode code may not contain 'with' statements */ +/* eslint-disable strict */ + /** * Check a |with| frame actor's bindings. */ @@ -9,24 +12,23 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let env = aPacket.frame.environment; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let env = packet.frame.environment; do_check_neq(env, undefined); let parentEnv = env.parent; @@ -36,18 +38,18 @@ function test_pause_frame() let args = bindings.arguments; let vars = bindings.variables; do_check_eq(args.length, 1); - do_check_eq(args[0].aNumber.value, 10); + do_check_eq(args[0].number.value, 10); do_check_eq(vars.r.value, 10); do_check_eq(vars.a.value, Math.PI * 100); do_check_eq(vars.arguments.value.class, "Arguments"); do_check_true(!!vars.arguments.value.actor); let objClient = gThreadClient.pauseGrip(env.object); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.PI.value, Math.PI); - do_check_eq(aResponse.ownProperties.cos.value.type, "object"); - do_check_eq(aResponse.ownProperties.cos.value.class, "Function"); - do_check_true(!!aResponse.ownProperties.cos.value.actor); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.PI.value, Math.PI); + do_check_eq(response.ownProperties.cos.value.type, "object"); + do_check_eq(response.ownProperties.cos.value.class, "Function"); + do_check_true(!!response.ownProperties.cos.value.actor); gThreadClient.resume(function () { finishClient(gClient); @@ -55,10 +57,11 @@ function test_pause_frame() }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { - function stopMe(aNumber) { + function stopMe(number) { var a; - var r = aNumber; + var r = number; with (Math) { a = PI * r * r; debugger; @@ -66,4 +69,5 @@ function test_pause_frame() } stopMe(10); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_framebindings-04.js b/devtools/server/tests/unit/test_framebindings-04.js index 963a12055076..311c2b318e45 100644 --- a/devtools/server/tests/unit/test_framebindings-04.js +++ b/devtools/server/tests/unit/test_framebindings-04.js @@ -1,49 +1,52 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +/* strict mode code may not contain 'with' statements */ +/* eslint-disable strict */ /** - * Check the environment bindongs of a |with| within a |with|. + * Check the environment bindings of a |with| within a |with|. */ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let env = aPacket.frame.environment; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let env = packet.frame.environment; do_check_neq(env, undefined); let objClient = gThreadClient.pauseGrip(env.object); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.one.value, 1); - do_check_eq(aResponse.ownProperties.two.value, 2); - do_check_eq(aResponse.ownProperties.foo, undefined); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.one.value, 1); + do_check_eq(response.ownProperties.two.value, 2); + do_check_eq(response.ownProperties.foo, undefined); let parentEnv = env.parent; do_check_neq(parentEnv, undefined); let parentClient = gThreadClient.pauseGrip(parentEnv.object); - parentClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.PI.value, Math.PI); - do_check_eq(aResponse.ownProperties.cos.value.type, "object"); - do_check_eq(aResponse.ownProperties.cos.value.class, "Function"); - do_check_true(!!aResponse.ownProperties.cos.value.actor); + parentClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.PI.value, Math.PI); + do_check_eq(response.ownProperties.cos.value.type, "object"); + do_check_eq(response.ownProperties.cos.value.class, "Function"); + do_check_true(!!response.ownProperties.cos.value.actor); parentEnv = parentEnv.parent; do_check_neq(parentEnv, undefined); @@ -52,7 +55,7 @@ function test_pause_frame() let args = bindings.arguments; let vars = bindings.variables; do_check_eq(args.length, 1); - do_check_eq(args[0].aNumber.value, 10); + do_check_eq(args[0].number.value, 10); do_check_eq(vars.r.value, 10); do_check_eq(vars.a.value, Math.PI * 100); do_check_eq(vars.arguments.value.class, "Arguments"); @@ -64,13 +67,13 @@ function test_pause_frame() }); }); }); - }); + /* eslint-disable */ gDebuggee.eval("(" + function () { - function stopMe(aNumber) { + function stopMe(number) { var a, obj = { one: 1, two: 2 }; - var r = aNumber; + var r = number; with (Math) { a = PI * r * r; with (obj) { @@ -81,4 +84,5 @@ function test_pause_frame() } stopMe(10); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_framebindings-05.js b/devtools/server/tests/unit/test_framebindings-05.js index 9827c617a6b1..7a3eac60d83a 100644 --- a/devtools/server/tests/unit/test_framebindings-05.js +++ b/devtools/server/tests/unit/test_framebindings-05.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check the environment bindings of a |with| in global scope. @@ -9,44 +12,43 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let env = aPacket.frame.environment; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let env = packet.frame.environment; do_check_neq(env, undefined); let objClient = gThreadClient.pauseGrip(env.object); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.PI.value, Math.PI); - do_check_eq(aResponse.ownProperties.cos.value.type, "object"); - do_check_eq(aResponse.ownProperties.cos.value.class, "Function"); - do_check_true(!!aResponse.ownProperties.cos.value.actor); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.PI.value, Math.PI); + do_check_eq(response.ownProperties.cos.value.type, "object"); + do_check_eq(response.ownProperties.cos.value.class, "Function"); + do_check_true(!!response.ownProperties.cos.value.actor); // Skip the global lexical scope. let parentEnv = env.parent.parent; do_check_neq(parentEnv, undefined); let parentClient = gThreadClient.pauseGrip(parentEnv.object); - parentClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.a.value, Math.PI * 100); - do_check_eq(aResponse.ownProperties.r.value, 10); - do_check_eq(aResponse.ownProperties.Object.value.type, "object"); - do_check_eq(aResponse.ownProperties.Object.value.class, "Function"); - do_check_true(!!aResponse.ownProperties.Object.value.actor); + parentClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.a.value, Math.PI * 100); + do_check_eq(response.ownProperties.r.value, 10); + do_check_eq(response.ownProperties.Object.value.type, "object"); + do_check_eq(response.ownProperties.Object.value.class, "Function"); + do_check_true(!!response.ownProperties.Object.value.actor); gThreadClient.resume(function () { finishClient(gClient); diff --git a/devtools/server/tests/unit/test_framebindings-06.js b/devtools/server/tests/unit/test_framebindings-06.js index 9d8478a299e6..b7d6392c9751 100644 --- a/devtools/server/tests/unit/test_framebindings-06.js +++ b/devtools/server/tests/unit/test_framebindings-06.js @@ -1,32 +1,32 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_banana_environment(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_banana_environment(); + }); }); do_test_pending(); } -function test_banana_environment() -{ - +function test_banana_environment() { gThreadClient.addOneTimeListener("paused", - function (aEvent, aPacket) { - equal(aPacket.type, "paused"); - let env = aPacket.frame.environment; + function (event, packet) { + equal(packet.type, "paused"); + let env = packet.frame.environment; equal(env.type, "function"); equal(env.function.name, "banana3"); let parent = env.parent; @@ -47,14 +47,12 @@ function test_banana_environment() }); }); - gDebuggee.eval("\ - function banana(x) { \n\ - return function banana2(y) { \n\ - return function banana3(z) { \n\ - debugger; \n\ - }; \n\ - }; \n\ - } \n\ - banana('x')('y')('z'); \n\ - "); + gDebuggee.eval("function banana(x) {\n" + + " return function banana2(y) {\n" + + " return function banana3(z) {\n" + + " debugger;\n" + + " };\n" + + " };\n" + + "}\n" + + "banana('x')('y')('z');\n"); } diff --git a/devtools/server/tests/unit/test_framebindings-07.js b/devtools/server/tests/unit/test_framebindings-07.js index bdfc36d97ad7..44c00f58461d 100644 --- a/devtools/server/tests/unit/test_framebindings-07.js +++ b/devtools/server/tests/unit/test_framebindings-07.js @@ -1,31 +1,32 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; var gThreadClient; // Test that the EnvironmentClient's getBindings() method works as expected. -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-bindings"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-bindings", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_banana_environment(); - }); + attachTestTabAndResume(gClient, "test-bindings", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_banana_environment(); + }); }); do_test_pending(); } -function test_banana_environment() -{ - - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let environment = aPacket.frame.environment; +function test_banana_environment() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let environment = packet.frame.environment; do_check_eq(environment.type, "function"); let parent = environment.parent; @@ -35,30 +36,28 @@ function test_banana_environment() do_check_eq(grandpa.type, "function"); let envClient = gThreadClient.environment(environment); - envClient.getBindings(aResponse => { - do_check_eq(aResponse.bindings.arguments[0].z.value, "z"); + envClient.getBindings(response => { + do_check_eq(response.bindings.arguments[0].z.value, "z"); let parentClient = gThreadClient.environment(parent); - parentClient.getBindings(aResponse => { - do_check_eq(aResponse.bindings.variables.banana3.value.class, "Function"); + parentClient.getBindings(response => { + do_check_eq(response.bindings.variables.banana3.value.class, "Function"); let grandpaClient = gThreadClient.environment(grandpa); - grandpaClient.getBindings(aResponse => { - do_check_eq(aResponse.bindings.arguments[0].y.value, "y"); + grandpaClient.getBindings(response => { + do_check_eq(response.bindings.arguments[0].y.value, "y"); gThreadClient.resume(() => finishClient(gClient)); }); }); }); }); - gDebuggee.eval("\ - function banana(x) { \n\ - return function banana2(y) { \n\ - return function banana3(z) { \n\ - debugger; \n\ - }; \n\ - }; \n\ - } \n\ - banana('x')('y')('z'); \n\ - "); + gDebuggee.eval("function banana(x) {\n" + + " return function banana2(y) {\n" + + " return function banana3(z) {\n" + + " debugger;\n" + + " };\n" + + " };\n" + + "}\n" + + "banana('x')('y')('z');\n"); } diff --git a/devtools/server/tests/unit/test_frameclient-01.js b/devtools/server/tests/unit/test_frameclient-01.js index a441c9adeb37..290649252128 100644 --- a/devtools/server/tests/unit/test_frameclient-01.js +++ b/devtools/server/tests/unit/test_frameclient-01.js @@ -1,27 +1,29 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { gThreadClient.addOneTimeListener("framesadded", function () { do_check_eq(gThreadClient.cachedFrames.length, 3); do_check_true(gThreadClient.moreFrames); @@ -39,6 +41,7 @@ function test_pause_frame() do_check_true(gThreadClient.fillFrames(3)); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { var recurseLeft = 5; function recurse() { @@ -50,4 +53,5 @@ function test_pause_frame() } recurse(); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_frameclient-02.js b/devtools/server/tests/unit/test_frameclient-02.js index a257e5960837..323966491ead 100644 --- a/devtools/server/tests/unit/test_frameclient-02.js +++ b/devtools/server/tests/unit/test_frameclient-02.js @@ -1,27 +1,28 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Ask for exactly the number of frames we expect. gThreadClient.addOneTimeListener("framesadded", function () { do_check_false(gThreadClient.moreFrames); @@ -32,6 +33,7 @@ function test_pause_frame() do_check_true(gThreadClient.fillFrames(3)); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { var recurseLeft = 1; function recurse() { @@ -43,4 +45,5 @@ function test_pause_frame() } recurse(); } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_functiongrips-01.js b/devtools/server/tests/unit/test_functiongrips-01.js index 81b1b77670b0..b5adc8ebc8e8 100644 --- a/devtools/server/tests/unit/test_functiongrips-01.js +++ b/devtools/server/tests/unit/test_functiongrips-01.js @@ -1,12 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gDebuggee.eval(function stopMe(arg1) { @@ -15,39 +16,38 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_named_function(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_named_function(); + }); }); do_test_pending(); } -function test_named_function() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_named_function() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Function"); do_check_eq(args[0].name, "stopMe"); do_check_eq(args[0].displayName, "stopMe"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getParameterNames(function (aResponse) { - do_check_eq(aResponse.parameterNames.length, 1); - do_check_eq(aResponse.parameterNames[0], "arg1"); + objClient.getParameterNames(function (response) { + do_check_eq(response.parameterNames.length, 1); + do_check_eq(response.parameterNames[0], "arg1"); gThreadClient.resume(test_inferred_name_function); }); - }); gDebuggee.eval("stopMe(stopMe)"); } function test_inferred_name_function() { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Function"); // No name for an anonymous function, but it should have an inferred name. @@ -55,11 +55,11 @@ function test_inferred_name_function() { do_check_eq(args[0].displayName, "m"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getParameterNames(function (aResponse) { - do_check_eq(aResponse.parameterNames.length, 3); - do_check_eq(aResponse.parameterNames[0], "foo"); - do_check_eq(aResponse.parameterNames[1], "bar"); - do_check_eq(aResponse.parameterNames[2], "baz"); + objClient.getParameterNames(function (response) { + do_check_eq(response.parameterNames.length, 3); + do_check_eq(response.parameterNames[0], "foo"); + do_check_eq(response.parameterNames[1], "bar"); + do_check_eq(response.parameterNames[2], "baz"); gThreadClient.resume(test_anonymous_function); }); @@ -69,8 +69,8 @@ function test_inferred_name_function() { } function test_anonymous_function() { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Function"); // No name for an anonymous function, and no inferred name, either. @@ -78,11 +78,11 @@ function test_anonymous_function() { do_check_eq(args[0].displayName, undefined); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getParameterNames(function (aResponse) { - do_check_eq(aResponse.parameterNames.length, 3); - do_check_eq(aResponse.parameterNames[0], "foo"); - do_check_eq(aResponse.parameterNames[1], "bar"); - do_check_eq(aResponse.parameterNames[2], "baz"); + objClient.getParameterNames(function (response) { + do_check_eq(response.parameterNames.length, 3); + do_check_eq(response.parameterNames[0], "foo"); + do_check_eq(response.parameterNames[1], "bar"); + do_check_eq(response.parameterNames[2], "baz"); gThreadClient.resume(function () { finishClient(gClient); diff --git a/devtools/server/tests/unit/test_get-executable-lines-source-map.js b/devtools/server/tests/unit/test_get-executable-lines-source-map.js index bca8eebee2c0..42794535b784 100644 --- a/devtools/server/tests/unit/test_get-executable-lines-source-map.js +++ b/devtools/server/tests/unit/test_get-executable-lines-source-map.js @@ -2,6 +2,8 @@ * 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"; + /** * Test if getExecutableLines return correct information */ @@ -20,8 +22,8 @@ function run_test() { attachTestTabAndResume( gClient, "test-get-executable-lines", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; test_executable_lines(); } ); diff --git a/devtools/server/tests/unit/test_get-executable-lines.js b/devtools/server/tests/unit/test_get-executable-lines.js index 233fb6ada9df..3660a4db93e4 100644 --- a/devtools/server/tests/unit/test_get-executable-lines.js +++ b/devtools/server/tests/unit/test_get-executable-lines.js @@ -2,6 +2,8 @@ * 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"; + /** * Test if getExecutableLines return correct information */ @@ -20,8 +22,8 @@ function run_test() { attachTestTabAndResume( gClient, "test-get-executable-lines", - function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + function (response, tabClient, threadClient) { + gThreadClient = threadClient; test_executable_lines(); } ); diff --git a/devtools/server/tests/unit/test_getRuleText.js b/devtools/server/tests/unit/test_getRuleText.js index fe735928daa9..0f8e8d8325c7 100644 --- a/devtools/server/tests/unit/test_getRuleText.js +++ b/devtools/server/tests/unit/test_getRuleText.js @@ -24,7 +24,8 @@ const TEST_DATA = [ }, { desc: "Multiple rules test case", - input: "#id{color:red;background:yellow;}.class-one .class-two { position:absolute; line-height: 45px}", + input: "#id{color:red;background:yellow;}.class-one .class-two " + + "{ position:absolute; line-height: 45px}", line: 1, column: 34, expected: {offset: 56, text: " position:absolute; line-height: 45px"} diff --git a/devtools/server/tests/unit/test_getyoungestframe.js b/devtools/server/tests/unit/test_getyoungestframe.js index 035ab5b0c328..1254f53bf8a6 100644 --- a/devtools/server/tests/unit/test_getyoungestframe.js +++ b/devtools/server/tests/unit/test_getyoungestframe.js @@ -1,22 +1,22 @@ -function run_test() -{ +/* eslint-disable strict */ +function run_test() { Components.utils.import("resource://gre/modules/jsdebugger.jsm"); addDebuggerToGlobal(this); - var xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector); - var g = testGlobal("test1"); + let xpcInspector = Cc["@mozilla.org/jsinspector;1"].getService(Ci.nsIJSInspector); + let g = testGlobal("test1"); - var dbg = new Debugger(); + let dbg = new Debugger(); dbg.uncaughtExceptionHook = testExceptionHook; dbg.addDebuggee(g); - dbg.onDebuggerStatement = function (aFrame) { - do_check_true(aFrame === dbg.getNewestFrame()); + dbg.onDebuggerStatement = function (frame) { + do_check_true(frame === dbg.getNewestFrame()); // Execute from the nested event loop, dbg.getNewestFrame() won't // be working anymore. do_execute_soon(function () { try { - do_check_true(aFrame === dbg.getNewestFrame()); + do_check_true(frame === dbg.getNewestFrame()); } finally { xpcInspector.exitNestedEventLoop("test"); } diff --git a/devtools/server/tests/unit/test_ignore_caught_exceptions.js b/devtools/server/tests/unit/test_ignore_caught_exceptions.js index a4b2218238e8..05ba9277a0b5 100644 --- a/devtools/server/tests/unit/test_ignore_caught_exceptions.js +++ b/devtools/server/tests/unit/test_ignore_caught_exceptions.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that setting ignoreCaughtExceptions will cause the debugger to ignore @@ -10,26 +13,25 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "exception"); - do_check_eq(aPacket.why.exception, "bar"); +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "exception"); + do_check_eq(packet.why.exception, "bar"); gThreadClient.resume(function () { finishClient(gClient); }); @@ -39,6 +41,7 @@ function test_pause_frame() }); try { + /* eslint-disable */ gDebuggee.eval("(" + function () { debugger; try { @@ -46,5 +49,8 @@ function test_pause_frame() } catch (e) {} throw "bar"; } + ")()"); - } catch (e) {} + /* eslint-enable */ + } catch (e) { + /* Empty */ + } } diff --git a/devtools/server/tests/unit/test_ignore_no_interface_exceptions.js b/devtools/server/tests/unit/test_ignore_no_interface_exceptions.js index 5aaa31de3dc0..37b0bfbfe191 100644 --- a/devtools/server/tests/unit/test_ignore_no_interface_exceptions.js +++ b/devtools/server/tests/unit/test_ignore_no_interface_exceptions.js @@ -1,41 +1,42 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that the debugger automatically ignores NS_ERROR_NO_INTERFACE * exceptions, but not normal ones. */ - var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-no-interface"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-no-interface", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-no-interface", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ +function test_pause_frame() { gThreadClient.pauseOnExceptions(true, false, function () { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "exception"); - do_check_eq(aPacket.why.exception, 42); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "exception"); + do_check_eq(packet.why.exception, 42); gThreadClient.resume(function () { finishClient(gClient); }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { function QueryInterface() { throw Components.results.NS_ERROR_NO_INTERFACE; @@ -50,5 +51,6 @@ function test_pause_frame() stopMe(); } catch (e) {} } + ")()"); + /* eslint-enable */ }); } diff --git a/devtools/server/tests/unit/test_interrupt.js b/devtools/server/tests/unit/test_interrupt.js index 34835cc0a0c0..e2190c5d7919 100644 --- a/devtools/server/tests/unit/test_interrupt.js +++ b/devtools/server/tests/unit/test_interrupt.js @@ -1,48 +1,47 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; var gClient; var gDebuggee; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = testGlobal("test-1"); DebuggerServer.addTestGlobal(gDebuggee); let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); - gClient.connect().then(function (aType, aTraits) { + gClient.connect().then(function (type, traits) { attachTestTab(gClient, "test-1", test_attach); }); do_test_pending(); } -function test_attach(aResponse, aTabClient) -{ - aTabClient.attachThread({}, function (aResponse, aThreadClient) { - do_check_eq(aThreadClient.paused, true); - aThreadClient.resume(function () { - test_interrupt(aThreadClient); +function test_attach(response, tabClient) { + tabClient.attachThread({}, function (response, threadClient) { + do_check_eq(threadClient.paused, true); + threadClient.resume(function () { + test_interrupt(threadClient); }); }); } -function test_interrupt(aThreadClient) -{ - do_check_eq(aThreadClient.paused, false); - aThreadClient.interrupt(function (aResponse) { - do_check_eq(aThreadClient.paused, true); - aThreadClient.resume(function () { - do_check_eq(aThreadClient.paused, false); +function test_interrupt(threadClient) { + do_check_eq(threadClient.paused, false); + threadClient.interrupt(function (response) { + do_check_eq(threadClient.paused, true); + threadClient.resume(function () { + do_check_eq(threadClient.paused, false); cleanup(); }); }); } -function cleanup() -{ - gClient.addListener("closed", function (aEvent) { +function cleanup() { + gClient.addListener("closed", function (event) { do_test_finished(); }); gClient.close(); diff --git a/devtools/server/tests/unit/test_layout-reflows-observer.js b/devtools/server/tests/unit/test_layout-reflows-observer.js index ff6c07b2646f..9fde8688fe6a 100644 --- a/devtools/server/tests/unit/test_layout-reflows-observer.js +++ b/devtools/server/tests/unit/test_layout-reflows-observer.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test the LayoutChangesObserver var { diff --git a/devtools/server/tests/unit/test_listsources-01.js b/devtools/server/tests/unit/test_listsources-01.js index 231e6a1e4fa7..8c9c75ec9ebb 100644 --- a/devtools/server/tests/unit/test_listsources-01.js +++ b/devtools/server/tests/unit/test_listsources-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check basic getSources functionality. */ @@ -11,33 +13,32 @@ var gThreadClient; var gNumTimesSourcesSent = 0; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); - gClient.request = (function (request) { - return function (aRequest, aOnResponse) { - if (aRequest.type === "sources") { + gClient.request = (function (origRequest) { + return function (request, onResponse) { + if (request.type === "sources") { ++gNumTimesSourcesSent; } - return request.call(this, aRequest, aOnResponse); + return origRequest.call(this, request, onResponse); }; }(gClient.request)); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_listsources(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_listsources(); + }); }); do_test_pending(); } -function test_simple_listsources() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.getSources(function (aResponse) { - do_check_true(aResponse.sources.some(function (s) { +function test_simple_listsources() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getSources(function (response) { + do_check_true(response.sources.some(function (s) { return s.url && s.url.match(/test_listsources-01.js/); })); @@ -51,9 +52,11 @@ function test_simple_listsources() }); }); + /* eslint-disable */ Components.utils.evalInSandbox("var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 "var a = 1;\n" + // line0 + 2 "var b = 2;\n", // line0 + 3 gDebuggee); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_listsources-02.js b/devtools/server/tests/unit/test_listsources-02.js index 190a5e31bc95..272eb1ec4c85 100644 --- a/devtools/server/tests/unit/test_listsources-02.js +++ b/devtools/server/tests/unit/test_listsources-02.js @@ -1,44 +1,44 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check getting sources before there are any. */ -var gDebuggee; var gClient; var gThreadClient; var gNumTimesSourcesSent = 0; -function run_test() -{ +function run_test() { initTestDebuggerServer(); - gDebuggee = addTestGlobal("test-stack"); + addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); - gClient.request = (function (request) { - return function (aRequest, aOnResponse) { - if (aRequest.type === "sources") { + gClient.request = (function (origRequest) { + return function (request, onResponse) { + if (request.type === "sources") { ++gNumTimesSourcesSent; } - return request.call(this, aRequest, aOnResponse); + return origRequest.call(this, request, onResponse); }; }(gClient.request)); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_listing_zero_sources(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_listing_zero_sources(); + }); }); do_test_pending(); } -function test_listing_zero_sources() -{ - gThreadClient.getSources(function (aPacket) { - do_check_true(!aPacket.error); - do_check_true(!!aPacket.sources); - do_check_eq(aPacket.sources.length, 0); +function test_listing_zero_sources() { + gThreadClient.getSources(function (packet) { + do_check_true(!packet.error); + do_check_true(!!packet.sources); + do_check_eq(packet.sources.length, 0); do_check_true(gNumTimesSourcesSent <= 1, "Should only send one sources request at most, even though we" diff --git a/devtools/server/tests/unit/test_listsources-03.js b/devtools/server/tests/unit/test_listsources-03.js index 72ebb5e1c281..c5f77a298e5f 100644 --- a/devtools/server/tests/unit/test_listsources-03.js +++ b/devtools/server/tests/unit/test_listsources-03.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check getSources functionality when there are lots of sources. */ @@ -9,29 +11,28 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-sources"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-sources", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_listsources(); - }); + attachTestTabAndResume(gClient, "test-sources", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_listsources(); + }); }); do_test_pending(); } -function test_simple_listsources() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.getSources(function (aResponse) { +function test_simple_listsources() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getSources(function (response) { do_check_true( - !aResponse.error, + !response.error, "There shouldn't be an error fetching large amounts of sources."); - do_check_true(aResponse.sources.some(function (s) { + do_check_true(response.sources.some(function (s) { return s.url.match(/foo-999.js$/); })); diff --git a/devtools/server/tests/unit/test_listsources-04.js b/devtools/server/tests/unit/test_listsources-04.js index 8e1a57bf027f..9a1089c7d6b0 100644 --- a/devtools/server/tests/unit/test_listsources-04.js +++ b/devtools/server/tests/unit/test_listsources-04.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Check getSources functionality with sourcemaps. @@ -18,12 +21,12 @@ function run_test() { } function run_test_with_server(server, cb) { - Task.spawn(function*() { + Task.spawn(function* () { initTestDebuggerServer(server); const debuggee = addTestGlobal("test-sources", server); const client = new DebuggerClient(server.connectPipe()); yield client.connect(); - const [,,threadClient] = yield attachTestTabAndResume(client, "test-sources"); + const [,, threadClient] = yield attachTestTabAndResume(client, "test-sources"); yield threadClient.reconfigure({ useSourceMaps: true }); addSources(debuggee); @@ -33,7 +36,7 @@ function run_test_with_server(server, cb) { yield threadClient.reconfigure({ useSourceMaps: false }); - threadClient.getSources(function(res) { + threadClient.getSources(function (res) { do_check_eq(res.sources.length, 1, "1 source exist"); client.close().then(cb); }); diff --git a/devtools/server/tests/unit/test_longstringactor.js b/devtools/server/tests/unit/test_longstringactor.js index 18f01e363576..3f8aefac2b37 100644 --- a/devtools/server/tests/unit/test_longstringactor.js +++ b/devtools/server/tests/unit/test_longstringactor.js @@ -14,8 +14,7 @@ function run_test() { const TEST_STRING = "This is a very long string!"; -function makeMockLongStringActor() -{ +function makeMockLongStringActor() { let string = TEST_STRING; let actor = new LongStringActor(string); actor.actorID = "longString1"; @@ -27,8 +26,7 @@ function makeMockLongStringActor() return actor; } -function test_LSA_destroy() -{ +function test_LSA_destroy() { let actor = makeMockLongStringActor(); do_check_eq(actor.registeredPool.longStringActors[TEST_STRING], actor); @@ -36,27 +34,18 @@ function test_LSA_destroy() do_check_eq(actor.registeredPool.longStringActors[TEST_STRING], void 0); } -function test_LSA_substring() -{ - let actor = makeMockLongStringActor(); - do_check_eq(actor._substring(0, 4), TEST_STRING.substring(0, 4)); - do_check_eq(actor._substring(6, 9), TEST_STRING.substring(6, 9)); - do_check_eq(actor._substring(0, TEST_STRING.length), TEST_STRING); -} - -function test_LSA_grip() -{ +function test_LSA_grip() { let actor = makeMockLongStringActor(); let grip = actor.grip(); do_check_eq(grip.type, "longString"); - do_check_eq(grip.initial, TEST_STRING.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH)); + do_check_eq(grip.initial, + TEST_STRING.substring(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH)); do_check_eq(grip.length, TEST_STRING.length); do_check_eq(grip.actor, actor.actorID); } -function test_LSA_onSubstring() -{ +function test_LSA_onSubstring() { let actor = makeMockLongStringActor(); let response; diff --git a/devtools/server/tests/unit/test_longstringgrips-01.js b/devtools/server/tests/unit/test_longstringgrips-01.js index b8e6789c7e67..551e45fdd228 100644 --- a/devtools/server/tests/unit/test_longstringgrips-01.js +++ b/devtools/server/tests/unit/test_longstringgrips-01.js @@ -1,12 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gDebuggee.eval(function stopMe(arg1) { @@ -15,16 +16,16 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_longstring_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_longstring_grip(); + }); }); do_test_pending(); } -function test_longstring_grip() -{ +function test_longstring_grip() { let longString = "All I want is to be a monkey of moderate intelligence who" + " wears a suit... that's why I'm transferring to business school! Maybe I" + " love you so much, I love you no matter who you are pretending to be." @@ -38,20 +39,21 @@ function test_longstring_grip() DebuggerServer.LONG_STRING_LENGTH = 200; - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args.length, 1); let grip = args[0]; try { do_check_eq(grip.type, "longString"); do_check_eq(grip.length, longString.length); - do_check_eq(grip.initial, longString.substr(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH)); + do_check_eq(grip.initial, + longString.substr(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH)); let longStringClient = gThreadClient.pauseLongString(grip); - longStringClient.substring(22, 28, function (aResponse) { + longStringClient.substring(22, 28, function (response) { try { - do_check_eq(aResponse.substring, "monkey"); + do_check_eq(response.substring, "monkey"); } finally { gThreadClient.resume(function () { finishClient(gClient); diff --git a/devtools/server/tests/unit/test_longstringgrips-02.js b/devtools/server/tests/unit/test_longstringgrips-02.js index 01f9c1b8f256..65178f1fe74d 100644 --- a/devtools/server/tests/unit/test_longstringgrips-02.js +++ b/devtools/server/tests/unit/test_longstringgrips-02.js @@ -1,12 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gDebuggee.eval(function stopMe(arg1) { @@ -16,19 +17,18 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { attachTestTabAndResume( - gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; + gClient, "test-grips", function (response, tabClient, threadClient) { + gThreadClient = threadClient; test_longstring_grip(); }); }); do_test_pending(); } -function test_longstring_grip() -{ +function test_longstring_grip() { DebuggerServer.LONG_STRING_LENGTH = 200; - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { try { let fakeLongStringGrip = { type: "longString", @@ -37,9 +37,9 @@ function test_longstring_grip() initial: "" }; let longStringClient = gThreadClient.pauseLongString(fakeLongStringGrip); - longStringClient.substring(22, 28, function (aResponse) { + longStringClient.substring(22, 28, function (response) { try { - do_check_true(!!aResponse.error, + do_check_true(!!response.error, "We should not get a response, but an error."); } finally { gThreadClient.resume(function () { diff --git a/devtools/server/tests/unit/test_monitor_actor.js b/devtools/server/tests/unit/test_monitor_actor.js index 17c272d800a3..f4752dabc27c 100644 --- a/devtools/server/tests/unit/test_monitor_actor.js +++ b/devtools/server/tests/unit/test_monitor_actor.js @@ -7,8 +7,7 @@ "use strict"; -function run_test() -{ +function run_test() { let EventEmitter = require("devtools/shared/event-emitter"); function MonitorClient(client, form) { @@ -64,7 +63,7 @@ function run_test() do_check_eq(event.curve, "test"); do_check_eq(event.value, 42); do_check_eq(event.time, time); - monitor.stop(function (aResponse) { + monitor.stop(function (response) { monitor.destroy(); finishClient(client); }); diff --git a/devtools/server/tests/unit/test_nativewrappers.js b/devtools/server/tests/unit/test_nativewrappers.js index fbadfcdecdd4..8814a117ec83 100644 --- a/devtools/server/tests/unit/test_nativewrappers.js +++ b/devtools/server/tests/unit/test_nativewrappers.js @@ -1,13 +1,13 @@ -function run_test() -{ +/* eslint-disable strict */ +function run_test() { Components.utils.import("resource://gre/modules/jsdebugger.jsm"); addDebuggerToGlobal(this); - var g = testGlobal("test1"); + let g = testGlobal("test1"); - var dbg = new Debugger(); + let dbg = new Debugger(); dbg.addDebuggee(g); - dbg.onDebuggerStatement = function (aFrame) { - let args = aFrame.arguments; + dbg.onDebuggerStatement = function (frame) { + let args = frame.arguments; try { args[0]; do_check_true(true); @@ -21,7 +21,8 @@ function run_test() g2 = testGlobal("test2"); g2.g = g; g2.eval("(" + function createBadEvent() { - let parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser); + let parser = Components.classes["@mozilla.org/xmlextras/domparser;1"] + .createInstance(Components.interfaces.nsIDOMParser); let doc = parser.parseFromString("", "text/xml"); g.stopMe(doc.createEvent("MouseEvent")); } + ")()"); diff --git a/devtools/server/tests/unit/test_nesting-01.js b/devtools/server/tests/unit/test_nesting-01.js index e515f051ee82..0dcea0dc0434 100644 --- a/devtools/server/tests/unit/test_nesting-01.js +++ b/devtools/server/tests/unit/test_nesting-01.js @@ -2,6 +2,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test that we can nest event loops when needed in // ThreadActor.prototype.unsafeSynchronize. @@ -10,22 +12,25 @@ var gThreadActor; function run_test() { initTestDebuggerServer(); - let gDebuggee = addTestGlobal("test-nesting"); + addTestGlobal("test-nesting"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-nesting", function (aResponse, aTabClient, aThreadClient) { - // Reach over the protocol connection and get a reference to the thread actor. - gThreadActor = aThreadClient._transport._serverConnection.getActor(aThreadClient._actor); + attachTestTabAndResume( + gClient, "test-nesting", + function (response, tabClient, threadClient) { + // Reach over the protocol connection and get a reference to the thread actor. + gThreadActor = + threadClient._transport._serverConnection.getActor(threadClient._actor); - test_nesting(); - }); + test_nesting(); + }); }); do_test_pending(); } function test_nesting() { const thread = gThreadActor; - const { resolve, reject, promise: p } = promise.defer(); + const { resolve, promise: p } = promise.defer(); let currentStep = 0; diff --git a/devtools/server/tests/unit/test_nesting-02.js b/devtools/server/tests/unit/test_nesting-02.js index 928331be5697..b12c5fc9a0ec 100644 --- a/devtools/server/tests/unit/test_nesting-02.js +++ b/devtools/server/tests/unit/test_nesting-02.js @@ -2,6 +2,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test that we can nest event loops and then automatically exit nested event // loops when requested. @@ -10,23 +12,26 @@ var gThreadActor; function run_test() { initTestDebuggerServer(); - let gDebuggee = addTestGlobal("test-nesting"); + addTestGlobal("test-nesting"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-nesting", function (aResponse, aTabClient, aThreadClient) { - // Reach over the protocol connection and get a reference to the thread - // actor. - gThreadActor = aThreadClient._transport._serverConnection.getActor(aThreadClient._actor); + attachTestTabAndResume( + gClient, "test-nesting", + function (response, tabClient, threadClient) { + // Reach over the protocol connection and get a reference to the thread + // actor. + gThreadActor = + threadClient._transport._serverConnection.getActor(threadClient._actor); - test_nesting(); - }); + test_nesting(); + }); }); do_test_pending(); } function test_nesting() { const thread = gThreadActor; - const { resolve, reject, promise: p } = promise.defer(); + const { resolve, promise: p } = promise.defer(); // The following things should happen (in order): // 1. In the new event loop (created by unsafeSynchronize) diff --git a/devtools/server/tests/unit/test_nesting-03.js b/devtools/server/tests/unit/test_nesting-03.js index 6a0e5a66b274..d63b247538e6 100644 --- a/devtools/server/tests/unit/test_nesting-03.js +++ b/devtools/server/tests/unit/test_nesting-03.js @@ -1,6 +1,9 @@ /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; // Test that we can detect nested event loops in tabs with the same URL. @@ -13,10 +16,11 @@ function run_test() { // Conect the first client to the first debuggee. gClient1 = new DebuggerClient(DebuggerServer.connectPipe()); gClient1.connect(function () { - attachTestThread(gClient1, "test-nesting1", function (aResponse, aTabClient, aThreadClient) { - gThreadClient1 = aThreadClient; - start_second_connection(); - }); + attachTestThread(gClient1, "test-nesting1", + function (response, tabClient, threadClient) { + gThreadClient1 = threadClient; + start_second_connection(); + }); }); do_test_pending(); } @@ -24,25 +28,24 @@ function run_test() { function start_second_connection() { gClient2 = new DebuggerClient(DebuggerServer.connectPipe()); gClient2.connect(function () { - attachTestThread(gClient2, "test-nesting1", function (aResponse, aTabClient, aThreadClient) { - gThreadClient2 = aThreadClient; - test_nesting(); - }); + attachTestThread(gClient2, "test-nesting1", + function (response, tabClient, threadClient) { + gThreadClient2 = threadClient; + test_nesting(); + }); }); } function test_nesting() { - const { resolve, reject, promise: p } = promise.defer(); + gThreadClient1.resume(response => { + do_check_eq(response.error, "wrongOrder"); + gThreadClient2.resume(response => { + do_check_true(!response.error); + do_check_eq(response.from, gThreadClient2.actor); - gThreadClient1.resume(aResponse => { - do_check_eq(aResponse.error, "wrongOrder"); - gThreadClient2.resume(aResponse => { - do_check_true(!aResponse.error); - do_check_eq(aResponse.from, gThreadClient2.actor); - - gThreadClient1.resume(aResponse => { - do_check_true(!aResponse.error); - do_check_eq(aResponse.from, gThreadClient1.actor); + gThreadClient1.resume(response => { + do_check_true(!response.error); + do_check_eq(response.from, gThreadClient1.actor); gClient1.close(() => finishClient(gClient2)); }); diff --git a/devtools/server/tests/unit/test_new_source-01.js b/devtools/server/tests/unit/test_new_source-01.js index aa249837123a..56827ec48e90 100644 --- a/devtools/server/tests/unit/test_new_source-01.js +++ b/devtools/server/tests/unit/test_new_source-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check basic newSource packet sent from server. */ @@ -9,27 +11,26 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_new_source(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_new_source(); + }); }); do_test_pending(); } -function test_simple_new_source() -{ - gThreadClient.addOneTimeListener("newSource", function (aEvent, aPacket) { - do_check_eq(aEvent, "newSource"); - do_check_eq(aPacket.type, "newSource"); - do_check_true(!!aPacket.source); - do_check_true(!!aPacket.source.url.match(/test_new_source-01.js$/)); +function test_simple_new_source() { + gThreadClient.addOneTimeListener("newSource", function (event, packet) { + do_check_eq(event, "newSource"); + do_check_eq(packet.type, "newSource"); + do_check_true(!!packet.source); + do_check_true(!!packet.source.url.match(/test_new_source-01.js$/)); finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_nsjsinspector.js b/devtools/server/tests/unit/test_nsjsinspector.js index 14a99a308483..7cef47b940f7 100644 --- a/devtools/server/tests/unit/test_nsjsinspector.js +++ b/devtools/server/tests/unit/test_nsjsinspector.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test the basic functionality of the nsIJSInspector component. var gCount = 0; const MAX = 10; @@ -9,17 +11,15 @@ var tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); // Emulate 10 simultaneously-debugged windows from 3 separate client connections. var requestor = (count) => ({ - url:"http://foo/bar/" + count, + url: "http://foo/bar/" + count, connection: "conn" + (count % 3) }); -function run_test() -{ +function run_test() { test_nesting(); } -function test_nesting() -{ +function test_nesting() { do_check_eq(inspector.eventLoopNestLevel, 0); tm.currentThread.dispatch({ run: enterEventLoop}, 0); @@ -33,7 +33,7 @@ function enterEventLoop() { if (gCount++ < MAX) { tm.currentThread.dispatch({ run: enterEventLoop}, 0); - let r = Object.create(requestor(gCount)); + Object.create(requestor(gCount)); do_check_eq(inspector.eventLoopNestLevel, gCount); do_check_eq(inspector.lastNestRequestor.url, requestor(gCount - 1).url); diff --git a/devtools/server/tests/unit/test_objectgrips-01.js b/devtools/server/tests/unit/test_objectgrips-01.js index e1857e5b8667..4199dd7cc283 100644 --- a/devtools/server/tests/unit/test_objectgrips-01.js +++ b/devtools/server/tests/unit/test_objectgrips-01.js @@ -1,56 +1,55 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Object"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getOwnPropertyNames(function (aResponse) { - do_check_eq(aResponse.ownPropertyNames.length, 3); - do_check_eq(aResponse.ownPropertyNames[0], "a"); - do_check_eq(aResponse.ownPropertyNames[1], "b"); - do_check_eq(aResponse.ownPropertyNames[2], "c"); + objClient.getOwnPropertyNames(function (response) { + do_check_eq(response.ownPropertyNames.length, 3); + do_check_eq(response.ownPropertyNames[0], "a"); + do_check_eq(response.ownPropertyNames[1], "b"); + do_check_eq(response.ownPropertyNames[2], "c"); gThreadClient.resume(function () { gClient.close().then(gCallback); }); }); - }); gDebuggee.eval("stopMe({ a: 1, b: true, c: 'foo' })"); diff --git a/devtools/server/tests/unit/test_objectgrips-02.js b/devtools/server/tests/unit/test_objectgrips-02.js index 649d52c64c34..d2705c8b9df5 100644 --- a/devtools/server/tests/unit/test_objectgrips-02.js +++ b/devtools/server/tests/unit/test_objectgrips-02.js @@ -1,65 +1,66 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Object"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getPrototype(function (aResponse) { - do_check_true(aResponse.prototype != undefined); + objClient.getPrototype(function (response) { + do_check_true(response.prototype != undefined); - let protoClient = gThreadClient.pauseGrip(aResponse.prototype); - protoClient.getOwnPropertyNames(function (aResponse) { - do_check_eq(aResponse.ownPropertyNames.length, 2); - do_check_eq(aResponse.ownPropertyNames[0], "b"); - do_check_eq(aResponse.ownPropertyNames[1], "c"); + let protoClient = gThreadClient.pauseGrip(response.prototype); + protoClient.getOwnPropertyNames(function (response) { + do_check_eq(response.ownPropertyNames.length, 2); + do_check_eq(response.ownPropertyNames[0], "b"); + do_check_eq(response.ownPropertyNames[1], "c"); gThreadClient.resume(function () { gClient.close().then(gCallback); }); }); }); - }); gDebuggee.eval(function Constr() { this.a = 1; }.toString()); - gDebuggee.eval("Constr.prototype = { b: true, c: 'foo' }; var o = new Constr(); stopMe(o)"); + gDebuggee.eval( + "Constr.prototype = { b: true, c: 'foo' }; var o = new Constr(); stopMe(o)"); } diff --git a/devtools/server/tests/unit/test_objectgrips-03.js b/devtools/server/tests/unit/test_objectgrips-03.js index 8b19db713abf..280597549bd4 100644 --- a/devtools/server/tests/unit/test_objectgrips-03.js +++ b/devtools/server/tests/unit/test_objectgrips-03.js @@ -1,63 +1,64 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Object"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getProperty("x", function (aResponse) { - do_check_eq(aResponse.descriptor.configurable, true); - do_check_eq(aResponse.descriptor.enumerable, true); - do_check_eq(aResponse.descriptor.writable, true); - do_check_eq(aResponse.descriptor.value, 10); + objClient.getProperty("x", function (response) { + do_check_eq(response.descriptor.configurable, true); + do_check_eq(response.descriptor.enumerable, true); + do_check_eq(response.descriptor.writable, true); + do_check_eq(response.descriptor.value, 10); - objClient.getProperty("y", function (aResponse) { - do_check_eq(aResponse.descriptor.configurable, true); - do_check_eq(aResponse.descriptor.enumerable, true); - do_check_eq(aResponse.descriptor.writable, true); - do_check_eq(aResponse.descriptor.value, "kaiju"); + objClient.getProperty("y", function (response) { + do_check_eq(response.descriptor.configurable, true); + do_check_eq(response.descriptor.enumerable, true); + do_check_eq(response.descriptor.writable, true); + do_check_eq(response.descriptor.value, "kaiju"); - objClient.getProperty("a", function (aResponse) { - do_check_eq(aResponse.descriptor.configurable, true); - do_check_eq(aResponse.descriptor.enumerable, true); - do_check_eq(aResponse.descriptor.get.type, "object"); - do_check_eq(aResponse.descriptor.get.class, "Function"); - do_check_eq(aResponse.descriptor.set.type, "undefined"); + objClient.getProperty("a", function (response) { + do_check_eq(response.descriptor.configurable, true); + do_check_eq(response.descriptor.enumerable, true); + do_check_eq(response.descriptor.get.type, "object"); + do_check_eq(response.descriptor.get.class, "Function"); + do_check_eq(response.descriptor.set.type, "undefined"); gThreadClient.resume(function () { gClient.close().then(gCallback); @@ -65,7 +66,6 @@ function test_object_grip() }); }); }); - }); gDebuggee.eval("stopMe({ x: 10, y: 'kaiju', get a() { return 42; } })"); diff --git a/devtools/server/tests/unit/test_objectgrips-04.js b/devtools/server/tests/unit/test_objectgrips-04.js index 1662358e0215..b12159ec6cce 100644 --- a/devtools/server/tests/unit/test_objectgrips-04.js +++ b/devtools/server/tests/unit/test_objectgrips-04.js @@ -1,74 +1,74 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Object"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.x.configurable, true); - do_check_eq(aResponse.ownProperties.x.enumerable, true); - do_check_eq(aResponse.ownProperties.x.writable, true); - do_check_eq(aResponse.ownProperties.x.value, 10); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.x.configurable, true); + do_check_eq(response.ownProperties.x.enumerable, true); + do_check_eq(response.ownProperties.x.writable, true); + do_check_eq(response.ownProperties.x.value, 10); - do_check_eq(aResponse.ownProperties.y.configurable, true); - do_check_eq(aResponse.ownProperties.y.enumerable, true); - do_check_eq(aResponse.ownProperties.y.writable, true); - do_check_eq(aResponse.ownProperties.y.value, "kaiju"); + do_check_eq(response.ownProperties.y.configurable, true); + do_check_eq(response.ownProperties.y.enumerable, true); + do_check_eq(response.ownProperties.y.writable, true); + do_check_eq(response.ownProperties.y.value, "kaiju"); - do_check_eq(aResponse.ownProperties.a.configurable, true); - do_check_eq(aResponse.ownProperties.a.enumerable, true); - do_check_eq(aResponse.ownProperties.a.get.type, "object"); - do_check_eq(aResponse.ownProperties.a.get.class, "Function"); - do_check_eq(aResponse.ownProperties.a.set.type, "undefined"); + do_check_eq(response.ownProperties.a.configurable, true); + do_check_eq(response.ownProperties.a.enumerable, true); + do_check_eq(response.ownProperties.a.get.type, "object"); + do_check_eq(response.ownProperties.a.get.class, "Function"); + do_check_eq(response.ownProperties.a.set.type, "undefined"); - do_check_true(aResponse.prototype != undefined); + do_check_true(response.prototype != undefined); - let protoClient = gThreadClient.pauseGrip(aResponse.prototype); - protoClient.getOwnPropertyNames(function (aResponse) { - do_check_true(aResponse.ownPropertyNames.toString != undefined); + let protoClient = gThreadClient.pauseGrip(response.prototype); + protoClient.getOwnPropertyNames(function (response) { + do_check_true(response.ownPropertyNames.toString != undefined); gThreadClient.resume(function () { gClient.close().then(gCallback); }); }); }); - }); gDebuggee.eval("stopMe({ x: 10, y: 'kaiju', get a() { return 42; } })"); diff --git a/devtools/server/tests/unit/test_objectgrips-05.js b/devtools/server/tests/unit/test_objectgrips-05.js index 5bbb37d8864d..0e6b6f28ea4d 100644 --- a/devtools/server/tests/unit/test_objectgrips-05.js +++ b/devtools/server/tests/unit/test_objectgrips-05.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * This test checks that frozen objects report themselves as frozen in their * grip. @@ -11,42 +13,40 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1, arg2) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let obj1 = aPacket.frame.arguments[0]; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let obj1 = packet.frame.arguments[0]; do_check_true(obj1.frozen); let obj1Client = gThreadClient.pauseGrip(obj1); do_check_true(obj1Client.isFrozen); - let obj2 = aPacket.frame.arguments[1]; + let obj2 = packet.frame.arguments[1]; do_check_false(obj2.frozen); let obj2Client = gThreadClient.pauseGrip(obj2); diff --git a/devtools/server/tests/unit/test_objectgrips-06.js b/devtools/server/tests/unit/test_objectgrips-06.js index bb9888ab8309..dd4a36c878d0 100644 --- a/devtools/server/tests/unit/test_objectgrips-06.js +++ b/devtools/server/tests/unit/test_objectgrips-06.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * This test checks that sealed objects report themselves as sealed in their * grip. @@ -11,42 +13,40 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1, arg2) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let obj1 = aPacket.frame.arguments[0]; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let obj1 = packet.frame.arguments[0]; do_check_true(obj1.sealed); let obj1Client = gThreadClient.pauseGrip(obj1); do_check_true(obj1Client.isSealed); - let obj2 = aPacket.frame.arguments[1]; + let obj2 = packet.frame.arguments[1]; do_check_false(obj2.sealed); let obj2Client = gThreadClient.pauseGrip(obj2); diff --git a/devtools/server/tests/unit/test_objectgrips-07.js b/devtools/server/tests/unit/test_objectgrips-07.js index 6d9ac11fb3db..c562872a732f 100644 --- a/devtools/server/tests/unit/test_objectgrips-07.js +++ b/devtools/server/tests/unit/test_objectgrips-07.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * This test checks that objects which are not extensible report themselves as * such. @@ -11,37 +13,35 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1, arg2, arg3, arg4) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let [f, s, ne, e] = aPacket.frame.arguments; - let [fClient, sClient, neClient, eClient] = aPacket.frame.arguments.map( +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let [f, s, ne, e] = packet.frame.arguments; + let [fClient, sClient, neClient, eClient] = packet.frame.arguments.map( a => gThreadClient.pauseGrip(a)); do_check_false(f.extensible); diff --git a/devtools/server/tests/unit/test_objectgrips-08.js b/devtools/server/tests/unit/test_objectgrips-08.js index ecaa7146dbd1..71a7039c0c3a 100644 --- a/devtools/server/tests/unit/test_objectgrips-08.js +++ b/devtools/server/tests/unit/test_objectgrips-08.js @@ -1,65 +1,65 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + var gDebuggee; var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; do_check_eq(args[0].class, "Object"); let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getPrototypeAndProperties(function (aResponse) { - do_check_eq(aResponse.ownProperties.a.configurable, true); - do_check_eq(aResponse.ownProperties.a.enumerable, true); - do_check_eq(aResponse.ownProperties.a.writable, true); - do_check_eq(aResponse.ownProperties.a.value.type, "Infinity"); + objClient.getPrototypeAndProperties(function (response) { + do_check_eq(response.ownProperties.a.configurable, true); + do_check_eq(response.ownProperties.a.enumerable, true); + do_check_eq(response.ownProperties.a.writable, true); + do_check_eq(response.ownProperties.a.value.type, "Infinity"); - do_check_eq(aResponse.ownProperties.b.configurable, true); - do_check_eq(aResponse.ownProperties.b.enumerable, true); - do_check_eq(aResponse.ownProperties.b.writable, true); - do_check_eq(aResponse.ownProperties.b.value.type, "-Infinity"); + do_check_eq(response.ownProperties.b.configurable, true); + do_check_eq(response.ownProperties.b.enumerable, true); + do_check_eq(response.ownProperties.b.writable, true); + do_check_eq(response.ownProperties.b.value.type, "-Infinity"); - do_check_eq(aResponse.ownProperties.c.configurable, true); - do_check_eq(aResponse.ownProperties.c.enumerable, true); - do_check_eq(aResponse.ownProperties.c.writable, true); - do_check_eq(aResponse.ownProperties.c.value.type, "NaN"); + do_check_eq(response.ownProperties.c.configurable, true); + do_check_eq(response.ownProperties.c.enumerable, true); + do_check_eq(response.ownProperties.c.writable, true); + do_check_eq(response.ownProperties.c.value.type, "NaN"); - do_check_eq(aResponse.ownProperties.d.configurable, true); - do_check_eq(aResponse.ownProperties.d.enumerable, true); - do_check_eq(aResponse.ownProperties.d.writable, true); - do_check_eq(aResponse.ownProperties.d.value.type, "-0"); + do_check_eq(response.ownProperties.d.configurable, true); + do_check_eq(response.ownProperties.d.enumerable, true); + do_check_eq(response.ownProperties.d.writable, true); + do_check_eq(response.ownProperties.d.value.type, "-0"); gThreadClient.resume(function () { gClient.close().then(gCallback); diff --git a/devtools/server/tests/unit/test_objectgrips-09.js b/devtools/server/tests/unit/test_objectgrips-09.js index 498154b1ed1a..7f521e9cd0be 100644 --- a/devtools/server/tests/unit/test_objectgrips-09.js +++ b/devtools/server/tests/unit/test_objectgrips-09.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + /** * This tests exercises getProtypesAndProperties message accepted * by a thread actor. @@ -10,63 +13,61 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-grips", aServer); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-grips", server); gDebuggee.eval(function stopMe(arg1, arg2) { debugger; }.toString()); - gClient = new DebuggerClient(aServer.connectPipe()); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; - gThreadClient.getPrototypesAndProperties([args[0].actor, args[1].actor], function (aResponse) { - let obj1 = aResponse.actors[args[0].actor]; - let obj2 = aResponse.actors[args[1].actor]; - do_check_eq(obj1.ownProperties.x.configurable, true); - do_check_eq(obj1.ownProperties.x.enumerable, true); - do_check_eq(obj1.ownProperties.x.writable, true); - do_check_eq(obj1.ownProperties.x.value, 10); + gThreadClient.getPrototypesAndProperties( + [args[0].actor, args[1].actor], function (response) { + let obj1 = response.actors[args[0].actor]; + let obj2 = response.actors[args[1].actor]; + do_check_eq(obj1.ownProperties.x.configurable, true); + do_check_eq(obj1.ownProperties.x.enumerable, true); + do_check_eq(obj1.ownProperties.x.writable, true); + do_check_eq(obj1.ownProperties.x.value, 10); - do_check_eq(obj1.ownProperties.y.configurable, true); - do_check_eq(obj1.ownProperties.y.enumerable, true); - do_check_eq(obj1.ownProperties.y.writable, true); - do_check_eq(obj1.ownProperties.y.value, "kaiju"); + do_check_eq(obj1.ownProperties.y.configurable, true); + do_check_eq(obj1.ownProperties.y.enumerable, true); + do_check_eq(obj1.ownProperties.y.writable, true); + do_check_eq(obj1.ownProperties.y.value, "kaiju"); - do_check_eq(obj2.ownProperties.z.configurable, true); - do_check_eq(obj2.ownProperties.z.enumerable, true); - do_check_eq(obj2.ownProperties.z.writable, true); - do_check_eq(obj2.ownProperties.z.value, 123); + do_check_eq(obj2.ownProperties.z.configurable, true); + do_check_eq(obj2.ownProperties.z.enumerable, true); + do_check_eq(obj2.ownProperties.z.writable, true); + do_check_eq(obj2.ownProperties.z.value, 123); - do_check_true(obj1.prototype != undefined); - do_check_true(obj2.prototype != undefined); + do_check_true(obj1.prototype != undefined); + do_check_true(obj2.prototype != undefined); - gThreadClient.resume(function () { - gClient.close().then(gCallback); + gThreadClient.resume(function () { + gClient.close().then(gCallback); + }); }); - }); - }); gDebuggee.eval("stopMe({ x: 10, y: 'kaiju'}, { z: 123 })"); diff --git a/devtools/server/tests/unit/test_objectgrips-10.js b/devtools/server/tests/unit/test_objectgrips-10.js index a5d1b18c6076..7b3eed94d934 100644 --- a/devtools/server/tests/unit/test_objectgrips-10.js +++ b/devtools/server/tests/unit/test_objectgrips-10.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; @@ -7,56 +10,55 @@ var gThreadClient; // Test that closures can be inspected. -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-closures"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-closures", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-closures", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); do_test_pending(); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let person = aPacket.frame.environment.bindings.variables.person; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let person = packet.frame.environment.bindings.variables.person; do_check_eq(person.value.class, "Object"); let personClient = gThreadClient.pauseGrip(person.value); - personClient.getPrototypeAndProperties(aResponse => { - do_check_eq(aResponse.ownProperties.getName.value.class, "Function"); + personClient.getPrototypeAndProperties(response => { + do_check_eq(response.ownProperties.getName.value.class, "Function"); - do_check_eq(aResponse.ownProperties.getAge.value.class, "Function"); + do_check_eq(response.ownProperties.getAge.value.class, "Function"); - do_check_eq(aResponse.ownProperties.getFoo.value.class, "Function"); + do_check_eq(response.ownProperties.getFoo.value.class, "Function"); - let getNameClient = gThreadClient.pauseGrip(aResponse.ownProperties.getName.value); - let getAgeClient = gThreadClient.pauseGrip(aResponse.ownProperties.getAge.value); - let getFooClient = gThreadClient.pauseGrip(aResponse.ownProperties.getFoo.value); - getNameClient.getScope(aResponse => { - do_check_eq(aResponse.scope.bindings.arguments[0].name.value, "Bob"); + let getNameClient = gThreadClient.pauseGrip(response.ownProperties.getName.value); + let getAgeClient = gThreadClient.pauseGrip(response.ownProperties.getAge.value); + let getFooClient = gThreadClient.pauseGrip(response.ownProperties.getFoo.value); + getNameClient.getScope(response => { + do_check_eq(response.scope.bindings.arguments[0].name.value, "Bob"); - getAgeClient.getScope(aResponse => { - do_check_eq(aResponse.scope.bindings.arguments[1].age.value, 58); + getAgeClient.getScope(response => { + do_check_eq(response.scope.bindings.arguments[1].age.value, 58); - getFooClient.getScope(aResponse => { - do_check_eq(aResponse.scope.bindings.variables.foo.value, 10); + getFooClient.getScope(response => { + do_check_eq(response.scope.bindings.variables.foo.value, 10); gThreadClient.resume(() => finishClient(gClient)); }); }); }); }); - }); + /* eslint-disable */ gDebuggee.eval("(" + function () { var PersonFactory = function (name, age) { var foo = 10; @@ -69,4 +71,5 @@ function test_object_grip() var person = new PersonFactory("Bob", 58); debugger; } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_objectgrips-11.js b/devtools/server/tests/unit/test_objectgrips-11.js index 1ad5c353a7be..dea3fb6d9bc4 100644 --- a/devtools/server/tests/unit/test_objectgrips-11.js +++ b/devtools/server/tests/unit/test_objectgrips-11.js @@ -1,14 +1,15 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test that we get the magic properties on Error objects. var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gDebuggee.eval(function stopMe(arg1) { @@ -17,22 +18,22 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_object_grip(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_object_grip(); + }); }); do_test_pending(); } -function test_object_grip() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_object_grip() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; let objClient = gThreadClient.pauseGrip(args[0]); - objClient.getOwnPropertyNames(function (aResponse) { - var opn = aResponse.ownPropertyNames; + objClient.getOwnPropertyNames(function (response) { + let opn = response.ownPropertyNames; do_check_eq(opn.length, 4); opn.sort(); do_check_eq(opn[0], "columnNumber"); @@ -44,7 +45,6 @@ function test_object_grip() finishClient(gClient); }); }); - }); gDebuggee.eval("stopMe(new TypeError('error message text'))"); diff --git a/devtools/server/tests/unit/test_objectgrips-12.js b/devtools/server/tests/unit/test_objectgrips-12.js index 32d4d47e01f8..419a4fe2ec90 100644 --- a/devtools/server/tests/unit/test_objectgrips-12.js +++ b/devtools/server/tests/unit/test_objectgrips-12.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; // Test getDisplayString. @@ -9,8 +12,7 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gDebuggee.eval(function stopMe(arg1) { @@ -19,16 +21,16 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_display_string(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_display_string(); + }); }); do_test_pending(); } -function test_display_string() -{ +function test_display_string() { const testCases = [ { input: "new Boolean(true)", @@ -139,8 +141,8 @@ function test_display_string() PromiseTestUtils.expectUncaughtRejection(/Error/); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - const args = aPacket.frame.arguments; + gThreadClient.addOneTimeListener("paused", function (event, packet) { + const args = packet.frame.arguments; (function loop() { const objClient = gThreadClient.pauseGrip(args.pop()); diff --git a/devtools/server/tests/unit/test_objectgrips-13.js b/devtools/server/tests/unit/test_objectgrips-13.js index 166e8a0d543b..29b3faa699ac 100644 --- a/devtools/server/tests/unit/test_objectgrips-13.js +++ b/devtools/server/tests/unit/test_objectgrips-13.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test that ObjectClient.prototype.getDefinitionSite and the "definitionSite" // request work properly. @@ -8,8 +10,7 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); Components.utils.evalInSandbox(function stopMe() { @@ -18,18 +19,18 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - add_pause_listener(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + add_pause_listener(); + }); }); do_test_pending(); } -function add_pause_listener() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - const [funcGrip, objGrip] = aPacket.frame.arguments; +function add_pause_listener() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + const [funcGrip, objGrip] = packet.frame.arguments; const func = gThreadClient.pauseGrip(funcGrip); const obj = gThreadClient.pauseGrip(objGrip); test_definition_site(func, obj); diff --git a/devtools/server/tests/unit/test_pause_exceptions-01.js b/devtools/server/tests/unit/test_pause_exceptions-01.js index 56ee6816d6da..f2a20dfca4f5 100644 --- a/devtools/server/tests/unit/test_pause_exceptions-01.js +++ b/devtools/server/tests/unit/test_pause_exceptions-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that setting pauseOnExceptions to true will cause the debuggee to pause @@ -10,26 +13,25 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "exception"); - do_check_eq(aPacket.why.exception, 42); +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "exception"); + do_check_eq(packet.why.exception, 42); gThreadClient.resume(function () { finishClient(gClient); }); @@ -38,6 +40,7 @@ function test_pause_frame() gThreadClient.resume(); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { function stopMe() { debugger; @@ -47,4 +50,5 @@ function test_pause_frame() stopMe(); } catch (e) {} } + ")()"); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_pause_exceptions-02.js b/devtools/server/tests/unit/test_pause_exceptions-02.js index fa9b419f0350..74cc816de739 100644 --- a/devtools/server/tests/unit/test_pause_exceptions-02.js +++ b/devtools/server/tests/unit/test_pause_exceptions-02.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that setting pauseOnExceptions to true when the debugger isn't in a * paused state will cause the debuggee to pause when an exceptions is thrown. @@ -10,31 +12,31 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ +function test_pause_frame() { gThreadClient.pauseOnExceptions(true, false, function () { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "exception"); - do_check_eq(aPacket.why.exception, 42); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "exception"); + do_check_eq(packet.why.exception, 42); gThreadClient.resume(function () { finishClient(gClient); }); }); + /* eslint-disable */ gDebuggee.eval("(" + function () { function stopMe() { throw 42; @@ -43,5 +45,6 @@ function test_pause_frame() stopMe(); } catch (e) {} } + ")()"); + /* eslint-enable */ }); } diff --git a/devtools/server/tests/unit/test_pauselifetime-01.js b/devtools/server/tests/unit/test_pauselifetime-01.js index 71c2ddae7ac6..3ad2d56c6e8f 100644 --- a/devtools/server/tests/unit/test_pauselifetime-01.js +++ b/devtools/server/tests/unit/test_pauselifetime-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that pause-lifetime grips go away correctly after a resume. @@ -9,39 +12,37 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let pauseActor = aPacket.actor; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let pauseActor = packet.actor; - // Make a bogus request to the pause-liftime actor. Should get + // Make a bogus request to the pause-lifetime actor. Should get // unrecognized-packet-type (and not no-such-actor). - gClient.request({ to: pauseActor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "unrecognizedPacketType"); + gClient.request({ to: pauseActor, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "unrecognizedPacketType"); gThreadClient.resume(function () { // Now that we've resumed, should get no-such-actor for the // same request. - gClient.request({ to: pauseActor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); + gClient.request({ to: pauseActor, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "noSuchActor"); finishClient(gClient); }); }); - }); }); diff --git a/devtools/server/tests/unit/test_pauselifetime-02.js b/devtools/server/tests/unit/test_pauselifetime-02.js index 6c90725bbe67..c3d4b9254858 100644 --- a/devtools/server/tests/unit/test_pauselifetime-02.js +++ b/devtools/server/tests/unit/test_pauselifetime-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that pause-lifetime grips go away correctly after a resume. @@ -9,38 +12,37 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; let objActor = args[0].actor; do_check_eq(args[0].class, "Object"); do_check_true(!!objActor); // Make a bogus request to the grip actor. Should get // unrecognized-packet-type (and not no-such-actor). - gClient.request({ to: objActor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "unrecognizedPacketType"); + gClient.request({ to: objActor, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "unrecognizedPacketType"); gThreadClient.resume(function () { // Now that we've resumed, should get no-such-actor for the // same request. - gClient.request({ to: objActor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); + gClient.request({ to: objActor, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "noSuchActor"); finishClient(gClient); }); }); @@ -48,7 +50,7 @@ function test_pause_frame() }); gDebuggee.eval("(" + function () { - function stopMe(aObject) { + function stopMe(obj) { debugger; } stopMe({ foo: "bar" }); diff --git a/devtools/server/tests/unit/test_pauselifetime-03.js b/devtools/server/tests/unit/test_pauselifetime-03.js index 9fca887b70c0..eaa5477f55d1 100644 --- a/devtools/server/tests/unit/test_pauselifetime-03.js +++ b/devtools/server/tests/unit/test_pauselifetime-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that pause-lifetime grip clients are marked invalid after a resume. @@ -9,24 +12,23 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; let objActor = args[0].actor; do_check_eq(args[0].class, "Object"); do_check_true(!!objActor); @@ -36,16 +38,16 @@ function test_pause_frame() // Make a bogus request to the grip actor. Should get // unrecognized-packet-type (and not no-such-actor). - gClient.request({ to: objActor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "unrecognizedPacketType"); + gClient.request({ to: objActor, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "unrecognizedPacketType"); do_check_true(objClient.valid); gThreadClient.resume(function () { // Now that we've resumed, should get no-such-actor for the // same request. - gClient.request({ to: objActor, type: "bogusRequest" }, function (aResponse) { + gClient.request({ to: objActor, type: "bogusRequest" }, function (response) { do_check_false(objClient.valid); - do_check_eq(aResponse.error, "noSuchActor"); + do_check_eq(response.error, "noSuchActor"); finishClient(gClient); }); }); @@ -53,7 +55,7 @@ function test_pause_frame() }); gDebuggee.eval("(" + function () { - function stopMe(aObject) { + function stopMe(obj) { debugger; } stopMe({ foo: "bar" }); diff --git a/devtools/server/tests/unit/test_pauselifetime-04.js b/devtools/server/tests/unit/test_pauselifetime-04.js index c863da92155e..27ca291a6a07 100644 --- a/devtools/server/tests/unit/test_pauselifetime-04.js +++ b/devtools/server/tests/unit/test_pauselifetime-04.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that requesting a pause actor for the same value multiple * times returns the same actor. @@ -10,28 +12,27 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-stack"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_pause_frame(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_pause_frame(); + }); }); do_test_pending(); } -function test_pause_frame() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let args = aPacket.frame.arguments; +function test_pause_frame() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let args = packet.frame.arguments; let objActor1 = args[0].actor; - gThreadClient.getFrames(0, 1, function (aResponse) { - let frame = aResponse.frames[0]; + gThreadClient.getFrames(0, 1, function (response) { + let frame = response.frames[0]; do_check_eq(objActor1, frame.arguments[0].actor); gThreadClient.resume(function () { finishClient(gClient); @@ -40,7 +41,7 @@ function test_pause_frame() }); gDebuggee.eval("(" + function () { - function stopMe(aObject) { + function stopMe(obj) { debugger; } stopMe({ foo: "bar" }); diff --git a/devtools/server/tests/unit/test_profiler_activation-01.js b/devtools/server/tests/unit/test_profiler_activation-01.js index 31efbb5e3a77..0fd417585557 100644 --- a/devtools/server/tests/unit/test_profiler_activation-01.js +++ b/devtools/server/tests/unit/test_profiler_activation-01.js @@ -1,5 +1,6 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ "use strict"; @@ -11,8 +12,7 @@ const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); const MAX_PROFILER_ENTRIES = 10000000; -function run_test() -{ +function run_test() { // Ensure the profiler is not running when the test starts (it could // happen if the MOZ_PROFILER_STARTUP environment variable is set). Profiler.StopProfiler(); @@ -41,49 +41,50 @@ function test_activate(client1, actor1, client2, actor2, callback) { do_check_true(typeof response.generation === "number"); // Start the profiler on the first connection.... - client1.request({ to: actor1, type: "startProfiler", entries: MAX_PROFILER_ENTRIES }, response => { - do_check_true(Profiler.IsActive()); - do_check_true(response.started); - do_check_true(typeof response.position === "number"); - do_check_true(typeof response.totalSize === "number"); - do_check_true(typeof response.generation === "number"); - do_check_true(response.position >= 0 && response.position < response.totalSize); - do_check_true(response.totalSize === MAX_PROFILER_ENTRIES); - - // On the next connection just make sure the actor has been instantiated. - client2.request({ to: actor2, type: "isActive" }, response => { + client1.request( + { to: actor1, type: "startProfiler", entries: MAX_PROFILER_ENTRIES }, response => { do_check_true(Profiler.IsActive()); - do_check_true(response.isActive); - do_check_true(response.currentTime > 0); + do_check_true(response.started); do_check_true(typeof response.position === "number"); do_check_true(typeof response.totalSize === "number"); do_check_true(typeof response.generation === "number"); do_check_true(response.position >= 0 && response.position < response.totalSize); do_check_true(response.totalSize === MAX_PROFILER_ENTRIES); - let origConnectionClosed = DebuggerServer._connectionClosed; - - DebuggerServer._connectionClosed = function (conn) { - origConnectionClosed.call(this, conn); - - // The first client is the only actor that started the profiler, - // however the second client can request the accumulated profile data - // at any moment, so the profiler module shouldn't have deactivated. + // On the next connection just make sure the actor has been instantiated. + client2.request({ to: actor2, type: "isActive" }, response => { do_check_true(Profiler.IsActive()); + do_check_true(response.isActive); + do_check_true(response.currentTime > 0); + do_check_true(typeof response.position === "number"); + do_check_true(typeof response.totalSize === "number"); + do_check_true(typeof response.generation === "number"); + do_check_true(response.position >= 0 && response.position < response.totalSize); + do_check_true(response.totalSize === MAX_PROFILER_ENTRIES); + + let origConnectionClosed = DebuggerServer._connectionClosed; DebuggerServer._connectionClosed = function (conn) { origConnectionClosed.call(this, conn); - // Now there are no open clients at all, it should *definitely* - // be deactivated by now. - do_check_false(Profiler.IsActive()); + // The first client is the only actor that started the profiler, + // however the second client can request the accumulated profile data + // at any moment, so the profiler module shouldn't have deactivated. + do_check_true(Profiler.IsActive()); - callback(); + DebuggerServer._connectionClosed = function (conn) { + origConnectionClosed.call(this, conn); + + // Now there are no open clients at all, it should *definitely* + // be deactivated by now. + do_check_false(Profiler.IsActive()); + + callback(); + }; + client2.close(); }; - client2.close(); - }; - client1.close(); + client1.close(); + }); }); - }); }); } diff --git a/devtools/server/tests/unit/test_profiler_activation-02.js b/devtools/server/tests/unit/test_profiler_activation-02.js index cf06b1e06613..69415d112780 100644 --- a/devtools/server/tests/unit/test_profiler_activation-02.js +++ b/devtools/server/tests/unit/test_profiler_activation-02.js @@ -11,13 +11,11 @@ const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); const WAIT_TIME = 1000; // ms -function run_test() -{ +function run_test() { // Ensure the profiler is already running when the test starts. Profiler.StartProfiler(1000000, 1, ["js"], 1); DevToolsUtils.waitForTime(WAIT_TIME).then(() => { - get_chrome_actors((client, form) => { let actor = form.profilerActor; test_start_time(client, actor, () => { diff --git a/devtools/server/tests/unit/test_profiler_bufferstatus.js b/devtools/server/tests/unit/test_profiler_bufferstatus.js index 9c86bf817ed6..df1eda2af330 100644 --- a/devtools/server/tests/unit/test_profiler_bufferstatus.js +++ b/devtools/server/tests/unit/test_profiler_bufferstatus.js @@ -1,5 +1,6 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ "use strict"; @@ -12,8 +13,7 @@ const INITIAL_WAIT_TIME = 100; // ms const MAX_WAIT_TIME = 20000; // ms const MAX_PROFILER_ENTRIES = 10000000; -function run_test() -{ +function run_test() { // Ensure the profiler is not running when the test starts (it could // happen if the MOZ_PROFILER_STARTUP environment variable is set). Profiler.StopProfiler(); @@ -36,8 +36,7 @@ function run_test() do_test_pending(); } -function check_buffer(client, actor, callback) -{ +function check_buffer(client, actor, callback) { client.request({ to: actor, type: "isActive" }, response => { do_check_true(typeof response.position === "number"); do_check_true(typeof response.totalSize === "number"); @@ -51,8 +50,7 @@ function check_buffer(client, actor, callback) }); } -function check_empty_buffer(client, actor, callback) -{ +function check_empty_buffer(client, actor, callback) { client.request({ to: actor, type: "isActive" }, response => { do_check_false(Profiler.IsActive()); do_check_false(response.isActive); @@ -65,19 +63,18 @@ function check_empty_buffer(client, actor, callback) }); } -function activate_profiler(client, actor, callback) -{ - client.request({ to: actor, type: "startProfiler", entries: MAX_PROFILER_ENTRIES }, response => { - do_check_true(response.started); - client.request({ to: actor, type: "isActive" }, response => { - do_check_true(response.isActive); - callback(response.currentTime); +function activate_profiler(client, actor, callback) { + client.request( + { to: actor, type: "startProfiler", entries: MAX_PROFILER_ENTRIES }, response => { + do_check_true(response.started); + client.request({ to: actor, type: "isActive" }, response => { + do_check_true(response.isActive); + callback(response.currentTime); + }); }); - }); } -function deactivate_profiler(client, actor, callback) -{ +function deactivate_profiler(client, actor, callback) { client.request({ to: actor, type: "stopProfiler" }, response => { do_check_false(response.started); client.request({ to: actor, type: "isActive" }, response => { @@ -87,18 +84,15 @@ function deactivate_profiler(client, actor, callback) }); } -function wait_for_samples(client, actor, callback) -{ - function attempt(delay) - { - // No idea why, but Components.stack.sourceLine returns null. - let funcLine = Components.stack.lineNumber - 3; - +function wait_for_samples(client, actor, callback) { + function attempt(delay) { // Spin for the requested time, then take a sample. let start = Date.now(); - let stack; + do_print("Attempt: delay = " + delay); - while (Date.now() - start < delay) { stack = Components.stack; } + while (Date.now() - start < delay) { + /* Empty */ + } do_print("Attempt: finished waiting."); client.request({ to: actor, type: "getProfile" }, response => { @@ -109,14 +103,14 @@ function wait_for_samples(client, actor, callback) if (delay < MAX_WAIT_TIME) { // Double the spin-wait time and try again. do_print("Attempt: no samples, going around again."); - return attempt(delay * 2); + attempt(delay * 2); } else { // We've waited long enough, so just fail. do_print("Attempt: waited a long time, but no samples were collected."); do_print("Giving up."); do_check_true(false); - return; } + return; } callback(); }); diff --git a/devtools/server/tests/unit/test_profiler_close.js b/devtools/server/tests/unit/test_profiler_close.js index a8b3040fdf2d..f7ebec68e99c 100644 --- a/devtools/server/tests/unit/test_profiler_close.js +++ b/devtools/server/tests/unit/test_profiler_close.js @@ -1,5 +1,6 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ "use strict"; @@ -10,8 +11,7 @@ const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); -function run_test() -{ +function run_test() { get_chrome_actors((client1, form1) => { let actor1 = form1.profilerActor; get_chrome_actors((client2, form2) => { @@ -29,8 +29,7 @@ function run_test() do_test_pending(); } -function activate_profiler(client, actor, callback) -{ +function activate_profiler(client, actor, callback) { client.request({ to: actor, type: "startProfiler" }, response => { do_check_true(response.started); do_check_true(Profiler.IsActive()); @@ -42,8 +41,7 @@ function activate_profiler(client, actor, callback) }); } -function deactivate_profiler(client, actor, callback) -{ +function deactivate_profiler(client, actor, callback) { client.request({ to: actor, type: "stopProfiler" }, response => { do_check_false(response.started); do_check_true(Profiler.IsActive()); @@ -55,8 +53,7 @@ function deactivate_profiler(client, actor, callback) }); } -function test_close(client1, actor1, client2, actor2, callback) -{ +function test_close(client1, actor1, client2, actor2, callback) { activate_profiler(client1, actor1, () => { activate_profiler(client2, actor2, () => { deactivate_profiler(client1, actor1, () => { diff --git a/devtools/server/tests/unit/test_profiler_data.js b/devtools/server/tests/unit/test_profiler_data.js index 2a79eed1f1de..65bdd5ffde11 100644 --- a/devtools/server/tests/unit/test_profiler_data.js +++ b/devtools/server/tests/unit/test_profiler_data.js @@ -1,5 +1,6 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ "use strict"; @@ -8,12 +9,10 @@ * it is activated. */ -const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); const INITIAL_WAIT_TIME = 100; // ms const MAX_WAIT_TIME = 20000; // ms -function run_test() -{ +function run_test() { get_chrome_actors((client, form) => { let actor = form.profilerActor; activate_profiler(client, actor, startTime => { @@ -28,8 +27,7 @@ function run_test() do_test_pending(); } -function activate_profiler(client, actor, callback) -{ +function activate_profiler(client, actor, callback) { client.request({ to: actor, type: "startProfiler" }, response => { do_check_true(response.started); client.request({ to: actor, type: "isActive" }, response => { @@ -39,8 +37,7 @@ function activate_profiler(client, actor, callback) }); } -function deactivate_profiler(client, actor, callback) -{ +function deactivate_profiler(client, actor, callback) { client.request({ to: actor, type: "stopProfiler" }, response => { do_check_false(response.started); client.request({ to: actor, type: "isActive" }, response => { @@ -50,18 +47,18 @@ function deactivate_profiler(client, actor, callback) }); } -function test_data(client, actor, startTime, callback) -{ - function attempt(delay) - { +function test_data(client, actor, startTime, callback) { + function attempt(delay) { // No idea why, but Components.stack.sourceLine returns null. - let funcLine = Components.stack.lineNumber - 3; + let funcLine = Components.stack.lineNumber - 2; // Spin for the requested time, then take a sample. let start = Date.now(); let stack; do_print("Attempt: delay = " + delay); - while (Date.now() - start < delay) { stack = Components.stack; } + while (Date.now() - start < delay) { + stack = Components.stack; + } do_print("Attempt: finished waiting."); client.request({ to: actor, type: "getProfile", startTime }, response => { @@ -81,14 +78,14 @@ function test_data(client, actor, startTime, callback) if (delay < MAX_WAIT_TIME) { // Double the spin-wait time and try again. do_print("Attempt: no samples, going around again."); - return attempt(delay * 2); + attempt(delay * 2); } else { // We've waited long enough, so just fail. do_print("Attempt: waited a long time, but no samples were collected."); do_print("Giving up."); do_check_true(false); - return; } + return; } // Now check the samples. At least one sample is expected to diff --git a/devtools/server/tests/unit/test_profiler_events-01.js b/devtools/server/tests/unit/test_profiler_events-01.js index b8ca592b9dd4..484928558116 100644 --- a/devtools/server/tests/unit/test_profiler_events-01.js +++ b/devtools/server/tests/unit/test_profiler_events-01.js @@ -7,7 +7,6 @@ * Tests the event notification service for the profiler actor. */ -const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); const { ProfilerFront } = require("devtools/shared/fronts/profiler"); function run_test() { @@ -36,7 +35,8 @@ add_task(function* () { do_check_true(events[2] === 0); do_check_true(events[3] === 0); - let ret = yield front.registerEventNotifications({ events: ["console-api-profiler", "profiler-started", "profiler-stopped"] }); + let ret = yield front.registerEventNotifications( + { events: ["console-api-profiler", "profiler-started", "profiler-stopped"] }); do_check_true(ret.registered.length === 3); yield front.startProfiler(); @@ -51,7 +51,8 @@ add_task(function* () { do_check_true(events[2] === 1); do_check_true(events[3] === 2, "compatibility events supported for eventNotifications"); - ret = yield front.unregisterEventNotifications({ events: ["console-api-profiler", "profiler-started", "profiler-stopped"] }); + ret = yield front.unregisterEventNotifications( + { events: ["console-api-profiler", "profiler-started", "profiler-stopped"] }); do_check_true(ret.registered.length === 3); }); diff --git a/devtools/server/tests/unit/test_profiler_events-02.js b/devtools/server/tests/unit/test_profiler_events-02.js index fed702043cfc..90a277da266b 100644 --- a/devtools/server/tests/unit/test_profiler_events-02.js +++ b/devtools/server/tests/unit/test_profiler_events-02.js @@ -48,7 +48,8 @@ add_task(function* () { yield waitForTime(500); yield front.stopProfiler(); - do_check_true(eventsCalled === 0, "No 'profiler-status' events should be fired before registering."); + do_check_true(eventsCalled === 0, + "No 'profiler-status' events should be fired before registering."); let ret = yield front.registerEventNotifications({ events: ["profiler-status"] }); do_check_true(ret.registered.length === 1); @@ -56,11 +57,13 @@ add_task(function* () { yield front.startProfiler(); yield handledThreeTimes.promise; yield front.stopProfiler(); - do_check_true(eventsCalled >= 3, "profiler-status fired atleast three times while recording"); + do_check_true(eventsCalled >= 3, + "profiler-status fired atleast three times while recording"); let totalEvents = eventsCalled; yield waitForTime(50); - do_check_true(totalEvents === eventsCalled, "No more profiler-status events after recording."); + do_check_true(totalEvents === eventsCalled, + "No more profiler-status events after recording."); }); function getChromeActors() { diff --git a/devtools/server/tests/unit/test_profiler_getbufferinfo.js b/devtools/server/tests/unit/test_profiler_getbufferinfo.js index 1ec536738179..1214a0d0a9be 100644 --- a/devtools/server/tests/unit/test_profiler_getbufferinfo.js +++ b/devtools/server/tests/unit/test_profiler_getbufferinfo.js @@ -1,5 +1,6 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ "use strict"; @@ -12,8 +13,7 @@ const INITIAL_WAIT_TIME = 100; // ms const MAX_WAIT_TIME = 20000; // ms const MAX_PROFILER_ENTRIES = 10000000; -function run_test() -{ +function run_test() { // Ensure the profiler is not running when the test starts (it could // happen if the MOZ_PROFILER_STARTUP environment variable is set). Profiler.StopProfiler(); @@ -36,8 +36,7 @@ function run_test() do_test_pending(); } -function check_empty_buffer(client, actor, callback) -{ +function check_empty_buffer(client, actor, callback) { client.request({ to: actor, type: "getBufferInfo" }, response => { do_check_true(response.position === 0); do_check_true(response.totalSize === 0); @@ -46,8 +45,7 @@ function check_empty_buffer(client, actor, callback) }); } -function check_buffer(client, actor, callback) -{ +function check_buffer(client, actor, callback) { client.request({ to: actor, type: "getBufferInfo" }, response => { do_check_true(typeof response.position === "number"); do_check_true(typeof response.totalSize === "number"); @@ -61,19 +59,18 @@ function check_buffer(client, actor, callback) }); } -function activate_profiler(client, actor, callback) -{ - client.request({ to: actor, type: "startProfiler", entries: MAX_PROFILER_ENTRIES }, response => { - do_check_true(response.started); - client.request({ to: actor, type: "isActive" }, response => { - do_check_true(response.isActive); - callback(response.currentTime); +function activate_profiler(client, actor, callback) { + client.request( + { to: actor, type: "startProfiler", entries: MAX_PROFILER_ENTRIES }, response => { + do_check_true(response.started); + client.request({ to: actor, type: "isActive" }, response => { + do_check_true(response.isActive); + callback(response.currentTime); + }); }); - }); } -function deactivate_profiler(client, actor, callback) -{ +function deactivate_profiler(client, actor, callback) { client.request({ to: actor, type: "stopProfiler" }, response => { do_check_false(response.started); client.request({ to: actor, type: "isActive" }, response => { @@ -83,18 +80,14 @@ function deactivate_profiler(client, actor, callback) }); } -function wait_for_samples(client, actor, callback) -{ - function attempt(delay) - { - // No idea why, but Components.stack.sourceLine returns null. - let funcLine = Components.stack.lineNumber - 3; - +function wait_for_samples(client, actor, callback) { + function attempt(delay) { // Spin for the requested time, then take a sample. let start = Date.now(); - let stack; + do_print("Attempt: delay = " + delay); - while (Date.now() - start < delay) { stack = Components.stack; } + /* eslint-disable no-empty */ + while (Date.now() - start < delay) {} do_print("Attempt: finished waiting."); client.request({ to: actor, type: "getProfile" }, response => { @@ -105,14 +98,14 @@ function wait_for_samples(client, actor, callback) if (delay < MAX_WAIT_TIME) { // Double the spin-wait time and try again. do_print("Attempt: no samples, going around again."); - return attempt(delay * 2); + attempt(delay * 2); } else { // We've waited long enough, so just fail. do_print("Attempt: waited a long time, but no samples were collected."); do_print("Giving up."); do_check_true(false); - return; } + return; } callback(); }); diff --git a/devtools/server/tests/unit/test_profiler_getfeatures.js b/devtools/server/tests/unit/test_profiler_getfeatures.js index 5b37e7d55bfd..426b625c4b66 100644 --- a/devtools/server/tests/unit/test_profiler_getfeatures.js +++ b/devtools/server/tests/unit/test_profiler_getfeatures.js @@ -7,10 +7,7 @@ * Tests whether the profiler responds to "getFeatures" adequately. */ -const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); - -function run_test() -{ +function run_test() { get_chrome_actors((client, form) => { let actor = form.profilerActor; test_getfeatures(client, actor, () => { @@ -23,8 +20,7 @@ function run_test() do_test_pending(); } -function test_getfeatures(client, actor, callback) -{ +function test_getfeatures(client, actor, callback) { client.request({ to: actor, type: "getFeatures" }, response => { do_check_eq(typeof response.features, "object"); do_check_true(response.features.length >= 1); diff --git a/devtools/server/tests/unit/test_profiler_sharedlibraries.js b/devtools/server/tests/unit/test_profiler_sharedlibraries.js index eac8e6fd4713..2b1cff3f99fd 100644 --- a/devtools/server/tests/unit/test_profiler_sharedlibraries.js +++ b/devtools/server/tests/unit/test_profiler_sharedlibraries.js @@ -7,8 +7,7 @@ * Tests whether the profiler responds to "sharedLibraries" adequately. */ -function run_test() -{ +function run_test() { get_chrome_actors((client, form) => { let actor = form.profilerActor; test_sharedlibraries(client, actor, () => { @@ -21,8 +20,7 @@ function run_test() do_test_pending(); } -function test_sharedlibraries(client, actor, callback) -{ +function test_sharedlibraries(client, actor, callback) { client.request({ to: actor, type: "sharedLibraries" }, libs => { do_check_eq(typeof libs, "object"); do_check_true(Array.isArray(libs)); diff --git a/devtools/server/tests/unit/test_promise_state-01.js b/devtools/server/tests/unit/test_promise_state-01.js index a525560ab267..7f0dbd40a466 100644 --- a/devtools/server/tests/unit/test_promise_state-01.js +++ b/devtools/server/tests/unit/test_promise_state-01.js @@ -1,34 +1,40 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; /** * Test that the preview in a Promise's grip is correct when the Promise is * pending. */ -function run_test() -{ +function run_test() { initTestDebuggerServer(); const debuggee = addTestGlobal("test-promise-state"); const client = new DebuggerClient(DebuggerServer.connectPipe()); client.connect().then(function () { - attachTestTabAndResume(client, "test-promise-state", function (response, tabClient, threadClient) { - Task.spawn(function* () { - const packet = yield executeOnNextTickAndWaitForPause(() => evalCode(debuggee), client); + attachTestTabAndResume( + client, "test-promise-state", + function (response, tabClient, threadClient) { + Task.spawn(function* () { + const packet = yield executeOnNextTickAndWaitForPause( + () => evalCode(debuggee), client); - const grip = packet.frame.environment.bindings.variables.p; - ok(grip.value.preview); - equal(grip.value.class, "Promise"); - equal(grip.value.promiseState.state, "pending"); + const grip = packet.frame.environment.bindings.variables.p; + ok(grip.value.preview); + equal(grip.value.class, "Promise"); + equal(grip.value.promiseState.state, "pending"); - finishClient(client); + finishClient(client); + }); }); - }); }); do_test_pending(); } function evalCode(debuggee) { + /* eslint-disable */ Components.utils.evalInSandbox( "doTest();\n" + function doTest() { @@ -37,4 +43,5 @@ function evalCode(debuggee) { }, debuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_promise_state-02.js b/devtools/server/tests/unit/test_promise_state-02.js index cf44f1946b97..f3b1b724525e 100644 --- a/devtools/server/tests/unit/test_promise_state-02.js +++ b/devtools/server/tests/unit/test_promise_state-02.js @@ -1,36 +1,43 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; /** * Test that the preview in a Promise's grip is correct when the Promise is * fulfilled. */ -function run_test() -{ +function run_test() { initTestDebuggerServer(); const debuggee = addTestGlobal("test-promise-state"); const client = new DebuggerClient(DebuggerServer.connectPipe()); client.connect().then(function () { - attachTestTabAndResume(client, "test-promise-state", function (response, tabClient, threadClient) { - Task.spawn(function* () { - const packet = yield executeOnNextTickAndWaitForPause(() => evalCode(debuggee), client); + attachTestTabAndResume( + client, "test-promise-state", + function (response, tabClient, threadClient) { + Task.spawn(function* () { + const packet = yield executeOnNextTickAndWaitForPause( + () => evalCode(debuggee), client); - const grip = packet.frame.environment.bindings.variables.p; - ok(grip.value.preview); - equal(grip.value.class, "Promise"); - equal(grip.value.promiseState.state, "fulfilled"); - equal(grip.value.promiseState.value.actorID, packet.frame.arguments[0].actorID, - "The promise's fulfilled state value should be the same value passed to the then function"); + const grip = packet.frame.environment.bindings.variables.p; + ok(grip.value.preview); + equal(grip.value.class, "Promise"); + equal(grip.value.promiseState.state, "fulfilled"); + equal(grip.value.promiseState.value.actorID, packet.frame.arguments[0].actorID, + "The promise's fulfilled state value should be the same value passed " + + "to the then function"); - finishClient(client); + finishClient(client); + }); }); - }); }); do_test_pending(); } function evalCode(debuggee) { + /* eslint-disable */ Components.utils.evalInSandbox( "doTest();\n" + function doTest() { @@ -42,4 +49,5 @@ function evalCode(debuggee) { }, debuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_promise_state-03.js b/devtools/server/tests/unit/test_promise_state-03.js index cf64e3e277c5..6b8a993dbd91 100644 --- a/devtools/server/tests/unit/test_promise_state-03.js +++ b/devtools/server/tests/unit/test_promise_state-03.js @@ -1,36 +1,43 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; /** * Test that the preview in a Promise's grip is correct when the Promise is * rejected. */ -function run_test() -{ +function run_test() { initTestDebuggerServer(); const debuggee = addTestGlobal("test-promise-state"); const client = new DebuggerClient(DebuggerServer.connectPipe()); client.connect().then(function () { - attachTestTabAndResume(client, "test-promise-state", function (response, tabClient, threadClient) { - Task.spawn(function* () { - const packet = yield executeOnNextTickAndWaitForPause(() => evalCode(debuggee), client); + attachTestTabAndResume( + client, "test-promise-state", + function (response, tabClient, threadClient) { + Task.spawn(function* () { + const packet = yield executeOnNextTickAndWaitForPause( + () => evalCode(debuggee), client); - const grip = packet.frame.environment.bindings.variables.p; - ok(grip.value.preview); - equal(grip.value.class, "Promise"); - equal(grip.value.promiseState.state, "rejected"); - equal(grip.value.promiseState.reason.actorID, packet.frame.arguments[0].actorID, - "The promise's rejected state reason should be the same value passed to the then function"); + const grip = packet.frame.environment.bindings.variables.p; + ok(grip.value.preview); + equal(grip.value.class, "Promise"); + equal(grip.value.promiseState.state, "rejected"); + equal(grip.value.promiseState.reason.actorID, packet.frame.arguments[0].actorID, + "The promise's rejected state reason should be the same value passed " + + "to the then function"); - finishClient(client); + finishClient(client); + }); }); - }); }); do_test_pending(); } function evalCode(debuggee) { + /* eslint-disable */ Components.utils.evalInSandbox( "doTest();\n" + function doTest() { @@ -42,4 +49,5 @@ function evalCode(debuggee) { }, debuggee ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_promises_actor_attach.js b/devtools/server/tests/unit/test_promises_actor_attach.js index 17c2a1f41620..5d11fb26ef2b 100644 --- a/devtools/server/tests/unit/test_promises_actor_attach.js +++ b/devtools/server/tests/unit/test_promises_actor_attach.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that we can attach and detach to the PromisesActor under the correct * states. diff --git a/devtools/server/tests/unit/test_promises_actor_exist.js b/devtools/server/tests/unit/test_promises_actor_exist.js index 13eef3e9936a..3a8405eed324 100644 --- a/devtools/server/tests/unit/test_promises_actor_exist.js +++ b/devtools/server/tests/unit/test_promises_actor_exist.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that the PromisesActor exists in the TabActors and ChromeActors. diff --git a/devtools/server/tests/unit/test_protocolSpec.js b/devtools/server/tests/unit/test_protocolSpec.js index cc0746387a3f..833daf0f4ff9 100644 --- a/devtools/server/tests/unit/test_protocolSpec.js +++ b/devtools/server/tests/unit/test_protocolSpec.js @@ -1,3 +1,5 @@ +"use strict"; + const run_test = Test(function* () { initTestDebuggerServer(); const connection = DebuggerServer.connectPipe(); diff --git a/devtools/server/tests/unit/test_protocol_abort.js b/devtools/server/tests/unit/test_protocol_abort.js index bb25d1b2ceaa..7136717e6b26 100644 --- a/devtools/server/tests/unit/test_protocol_abort.js +++ b/devtools/server/tests/unit/test_protocol_abort.js @@ -1,14 +1,15 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Outstanding requests should be rejected when the connection aborts * unexpectedly. */ var protocol = require("devtools/shared/protocol"); -var {Arg, Option, RetVal} = protocol; -var events = require("sdk/event/core"); +var {RetVal} = protocol; function simpleHello() { return { diff --git a/devtools/server/tests/unit/test_protocol_async.js b/devtools/server/tests/unit/test_protocol_async.js index 75f0538632ee..736649282bf4 100644 --- a/devtools/server/tests/unit/test_protocol_async.js +++ b/devtools/server/tests/unit/test_protocol_async.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Make sure we get replies in the same order that we sent their * requests even when earlier requests take several event ticks to @@ -8,8 +10,7 @@ */ var protocol = require("devtools/shared/protocol"); -var {Arg, Option, RetVal} = protocol; -var events = require("sdk/event/core"); +var {Arg, RetVal} = protocol; function simpleHello() { return { @@ -98,8 +99,7 @@ var RootFront = protocol.FrontClassWithSpec(rootSpec, { } }); -function run_test() -{ +function run_test() { DebuggerServer.createRootActor = RootActor; DebuggerServer.init(); @@ -116,26 +116,33 @@ function run_test() // Execute a call that won't finish processing until 2 // more calls have happened calls.push(rootClient.promiseReturn(2).then(ret => { - do_check_eq(sequence, 0); // Check right return order - do_check_eq(ret, sequence++); // Check request handling order + // Check right return order + do_check_eq(sequence, 0); + // Check request handling order + do_check_eq(ret, sequence++); })); // Put a few requests into the backlog calls.push(rootClient.simpleReturn().then(ret => { - do_check_eq(sequence, 1); // Check right return order - do_check_eq(ret, sequence++); // Check request handling order + // Check right return order + do_check_eq(sequence, 1); + // Check request handling order + do_check_eq(ret, sequence++); })); calls.push(rootClient.simpleReturn().then(ret => { - do_check_eq(sequence, 2); // Check right return order - do_check_eq(ret, sequence++); // Check request handling order + // Check right return order + do_check_eq(sequence, 2); + // Check request handling order + do_check_eq(ret, sequence++); })); calls.push(rootClient.simpleThrow().then(() => { do_check_true(false, "simpleThrow shouldn't succeed!"); }, error => { - do_check_eq(sequence++, 3); // Check right return order + // Check right return order + do_check_eq(sequence++, 3); })); // While packets are sent in the correct order, rejection handlers @@ -146,15 +153,18 @@ function run_test() calls.push(rootClient.promiseThrow().then(() => { do_check_true(false, "promiseThrow shouldn't succeed!"); }, error => { - do_check_eq(sequence++, 4); // Check right return order + // Check right return order + do_check_eq(sequence++, 4); do_check_true(true, "simple throw should throw"); deferAfterRejection.resolve(); })); calls.push(rootClient.simpleReturn().then(ret => { return deferAfterRejection.promise.then(function () { - do_check_eq(sequence, 5); // Check right return order - do_check_eq(ret, sequence++); // Check request handling order + // Check right return order + do_check_eq(sequence, 5); + // Check request handling order + do_check_eq(ret, sequence++); }); })); @@ -162,15 +172,19 @@ function run_test() // for another simpleReturn before completing calls.push(rootClient.promiseReturn(1).then(ret => { return deferAfterRejection.promise.then(function () { - do_check_eq(sequence, 6); // Check right return order - do_check_eq(ret, sequence++); // Check request handling order + // Check right return order + do_check_eq(sequence, 6); + // Check request handling order + do_check_eq(ret, sequence++); }); })); calls.push(rootClient.simpleReturn().then(ret => { return deferAfterRejection.promise.then(function () { - do_check_eq(sequence, 7); // Check right return order - do_check_eq(ret, sequence++); // Check request handling order + // Check right return order + do_check_eq(sequence, 7); + // Check request handling order + do_check_eq(ret, sequence++); }); })); diff --git a/devtools/server/tests/unit/test_protocol_children.js b/devtools/server/tests/unit/test_protocol_children.js index 67773ebefa8b..caee5492b584 100644 --- a/devtools/server/tests/unit/test_protocol_children.js +++ b/devtools/server/tests/unit/test_protocol_children.js @@ -1,11 +1,14 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; /** * Test simple requests using the protocol helpers. */ var protocol = require("devtools/shared/protocol"); -var {preEvent, types, Arg, Option, RetVal} = protocol; +var {preEvent, types, Arg, RetVal} = protocol; var events = require("sdk/event/core"); @@ -17,8 +20,6 @@ function simpleHello() { }; } -var testTypes = {}; - // Predeclaring the actor type so that it can be used in the // implementation of the child actor. types.addActorType("childActor"); @@ -27,12 +28,12 @@ const childSpec = protocol.generateActorSpec({ typeName: "childActor", events: { - "event1" : { + "event1": { a: Arg(0), b: Arg(1), c: Arg(2) }, - "event2" : { + "event2": { a: Arg(0), b: Arg(1), c: Arg(2) @@ -90,9 +91,13 @@ const childSpec = protocol.generateActorSpec({ var ChildActor = protocol.ActorClassWithSpec(childSpec, { // Actors returned by this actor should be owned by the root actor. - marshallPool: function () { return this.parent(); }, + marshallPool: function () { + return this.parent(); + }, - toString: function () { return "[ChildActor " + this.childID + "]"; }, + toString: function () { + return "[ChildActor " + this.childID + "]"; + }, initialize: function (conn, id) { protocol.Actor.prototype.initialize.call(this, conn); @@ -166,9 +171,13 @@ var ChildFront = protocol.FrontClassWithSpec(childSpec, { protocol.Front.prototype.destroy.call(this); }, - marshallPool: function () { return this.parent(); }, + marshallPool: function () { + return this.parent(); + }, - toString: function () { return "[child front " + this.childID + "]"; }, + toString: function () { + return "[child front " + this.childID + "]"; + }, form: function (form, detail) { if (detail === "actorid") { @@ -183,7 +192,9 @@ var ChildFront = protocol.FrontClassWithSpec(childSpec, { }), onEvent2a: preEvent("event2", function (a, b, c) { - return promise.resolve().then(() => this.event2arg3 = c); + return promise.resolve().then(() => { + this.event2arg3 = c; + }); }), onEvent2b: preEvent("event2", function (a, b, c) { @@ -227,7 +238,9 @@ const rootSpec = protocol.generateActorSpec({ var rootActor = null; var RootActor = protocol.ActorClassWithSpec(rootSpec, { - toString: function () { return "[root actor]"; }, + toString: function () { + return "[root actor]"; + }, initialize: function (conn) { rootActor = this; @@ -264,7 +277,8 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, { getManyChildren: function () { return { - foo: "bar", // note that this isn't in the specialization array. + // note that this isn't in the specialization array. + foo: "bar", child5: this.getChild("child5"), more: [ this.getChild("child6"), this.getChild("child7") ] }; @@ -288,7 +302,9 @@ var RootActor = protocol.ActorClassWithSpec(rootSpec, { }); var RootFront = protocol.FrontClassWithSpec(rootSpec, { - toString: function () { return "[root front]"; }, + toString: function () { + return "[root front]"; + }, initialize: function (client) { this.actorID = "root"; protocol.Front.prototype.initialize.call(this, client); @@ -319,8 +335,7 @@ var RootFront = protocol.FrontClassWithSpec(rootSpec, { }) }); -function run_test() -{ +function run_test() { DebuggerServer.createRootActor = (conn => { return RootActor(conn); }); @@ -329,7 +344,9 @@ function run_test() let trace = connectPipeTracing(); let client = new DebuggerClient(trace); client.connect().then(([applicationType, traits]) => { - trace.expectReceive({"from":"", "applicationType":"xpcshell-tests", "traits":[]}); + trace.expectReceive({"from": "", + "applicationType": "xpcshell-tests", + "traits": []}); do_check_eq(applicationType, "xpcshell-tests"); let rootFront = RootFront(client); @@ -344,8 +361,8 @@ function run_test() }; rootFront.getChild("child1").then(ret => { - trace.expectSend({"type":"getChild", "str":"child1", "to":""}); - trace.expectReceive({"actor":"", "from":""}); + trace.expectSend({"type": "getChild", "str": "child1", "to": ""}); + trace.expectReceive({"actor": "", "from": ""}); childFront = ret; do_check_true(childFront instanceof ChildFront); @@ -355,49 +372,57 @@ function run_test() // Request the child again, make sure the same is returned. return rootFront.getChild("child1"); }).then(ret => { - trace.expectSend({"type":"getChild", "str":"child1", "to":""}); - trace.expectReceive({"actor":"", "from":""}); + trace.expectSend({"type": "getChild", "str": "child1", "to": ""}); + trace.expectReceive({"actor": "", "from": ""}); expectRootChildren(1); do_check_true(ret === childFront); }).then(() => { return childFront.echo("hello"); }).then(ret => { - trace.expectSend({"type":"echo", "str":"hello", "to":""}); - trace.expectReceive({"str":"hello", "from":""}); + trace.expectSend({"type": "echo", "str": "hello", "to": ""}); + trace.expectReceive({"str": "hello", "from": ""}); do_check_eq(ret, "hello"); }).then(() => { return childFront.getDetail1(); }).then(ret => { - trace.expectSend({"type":"getDetail1", "to":""}); - trace.expectReceive({"actor":"", "childID":"child1", "detail":"detail1", "from":""}); + trace.expectSend({"type": "getDetail1", "to": ""}); + trace.expectReceive({"actor": "", + "childID": "child1", + "detail": "detail1", + "from": ""}); do_check_true(ret === childFront); do_check_eq(childFront.detail, "detail1"); }).then(() => { return childFront.getDetail2(); }).then(ret => { - trace.expectSend({"type":"getDetail2", "to":""}); - trace.expectReceive({"actor":"", "childID":"child1", "detail":"detail2", "from":""}); + trace.expectSend({"type": "getDetail2", "to": ""}); + trace.expectReceive({"actor": "", + "childID": "child1", + "detail": "detail2", + "from": ""}); do_check_true(ret === childFront); do_check_eq(childFront.detail, "detail2"); }).then(() => { return childFront.getIDDetail(); }).then(ret => { - trace.expectSend({"type":"getIDDetail", "to":""}); - trace.expectReceive({"idDetail": childFront.actorID, "from":""}); + trace.expectSend({"type": "getIDDetail", "to": ""}); + trace.expectReceive({"idDetail": childFront.actorID, "from": ""}); do_check_true(ret === childFront); }).then(() => { return childFront.getSibling("siblingID"); }).then(ret => { - trace.expectSend({"type":"getSibling", "id":"siblingID", "to":""}); - trace.expectReceive({"sibling":{"actor":"", "childID":"siblingID"}, "from":""}); + trace.expectSend({"type": "getSibling", "id": "siblingID", "to": ""}); + trace.expectReceive({"sibling": {"actor": "", "childID": "siblingID"}, + "from": ""}); expectRootChildren(2); }).then(ret => { return rootFront.getTemporaryChild("temp1").then(temp1 => { - trace.expectSend({"type":"getTemporaryChild", "id":"temp1", "to":""}); - trace.expectReceive({"child":{"actor":"", "childID":"temp1"}, "from":""}); + trace.expectSend({"type": "getTemporaryChild", "id": "temp1", "to": ""}); + trace.expectReceive({"child": {"actor": "", "childID": "temp1"}, + "from": ""}); // At this point we expect two direct children, plus the temporary holder // which should hold 1 itself. @@ -406,8 +431,11 @@ function run_test() expectRootChildren(3); return rootFront.getTemporaryChild("temp2").then(temp2 => { - trace.expectSend({"type":"getTemporaryChild", "id":"temp2", "to":""}); - trace.expectReceive({"child":{"actor":"", "childID":"temp2"}, "from":""}); + trace.expectSend({"type": "getTemporaryChild", + "id": "temp2", + "to": ""}); + trace.expectReceive({"child": {"actor": "", "childID": "temp2"}, + "from": ""}); // Same amount of direct children, and an extra in the temporary holder. expectRootChildren(3); @@ -416,12 +444,11 @@ function run_test() // Get the children of the temporary holder... let checkActors = rootActor._temporaryHolder.__poolMap.values(); - let checkFronts = rootFront._temporaryHolder.__poolMap.values(); // Now release the temporary holders and expect them to drop again. return rootFront.clearTemporaryChildren().then(() => { - trace.expectSend({"type":"clearTemporaryChildren", "to":""}); - trace.expectReceive({"from":""}); + trace.expectSend({"type": "clearTemporaryChildren", "to": ""}); + trace.expectReceive({"from": ""}); expectRootChildren(2); do_check_false(!!rootActor._temporaryHolder); @@ -436,8 +463,12 @@ function run_test() }).then(ret => { return rootFront.getChildren(["child1", "child2"]); }).then(ret => { - trace.expectSend({"type":"getChildren", "ids":["child1", "child2"], "to":""}); - trace.expectReceive({"children":[{"actor":"", "childID":"child1"}, {"actor":"", "childID":"child2"}], "from":""}); + trace.expectSend({"type": "getChildren", + "ids": ["child1", "child2"], + "to": ""}); + trace.expectReceive({"children": [{"actor": "", "childID": "child1"}, + {"actor": "", "childID": "child2"}], + "from": ""}); expectRootChildren(3); do_check_true(ret[0] === childFront); @@ -448,7 +479,8 @@ function run_test() // going to trigger events on the first child, so an event // triggered on the second should cause immediate failures. - let set = new Set(["event1", "event2", "named-event", "object-event", "array-object-event"]); + let set = new Set(["event1", "event2", "named-event", + "object-event", "array-object-event"]); childFront.on("event1", (a, b, c) => { do_check_eq(a, 1); @@ -497,22 +529,36 @@ function run_test() ret[1].on("array-object-event", fail); return childFront.emitEvents().then(() => { - trace.expectSend({"type":"emitEvents", "to":""}); - trace.expectReceive({"type":"event1", "a":1, "b":2, "c":3, "from":""}); - trace.expectReceive({"type":"event2", "a":4, "b":5, "c":6, "from":""}); - trace.expectReceive({"type":"namedEvent", "a":1, "b":2, "c":3, "from":""}); - trace.expectReceive({"type":"objectEvent", "detail":{"actor":"", "childID":"child1", "detail":"detail1"}, "from":""}); - trace.expectReceive({"type":"arrayObjectEvent", "detail":[{"actor":"", "childID":"child1", "detail":"detail2"}], "from":""}); - trace.expectReceive({"value":"correct response", "from":""}); - + trace.expectSend({"type": "emitEvents", "to": ""}); + trace.expectReceive({"type": "event1", "a": 1, "b": 2, "c": 3, + "from": ""}); + trace.expectReceive({"type": "event2", "a": 4, "b": 5, "c": 6, + "from": ""}); + trace.expectReceive({"type": "namedEvent", "a": 1, "b": 2, "c": 3, + "from": ""}); + trace.expectReceive({"type": "objectEvent", + "detail": {"actor": "", + "childID": "child1", + "detail": "detail1"}, + "from": ""}); + trace.expectReceive({"type": "arrayObjectEvent", + "detail": [{"actor": "", + "childID": "child1", + "detail": "detail2"}], + "from": ""}); + trace.expectReceive({"value": "correct response", "from": ""}); do_check_eq(set.size, 0); }); }).then(ret => { return rootFront.getManyChildren(); }).then(ret => { - trace.expectSend({"type":"getManyChildren", "to":""}); - trace.expectReceive({"foo":"bar", "child5":{"actor":"", "childID":"child5"}, "more":[{"actor":"", "childID":"child6"}, {"actor":"", "childID":"child7"}], "from":""}); + trace.expectSend({"type": "getManyChildren", "to": ""}); + trace.expectReceive({"foo": "bar", + "child5": {"actor": "", "childID": "child5"}, + "more": [{"actor": "", "childID": "child6"}, + {"actor": "", "childID": "child7"}], + "from": ""}); // Check all the crazy stuff we did in getManyChildren do_check_eq(ret.foo, "bar"); diff --git a/devtools/server/tests/unit/test_protocol_formtype.js b/devtools/server/tests/unit/test_protocol_formtype.js index 27ac0bee9456..5fa0bd5f67b9 100644 --- a/devtools/server/tests/unit/test_protocol_formtype.js +++ b/devtools/server/tests/unit/test_protocol_formtype.js @@ -1,5 +1,7 @@ +"use strict"; + var protocol = require("devtools/shared/protocol"); -var {Arg, Option, RetVal} = protocol; +var {RetVal} = protocol; protocol.types.addActorType("child"); protocol.types.addActorType("root"); @@ -171,6 +173,7 @@ const run_test = Test(function* () { yield rootFront.getUnknownDetail(); do_check_true(false); } catch (ex) { + // empty } yield client.close(); diff --git a/devtools/server/tests/unit/test_protocol_longstring.js b/devtools/server/tests/unit/test_protocol_longstring.js index c37f4251ec99..2cfd5025e14c 100644 --- a/devtools/server/tests/unit/test_protocol_longstring.js +++ b/devtools/server/tests/unit/test_protocol_longstring.js @@ -1,11 +1,14 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable max-nested-callbacks */ + +"use strict"; /** * Test simple requests using the protocol helpers. */ var protocol = require("devtools/shared/protocol"); -var {RetVal, Arg, Option} = protocol; +var {RetVal, Arg} = protocol; var events = require("sdk/event/core"); var {LongStringActor} = require("devtools/server/actors/string"); @@ -20,7 +23,9 @@ function simpleHello() { }; } -DebuggerServer.LONG_STRING_LENGTH = DebuggerServer.LONG_STRING_INITIAL_LENGTH = DebuggerServer.LONG_STRING_READ_LENGTH = 5; +DebuggerServer.LONG_STRING_LENGTH = + DebuggerServer.LONG_STRING_INITIAL_LENGTH = + DebuggerServer.LONG_STRING_READ_LENGTH = 5; var SHORT_STR = "abc"; var LONG_STR = "abcdefghijklmnop"; @@ -89,8 +94,7 @@ var RootFront = protocol.FrontClassWithSpec(rootSpec, { } }); -function run_test() -{ +function run_test() { DebuggerServer.createRootActor = (conn => { return RootActor(conn); }); @@ -107,18 +111,19 @@ function run_test() do_check_eq(rootClient.__poolMap.size, size + 1); }; - client.connect().then(([applicationType, traits]) => { rootClient = RootFront(client); // Root actor has no children yet. expectRootChildren(0); - trace.expectReceive({"from":"", "applicationType":"xpcshell-tests", "traits":[]}); + trace.expectReceive({"from": "", + "applicationType": "xpcshell-tests", + "traits": []}); do_check_eq(applicationType, "xpcshell-tests"); rootClient.shortString().then(ret => { - trace.expectSend({"type":"shortString", "to":""}); - trace.expectReceive({"value":"abc", "from":""}); + trace.expectSend({"type": "shortString", "to": ""}); + trace.expectReceive({"value": "abc", "from": ""}); // Should only own the one reference (itself) at this point. expectRootChildren(0); @@ -130,8 +135,12 @@ function run_test() }).then(() => { return rootClient.longString(); }).then(ret => { - trace.expectSend({"type":"longString", "to":""}); - trace.expectReceive({"value":{"type":"longString", "actor":"", "length":16, "initial":"abcde"}, "from":""}); + trace.expectSend({"type": "longString", "to": ""}); + trace.expectReceive({"value": {"type": "longString", + "actor": "", + "length": 16, + "initial": "abcde"}, + "from": ""}); strfront = ret; // Should own a reference to itself and an extra string now. @@ -139,34 +148,36 @@ function run_test() }).then(() => { return strfront.string(); }).then(ret => { - trace.expectSend({"type":"substring", "start":5, "end":10, "to":""}); - trace.expectReceive({"substring":"fghij", "from":""}); - trace.expectSend({"type":"substring", "start":10, "end":15, "to":""}); - trace.expectReceive({"substring":"klmno", "from":""}); - trace.expectSend({"type":"substring", "start":15, "end":20, "to":""}); - trace.expectReceive({"substring":"p", "from":""}); + trace.expectSend({"type": "substring", "start": 5, "end": 10, "to": ""}); + trace.expectReceive({"substring": "fghij", "from": ""}); + trace.expectSend({"type": "substring", "start": 10, "end": 15, "to": ""}); + trace.expectReceive({"substring": "klmno", "from": ""}); + trace.expectSend({"type": "substring", "start": 15, "end": 20, "to": ""}); + trace.expectReceive({"substring": "p", "from": ""}); do_check_eq(ret, LONG_STR); }).then(() => { return strfront.release(); }).then(() => { - trace.expectSend({"type":"release", "to":""}); - trace.expectReceive({"from":""}); + trace.expectSend({"type": "release", "to": ""}); + trace.expectReceive({"from": ""}); // That reference should be removed now. expectRootChildren(0); }).then(() => { let deferred = promise.defer(); rootClient.once("string-event", (str) => { - trace.expectSend({"type":"emitShortString", "to":""}); - trace.expectReceive({"type":"string-event", "str":"abc", "from":""}); + trace.expectSend({"type": "emitShortString", "to": ""}); + trace.expectReceive({"type": "string-event", "str": "abc", "from": ""}); do_check_true(!!str); strfront = str; // Shouldn't generate any new references expectRootChildren(0); // will generate no packets. - strfront.string().then((value) => { deferred.resolve(value); }); + strfront.string().then((value) => { + deferred.resolve(value); + }); }); rootClient.emitShortString(); return deferred.promise; @@ -178,20 +189,34 @@ function run_test() }).then(() => { let deferred = promise.defer(); rootClient.once("string-event", (str) => { - trace.expectSend({"type":"emitLongString", "to":""}); - trace.expectReceive({"type":"string-event", "str":{"type":"longString", "actor":"", "length":16, "initial":"abcde"}, "from":""}); + trace.expectSend({"type": "emitLongString", "to": ""}); + trace.expectReceive({"type": "string-event", + "str": {"type": "longString", + "actor": "", + "length": 16, + "initial": "abcde"}, + "from": ""}); do_check_true(!!str); // Should generate one new reference expectRootChildren(1); strfront = str; strfront.string().then((value) => { - trace.expectSend({"type":"substring", "start":5, "end":10, "to":""}); - trace.expectReceive({"substring":"fghij", "from":""}); - trace.expectSend({"type":"substring", "start":10, "end":15, "to":""}); - trace.expectReceive({"substring":"klmno", "from":""}); - trace.expectSend({"type":"substring", "start":15, "end":20, "to":""}); - trace.expectReceive({"substring":"p", "from":""}); + trace.expectSend({"type": "substring", + "start": 5, + "end": 10, + "to": ""}); + trace.expectReceive({"substring": "fghij", "from": ""}); + trace.expectSend({"type": "substring", + "start": 10, + "end": 15, + "to": ""}); + trace.expectReceive({"substring": "klmno", "from": ""}); + trace.expectSend({"type": "substring", + "start": 15, + "end": 20, + "to": ""}); + trace.expectReceive({"substring": "p", "from": ""}); deferred.resolve(value); }); @@ -203,8 +228,8 @@ function run_test() }).then(() => { return strfront.release(); }).then(() => { - trace.expectSend({"type":"release", "to":""}); - trace.expectReceive({"from":""}); + trace.expectSend({"type": "release", "to": ""}); + trace.expectReceive({"from": ""}); expectRootChildren(0); }).then(() => { client.close().then(() => { diff --git a/devtools/server/tests/unit/test_protocol_simple.js b/devtools/server/tests/unit/test_protocol_simple.js index c85003954923..c19550afc381 100644 --- a/devtools/server/tests/unit/test_protocol_simple.js +++ b/devtools/server/tests/unit/test_protocol_simple.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test simple requests using the protocol helpers. */ @@ -173,8 +175,7 @@ var RootFront = protocol.FrontClassWithSpec(rootSpec, { } }); -function run_test() -{ +function run_test() { DebuggerServer.createRootActor = (conn => { return RootActor(conn); }); @@ -185,6 +186,7 @@ function run_test() missing: preEvent("missing-event", function () { }) }); + void badActor; }); protocol.types.getType("array:array:array:number"); @@ -198,20 +200,22 @@ function run_test() let rootClient; client.connect().then(([applicationType, traits]) => { - trace.expectReceive({"from":"", "applicationType":"xpcshell-tests", "traits":[]}); + trace.expectReceive({"from": "", + "applicationType": "xpcshell-tests", + "traits": []}); do_check_eq(applicationType, "xpcshell-tests"); rootClient = RootFront(client); rootClient.simpleReturn().then(ret => { - trace.expectSend({"type":"simpleReturn", "to":""}); - trace.expectReceive({"value":1, "from":""}); + trace.expectSend({"type": "simpleReturn", "to": ""}); + trace.expectReceive({"value": 1, "from": ""}); do_check_eq(ret, 1); }).then(() => { return rootClient.promiseReturn(); }).then(ret => { - trace.expectSend({"type":"promiseReturn", "to":""}); - trace.expectReceive({"value":1, "from":""}); + trace.expectSend({"type": "promiseReturn", "to": ""}); + trace.expectReceive({"value": 1, "from": ""}); do_check_eq(ret, 1); }).then(() => { // Missing argument should throw an exception @@ -221,15 +225,23 @@ function run_test() return rootClient.simpleArgs(5, 10); }).then(ret => { - trace.expectSend({"type":"simpleArgs", "firstArg":5, "secondArg":10, "to":""}); - trace.expectReceive({"firstResponse":6, "secondResponse":11, "from":""}); + trace.expectSend({"type": "simpleArgs", + "firstArg": 5, + "secondArg": 10, + "to": ""}); + trace.expectReceive({"firstResponse": 6, + "secondResponse": 11, + "from": ""}); do_check_eq(ret.firstResponse, 6); do_check_eq(ret.secondResponse, 11); }).then(() => { return rootClient.nestedArgs(1, 2, 3); }).then(ret => { - trace.expectSend({"type":"nestedArgs", "firstArg":1, "nest":{"secondArg":2, "nest":{"thirdArg":3}}, "to":""}); - trace.expectReceive({"a":1, "b":2, "c":3, "from":""}); + trace.expectSend({"type": "nestedArgs", + "firstArg": 1, + "nest": {"secondArg": 2, "nest": {"thirdArg": 3}}, + "to": ""}); + trace.expectReceive({"a": 1, "b": 2, "c": 3, "from": ""}); do_check_eq(ret.a, 1); do_check_eq(ret.b, 2); do_check_eq(ret.c, 3); @@ -239,56 +251,59 @@ function run_test() "option2": 10 }); }).then(ret => { - trace.expectSend({"type":"optionArgs", "option1":5, "option2":10, "to":""}); - trace.expectReceive({"option1":5, "option2":10, "from":""}); + trace.expectSend({"type": "optionArgs", + "option1": 5, + "option2": 10, + "to": ""}); + trace.expectReceive({"option1": 5, "option2": 10, "from": ""}); do_check_eq(ret.option1, 5); do_check_eq(ret.option2, 10); }).then(() => { return rootClient.optionArgs({}); }).then(ret => { - trace.expectSend({"type":"optionArgs", "to":""}); - trace.expectReceive({"from":""}); + trace.expectSend({"type": "optionArgs", "to": ""}); + trace.expectReceive({"from": ""}); do_check_true(typeof (ret.option1) === "undefined"); do_check_true(typeof (ret.option2) === "undefined"); }).then(() => { // Explicitly call an optional argument... return rootClient.optionalArgs(5, 10); }).then(ret => { - trace.expectSend({"type":"optionalArgs", "a":5, "b":10, "to":""}); - trace.expectReceive({"value":10, "from":""}); + trace.expectSend({"type": "optionalArgs", "a": 5, "b": 10, "to": ""}); + trace.expectReceive({"value": 10, "from": ""}); do_check_eq(ret, 10); }).then(() => { // Now don't pass the optional argument, expect the default. return rootClient.optionalArgs(5); }).then(ret => { - trace.expectSend({"type":"optionalArgs", "a":5, "to":""}); - trace.expectReceive({"value":200, "from":""}); + trace.expectSend({"type": "optionalArgs", "a": 5, "to": ""}); + trace.expectReceive({"value": 200, "from": ""}); do_check_eq(ret, 200); }).then(ret => { return rootClient.arrayArgs([0, 1, 2, 3, 4, 5]); }).then(ret => { - trace.expectSend({"type":"arrayArgs", "a":[0, 1, 2, 3, 4, 5], "to":""}); - trace.expectReceive({"arrayReturn":[0, 1, 2, 3, 4, 5], "from":""}); + trace.expectSend({"type": "arrayArgs", "a": [0, 1, 2, 3, 4, 5], "to": ""}); + trace.expectReceive({"arrayReturn": [0, 1, 2, 3, 4, 5], "from": ""}); do_check_eq(ret[0], 0); do_check_eq(ret[5], 5); }).then(() => { return rootClient.arrayArgs([[5]]); }).then(ret => { - trace.expectSend({"type":"arrayArgs", "a":[[5]], "to":""}); - trace.expectReceive({"arrayReturn":[[5]], "from":""}); + trace.expectSend({"type": "arrayArgs", "a": [[5]], "to": ""}); + trace.expectReceive({"arrayReturn": [[5]], "from": ""}); do_check_eq(ret[0][0], 5); }).then(() => { return rootClient.renamedEcho("hello"); }).then(str => { - trace.expectSend({"type":"echo", "a":"hello", "to":""}); - trace.expectReceive({"value":"hello", "from":""}); + trace.expectSend({"type": "echo", "a": "hello", "to": ""}); + trace.expectReceive({"value": "hello", "from": ""}); do_check_eq(str, "hello"); let deferred = promise.defer(); rootClient.on("oneway", (response) => { - trace.expectSend({"type":"testOneWay", "a":"hello", "to":""}); - trace.expectReceive({"type":"oneway", "a":"hello", "from":""}); + trace.expectSend({"type": "testOneWay", "a": "hello", "to": ""}); + trace.expectReceive({"type": "oneway", "a": "hello", "from": ""}); do_check_eq(response, "hello"); deferred.resolve(); @@ -298,8 +313,11 @@ function run_test() }).then(() => { let deferred = promise.defer(); rootClient.on("falsyOptions", res => { - trace.expectSend({"type":"emitFalsyOptions", "to":""}); - trace.expectReceive({"type":"falsyOptions", "farce":false, "zero": 0, "from":""}); + trace.expectSend({"type": "emitFalsyOptions", "to": ""}); + trace.expectReceive({"type": "falsyOptions", + "farce": false, + "zero": 0, + "from": ""}); do_check_true(res.zero === 0); do_check_true(res.farce === false); diff --git a/devtools/server/tests/unit/test_protocol_stack.js b/devtools/server/tests/unit/test_protocol_stack.js index a81f99a8ea3c..123a64da7bce 100644 --- a/devtools/server/tests/unit/test_protocol_stack.js +++ b/devtools/server/tests/unit/test_protocol_stack.js @@ -11,8 +11,7 @@ */ var protocol = require("devtools/shared/protocol"); -var {Arg, Option, RetVal} = protocol; -var events = require("sdk/event/core"); +var {RetVal} = protocol; function simpleHello() { return { diff --git a/devtools/server/tests/unit/test_protocol_unregister.js b/devtools/server/tests/unit/test_protocol_unregister.js index 5b32dd0a3920..8f3d76e6c1f1 100644 --- a/devtools/server/tests/unit/test_protocol_unregister.js +++ b/devtools/server/tests/unit/test_protocol_unregister.js @@ -1,11 +1,11 @@ +"use strict"; + const {types} = require("devtools/shared/protocol"); - -function run_test() -{ +function run_test() { types.addType("test", { - read: (v) => { return "successful read: " + v; }, - write: (v) => { return "successful write: " + v; } + read: (v) => "successful read: " + v, + write: (v) => "successful write: " + v }); // Verify the type registered correctly. @@ -38,7 +38,5 @@ function run_test() } catch (ex) { do_check_eq(ex.toString(), "Error: Using defunct type: test"); } - } - diff --git a/devtools/server/tests/unit/test_reattach-thread.js b/devtools/server/tests/unit/test_reattach-thread.js index 6d089e896fbe..d78db1ee4ab2 100644 --- a/devtools/server/tests/unit/test_reattach-thread.js +++ b/devtools/server/tests/unit/test_reattach-thread.js @@ -1,14 +1,15 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that reattaching to a previously detached thread works. */ var gClient, gDebuggee, gThreadClient, gTabClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = testGlobal("test-reattach"); DebuggerServer.addTestGlobal(gDebuggee); @@ -16,25 +17,23 @@ function run_test() let transport = DebuggerServer.connectPipe(); gClient = new DebuggerClient(transport); gClient.connect().then(() => { - attachTestTab(gClient, "test-reattach", (aReply, aTabClient) => { - gTabClient = aTabClient; + attachTestTab(gClient, "test-reattach", (reply, tabClient) => { + gTabClient = tabClient; test_attach(); }); }); do_test_pending(); } -function test_attach() -{ - gTabClient.attachThread({}, (aResponse, aThreadClient) => { - do_check_eq(aThreadClient.state, "paused"); - gThreadClient = aThreadClient; - aThreadClient.resume(test_detach); +function test_attach() { + gTabClient.attachThread({}, (response, threadClient) => { + do_check_eq(threadClient.state, "paused"); + gThreadClient = threadClient; + threadClient.resume(test_detach); }); } -function test_detach() -{ +function test_detach() { gThreadClient.detach(() => { do_check_eq(gThreadClient.state, "detached"); do_check_eq(gTabClient.thread, null); @@ -42,17 +41,15 @@ function test_detach() }); } -function test_reattach() -{ - gTabClient.attachThread({}, (aResponse, aThreadClient) => { - do_check_neq(gThreadClient, aThreadClient); - do_check_eq(aThreadClient.state, "paused"); - do_check_eq(gTabClient.thread, aThreadClient); - aThreadClient.resume(cleanup); +function test_reattach() { + gTabClient.attachThread({}, (response, threadClient) => { + do_check_neq(gThreadClient, threadClient); + do_check_eq(threadClient.state, "paused"); + do_check_eq(gTabClient.thread, threadClient); + threadClient.resume(cleanup); }); } -function cleanup() -{ +function cleanup() { gClient.close().then(do_test_finished); } diff --git a/devtools/server/tests/unit/test_registerClient.js b/devtools/server/tests/unit/test_registerClient.js index c018e4454c1a..3fdb746918d3 100644 --- a/devtools/server/tests/unit/test_registerClient.js +++ b/devtools/server/tests/unit/test_registerClient.js @@ -1,12 +1,13 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + // Test the DebuggerClient.registerClient API var EventEmitter = require("devtools/shared/event-emitter"); var gClient; -var gActors; var gTestClient; function TestActor(conn) { @@ -49,8 +50,7 @@ TestClient.prototype = { } }; -function run_test() -{ +function run_test() { DebuggerServer.addGlobalActor(TestActor); DebuggerServer.init(); @@ -62,20 +62,17 @@ function run_test() run_next_test(); } -function init() -{ +function init() { gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect() .then(() => gClient.listTabs()) - .then(aResponse => { - gActors = aResponse; - gTestClient = new TestClient(gClient, aResponse); + .then(response => { + gTestClient = new TestClient(gClient, response); run_next_test(); }); } -function test_client_events() -{ +function test_client_events() { // Test DebuggerClient.registerClient and DebuggerServerConnection.sendActorEvent gTestClient.on("foo", function (type, data) { do_check_eq(type, "foo"); diff --git a/devtools/server/tests/unit/test_register_actor.js b/devtools/server/tests/unit/test_register_actor.js index c67e43986aba..818757d11e0e 100644 --- a/devtools/server/tests/unit/test_register_actor.js +++ b/devtools/server/tests/unit/test_register_actor.js @@ -3,18 +3,19 @@ "use strict"; -const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); - function check_actors(expect) { - do_check_eq(expect, DebuggerServer.tabActorFactories.hasOwnProperty("registeredActor1")); - do_check_eq(expect, DebuggerServer.tabActorFactories.hasOwnProperty("registeredActor2")); + do_check_eq(expect, + DebuggerServer.tabActorFactories.hasOwnProperty("registeredActor1")); + do_check_eq(expect, + DebuggerServer.tabActorFactories.hasOwnProperty("registeredActor2")); - do_check_eq(expect, DebuggerServer.globalActorFactories.hasOwnProperty("registeredActor2")); - do_check_eq(expect, DebuggerServer.globalActorFactories.hasOwnProperty("registeredActor1")); + do_check_eq(expect, + DebuggerServer.globalActorFactories.hasOwnProperty("registeredActor2")); + do_check_eq(expect, + DebuggerServer.globalActorFactories.hasOwnProperty("registeredActor1")); } -function run_test() -{ +function run_test() { // Allow incoming connections. DebuggerServer.init(); DebuggerServer.addBrowserActors(); @@ -74,19 +75,19 @@ function test_lazy_api() { client.connect().then(function onConnect() { client.listTabs(onListTabs); }); - function onListTabs(aResponse) { + function onListTabs(response) { // On listTabs, the actor is still not loaded, // but we can see its name in the list of available actors do_check_false(isActorLoaded); do_check_false(isActorInstanciated); - do_check_true("lazyActor" in aResponse); + do_check_true("lazyActor" in response); let {LazyFront} = require("xpcshell-test/registertestactors-03"); - let front = LazyFront(client, aResponse); + let front = LazyFront(client, response); front.hello().then(onRequest); } - function onRequest(aResponse) { - do_check_eq(aResponse, "world"); + function onRequest(response) { + do_check_eq(response, "world"); // Finally, the actor is loaded on the first request being made to it do_check_true(isActorLoaded); diff --git a/devtools/server/tests/unit/test_requestTypes.js b/devtools/server/tests/unit/test_requestTypes.js index 694e276bcada..7bafaa33e897 100644 --- a/devtools/server/tests/unit/test_requestTypes.js +++ b/devtools/server/tests/unit/test_requestTypes.js @@ -5,29 +5,27 @@ const { RootActor } = require("devtools/server/actors/root"); -function test_requestTypes_request(aClient, anActor) -{ - aClient.request({ to: "root", type: "requestTypes" }, function (aResponse) { - var expectedRequestTypes = Object.keys(RootActor. - prototype. - requestTypes); +function test_requestTypes_request(client, anActor) { + client.request({ to: "root", type: "requestTypes" }, function (response) { + let expectedRequestTypes = Object.keys(RootActor + .prototype + .requestTypes); - do_check_true(Array.isArray(aResponse.requestTypes)); - do_check_eq(JSON.stringify(aResponse.requestTypes), + do_check_true(Array.isArray(response.requestTypes)); + do_check_eq(JSON.stringify(response.requestTypes), JSON.stringify(expectedRequestTypes)); - aClient.close().then(() => { + client.close().then(() => { do_test_finished(); }); }); } -function run_test() -{ +function run_test() { DebuggerServer.init(); DebuggerServer.addBrowserActors(); - var client = new DebuggerClient(DebuggerServer.connectPipe()); + let client = new DebuggerClient(DebuggerServer.connectPipe()); client.connect().then(function () { test_requestTypes_request(client); }); diff --git a/devtools/server/tests/unit/test_safe-getter.js b/devtools/server/tests/unit/test_safe-getter.js index 08949154d06c..3517f89ccb0f 100644 --- a/devtools/server/tests/unit/test_safe-getter.js +++ b/devtools/server/tests/unit/test_safe-getter.js @@ -1,9 +1,10 @@ +/* eslint-disable strict */ function run_test() { Components.utils.import("resource://gre/modules/jsdebugger.jsm"); addDebuggerToGlobal(this); - var g = testGlobal("test"); - var dbg = new Debugger(); - var gw = dbg.addDebuggee(g); + let g = testGlobal("test"); + let dbg = new Debugger(); + let gw = dbg.addDebuggee(g); g.eval(` // This is not a CCW. diff --git a/devtools/server/tests/unit/test_setBreakpoint-on-column-with-no-offsets-at-end-of-line.js b/devtools/server/tests/unit/test_setBreakpoint-on-column-with-no-offsets-at-end-of-line.js index 6185cf589bc0..d6691f616174 100644 --- a/devtools/server/tests/unit/test_setBreakpoint-on-column-with-no-offsets-at-end-of-line.js +++ b/devtools/server/tests/unit/test_setBreakpoint-on-column-with-no-offsets-at-end-of-line.js @@ -27,7 +27,7 @@ function run_test() { let sourceClient = threadClient.source(source); let location = { line: 4, column: 23 }; - let [packet, breakpointClient] = yield setBreakpoint(sourceClient, location); + let [packet, ] = yield setBreakpoint(sourceClient, location); do_check_true(packet.isPending); do_check_false("actualLocation" in packet); diff --git a/devtools/server/tests/unit/test_source-01.js b/devtools/server/tests/unit/test_source-01.js index 3401cc660613..595c5dbd879b 100644 --- a/devtools/server/tests/unit/test_source-01.js +++ b/devtools/server/tests/unit/test_source-01.js @@ -1,6 +1,9 @@ /* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; var gDebuggee; var gClient; @@ -10,8 +13,7 @@ var gThreadClient; // and that they can communicate over the protocol to fetch the source text for // a given script. -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); Cu.evalInSandbox( @@ -25,10 +27,11 @@ function run_test() gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_source(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_source(); + }); }); do_test_pending(); } @@ -36,31 +39,30 @@ function run_test() const SOURCE_URL = "http://example.com/foobar.js"; const SOURCE_CONTENT = "stopMe()"; -function test_source() -{ +function test_source() { DebuggerServer.LONG_STRING_LENGTH = 200; - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.getSources(function (aResponse) { - do_check_true(!!aResponse); - do_check_true(!!aResponse.sources); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getSources(function (response) { + do_check_true(!!response); + do_check_true(!!response.sources); - let source = aResponse.sources.filter(function (s) { + let source = response.sources.filter(function (s) { return s.url === SOURCE_URL; })[0]; do_check_true(!!source); let sourceClient = gThreadClient.source(source); - sourceClient.source(function (aResponse) { - do_check_true(!!aResponse); - do_check_true(!aResponse.error); - do_check_true(!!aResponse.contentType); - do_check_true(aResponse.contentType.includes("javascript")); + sourceClient.source(function (response) { + do_check_true(!!response); + do_check_true(!response.error); + do_check_true(!!response.contentType); + do_check_true(response.contentType.includes("javascript")); - do_check_true(!!aResponse.source); + do_check_true(!!response.source); do_check_eq(SOURCE_CONTENT, - aResponse.source); + response.source); gThreadClient.resume(function () { finishClient(gClient); diff --git a/devtools/server/tests/unit/test_sourcemaps-01.js b/devtools/server/tests/unit/test_sourcemaps-01.js index 4d92bf9ccf9c..1fdc8b609977 100644 --- a/devtools/server/tests/unit/test_sourcemaps-01.js +++ b/devtools/server/tests/unit/test_sourcemaps-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check basic source map integration with the "newSource" packet in the RDP. */ @@ -11,36 +13,35 @@ var gThreadClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_source_map(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_source_map(); + }); }); do_test_pending(); } -function test_simple_source_map() -{ +function test_simple_source_map() { // Because we are source mapping, we should be notified of a.js, b.js, and // c.js as sources, and shouldn't receive abc.js or test_sourcemaps-01.js. let expectedSources = new Set(["http://example.com/www/js/a.js", "http://example.com/www/js/b.js", "http://example.com/www/js/c.js"]); - gThreadClient.addListener("newSource", function _onNewSource(aEvent, aPacket) { - do_check_eq(aEvent, "newSource"); - do_check_eq(aPacket.type, "newSource"); - do_check_true(!!aPacket.source); + gThreadClient.addListener("newSource", function _onNewSource(event, packet) { + do_check_eq(event, "newSource"); + do_check_eq(packet.type, "newSource"); + do_check_true(!!packet.source); - do_check_true(expectedSources.has(aPacket.source.url), + do_check_true(expectedSources.has(packet.source.url), "The source url should be one of our original sources."); - expectedSources.delete(aPacket.source.url); + expectedSources.delete(packet.source.url); if (expectedSources.size === 0) { gClient.removeListener("newSource", _onNewSource); diff --git a/devtools/server/tests/unit/test_sourcemaps-02.js b/devtools/server/tests/unit/test_sourcemaps-02.js index 2a343afaad8a..80d665382a4b 100644 --- a/devtools/server/tests/unit/test_sourcemaps-02.js +++ b/devtools/server/tests/unit/test_sourcemaps-02.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check basic source map integration with the "sources" packet in the RDP. */ @@ -11,33 +13,32 @@ var gThreadClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_source_map(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_source_map(); + }); }); do_test_pending(); } -function test_simple_source_map() -{ +function test_simple_source_map() { // Because we are source mapping, we should be notified of a.js, b.js, and // c.js as sources, and shouldn"t receive abc.js or test_sourcemaps-01.js. let expectedSources = new Set(["http://example.com/www/js/a.js", "http://example.com/www/js/b.js", "http://example.com/www/js/c.js"]); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.getSources(function (aResponse) { - do_check_true(!aResponse.error, "Should not get an error"); + gClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.getSources(function (response) { + do_check_true(!response.error, "Should not get an error"); - for (let s of aResponse.sources) { + for (let s of response.sources) { do_check_neq(s.url, "http://example.com/www/js/abc.js", "Shouldn't get the generated source's url."); expectedSources.delete(s.url); diff --git a/devtools/server/tests/unit/test_sourcemaps-03.js b/devtools/server/tests/unit/test_sourcemaps-03.js index 2fbd99aad538..58f229e9a38e 100644 --- a/devtools/server/tests/unit/test_sourcemaps-03.js +++ b/devtools/server/tests/unit/test_sourcemaps-03.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check setting breakpoints in source mapped sources. */ @@ -11,27 +13,26 @@ var gThreadClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_source_map(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_source_map(); + }); }); do_test_pending(); } -function testBreakpointMapping(aName, aCallback) -{ +function testBreakpointMapping(name, callback) { Task.spawn(function* () { let response = yield waitForPause(gThreadClient); do_check_eq(response.why.type, "debuggerStatement"); - const source = yield getSource(gThreadClient, "http://example.com/www/js/" + aName + ".js"); + const source = yield getSource(gThreadClient, "http://example.com/www/js/" + name + ".js"); response = yield setBreakpoint(source, { // Setting the breakpoint on an empty line so that it is pushed down one // line and we can check the source mapped actualLocation later. @@ -47,7 +48,7 @@ function testBreakpointMapping(aName, aCallback) // because of our breakpoint, we resume again to finish the eval, and // finally receive our last pause which has the result of the client // evaluation. - response = yield gThreadClient.eval(null, aName + "()"); + response = yield gThreadClient.eval(null, name + "()"); do_check_eq(response.type, "resumed"); response = yield waitForPause(gThreadClient); @@ -62,11 +63,11 @@ function testBreakpointMapping(aName, aCallback) response = yield waitForPause(gThreadClient); do_check_eq(response.why.type, "clientEvaluated"); - do_check_eq(response.why.frameFinished.return, aName); + do_check_eq(response.why.frameFinished.return, name); response = yield resume(gThreadClient); - aCallback(); + callback(); }); gDebuggee.eval("(" + function () { @@ -74,26 +75,27 @@ function testBreakpointMapping(aName, aCallback) } + "());"); } -function test_simple_source_map() -{ +function test_simple_source_map() { let expectedSources = new Set([ "http://example.com/www/js/a.js", "http://example.com/www/js/b.js", "http://example.com/www/js/c.js" ]); - gThreadClient.addListener("newSource", function _onNewSource(aEvent, aPacket) { - expectedSources.delete(aPacket.source.url); + gThreadClient.addListener("newSource", function _onNewSource(event, packet) { + expectedSources.delete(packet.source.url); if (expectedSources.size > 0) { return; } gThreadClient.removeListener("newSource", _onNewSource); + function finish() { + finishClient(gClient); + } + testBreakpointMapping("a", function () { testBreakpointMapping("b", function () { - testBreakpointMapping("c", function () { - finishClient(gClient); - }); + testBreakpointMapping("c", finish); }); }); }); diff --git a/devtools/server/tests/unit/test_sourcemaps-04.js b/devtools/server/tests/unit/test_sourcemaps-04.js index 5fecb44c856a..cd9f25c9331f 100644 --- a/devtools/server/tests/unit/test_sourcemaps-04.js +++ b/devtools/server/tests/unit/test_sourcemaps-04.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that absolute source map urls work. */ @@ -9,36 +11,35 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_absolute_source_map(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_absolute_source_map(); + }); }); do_test_pending(); } -function test_absolute_source_map() -{ - gThreadClient.addOneTimeListener("newSource", function _onNewSource(aEvent, aPacket) { - do_check_eq(aEvent, "newSource"); - do_check_eq(aPacket.type, "newSource"); - do_check_true(!!aPacket.source); +function test_absolute_source_map() { + gThreadClient.addOneTimeListener("newSource", function _onNewSource(event, packet) { + do_check_eq(event, "newSource"); + do_check_eq(packet.type, "newSource"); + do_check_true(!!packet.source); - do_check_true(aPacket.source.url.indexOf("sourcemapped.coffee") !== -1, + do_check_true(packet.source.url.indexOf("sourcemapped.coffee") !== -1, "The new source should be a coffee file."); - do_check_eq(aPacket.source.url.indexOf("sourcemapped.js"), -1, + do_check_eq(packet.source.url.indexOf("sourcemapped.js"), -1, "The new source should not be a js file."); finishClient(gClient); }); - code = readFile("sourcemapped.js") + let code = readFile("sourcemapped.js") + "\n//# sourceMappingURL=" + getFileUrl("source-map-data/sourcemapped.map"); Components.utils.evalInSandbox(code, gDebuggee, "1.8", diff --git a/devtools/server/tests/unit/test_sourcemaps-05.js b/devtools/server/tests/unit/test_sourcemaps-05.js index edc9178dbb19..4e4e54db2ba4 100644 --- a/devtools/server/tests/unit/test_sourcemaps-05.js +++ b/devtools/server/tests/unit/test_sourcemaps-05.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that relative source map urls work. */ @@ -9,36 +11,35 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_relative_source_map(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_relative_source_map(); + }); }); do_test_pending(); } -function test_relative_source_map() -{ - gThreadClient.addOneTimeListener("newSource", function _onNewSource(aEvent, aPacket) { - do_check_eq(aEvent, "newSource"); - do_check_eq(aPacket.type, "newSource"); - do_check_true(!!aPacket.source); +function test_relative_source_map() { + gThreadClient.addOneTimeListener("newSource", function _onNewSource(event, packet) { + do_check_eq(event, "newSource"); + do_check_eq(packet.type, "newSource"); + do_check_true(!!packet.source); - do_check_true(aPacket.source.url.indexOf("sourcemapped.coffee") !== -1, + do_check_true(packet.source.url.indexOf("sourcemapped.coffee") !== -1, "The new source should be a coffee file."); - do_check_eq(aPacket.source.url.indexOf("sourcemapped.js"), -1, + do_check_eq(packet.source.url.indexOf("sourcemapped.js"), -1, "The new source should not be a js file."); finishClient(gClient); }); - code = readFile("sourcemapped.js") + let code = readFile("sourcemapped.js") + "\n//# sourceMappingURL=source-map-data/sourcemapped.map"; Components.utils.evalInSandbox(code, gDebuggee, "1.8", diff --git a/devtools/server/tests/unit/test_sourcemaps-06.js b/devtools/server/tests/unit/test_sourcemaps-06.js index 41b518753bc9..3f0b3eb01bab 100644 --- a/devtools/server/tests/unit/test_sourcemaps-06.js +++ b/devtools/server/tests/unit/test_sourcemaps-06.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that we can load sources whose content is embedded in the * "sourcesContent" field of a source map. @@ -12,34 +14,33 @@ var gThreadClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_source_content(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_source_content(); + }); }); do_test_pending(); } -function test_source_content() -{ +function test_source_content() { let numNewSources = 0; - gThreadClient.addListener("newSource", function _onNewSource(aEvent, aPacket) { + gThreadClient.addListener("newSource", function _onNewSource(event, packet) { if (++numNewSources !== 3) { return; } gThreadClient.removeListener("newSource", _onNewSource); - gThreadClient.getSources(function (aResponse) { - do_check_true(!aResponse.error, "Should not get an error"); + gThreadClient.getSources(function (response) { + do_check_true(!response.error, "Should not get an error"); - testContents(aResponse.sources, 0, (timesCalled) => { + testContents(response.sources, 0, (timesCalled) => { do_check_eq(timesCalled, 3); finishClient(gClient); }); @@ -72,23 +73,21 @@ function testContents(sources, timesCalled, callback) { return; } - let source = sources[0]; let sourceClient = gThreadClient.source(sources[0]); if (sourceClient.url) { - sourceClient.source((aResponse) => { - do_check_true(!aResponse.error, + sourceClient.source((response) => { + do_check_true(!response.error, "Should not get an error loading the source from sourcesContent"); let expectedContent = "content for " + source.url; - do_check_eq(aResponse.source, expectedContent, + do_check_eq(response.source, expectedContent, "Should have the expected source content"); testContents(sources.slice(1), timesCalled + 1, callback); }); - } - else { + } else { testContents(sources.slice(1), timesCalled, callback); } } diff --git a/devtools/server/tests/unit/test_sourcemaps-07.js b/devtools/server/tests/unit/test_sourcemaps-07.js index b8a9462c0902..90cd38ee2e31 100644 --- a/devtools/server/tests/unit/test_sourcemaps-07.js +++ b/devtools/server/tests/unit/test_sourcemaps-07.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Test that we don't permanently cache sources from source maps. @@ -11,22 +14,21 @@ var gThreadClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_cached_original_sources(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_cached_original_sources(); + }); }); do_test_pending(); } -function test_cached_original_sources() -{ +function test_cached_original_sources() { writeFile("temp.js", "initial content"); gThreadClient.addOneTimeListener("newSource", onNewSource); @@ -39,26 +41,26 @@ function test_cached_original_sources() }); code += "//# sourceMappingURL=data:text/json;base64," + btoa(map.toString()); - Components.utils.evalInSandbox(code, gDebuggee, "1.8", "http://example.com/www/js/abc.js", 1); } -function onNewSource(aEvent, aPacket) { - let sourceClient = gThreadClient.source(aPacket.source); - sourceClient.source(function (aResponse) { - do_check_true(!aResponse.error, +function onNewSource(event, packet) { + let sourceClient = gThreadClient.source(packet.source); + sourceClient.source(function (response) { + do_check_true(!response.error, "Should not be an error grabbing the source"); - do_check_eq(aResponse.source, "initial content", + do_check_eq(response.source, "initial content", "The correct source content should be sent"); writeFile("temp.js", "new content"); - sourceClient.source(function (aResponse) { - do_check_true(!aResponse.error, + sourceClient.source(function (response) { + do_check_true(!response.error, "Should not be an error grabbing the source"); - do_check_eq(aResponse.source, "new content", - "The correct source content should not be cached, so we should get the new content"); + do_check_eq(response.source, "new content", + "The correct source content should not be cached, " + + "so we should get the new content"); do_get_file("temp.js").remove(false); finishClient(gClient); diff --git a/devtools/server/tests/unit/test_sourcemaps-08.js b/devtools/server/tests/unit/test_sourcemaps-08.js index b23665e43979..b0c5f84b80bf 100644 --- a/devtools/server/tests/unit/test_sourcemaps-08.js +++ b/devtools/server/tests/unit/test_sourcemaps-08.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Regression test for bug 882986 regarding sourcesContent and absolute source * URLs. @@ -10,24 +12,23 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_source_maps(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_source_maps(); + }); }); do_test_pending(); } -function test_source_maps() -{ - gThreadClient.addOneTimeListener("newSource", function (aEvent, aPacket) { - let sourceClient = gThreadClient.source(aPacket.source); +function test_source_maps() { + gThreadClient.addOneTimeListener("newSource", function (event, packet) { + let sourceClient = gThreadClient.source(packet.source); sourceClient.source(function ({error, source}) { do_check_true(!error, "should be able to grab the source"); do_check_eq(source, "foo", diff --git a/devtools/server/tests/unit/test_sourcemaps-09.js b/devtools/server/tests/unit/test_sourcemaps-09.js index c317cf72370b..012d83b9343d 100644 --- a/devtools/server/tests/unit/test_sourcemaps-09.js +++ b/devtools/server/tests/unit/test_sourcemaps-09.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that source maps and breakpoints work with minified javascript. */ @@ -9,48 +11,43 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_minified(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_minified(); + }); }); do_test_pending(); } -function test_minified() -{ - let newSourceFired = false; +function test_minified() { + gThreadClient.addOneTimeListener("newSource", function _onNewSource(event, packet) { + do_check_eq(event, "newSource"); + do_check_eq(packet.type, "newSource"); + do_check_true(!!packet.source); - gThreadClient.addOneTimeListener("newSource", function _onNewSource(aEvent, aPacket) { - do_check_eq(aEvent, "newSource"); - do_check_eq(aPacket.type, "newSource"); - do_check_true(!!aPacket.source); - - do_check_eq(aPacket.source.url, "http://example.com/foo.js", + do_check_eq(packet.source.url, "http://example.com/foo.js", "The new source should be foo.js"); - do_check_eq(aPacket.source.url.indexOf("foo.min.js"), -1, + do_check_eq(packet.source.url.indexOf("foo.min.js"), -1, "The new source should not be the minified file"); - - newSourceFired = true; }); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aEvent, "paused"); - do_check_eq(aPacket.why.type, "debuggerStatement"); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(event, "paused"); + do_check_eq(packet.why.type, "debuggerStatement"); let location = { line: 5 }; getSource(gThreadClient, "http://example.com/foo.js").then(source => { - source.setBreakpoint(location, function (aResponse, bpClient) { - do_check_true(!aResponse.error); + source.setBreakpoint(location, function (response, bpClient) { + do_check_true(!response.error); testHitBreakpoint(); }); }); @@ -71,6 +68,7 @@ function test_minified() // } // }()); + // eslint-disable-next-line max-len let code = '(function(){debugger;function r(r){var n=r+r;var u=null;return n}for(var n=0;n<10;n++){r(n)}})();\n//# sourceMappingURL=data:text/json,{"file":"foo.min.js","version":3,"sources":["foo.js"],"names":["foo","n","bar","unused","i"],"mappings":"CAAC,WACC,QACA,SAASA,GAAIC,GACX,GAAIC,GAAMD,EAAIA,CACd,IAAIE,GAAS,IACb,OAAOD,GAET,IAAK,GAAIE,GAAI,EAAGA,EAAI,GAAIA,IAAK,CAC3BJ,EAAII"}'; Components.utils.evalInSandbox(code, gDebuggee, "1.8", @@ -78,11 +76,11 @@ function test_minified() } function testHitBreakpoint(timesHit = 0) { - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gClient.addOneTimeListener("paused", function (event, packet) { ++timesHit; - do_check_eq(aEvent, "paused"); - do_check_eq(aPacket.why.type, "breakpoint"); + do_check_eq(event, "paused"); + do_check_eq(packet.why.type, "breakpoint"); if (timesHit === 10) { gThreadClient.resume(() => finishClient(gClient)); diff --git a/devtools/server/tests/unit/test_sourcemaps-10.js b/devtools/server/tests/unit/test_sourcemaps-10.js index e955dc8fb525..bc66fdbd7dd2 100644 --- a/devtools/server/tests/unit/test_sourcemaps-10.js +++ b/devtools/server/tests/unit/test_sourcemaps-10.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that we source map frame locations for the frame we are paused at. */ @@ -16,20 +18,22 @@ function run_test() { gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - promise.resolve(define_code()) - .then(run_code) - .then(test_frame_location) - .then(null, error => { - dump(error + "\n"); - dump(error.stack); - do_check_true(false); - }) - .then(() => { - finishClient(gClient); - }); - }); + attachTestTabAndResume( + gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + promise.resolve(define_code()) + .then(run_code) + .then(test_frame_location) + .then(null, error => { + dump(error + "\n"); + dump(error.stack); + do_check_true(false); + }) + .then(() => { + finishClient(gClient); + }); + }); }); do_test_pending(); } @@ -58,8 +62,8 @@ function define_code() { function run_code() { const d = promise.defer(); - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - d.resolve(aPacket); + gClient.addOneTimeListener("paused", function (event, packet) { + d.resolve(packet); gThreadClient.resume(); }); gDebuggee.a(); diff --git a/devtools/server/tests/unit/test_sourcemaps-11.js b/devtools/server/tests/unit/test_sourcemaps-11.js index e598c4c0975d..8993a32d0176 100644 --- a/devtools/server/tests/unit/test_sourcemaps-11.js +++ b/devtools/server/tests/unit/test_sourcemaps-11.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that we source map frame locations returned by "frames" requests. */ @@ -16,20 +18,22 @@ function run_test() { gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - promise.resolve(define_code()) - .then(run_code) - .then(test_frames) - .then(null, error => { - dump(error + "\n"); - dump(error.stack); - do_check_true(false); - }) - .then(() => { - finishClient(gClient); - }); - }); + attachTestTabAndResume( + gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + promise.resolve(define_code()) + .then(run_code) + .then(test_frames) + .then(null, error => { + dump(error + "\n"); + dump(error.stack); + do_check_true(false); + }) + .then(() => { + finishClient(gClient); + }); + }); }); do_test_pending(); } @@ -59,8 +63,8 @@ function define_code() { function run_code() { const d = promise.defer(); gClient.addOneTimeListener("paused", function () { - gThreadClient.getFrames(0, 3, function (aResponse) { - d.resolve(aResponse); + gThreadClient.getFrames(0, 3, function (response) { + d.resolve(response); gThreadClient.resume(); }); }); @@ -76,8 +80,8 @@ function test_frames({ error, frames }) { check_frame(frames[2], "http://example.com/www/js/a.js"); } -function check_frame({ where: { source, line, column } }, aExpectedUrl) { - do_check_eq(source.url, aExpectedUrl); +function check_frame({ where: { source, line, column } }, expectedUrl) { + do_check_eq(source.url, expectedUrl); do_check_eq(line, 2); do_check_eq(column, 0); } diff --git a/devtools/server/tests/unit/test_sourcemaps-12.js b/devtools/server/tests/unit/test_sourcemaps-12.js index cb7f29920514..1148e3711c38 100644 --- a/devtools/server/tests/unit/test_sourcemaps-12.js +++ b/devtools/server/tests/unit/test_sourcemaps-12.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that we continue stepping when a single original source's line * corresponds to multiple generated js lines. @@ -17,10 +19,11 @@ function run_test() { gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - define_code(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + define_code(); + }); }); do_test_pending(); } @@ -51,17 +54,17 @@ function define_code() { } function run_code() { - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "debuggerStatement"); + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "debuggerStatement"); step_in(); }); gDebuggee.runTest(); } function step_in() { - gClient.addOneTimeListener("paused", function (aEvent, aPacket) { - do_check_eq(aPacket.why.type, "resumeLimit"); - let { frame: { environment, where: { source, line } } } = aPacket; + gClient.addOneTimeListener("paused", function (event, packet) { + do_check_eq(packet.why.type, "resumeLimit"); + let { frame: { environment, where: { source, line } } } = packet; // Stepping should have moved us to the next source mapped line. do_check_eq(source.url, "http://example.com/a.js"); do_check_eq(line, 3); diff --git a/devtools/server/tests/unit/test_sourcemaps-13.js b/devtools/server/tests/unit/test_sourcemaps-13.js index 203731fda5a9..ac00a9d247e9 100644 --- a/devtools/server/tests/unit/test_sourcemaps-13.js +++ b/devtools/server/tests/unit/test_sourcemaps-13.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that we don't permanently cache source maps across reloads. */ @@ -12,17 +14,17 @@ var gTabClient; const {SourceNode} = require("source-map"); -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - gTabClient = aTabClient; - setup_code(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + gTabClient = tabClient; + setup_code(); + }); }); do_test_pending(); } @@ -92,7 +94,7 @@ function test_new_sources() { // Should now have TEMP_FILE_2 as a source. do_check_eq(sources.length, 1); - let s = sources.filter(s => s.url === getFileUrl(TEMP_FILE_2, true))[0]; + let s = sources.filter(source => source.url === getFileUrl(TEMP_FILE_2, true))[0]; do_check_true(!!s); finish_test(); diff --git a/devtools/server/tests/unit/test_sourcemaps-16.js b/devtools/server/tests/unit/test_sourcemaps-16.js index 4df9ece23cb7..e3defc02713f 100644 --- a/devtools/server/tests/unit/test_sourcemaps-16.js +++ b/devtools/server/tests/unit/test_sourcemaps-16.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Verify that we can load the contents of every source in a source map produced * by babel and browserify. @@ -9,8 +11,7 @@ var gDebuggee; var gClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-sourcemaps"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); @@ -20,19 +21,21 @@ function run_test() do_test_pending(); } -const testSourcemap = Task.async(function* (threadResponse, tabClient, threadClient, tabResponse) { - evalTestCode(); +const testSourcemap = Task.async( + function* (threadResponse, tabClient, threadClient, tabResponse) { + evalTestCode(); - const { sources } = yield getSources(threadClient); + const { sources } = yield getSources(threadClient); - for (let form of sources) { - let sourceResponse = yield getSourceContent(threadClient.source(form)); - ok(sourceResponse, "Should be able to get the source response"); - ok(sourceResponse.source, "Should have the source text as well"); + for (let form of sources) { + let sourceResponse = yield getSourceContent(threadClient.source(form)); + ok(sourceResponse, "Should be able to get the source response"); + ok(sourceResponse.source, "Should have the source text as well"); + } + + finishClient(gClient); } - - finishClient(gClient); -}); +); const TEST_FILE = "babel_and_browserify_script_with_source_map.js"; diff --git a/devtools/server/tests/unit/test_sourcemaps-17.js b/devtools/server/tests/unit/test_sourcemaps-17.js index 85da959722ce..e7953acf11c3 100644 --- a/devtools/server/tests/unit/test_sourcemaps-17.js +++ b/devtools/server/tests/unit/test_sourcemaps-17.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that we properly handle frames that cannot be sourcemapped * when using sourcemaps. @@ -17,10 +19,11 @@ function run_test() { gDebuggee = addTestGlobal("test-source-map"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-source-map", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_source_map(); - }); + attachTestTabAndResume(gClient, "test-source-map", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_source_map(); + }); }); do_test_pending(); } @@ -32,7 +35,9 @@ function test_source_map() { const c = new SourceNode(1, 1, "c.js", "function c() { d(); }"); const d = new SourceNode(null, null, null, "function d() { e(); }"); const e = new SourceNode(1, 1, "e.js", "function e() { debugger; }"); - const { map, code } = (new SourceNode(null, null, null, [a, b, c, d, e])).toStringWithSourceMap({ + const { map, code } = (new SourceNode( + null, null, null, [a, b, c, d, e] + )).toStringWithSourceMap({ file: "root.js", sourceRoot: "root", }); @@ -44,7 +49,7 @@ function test_source_map() { 1 ); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { gThreadClient.getFrames(0, 50, function ({ error, frames }) { do_check_true(!error); do_check_eq(frames.length, 4); diff --git a/devtools/server/tests/unit/test_stepping-01.js b/devtools/server/tests/unit/test_stepping-01.js index 593a485a161e..d31244f84967 100644 --- a/devtools/server/tests/unit/test_stepping-01.js +++ b/devtools/server/tests/unit/test_stepping-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check basic step-over functionality. @@ -10,55 +13,53 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_stepping(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_stepping(); + }); }); } -function test_simple_stepping() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_simple_stepping() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 2); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 2); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, undefined); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); + do_check_eq(packet.type, "paused"); // When leaving a stack frame the line number doesn't change. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, 2); @@ -70,14 +71,14 @@ function test_simple_stepping() gThreadClient.stepOver(); }); gThreadClient.stepOver(); - }); gThreadClient.stepOver(); - }); + /* eslint-disable */ gDebuggee.eval("var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 "var a = 1;\n" + // line0 + 2 "var b = 2;\n"); // line0 + 3 + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_stepping-02.js b/devtools/server/tests/unit/test_stepping-02.js index eaee099b99b6..f1824d064594 100644 --- a/devtools/server/tests/unit/test_stepping-02.js +++ b/devtools/server/tests/unit/test_stepping-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check basic step-in functionality. @@ -10,55 +13,53 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_stepping(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_stepping(); + }); }); } -function test_simple_stepping() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_simple_stepping() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 2); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 2); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, undefined); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); + do_check_eq(packet.type, "paused"); // When leaving a stack frame the line number doesn't change. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, 2); @@ -70,14 +71,14 @@ function test_simple_stepping() gThreadClient.stepIn(); }); gThreadClient.stepIn(); - }); gThreadClient.stepIn(); - }); + /* eslint-disable */ gDebuggee.eval("var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 "var a = 1;\n" + // line0 + 2 "var b = 2;\n"); // line0 + 3 + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_stepping-03.js b/devtools/server/tests/unit/test_stepping-03.js index 6123928d7678..5ea74dac0d47 100644 --- a/devtools/server/tests/unit/test_stepping-03.js +++ b/devtools/server/tests/unit/test_stepping-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow */ + +"use strict"; /** * Check basic step-out functionality. @@ -10,36 +13,34 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_stepping(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_stepping(); + }); }); } -function test_simple_stepping() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_simple_stepping() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, 2); @@ -49,9 +50,9 @@ function test_simple_stepping() }); }); gThreadClient.stepOut(); - }); + /* eslint-disable */ gDebuggee.eval("var line0 = Error().lineNumber;\n" + "function f() {\n" + // line0 + 1 " debugger;\n" + // line0 + 2 @@ -59,4 +60,5 @@ function test_simple_stepping() " this.b = 2;\n" + // line0 + 4 "}\n" + // line0 + 5 "f();\n"); // line0 + 6 + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_stepping-04.js b/devtools/server/tests/unit/test_stepping-04.js index efe52200dc9e..b74869737708 100644 --- a/devtools/server/tests/unit/test_stepping-04.js +++ b/devtools/server/tests/unit/test_stepping-04.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that stepping over a function call does not pause inside the function. @@ -10,45 +13,43 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_simple_stepping(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_simple_stepping(); + }); }); } -function test_simple_stepping() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_simple_stepping() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, undefined); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 6); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); @@ -58,12 +59,11 @@ function test_simple_stepping() }); }); gThreadClient.stepOver(); - }); gThreadClient.stepOver(); - }); + /* eslint-disable */ gDebuggee.eval("var line0 = Error().lineNumber;\n" + "function f() {\n" + // line0 + 1 " this.a = 1;\n" + // line0 + 2 @@ -71,4 +71,5 @@ function test_simple_stepping() "debugger;\n" + // line0 + 4 "f();\n" + // line0 + 5 "let b = 2;\n"); // line0 + 6 + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_stepping-05.js b/devtools/server/tests/unit/test_stepping-05.js index 2ab4570afde8..1018943b07b5 100644 --- a/devtools/server/tests/unit/test_stepping-05.js +++ b/devtools/server/tests/unit/test_stepping-05.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Make sure that stepping in the last statement of the last frame doesn't @@ -12,55 +15,53 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_stepping_last(); - }); + attachTestTabAndResume(gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_stepping_last(); + }); }); } -function test_stepping_last() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_stepping_last() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 2); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 2); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, undefined); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); + do_check_eq(packet.type, "paused"); // When leaving a stack frame the line number doesn't change. - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3); - do_check_eq(aPacket.why.type, "resumeLimit"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 3); + do_check_eq(packet.why.type, "resumeLimit"); // Check that stepping worked. do_check_eq(gDebuggee.a, 1); do_check_eq(gDebuggee.b, 2); @@ -72,25 +73,24 @@ function test_stepping_last() gThreadClient.stepIn(); }); gThreadClient.stepIn(); - }); gThreadClient.stepIn(); - }); + /* eslint-disable */ gDebuggee.eval("var line0 = Error().lineNumber;\n" + "debugger;\n" + // line0 + 1 "var a = 1;\n" + // line0 + 2 "var b = 2;\n"); // line0 + 3 + /* eslint-enable */ } -function test_next_pause() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_next_pause() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check the return value. - do_check_eq(aPacket.type, "paused"); + do_check_eq(packet.type, "paused"); // Before fixing bug 785689, the type was resumeLimit. - do_check_eq(aPacket.why.type, "debuggerStatement"); + do_check_eq(packet.why.type, "debuggerStatement"); gThreadClient.resume(function () { gClient.close().then(gCallback); diff --git a/devtools/server/tests/unit/test_stepping-06.js b/devtools/server/tests/unit/test_stepping-06.js index 49689f830452..9842b01057e1 100644 --- a/devtools/server/tests/unit/test_stepping-06.js +++ b/devtools/server/tests/unit/test_stepping-06.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that stepping out of a function returns the right return value. @@ -10,58 +13,57 @@ var gClient; var gThreadClient; var gCallback; -function run_test() -{ +function run_test() { run_test_with_server(DebuggerServer, function () { run_test_with_server(WorkerDebuggerServer, do_test_finished); }); do_test_pending(); } -function run_test_with_server(aServer, aCallback) -{ - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stack", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stack", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-stack", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - // XXX: We have to do an executeSoon so that the error isn't caught and - // reported by DebuggerClient.requester (because we are using the local - // transport and share a stack) which causes the test to fail. - Services.tm.mainThread.dispatch({ - run: test_simple_stepping - }, Ci.nsIThread.DISPATCH_NORMAL); - }); + attachTestTabAndResume( + gClient, "test-stack", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + // XXX: We have to do an executeSoon so that the error isn't caught and + // reported by DebuggerClient.requester (because we are using the local + // transport and share a stack) which causes the test to fail. + Services.tm.mainThread.dispatch({ + run: test_simple_stepping + }, Ci.nsIThread.DISPATCH_NORMAL); + }); }); } -function test_simple_stepping() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_simple_stepping() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check that the return value is 10. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.why.frameFinished.return, 10); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 5); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.why.frameFinished.return, 10); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check that the return value is undefined. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 8); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.why.frameFinished.return.type, "undefined"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 8); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.why.frameFinished.return.type, "undefined"); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Check that the exception was thrown. - do_check_eq(aPacket.type, "paused"); - do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 11); - do_check_eq(aPacket.why.type, "resumeLimit"); - do_check_eq(aPacket.why.frameFinished.throw, "ah"); + do_check_eq(packet.type, "paused"); + do_check_eq(packet.frame.where.line, gDebuggee.line0 + 11); + do_check_eq(packet.why.type, "resumeLimit"); + do_check_eq(packet.why.frameFinished.throw, "ah"); gThreadClient.resume(function () { gClient.close().then(gCallback); @@ -76,9 +78,9 @@ function test_simple_stepping() gThreadClient.resume(); }); gThreadClient.stepOut(); - }); + /* eslint-disable */ gDebuggee.eval("var line0 = Error().lineNumber;\n" + "function f() {\n" + // line0 + 1 " debugger;\n" + // line0 + 2 @@ -96,4 +98,5 @@ function test_simple_stepping() "f();\n" + // line0 + 14 "g();\n" + // line0 + 15 "try { h() } catch (ex) { };\n"); // line0 + 16 + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_stepping-07.js b/devtools/server/tests/unit/test_stepping-07.js index 9ad0d79ffc8d..37c0fc72f95a 100644 --- a/devtools/server/tests/unit/test_stepping-07.js +++ b/devtools/server/tests/unit/test_stepping-07.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Check that stepping over an implicit return makes sense. Bug 1155966. */ @@ -16,16 +18,17 @@ function run_test() { }); } -function run_test_with_server(aServer, aCallback) { - gCallback = aCallback; - initTestDebuggerServer(aServer); - gDebuggee = addTestGlobal("test-stepping", aServer); - gClient = new DebuggerClient(aServer.connectPipe()); +function run_test_with_server(server, callback) { + gCallback = callback; + initTestDebuggerServer(server); + gDebuggee = addTestGlobal("test-stepping", server); + gClient = new DebuggerClient(server.connectPipe()); gClient.connect(testSteppingAndReturns); } const testSteppingAndReturns = Task.async(function* () { - const [attachResponse, tabClient, threadClient] = yield attachTestTabAndResume(gClient, "test-stepping"); + const [attachResponse,, threadClient] = yield attachTestTabAndResume(gClient, + "test-stepping"); ok(!attachResponse.error, "Should not get an error attaching"); dumpn("Evaluating test code and waiting for first debugger statement"); @@ -64,6 +67,7 @@ const testSteppingAndReturns = Task.async(function* () { }); function evaluateTestCode() { + /* eslint-disable */ Cu.evalInSandbox( ` // 1 function implicitReturn() { // 2 @@ -89,4 +93,5 @@ function evaluateTestCode() { "test_stepping-07-test-code.js", 1 ); + /* eslint-enable */ } diff --git a/devtools/server/tests/unit/test_symbols-01.js b/devtools/server/tests/unit/test_symbols-01.js index 8ea26086adfc..e0afe113c170 100644 --- a/devtools/server/tests/unit/test_symbols-01.js +++ b/devtools/server/tests/unit/test_symbols-01.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that we can represent ES6 Symbols over the RDP. */ @@ -13,10 +15,11 @@ function run_test() { const client = new DebuggerClient(DebuggerServer.connectPipe()); client.connect().then(function () { - attachTestTabAndResume(client, "test-symbols", function (response, tabClient, threadClient) { - add_task(testSymbols.bind(null, client, debuggee)); - run_next_test(); - }); + attachTestTabAndResume(client, "test-symbols", + function (response, tabClient, threadClient) { + add_task(testSymbols.bind(null, client, debuggee)); + run_next_test(); + }); }); do_test_pending(); @@ -24,6 +27,7 @@ function run_test() { function* testSymbols(client, debuggee) { const evalCode = () => { + /* eslint-disable */ Components.utils.evalInSandbox( "(" + function () { var symbolWithName = Symbol("Chris"); @@ -36,6 +40,7 @@ function* testSymbols(client, debuggee) { URL, 1 ); + /* eslint-enable */ }; const packet = yield executeOnNextTickAndWaitForPause(evalCode, client); diff --git a/devtools/server/tests/unit/test_symbols-02.js b/devtools/server/tests/unit/test_symbols-02.js index f80dc332236f..73df6585c32c 100644 --- a/devtools/server/tests/unit/test_symbols-02.js +++ b/devtools/server/tests/unit/test_symbols-02.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Test that we don't run debuggee code when getting symbol names. */ @@ -13,10 +15,11 @@ function run_test() { const client = new DebuggerClient(DebuggerServer.connectPipe()); client.connect().then(function () { - attachTestTabAndResume(client, "test-symbols", function (response, tabClient, threadClient) { - add_task(testSymbols.bind(null, client, debuggee)); - run_next_test(); - }); + attachTestTabAndResume(client, "test-symbols", + function (response, tabClient, threadClient) { + add_task(testSymbols.bind(null, client, debuggee)); + run_next_test(); + }); }); do_test_pending(); @@ -24,6 +27,7 @@ function run_test() { function* testSymbols(client, debuggee) { const evalCode = () => { + /* eslint-disable */ Components.utils.evalInSandbox( "(" + function () { Symbol.prototype.toString = () => { @@ -37,6 +41,7 @@ function* testSymbols(client, debuggee) { URL, 1 ); + /* eslint-enable */ }; const packet = yield executeOnNextTickAndWaitForPause(evalCode, client); diff --git a/devtools/server/tests/unit/test_threadlifetime-01.js b/devtools/server/tests/unit/test_threadlifetime-01.js index 1325a45fa475..7dad64558a69 100644 --- a/devtools/server/tests/unit/test_threadlifetime-01.js +++ b/devtools/server/tests/unit/test_threadlifetime-01.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that thread-lifetime grips last past a resume. @@ -9,36 +12,35 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_thread_lifetime(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_thread_lifetime(); + }); }); do_test_pending(); } -function test_thread_lifetime() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let pauseGrip = aPacket.frame.arguments[0]; +function test_thread_lifetime() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let pauseGrip = packet.frame.arguments[0]; // Create a thread-lifetime actor for this object. - gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (aResponse) { + gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (response) { // Successful promotion won't return an error. - do_check_eq(aResponse.error, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + do_check_eq(response.error, undefined); + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Verify that the promoted actor is returned again. - do_check_eq(pauseGrip.actor, aPacket.frame.arguments[0].actor); + do_check_eq(pauseGrip.actor, packet.frame.arguments[0].actor); // Now that we've resumed, should get unrecognizePacketType for the // promoted grip. - gClient.request({ to: pauseGrip.actor, type: "bogusRequest"}, function (aResponse) { - do_check_eq(aResponse.error, "unrecognizedPacketType"); + gClient.request({to: pauseGrip.actor, type: "bogusRequest"}, function (response) { + do_check_eq(response.error, "unrecognizedPacketType"); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_threadlifetime-02.js b/devtools/server/tests/unit/test_threadlifetime-02.js index a7d21a7f9bd6..cb98ac2b933b 100644 --- a/devtools/server/tests/unit/test_threadlifetime-02.js +++ b/devtools/server/tests/unit/test_threadlifetime-02.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that thread-lifetime grips last past a resume. @@ -9,40 +12,40 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_thread_lifetime(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_thread_lifetime(); + }); }); do_test_pending(); } -function test_thread_lifetime() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let pauseGrip = aPacket.frame.arguments[0]; +function test_thread_lifetime() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let pauseGrip = packet.frame.arguments[0]; // Create a thread-lifetime actor for this object. - gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (aResponse) { + gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (response) { // Successful promotion won't return an error. - do_check_eq(aResponse.error, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + do_check_eq(response.error, undefined); + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Verify that the promoted actor is returned again. - do_check_eq(pauseGrip.actor, aPacket.frame.arguments[0].actor); + do_check_eq(pauseGrip.actor, packet.frame.arguments[0].actor); // Now that we've resumed, release the thread-lifetime grip. - gClient.release(pauseGrip.actor, function (aResponse) { - gClient.request({ to: pauseGrip.actor, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); - gThreadClient.resume(function (aResponse) { - finishClient(gClient); + gClient.release(pauseGrip.actor, function (response) { + gClient.request( + {to: pauseGrip.actor, type: "bogusRequest"}, function (response) { + do_check_eq(response.error, "noSuchActor"); + gThreadClient.resume(function (response) { + finishClient(gClient); + }); }); - }); }); }); gThreadClient.resume(); diff --git a/devtools/server/tests/unit/test_threadlifetime-03.js b/devtools/server/tests/unit/test_threadlifetime-03.js index 22b707ff89c2..608d7418dec2 100644 --- a/devtools/server/tests/unit/test_threadlifetime-03.js +++ b/devtools/server/tests/unit/test_threadlifetime-03.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that thread-lifetime grips last past a resume. @@ -9,38 +12,37 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_thread_lifetime(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_thread_lifetime(); + }); }); do_test_pending(); } -function test_thread_lifetime() -{ +function test_thread_lifetime() { // Get three thread-lifetime grips. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { let grips = []; - let handler = function (aResponse) { - if (aResponse.error) { - do_check_eq(aResponse.error, ""); + let handler = function (response) { + if (response.error) { + do_check_eq(response.error, ""); finishClient(gClient); } - grips.push(aResponse.from); + grips.push(response.from); if (grips.length == 3) { test_release_many(grips); } }; for (let i = 0; i < 3; i++) { - gClient.request({ to: aPacket.frame.arguments[i].actor, type: "threadGrip" }, + gClient.request({ to: packet.frame.arguments[i].actor, type: "threadGrip" }, handler); } }); @@ -53,24 +55,23 @@ function test_thread_lifetime() } + ")()"); } -function test_release_many(grips) -{ +function test_release_many(grips) { // Release the first two grips, leave the third alive. let release = [grips[0], grips[1]]; - gThreadClient.releaseMany(release, function (aResponse) { + gThreadClient.releaseMany(release, function (response) { // First two actors should return a noSuchActor error, because // they're gone now. - gClient.request({ to: grips[0], type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); - gClient.request({ to: grips[1], type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); + gClient.request({ to: grips[0], type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "noSuchActor"); + gClient.request({ to: grips[1], type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "noSuchActor"); // Last actor should return unrecognizedPacketType, because it's still // alive. - gClient.request({ to: grips[2], type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "unrecognizedPacketType"); + gClient.request({ to: grips[2], type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "unrecognizedPacketType"); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_threadlifetime-04.js b/devtools/server/tests/unit/test_threadlifetime-04.js index aff8b525ce6f..da3a12723118 100644 --- a/devtools/server/tests/unit/test_threadlifetime-04.js +++ b/devtools/server/tests/unit/test_threadlifetime-04.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that requesting a thread-lifetime actor twice for the same @@ -10,33 +13,32 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_thread_lifetime(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_thread_lifetime(); + }); }); do_test_pending(); } -function test_thread_lifetime() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - let pauseGrip = aPacket.frame.arguments[0]; +function test_thread_lifetime() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let pauseGrip = packet.frame.arguments[0]; - gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (aResponse) { + gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (response) { // Successful promotion won't return an error. - do_check_eq(aResponse.error, undefined); + do_check_eq(response.error, undefined); - let threadGrip1 = aResponse.from; + let threadGrip1 = response.from; - gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (aResponse) { - do_check_eq(threadGrip1, aResponse.from); + gClient.request({ to: pauseGrip.actor, type: "threadGrip" }, function (response) { + do_check_eq(threadGrip1, response.from); gThreadClient.resume(function () { finishClient(gClient); }); diff --git a/devtools/server/tests/unit/test_threadlifetime-05.js b/devtools/server/tests/unit/test_threadlifetime-05.js index 6697947c16ed..71f88cd7e5a0 100644 --- a/devtools/server/tests/unit/test_threadlifetime-05.js +++ b/devtools/server/tests/unit/test_threadlifetime-05.js @@ -1,6 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + /** * Make sure that releasing a pause-lifetime actorin a releaseMany returns an * error, but releases all the thread-lifetime actors. @@ -11,47 +13,45 @@ var gClient; var gThreadClient; var gPauseGrip; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_thread_lifetime(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_thread_lifetime(); + }); }); do_test_pending(); } -function arg_grips(aFrameArgs, aOnResponse) { +function arg_grips(frameArgs, onResponse) { let grips = []; - let handler = function (aResponse) { - if (aResponse.error) { - grips.push(aResponse.error); + let handler = function (response) { + if (response.error) { + grips.push(response.error); } else { - grips.push(aResponse.from); + grips.push(response.from); } - if (grips.length == aFrameArgs.length) { - aOnResponse(grips); + if (grips.length == frameArgs.length) { + onResponse(grips); } }; - for (let i = 0; i < aFrameArgs.length; i++) { - gClient.request({ to: aFrameArgs[i].actor, type: "threadGrip" }, + for (let i = 0; i < frameArgs.length; i++) { + gClient.request({ to: frameArgs[i].actor, type: "threadGrip" }, handler); } } -function test_thread_lifetime() -{ +function test_thread_lifetime() { // Get two thread-lifetime grips. - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { - - let frameArgs = [ aPacket.frame.arguments[0], aPacket.frame.arguments[1] ]; - gPauseGrip = aPacket.frame.arguments[2]; - arg_grips(frameArgs, function (aGrips) { - release_grips(frameArgs, aGrips); + gThreadClient.addOneTimeListener("paused", function (event, packet) { + let frameArgs = [ packet.frame.arguments[0], packet.frame.arguments[1] ]; + gPauseGrip = packet.frame.arguments[2]; + arg_grips(frameArgs, function (grips) { + release_grips(frameArgs, grips); }); }); @@ -63,17 +63,15 @@ function test_thread_lifetime() } + ")()"); } - -function release_grips(aFrameArgs, aThreadGrips) -{ +function release_grips(frameArgs, threadGrips) { // Release all actors with releaseMany... - let release = [aThreadGrips[0], aThreadGrips[1], gPauseGrip.actor]; - gThreadClient.releaseMany(release, function (aResponse) { - do_check_eq(aResponse.error, "notReleasable"); + let release = [threadGrips[0], threadGrips[1], gPauseGrip.actor]; + gThreadClient.releaseMany(release, function (response) { + do_check_eq(response.error, "notReleasable"); // Now ask for thread grips again, they should not exist. - arg_grips(aFrameArgs, function (aNewGrips) { - for (let i = 0; i < aNewGrips.length; i++) { - do_check_eq(aNewGrips[i], "noSuchActor"); + arg_grips(frameArgs, function (newGrips) { + for (let i = 0; i < newGrips.length; i++) { + do_check_eq(newGrips[i], "noSuchActor"); } gThreadClient.resume(function () { finishClient(gClient); diff --git a/devtools/server/tests/unit/test_threadlifetime-06.js b/devtools/server/tests/unit/test_threadlifetime-06.js index dba0156f93fa..42fd02a82ca5 100644 --- a/devtools/server/tests/unit/test_threadlifetime-06.js +++ b/devtools/server/tests/unit/test_threadlifetime-06.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; /** * Check that promoting multiple pause-lifetime actors to thread-lifetime actors @@ -10,48 +13,47 @@ var gDebuggee; var gClient; var gThreadClient; -function run_test() -{ +function run_test() { initTestDebuggerServer(); gDebuggee = addTestGlobal("test-grips"); gClient = new DebuggerClient(DebuggerServer.connectPipe()); gClient.connect().then(function () { - attachTestTabAndResume(gClient, "test-grips", function (aResponse, aTabClient, aThreadClient) { - gThreadClient = aThreadClient; - test_thread_lifetime(); - }); + attachTestTabAndResume(gClient, "test-grips", + function (response, tabClient, threadClient) { + gThreadClient = threadClient; + test_thread_lifetime(); + }); }); do_test_pending(); } -function test_thread_lifetime() -{ - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { +function test_thread_lifetime() { + gThreadClient.addOneTimeListener("paused", function (event, packet) { let actors = []; let last; - for (let aGrip of aPacket.frame.arguments) { - actors.push(aGrip.actor); - last = aGrip.actor; + for (let grip of packet.frame.arguments) { + actors.push(grip.actor); + last = grip.actor; } // Create thread-lifetime actors for these objects. - gThreadClient.threadGrips(actors, function (aResponse) { + gThreadClient.threadGrips(actors, function (response) { // Successful promotion won't return an error. - do_check_eq(aResponse.error, undefined); + do_check_eq(response.error, undefined); - gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) { + gThreadClient.addOneTimeListener("paused", function (event, packet) { // Verify that the promoted actors are returned again. actors.forEach(function (actor, i) { - do_check_eq(actor, aPacket.frame.arguments[i].actor); + do_check_eq(actor, packet.frame.arguments[i].actor); }); // Now that we've resumed, release the thread-lifetime grips. - gThreadClient.releaseMany(actors, function (aResponse) { + gThreadClient.releaseMany(actors, function (response) { // Successful release won't return an error. - do_check_eq(aResponse.error, undefined); + do_check_eq(response.error, undefined); - gClient.request({ to: last, type: "bogusRequest" }, function (aResponse) { - do_check_eq(aResponse.error, "noSuchActor"); - gThreadClient.resume(function (aResponse) { + gClient.request({ to: last, type: "bogusRequest" }, function (response) { + do_check_eq(response.error, "noSuchActor"); + gThreadClient.resume(function (response) { finishClient(gClient); }); }); diff --git a/devtools/server/tests/unit/test_unsafeDereference.js b/devtools/server/tests/unit/test_unsafeDereference.js index d7afe645f076..baddf06f1216 100644 --- a/devtools/server/tests/unit/test_unsafeDereference.js +++ b/devtools/server/tests/unit/test_unsafeDereference.js @@ -1,6 +1,8 @@ // Any copyright is dedicated to the Public Domain. // http://creativecommons.org/publicdomain/zero/1.0/ +/* eslint-disable strict */ + // Test Debugger.Object.prototype.unsafeDereference in the presence of // interesting cross-compartment wrappers. // @@ -14,13 +16,14 @@ addDebuggerToGlobal(this); // Add a method to Debugger.Object for fetching value properties // conveniently. -Debugger.Object.prototype.getProperty = function (aName) { - let desc = this.getOwnPropertyDescriptor(aName); - if (!desc) +Debugger.Object.prototype.getProperty = function (name) { + let desc = this.getOwnPropertyDescriptor(name); + if (!desc) { return undefined; + } if (!desc.value) { throw Error("Debugger.Object.prototype.getProperty: " + - "not a value property: " + aName); + "not a value property: " + name); } return desc.value; }; @@ -33,7 +36,7 @@ function run_test() { // Create an objects in this compartment, and one in each sandbox. We'll // refer to the objects as "mainObj", "contentObj", and "chromeObj", in // variable and property names. - var mainObj = { name: "mainObj" }; + let mainObj = { name: "mainObj" }; Components.utils.evalInSandbox('var contentObj = { name: "contentObj" };', contentBox); Components.utils.evalInSandbox('var chromeObj = { name: "chromeObj" };', @@ -41,8 +44,8 @@ function run_test() { // Give each global a pointer to all the other globals' objects. contentBox.mainObj = chromeBox.mainObj = mainObj; - var contentObj = chromeBox.contentObj = contentBox.contentObj; - var chromeObj = contentBox.chromeObj = chromeBox.chromeObj; + let contentObj = chromeBox.contentObj = contentBox.contentObj; + let chromeObj = contentBox.chromeObj = chromeBox.chromeObj; // First, a whole bunch of basic sanity checks, to ensure that JavaScript // evaluated in various scopes really does see the world the way this @@ -91,7 +94,7 @@ function run_test() { // would. // Create a debugger, debugging our two sandboxes. - let dbg = new Debugger; + let dbg = new Debugger(); // Create Debugger.Object instances referring to the two sandboxes, as // seen from their own compartments. diff --git a/devtools/server/tests/unit/test_xpcshell_debugging.js b/devtools/server/tests/unit/test_xpcshell_debugging.js index 7026a02b344c..f620c97c7046 100644 --- a/devtools/server/tests/unit/test_xpcshell_debugging.js +++ b/devtools/server/tests/unit/test_xpcshell_debugging.js @@ -1,5 +1,8 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +/* eslint-disable no-shadow, max-nested-callbacks */ + +"use strict"; // Test the xpcshell-test debug support. Ideally we should have this test // next to the xpcshell support code, but that's tricky... @@ -9,7 +12,9 @@ function run_test() { // _setupDebuggerServer is from xpcshell-test's head.js let testResumed = false; - let DebuggerServer = _setupDebuggerServer([testFile.path], () => testResumed = true); + let DebuggerServer = _setupDebuggerServer([testFile.path], () => { + testResumed = true; + }); let transport = DebuggerServer.connectPipe(); let client = new DebuggerClient(transport); client.connect().then(() => { diff --git a/devtools/server/tests/unit/testactors.js b/devtools/server/tests/unit/testactors.js index 39564eeef7e7..b8d9ce391126 100644 --- a/devtools/server/tests/unit/testactors.js +++ b/devtools/server/tests/unit/testactors.js @@ -1,17 +1,18 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + const { ActorPool, appendExtraActors, createExtraActors } = require("devtools/server/actors/common"); const { RootActor } = require("devtools/server/actors/root"); const { ThreadActor } = require("devtools/server/actors/script"); const { DebuggerServer } = require("devtools/server/main"); const { TabSources } = require("devtools/server/actors/utils/TabSources"); -const promise = require("promise"); const makeDebugger = require("devtools/server/actors/utils/make-debugger"); var gTestGlobals = []; -DebuggerServer.addTestGlobal = function (aGlobal) { - gTestGlobals.push(aGlobal); +DebuggerServer.addTestGlobal = function (global) { + gTestGlobals.push(global); }; DebuggerServer.getTestGlobal = function (name) { @@ -31,18 +32,18 @@ DebuggerServer.getTestGlobal = function (name) { // As implemented now, we consult gTestGlobals when we're constructed, not // when we're iterated over, so tests have to add their globals before the // root actor is created. -function TestTabList(aConnection) { - this.conn = aConnection; +function TestTabList(connection) { + this.conn = connection; // An array of actors for each global added with // DebuggerServer.addTestGlobal. this._tabActors = []; // A pool mapping those actors' names to the actors. - this._tabActorPool = new ActorPool(aConnection); + this._tabActorPool = new ActorPool(connection); for (let global of gTestGlobals) { - let actor = new TestTabActor(aConnection, global); + let actor = new TestTabActor(connection, global); actor.selected = false; this._tabActors.push(actor); this._tabActorPool.addActor(actor); @@ -51,7 +52,7 @@ function TestTabList(aConnection) { this._tabActors[0].selected = true; } - aConnection.addActorPool(this._tabActorPool); + connection.addActorPool(this._tabActorPool); } TestTabList.prototype = { @@ -61,10 +62,9 @@ TestTabList.prototype = { } }; -function createRootActor(aConnection) -{ - let root = new RootActor(aConnection, { - tabList: new TestTabList(aConnection), +function createRootActor(connection) { + let root = new RootActor(connection, { + tabList: new TestTabList(connection), globalActorFactories: DebuggerServer.globalActorFactories, }); @@ -72,11 +72,10 @@ function createRootActor(aConnection) return root; } -function TestTabActor(aConnection, aGlobal) -{ - this.conn = aConnection; - this._global = aGlobal; - this._global.wrappedJSObject = aGlobal; +function TestTabActor(connection, global) { + this.conn = connection; + this._global = global; + this._global.wrappedJSObject = global; this.threadActor = new ThreadActor(this, this._global); this.conn.addActor(this.threadActor); this._attached = false; @@ -125,7 +124,7 @@ TestTabActor.prototype = { return response; }, - onAttach: function (aRequest) { + onAttach: function (request) { this._attached = true; let response = { type: "tabAttached", threadActor: this.threadActor.actorID }; @@ -134,26 +133,26 @@ TestTabActor.prototype = { return response; }, - onDetach: function (aRequest) { + onDetach: function (request) { if (!this._attached) { - return { "error":"wrongState" }; + return { "error": "wrongState" }; } return { type: "detached" }; }, - onReload: function (aRequest) { + onReload: function (request) { this.sources.reset({ sourceMaps: true }); this.threadActor.clearDebuggees(); this.threadActor.dbg.addDebuggees(); return {}; }, - removeActorByName: function (aName) { - const actor = this._extraActors[aName]; + removeActorByName: function (name) { + const actor = this._extraActors[name]; if (this._tabActorPool) { this._tabActorPool.removeActor(actor); } - delete this._extraActors[aName]; + delete this._extraActors[name]; }, /* Support for DebuggerServer.addTabActor. */ diff --git a/devtools/server/tests/unit/tracerlocations.js b/devtools/server/tests/unit/tracerlocations.js deleted file mode 100644 index aa4677c0f70a..000000000000 --- a/devtools/server/tests/unit/tracerlocations.js +++ /dev/null @@ -1,8 +0,0 @@ -// For JS Tracer tests dealing with source locations. - -function foo(x) { - x += 6; - return "bar"; -} - -foo(42); diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 3386f89689d2..76b47b427255 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -2135,6 +2135,7 @@ Element::DispatchClickEvent(nsPresContext* aPresContext, pointerId = sourceMouseEvent->pointerId; inputSource = sourceMouseEvent->inputSource; } else if (aSourceEvent->mClass == eKeyboardEventClass) { + event.mFlags.mIsPositionless = true; inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD; } event.pressure = pressure; diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index a89b3419127a..26d276c4bfe2 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -376,6 +376,13 @@ AutoJSAPI::InitInternal(nsIGlobalObject* aGlobalObject, JSObject* aGlobal, if (exn.isObject()) { JS::Rooted exnObj(aCx, &exn.toObject()); + // Make sure we can actually read things from it. This UncheckedUwrap is + // safe because we're only getting data for a debug printf. In + // particular, we do not expose this data to anyone, which is very + // important; otherwise it could be a cross-origin information leak. + exnObj = js::UncheckedUnwrap(exnObj); + JSAutoCompartment ac(aCx, exnObj); + nsAutoJSString stack, filename, name, message; int32_t line; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index f0d69a3f0cbf..76fbaa3906e5 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -14832,7 +14832,7 @@ nsGlobalWindow::CreateImageBitmap(JSContext* aCx, const Sequence& aLayout, ErrorResult& aRv) { - if (!ImageBitmap::ExtensionsEnabled(aCx, nullptr)) { + if (!ImageBitmap::ExtensionsEnabled(aCx)) { aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index 6fcf17a1fd1e..95503edb05ce 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -134,9 +134,12 @@ EvaluationExceptionToNSResult(JSContext* aCx) nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx, JS::Handle aGlobal) - : mSamplerRAII("nsJSUtils::ExecutionContext", /* PROFILER_LABEL */ - js::ProfileEntry::Category::JS, __LINE__) - , mCx(aCx) + : +#ifdef MOZ_GECKO_PROFILER + mSamplerRAII("nsJSUtils::ExecutionContext", /* PROFILER_LABEL */ + js::ProfileEntry::Category::JS, __LINE__), +#endif + mCx(aCx) , mCompartment(aCx, aGlobal) , mRetValue(aCx) , mScopeChain(aCx) diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h index e6285b9bf9da..94b208e3610e 100644 --- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h @@ -68,8 +68,10 @@ public: // ExecutionContext is used to switch compartment. class MOZ_STACK_CLASS ExecutionContext { +#ifdef MOZ_GECKO_PROFILER // Register stack annotations for the Gecko profiler. mozilla::SamplerStackFrameRAII mSamplerRAII; +#endif JSContext* mCx; diff --git a/dom/canvas/ImageBitmap.h b/dom/canvas/ImageBitmap.h index d362eb6ff4ca..1726459ecb9b 100644 --- a/dom/canvas/ImageBitmap.h +++ b/dom/canvas/ImageBitmap.h @@ -152,7 +152,10 @@ public: ImageBitmap* aImageBitmap); // Mozilla Extensions - static bool ExtensionsEnabled(JSContext* aCx, JSObject* aObj); + // aObj is an optional argument that isn't used by ExtensionsEnabled() and + // only exists because the bindings layer insists on passing it to us. All + // other consumers of this function should only call it passing one argument. + static bool ExtensionsEnabled(JSContext* aCx, JSObject* aObj = nullptr); friend CreateImageBitmapFromBlob; friend CreateImageBitmapFromBlobTask; diff --git a/dom/events/MouseEvent.cpp b/dom/events/MouseEvent.cpp index 0a2871daf9d4..28cdbf8e7125 100644 --- a/dom/events/MouseEvent.cpp +++ b/dom/events/MouseEvent.cpp @@ -344,6 +344,10 @@ MouseEvent::GetScreenX(int32_t* aScreenX) int32_t MouseEvent::ScreenX(CallerType aCallerType) { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } + if (nsContentUtils::ResistFingerprinting(aCallerType)) { // Sanitize to something sort of like client cooords, but not quite // (defaulting to (0,0) instead of our pre-specified client coords). @@ -365,6 +369,10 @@ MouseEvent::GetScreenY(int32_t* aScreenY) int32_t MouseEvent::ScreenY(CallerType aCallerType) { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } + if (nsContentUtils::ResistFingerprinting(aCallerType)) { // Sanitize to something sort of like client cooords, but not quite // (defaulting to (0,0) instead of our pre-specified client coords). @@ -387,6 +395,10 @@ MouseEvent::GetClientX(int32_t* aClientX) int32_t MouseEvent::ClientX() { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } + return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint, mClientPoint).x; } @@ -402,6 +414,10 @@ MouseEvent::GetClientY(int32_t* aClientY) int32_t MouseEvent::ClientY() { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } + return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint, mClientPoint).y; } @@ -409,6 +425,9 @@ MouseEvent::ClientY() int32_t MouseEvent::OffsetX() { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } return Event::GetOffsetCoords(mPresContext, mEvent, mEvent->mRefPoint, mClientPoint).x; } @@ -416,6 +435,9 @@ MouseEvent::OffsetX() int32_t MouseEvent::OffsetY() { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } return Event::GetOffsetCoords(mPresContext, mEvent, mEvent->mRefPoint, mClientPoint).y; } diff --git a/dom/events/UIEvent.cpp b/dom/events/UIEvent.cpp index 12518dd78869..ac1c1d33edaf 100644 --- a/dom/events/UIEvent.cpp +++ b/dom/events/UIEvent.cpp @@ -115,6 +115,10 @@ DevPixelsToCSSPixels(const LayoutDeviceIntPoint& aPoint, nsIntPoint UIEvent::GetMovementPoint() { + if (mEvent->mFlags.mIsPositionless) { + return nsIntPoint(0, 0); + } + if (mPrivateDataDuplicated || mEventIsInternal) { return mMovementPoint; } @@ -191,6 +195,10 @@ UIEvent::GetPageX(int32_t* aPageX) int32_t UIEvent::PageX() const { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } + if (mPrivateDataDuplicated) { return mPagePoint.x; } @@ -210,6 +218,10 @@ UIEvent::GetPageY(int32_t* aPageY) int32_t UIEvent::PageY() const { + if (mEvent->mFlags.mIsPositionless) { + return 0; + } + if (mPrivateDataDuplicated) { return mPagePoint.y; } @@ -291,6 +303,10 @@ UIEvent::RangeOffset() const nsIntPoint UIEvent::GetLayerPoint() const { + if (mEvent->mFlags.mIsPositionless) { + return nsIntPoint(0, 0); + } + if (!mEvent || (mEvent->mClass != eMouseEventClass && mEvent->mClass != eMouseScrollEventClass && diff --git a/dom/events/test/mochitest.ini b/dom/events/test/mochitest.ini index 94fdcf97fafe..a4daa5490783 100644 --- a/dom/events/test/mochitest.ini +++ b/dom/events/test/mochitest.ini @@ -176,4 +176,5 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM [test_bug1298970.html] [test_bug1304044.html] [test_bug1332699.html] +[test_bug1339758.html] [test_dnd_with_modifiers.html] diff --git a/dom/events/test/test_bug1339758.html b/dom/events/test/test_bug1339758.html new file mode 100644 index 000000000000..778fe2e25183 --- /dev/null +++ b/dom/events/test/test_bug1339758.html @@ -0,0 +1,80 @@ + + + + + + Test for Bug 1339758 + + + + + + +Mozilla Bug 1339758 +

+ +
 
+test link
+ + + +
+
+ + diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 54b140129778..8ed078b8acad 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -2437,6 +2437,7 @@ nsGenericHTMLElement::Click(CallerType aCallerType) // Mark this event trusted if Click() is called from system code. WidgetMouseEvent event(aCallerType == CallerType::System, eMouseClick, nullptr, WidgetMouseEvent::eReal); + event.mFlags.mIsPositionless = true; event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; EventDispatcher::Dispatch(static_cast(this), context, &event); @@ -2561,6 +2562,7 @@ nsGenericHTMLElement::DispatchSimulatedClick(nsGenericHTMLElement* aElement, WidgetMouseEvent event(aIsTrusted, eMouseClick, nullptr, WidgetMouseEvent::eReal); event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD; + event.mFlags.mIsPositionless = true; return EventDispatcher::Dispatch(ToSupports(aElement), aPresContext, &event); } diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 083810be7723..880004f2bfcf 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -26491,9 +26491,13 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) } key.SetFromInteger(autoIncrementNum); - } else if (key.IsFloat() && - key.ToFloat() >= mMetadata->mNextAutoIncrementId) { - autoIncrementNum = floor(key.ToFloat()); + } else if (key.IsFloat()) { + double numericKey = key.ToFloat(); + numericKey = std::min(numericKey, double(1LL << 53)); + numericKey = floor(numericKey); + if (numericKey >= mMetadata->mNextAutoIncrementId) { + autoIncrementNum = numericKey; + } } if (keyUnset && mMetadata->mCommonMetadata.keyPath().IsValid()) { diff --git a/dom/ipc/DOMTypes.ipdlh b/dom/ipc/DOMTypes.ipdlh index d2a7c9deacfa..f1e954db7680 100644 --- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -19,12 +19,6 @@ using struct mozilla::SerializedStructuredCloneBuffer namespace mozilla { namespace dom { -union OptionalID -{ - nsID; - void_t; -}; - struct MessagePortIdentifier { nsID uuid; diff --git a/dom/workers/FileReaderSync.cpp b/dom/workers/FileReaderSync.cpp index 18efcb194c71..d62c387f4b71 100644 --- a/dom/workers/FileReaderSync.cpp +++ b/dom/workers/FileReaderSync.cpp @@ -20,7 +20,8 @@ #include "nsError.h" #include "nsIConverterInputStream.h" #include "nsIInputStream.h" -#include "nsISeekableStream.h" +#include "nsIMultiplexInputStream.h" +#include "nsStringStream.h" #include "nsISupportsImpl.h" #include "nsNetUtil.h" #include "nsServiceManagerUtils.h" @@ -133,17 +134,23 @@ FileReaderSync::ReadAsText(Blob& aBlob, } nsAutoCString encoding; - unsigned char sniffBuf[3] = { 0, 0, 0 }; - uint32_t numRead; - aRv = stream->Read(reinterpret_cast(sniffBuf), - sizeof(sniffBuf), &numRead); + + nsCString sniffBuf; + if (!sniffBuf.SetLength(3, fallible)) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return; + } + + uint32_t numRead = 0; + aRv = stream->Read(sniffBuf.BeginWriting(), sniffBuf.Length(), &numRead); if (NS_WARN_IF(aRv.Failed())) { return; } // The BOM sniffing is baked into the "decode" part of the Encoding // Standard, which the File API references. - if (!nsContentUtils::CheckForBOM(sniffBuf, numRead, encoding)) { + if (!nsContentUtils::CheckForBOM((const unsigned char*)sniffBuf.BeginReading(), + numRead, encoding)) { // BOM sniffing failed. Try the API argument. if (!aEncoding.WasPassed() || !EncodingUtils::FindEncodingForLabel(aEncoding.Value(), @@ -167,20 +174,39 @@ FileReaderSync::ReadAsText(Blob& aBlob, } } - nsCOMPtr seekable = do_QueryInterface(stream); - if (!seekable) { - aRv.Throw(NS_ERROR_FAILURE); - return; + if (numRead < sniffBuf.Length()) { + sniffBuf.Truncate(numRead); } - // Seek to 0 because to undo the BOM sniffing advance. UTF-8 and UTF-16 - // decoders will swallow the BOM. - aRv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); + // Let's recreate the full stream using a: + // multiplexStream(stringStream + original stream) + // In theory, we could try to see if the inputStream is a nsISeekableStream, + // but this doesn't work correctly for nsPipe3 - See bug 1349570. + + nsCOMPtr stringStream; + aRv = NS_NewCStringInputStream(getter_AddRefs(stringStream), sniffBuf); if (NS_WARN_IF(aRv.Failed())) { return; } - aRv = ConvertStream(stream, encoding.get(), aResult); + nsCOMPtr multiplexStream = + do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); + if (NS_WARN_IF(!multiplexStream)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + aRv = multiplexStream->AppendStream(stringStream); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + + aRv = multiplexStream->AppendStream(stream); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + + aRv = ConvertStream(multiplexStream, encoding.get(), aResult); if (NS_WARN_IF(aRv.Failed())) { return; } diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index 60582808bb16..1ab647e70108 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -475,7 +475,7 @@ WorkerGlobalScope::CreateImageBitmap(JSContext* aCx, const Sequence& aLayout, ErrorResult& aRv) { - if (!ImageBitmap::ExtensionsEnabled(aCx, nullptr)) { + if (!ImageBitmap::ExtensionsEnabled(aCx)) { aRv.Throw(NS_ERROR_TYPE_ERR); return nullptr; } diff --git a/image/DynamicImage.cpp b/image/DynamicImage.cpp index d6444066a9e9..47c920944c3e 100644 --- a/image/DynamicImage.cpp +++ b/image/DynamicImage.cpp @@ -127,6 +127,12 @@ DynamicImage::GetHeight(int32_t* aHeight) return NS_OK; } +nsresult +DynamicImage::GetNativeSizes(nsTArray& aNativeSizes) const +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP DynamicImage::GetIntrinsicSize(nsSize* aSize) { diff --git a/image/DynamicImage.h b/image/DynamicImage.h index a39a29b8e37e..09c6ed550a25 100644 --- a/image/DynamicImage.h +++ b/image/DynamicImage.h @@ -31,6 +31,7 @@ public: } // Inherited methods from Image. + nsresult GetNativeSizes(nsTArray& aNativeSizes) const override; virtual already_AddRefed GetProgressTracker() override; virtual size_t SizeOfSourceWithComputedFallback( MallocSizeOf aMallocSizeOf) const override; diff --git a/image/FrameTimeout.h b/image/FrameTimeout.h new file mode 100644 index 000000000000..4070bba65b2b --- /dev/null +++ b/image/FrameTimeout.h @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#ifndef mozilla_image_FrameTimeout_h +#define mozilla_image_FrameTimeout_h + +#include +#include "mozilla/Assertions.h" + +namespace mozilla { +namespace image { + +/** + * FrameTimeout wraps a frame timeout value (measured in milliseconds) after + * first normalizing it. This normalization is necessary because some tools + * generate incorrect frame timeout values which we nevertheless have to + * support. For this reason, code that deals with frame timeouts should always + * use a FrameTimeout value rather than the raw value from the image header. + */ +struct FrameTimeout +{ + /** + * @return a FrameTimeout of zero. This should be used only for math + * involving FrameTimeout values. You can't obtain a zero FrameTimeout from + * FromRawMilliseconds(). + */ + static FrameTimeout Zero() { return FrameTimeout(0); } + + /// @return an infinite FrameTimeout. + static FrameTimeout Forever() { return FrameTimeout(-1); } + + /// @return a FrameTimeout obtained by normalizing a raw timeout value. + static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds) + { + // Normalize all infinite timeouts to the same value. + if (aRawMilliseconds < 0) { + return FrameTimeout::Forever(); + } + + // Very small timeout values are problematic for two reasons: we don't want + // to burn energy redrawing animated images extremely fast, and broken tools + // generate these values when they actually want a "default" value, so such + // images won't play back right without normalization. For some context, + // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical + // behavior of IE and Opera was: + // IE 6/Win: + // 10 - 50ms is normalized to 100ms. + // >50ms is used unnormalized. + // Opera 7 final/Win: + // 10ms is normalized to 100ms. + // >10ms is used unnormalized. + if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10 ) { + return FrameTimeout(100); + } + + // The provided timeout value is OK as-is. + return FrameTimeout(aRawMilliseconds); + } + + bool operator==(const FrameTimeout& aOther) const + { + return mTimeout == aOther.mTimeout; + } + + bool operator!=(const FrameTimeout& aOther) const { return !(*this == aOther); } + + FrameTimeout operator+(const FrameTimeout& aOther) + { + if (*this == Forever() || aOther == Forever()) { + return Forever(); + } + + return FrameTimeout(mTimeout + aOther.mTimeout); + } + + FrameTimeout& operator+=(const FrameTimeout& aOther) + { + *this = *this + aOther; + return *this; + } + + /** + * @return this FrameTimeout's value in milliseconds. Illegal to call on a + * an infinite FrameTimeout value. + */ + uint32_t AsMilliseconds() const + { + if (*this == Forever()) { + MOZ_ASSERT_UNREACHABLE("Calling AsMilliseconds() on an infinite FrameTimeout"); + return 100; // Fail to something sane. + } + + return uint32_t(mTimeout); + } + + /** + * @return this FrameTimeout value encoded so that non-negative values + * represent a timeout in milliseconds, and -1 represents an infinite + * timeout. + * + * XXX(seth): This is a backwards compatibility hack that should be removed. + */ + int32_t AsEncodedValueDeprecated() const { return mTimeout; } + +private: + explicit FrameTimeout(int32_t aTimeout) + : mTimeout(aTimeout) + { } + + int32_t mTimeout; +}; + +} // namespace image +} // namespace mozilla + +#endif // mozilla_image_FrameTimeout_h diff --git a/image/ImageMetadata.h b/image/ImageMetadata.h index 05f5729802c7..b1a2edfb03fd 100644 --- a/image/ImageMetadata.h +++ b/image/ImageMetadata.h @@ -11,12 +11,11 @@ #include "mozilla/Maybe.h" #include "nsSize.h" #include "Orientation.h" +#include "FrameTimeout.h" namespace mozilla { namespace image { -class RasterImage; - // The metadata about an image that decoders accumulate as they decode. class ImageMetadata { @@ -64,6 +63,13 @@ public: nsIntSize GetSize() const { return *mSize; } bool HasSize() const { return mSize.isSome(); } + void AddNativeSize(const nsIntSize& aSize) + { + mNativeSizes.AppendElement(aSize); + } + + const nsTArray& GetNativeSizes() const { return mNativeSizes; } + Orientation GetOrientation() const { return *mOrientation; } bool HasOrientation() const { return mOrientation.isSome(); } @@ -90,6 +96,9 @@ private: Maybe mSize; Maybe mOrientation; + // Sizes the image can natively decode to. + nsTArray mNativeSizes; + bool mHasAnimation : 1; }; diff --git a/image/ImageOps.cpp b/image/ImageOps.cpp index d1d5da283642..3ff7819768e7 100644 --- a/image/ImageOps.cpp +++ b/image/ImageOps.cpp @@ -14,6 +14,7 @@ #include "FrozenImage.h" #include "IDecodingTask.h" #include "Image.h" +#include "ImageMetadata.h" #include "imgIContainer.h" #include "mozilla/gfx/2D.h" #include "nsStreamUtils.h" @@ -79,10 +80,27 @@ ImageOps::CreateFromDrawable(gfxDrawable* aDrawable) return drawableImage.forget(); } -/* static */ already_AddRefed -ImageOps::DecodeToSurface(nsIInputStream* aInputStream, - const nsACString& aMimeType, - uint32_t aFlags) +class ImageOps::ImageBufferImpl final : public ImageOps::ImageBuffer { +public: + explicit ImageBufferImpl(already_AddRefed aSourceBuffer) + : mSourceBuffer(aSourceBuffer) + { } + +protected: + ~ImageBufferImpl() override { } + + already_AddRefed GetSourceBuffer() const override + { + RefPtr sourceBuffer = mSourceBuffer; + return sourceBuffer.forget(); + } + +private: + RefPtr mSourceBuffer; +}; + +/* static */ already_AddRefed +ImageOps::CreateImageBuffer(nsIInputStream* aInputStream) { MOZ_ASSERT(aInputStream); @@ -107,7 +125,7 @@ ImageOps::DecodeToSurface(nsIInputStream* aInputStream, } // Write the data into a SourceBuffer. - NotNull> sourceBuffer = WrapNotNull(new SourceBuffer()); + RefPtr sourceBuffer = new SourceBuffer(); sourceBuffer->ExpectLength(length); rv = sourceBuffer->AppendFromInputStream(inputStream, length); if (NS_FAILED(rv)) { @@ -122,12 +140,90 @@ ImageOps::DecodeToSurface(nsIInputStream* aInputStream, } sourceBuffer->Complete(NS_OK); + RefPtr imageBuffer = new ImageBufferImpl(sourceBuffer.forget()); + return imageBuffer.forget(); +} + +/* static */ nsresult +ImageOps::DecodeMetadata(nsIInputStream* aInputStream, + const nsACString& aMimeType, + ImageMetadata& aMetadata) +{ + RefPtr buffer = CreateImageBuffer(aInputStream); + return DecodeMetadata(buffer, aMimeType, aMetadata); +} + +/* static */ nsresult +ImageOps::DecodeMetadata(ImageBuffer* aBuffer, + const nsACString& aMimeType, + ImageMetadata& aMetadata) +{ + if (!aBuffer) { + return NS_ERROR_FAILURE; + } + + RefPtr sourceBuffer = aBuffer->GetSourceBuffer(); + if (NS_WARN_IF(!sourceBuffer)) { + return NS_ERROR_FAILURE; + } + // Create a decoder. DecoderType decoderType = DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get()); RefPtr decoder = - DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, - Nothing(), ToSurfaceFlags(aFlags)); + DecoderFactory::CreateAnonymousMetadataDecoder(decoderType, + WrapNotNull(sourceBuffer)); + if (!decoder) { + return NS_ERROR_FAILURE; + } + + // Run the decoder synchronously. + RefPtr task = new AnonymousDecodingTask(WrapNotNull(decoder)); + task->Run(); + if (!decoder->GetDecodeDone() || decoder->HasError()) { + return NS_ERROR_FAILURE; + } + + aMetadata = decoder->GetImageMetadata(); + if (aMetadata.GetNativeSizes().IsEmpty() && aMetadata.HasSize()) { + aMetadata.AddNativeSize(aMetadata.GetSize()); + } + + return NS_OK; +} + +/* static */ already_AddRefed +ImageOps::DecodeToSurface(nsIInputStream* aInputStream, + const nsACString& aMimeType, + uint32_t aFlags, + const Maybe& aSize /* = Nothing() */) +{ + RefPtr buffer = CreateImageBuffer(aInputStream); + return DecodeToSurface(buffer, aMimeType, aFlags, aSize); +} + +/* static */ already_AddRefed +ImageOps::DecodeToSurface(ImageBuffer* aBuffer, + const nsACString& aMimeType, + uint32_t aFlags, + const Maybe& aSize /* = Nothing() */) +{ + if (!aBuffer) { + return nullptr; + } + + RefPtr sourceBuffer = aBuffer->GetSourceBuffer(); + if (NS_WARN_IF(!sourceBuffer)) { + return nullptr; + } + + // Create a decoder. + DecoderType decoderType = + DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get()); + RefPtr decoder = + DecoderFactory::CreateAnonymousDecoder(decoderType, + WrapNotNull(sourceBuffer), + aSize, ToSurfaceFlags(aFlags)); if (!decoder) { return nullptr; } diff --git a/image/ImageOps.h b/image/ImageOps.h index 7a8e19be3441..a95c6047f5c2 100644 --- a/image/ImageOps.h +++ b/image/ImageOps.h @@ -9,6 +9,7 @@ #include "nsCOMPtr.h" #include "nsRect.h" +#include "ImageMetadata.h" class gfxDrawable; class imgIContainer; @@ -24,10 +25,23 @@ namespace image { class Image; struct Orientation; +class SourceBuffer; class ImageOps { public: + class ImageBuffer { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageOps::ImageBuffer); + protected: + friend class ImageOps; + + ImageBuffer() { } + virtual ~ImageBuffer() { } + + virtual already_AddRefed GetSourceBuffer() const = 0; + }; + /** * Creates a version of an existing image which does not animate and is frozen * at the first frame. @@ -74,6 +88,39 @@ public: static already_AddRefed CreateFromDrawable(gfxDrawable* aDrawable); + /** + * Create a buffer to be used with DecodeMetadata and DecodeToSurface. Reusing + * an ImageBuffer representing the given input stream is more efficient if one + * has multiple Decode* calls to make on that stream. + * + * @param aInputStream An input stream containing an encoded image. + * @return An image buffer derived from the input stream. + */ + static already_AddRefed + CreateImageBuffer(nsIInputStream* aInputStream); + + /** + * Decodes an image's metadata from an nsIInputStream into the given + * structure. This function may be called off-main-thread. + * + * @param aInputStream An input stream containing an encoded image. + * @param aMimeType The MIME type of the image. + * @param aMetadata Where the image metadata is stored upon success. + * @return The status of the operation. + */ + static nsresult + DecodeMetadata(nsIInputStream* aInputStream, + const nsACString& aMimeType, + ImageMetadata& aMetadata); + + /** + * Same as above but takes an ImageBuffer instead of nsIInputStream. + */ + static nsresult + DecodeMetadata(ImageBuffer* aBuffer, + const nsACString& aMimeType, + ImageMetadata& aMetadata); + /** * Decodes an image from an nsIInputStream directly into a SourceSurface, * without ever creating an Image or imgIContainer (which are mostly @@ -89,9 +136,21 @@ public: static already_AddRefed DecodeToSurface(nsIInputStream* aInputStream, const nsACString& aMimeType, - uint32_t aFlags); + uint32_t aFlags, + const Maybe& aSize = Nothing()); + + /** + * Same as above but takes an ImageBuffer instead of nsIInputStream. + */ + static already_AddRefed + DecodeToSurface(ImageBuffer* aBuffer, + const nsACString& aMimeType, + uint32_t aFlags, + const Maybe& aSize = Nothing()); private: + class ImageBufferImpl; + // This is a static utility class, so disallow instantiation. virtual ~ImageOps() = 0; }; diff --git a/image/ImageWrapper.cpp b/image/ImageWrapper.cpp index dfc76641fd6f..852479904567 100644 --- a/image/ImageWrapper.cpp +++ b/image/ImageWrapper.cpp @@ -139,6 +139,12 @@ ImageWrapper::GetHeight(int32_t* aHeight) return mInnerImage->GetHeight(aHeight); } +nsresult +ImageWrapper::GetNativeSizes(nsTArray& aNativeSizes) const +{ + return mInnerImage->GetNativeSizes(aNativeSizes); +} + NS_IMETHODIMP ImageWrapper::GetIntrinsicSize(nsSize* aSize) { diff --git a/image/ImageWrapper.h b/image/ImageWrapper.h index 94cf0948b537..19e9cb858232 100644 --- a/image/ImageWrapper.h +++ b/image/ImageWrapper.h @@ -22,6 +22,7 @@ public: NS_DECL_IMGICONTAINER // Inherited methods from Image. + nsresult GetNativeSizes(nsTArray& aNativeSizes) const override; virtual already_AddRefed GetProgressTracker() override; virtual size_t diff --git a/image/OrientedImage.cpp b/image/OrientedImage.cpp index 951b0acbc94d..79767e2a796a 100644 --- a/image/OrientedImage.cpp +++ b/image/OrientedImage.cpp @@ -46,6 +46,22 @@ OrientedImage::GetHeight(int32_t* aHeight) } } +nsresult +OrientedImage::GetNativeSizes(nsTArray& aNativeSizes) const +{ + nsresult rv = InnerImage()->GetNativeSizes(aNativeSizes); + + if (mOrientation.SwapsWidthAndHeight()) { + auto i = aNativeSizes.Length(); + while (i > 0) { + --i; + swap(aNativeSizes[i].width, aNativeSizes[i].height); + } + } + + return rv; +} + NS_IMETHODIMP OrientedImage::GetIntrinsicSize(nsSize* aSize) { diff --git a/image/OrientedImage.h b/image/OrientedImage.h index 2edf05de9f50..d1291ea74b20 100644 --- a/image/OrientedImage.h +++ b/image/OrientedImage.h @@ -30,6 +30,7 @@ public: NS_IMETHOD GetWidth(int32_t* aWidth) override; NS_IMETHOD GetHeight(int32_t* aHeight) override; + nsresult GetNativeSizes(nsTArray& aNativeSizes) const override; NS_IMETHOD GetIntrinsicSize(nsSize* aSize) override; NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override; NS_IMETHOD_(already_AddRefed) diff --git a/image/RasterImage.cpp b/image/RasterImage.cpp index 3796041881b1..0ef029d3c1c1 100644 --- a/image/RasterImage.cpp +++ b/image/RasterImage.cpp @@ -223,6 +223,24 @@ RasterImage::GetHeight(int32_t* aHeight) return NS_OK; } +//****************************************************************************** +nsresult +RasterImage::GetNativeSizes(nsTArray& aNativeSizes) const +{ + if (mError) { + return NS_ERROR_FAILURE; + } + + if (mNativeSizes.IsEmpty()) { + aNativeSizes.Clear(); + aNativeSizes.AppendElement(mSize); + } else { + aNativeSizes = mNativeSizes; + } + + return NS_OK; +} + //****************************************************************************** NS_IMETHODIMP RasterImage::GetIntrinsicSize(nsSize* aSize) @@ -706,6 +724,7 @@ RasterImage::SetMetadata(const ImageMetadata& aMetadata, // Set the size and flag that we have it. mSize = size; mOrientation = orientation; + mNativeSizes = aMetadata.GetNativeSizes(); mHasSize = true; } diff --git a/image/RasterImage.h b/image/RasterImage.h index 09fa18b4df65..023985669a7a 100644 --- a/image/RasterImage.h +++ b/image/RasterImage.h @@ -160,6 +160,7 @@ public: NS_DECL_IMGICONTAINERDEBUG #endif + nsresult GetNativeSizes(nsTArray& aNativeSizes) const override; virtual nsresult StartAnimation() override; virtual nsresult StopAnimation() override; @@ -380,6 +381,7 @@ private: private: // data nsIntSize mSize; + nsTArray mNativeSizes; Orientation mOrientation; /// If this has a value, we're waiting for SetSize() to send the load event. diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index fa3ecb8bc049..7c650fc7545c 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -520,6 +520,13 @@ VectorImage::GetWidth(int32_t* aWidth) return NS_OK; } +//****************************************************************************** +nsresult +VectorImage::GetNativeSizes(nsTArray& aNativeSizes) const +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + //****************************************************************************** NS_IMETHODIMP_(void) VectorImage::RequestRefresh(const TimeStamp& aTime) diff --git a/image/VectorImage.h b/image/VectorImage.h index cb55e057753c..a05c92f3cf38 100644 --- a/image/VectorImage.h +++ b/image/VectorImage.h @@ -34,6 +34,7 @@ public: // (no public constructor - use ImageFactory) // Methods inherited from Image + nsresult GetNativeSizes(nsTArray& aNativeSizes) const override; virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const override; virtual void CollectSizeOfSurfaces(nsTArray& aCounters, diff --git a/image/decoders/nsICODecoder.cpp b/image/decoders/nsICODecoder.cpp index 85b3c139b0d7..d8171431ea83 100644 --- a/image/decoders/nsICODecoder.cpp +++ b/image/decoders/nsICODecoder.cpp @@ -242,6 +242,8 @@ nsICODecoder::ReadDirEntry(const char* aData) } } + mImageMetadata.AddNativeSize(entrySize); + if (desiredSize) { // Calculate the delta between this resource's size and the desired size, so // we can see if it is better than our current-best option. In the case of diff --git a/image/imgFrame.h b/image/imgFrame.h index 77ff3507b177..bd858e088dcf 100644 --- a/image/imgFrame.h +++ b/image/imgFrame.h @@ -11,6 +11,7 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/Monitor.h" #include "mozilla/Move.h" +#include "FrameTimeout.h" #include "gfxDrawable.h" #include "imgIContainer.h" #include "MainThreadUtils.h" @@ -46,106 +47,6 @@ enum class Opacity : uint8_t { SOME_TRANSPARENCY }; -/** - * FrameTimeout wraps a frame timeout value (measured in milliseconds) after - * first normalizing it. This normalization is necessary because some tools - * generate incorrect frame timeout values which we nevertheless have to - * support. For this reason, code that deals with frame timeouts should always - * use a FrameTimeout value rather than the raw value from the image header. - */ -struct FrameTimeout -{ - /** - * @return a FrameTimeout of zero. This should be used only for math - * involving FrameTimeout values. You can't obtain a zero FrameTimeout from - * FromRawMilliseconds(). - */ - static FrameTimeout Zero() { return FrameTimeout(0); } - - /// @return an infinite FrameTimeout. - static FrameTimeout Forever() { return FrameTimeout(-1); } - - /// @return a FrameTimeout obtained by normalizing a raw timeout value. - static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds) - { - // Normalize all infinite timeouts to the same value. - if (aRawMilliseconds < 0) { - return FrameTimeout::Forever(); - } - - // Very small timeout values are problematic for two reasons: we don't want - // to burn energy redrawing animated images extremely fast, and broken tools - // generate these values when they actually want a "default" value, so such - // images won't play back right without normalization. For some context, - // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical - // behavior of IE and Opera was: - // IE 6/Win: - // 10 - 50ms is normalized to 100ms. - // >50ms is used unnormalized. - // Opera 7 final/Win: - // 10ms is normalized to 100ms. - // >10ms is used unnormalized. - if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10 ) { - return FrameTimeout(100); - } - - // The provided timeout value is OK as-is. - return FrameTimeout(aRawMilliseconds); - } - - bool operator==(const FrameTimeout& aOther) const - { - return mTimeout == aOther.mTimeout; - } - - bool operator!=(const FrameTimeout& aOther) const { return !(*this == aOther); } - - FrameTimeout operator+(const FrameTimeout& aOther) - { - if (*this == Forever() || aOther == Forever()) { - return Forever(); - } - - return FrameTimeout(mTimeout + aOther.mTimeout); - } - - FrameTimeout& operator+=(const FrameTimeout& aOther) - { - *this = *this + aOther; - return *this; - } - - /** - * @return this FrameTimeout's value in milliseconds. Illegal to call on a - * an infinite FrameTimeout value. - */ - uint32_t AsMilliseconds() const - { - if (*this == Forever()) { - MOZ_ASSERT_UNREACHABLE("Calling AsMilliseconds() on an infinite FrameTimeout"); - return 100; // Fail to something sane. - } - - return uint32_t(mTimeout); - } - - /** - * @return this FrameTimeout value encoded so that non-negative values - * represent a timeout in milliseconds, and -1 represents an infinite - * timeout. - * - * XXX(seth): This is a backwards compatibility hack that should be removed. - */ - int32_t AsEncodedValueDeprecated() const { return mTimeout; } - -private: - explicit FrameTimeout(int32_t aTimeout) - : mTimeout(aTimeout) - { } - - int32_t mTimeout; -}; - /** * AnimationData contains all of the information necessary for using an imgFrame * as part of an animation. diff --git a/image/imgIContainer.idl b/image/imgIContainer.idl index 640eae352558..49f9f35b68a5 100644 --- a/image/imgIContainer.idl +++ b/image/imgIContainer.idl @@ -559,4 +559,11 @@ interface imgIContainer : nsISupports * document. */ [noscript, notxpcom] void propagateUseCounters(in nsIDocument aDocument); + + %{C++ + /* + * Get the set of sizes the image can decode to natively. + */ + virtual nsresult GetNativeSizes(nsTArray& aNativeSizes) const = 0; + %} }; diff --git a/image/moz.build b/image/moz.build index c3a3a610fd8e..8ccb30247e91 100644 --- a/image/moz.build +++ b/image/moz.build @@ -37,8 +37,10 @@ XPIDL_MODULE = 'imglib2' EXPORTS += [ 'DrawResult.h', + 'FrameTimeout.h', 'ImageCacheKey.h', 'ImageLogging.h', + 'ImageMetadata.h', 'ImageOps.h', 'ImageRegion.h', 'imgLoader.h', diff --git a/image/test/gtest/Common.cpp b/image/test/gtest/Common.cpp index 4be34461c71c..4bc7fce1c32e 100644 --- a/image/test/gtest/Common.cpp +++ b/image/test/gtest/Common.cpp @@ -679,5 +679,11 @@ ImageTestCase TruncatedSmallGIFTestCase() return ImageTestCase("green-1x1-truncated.gif", "image/gif", IntSize(1, 1)); } +ImageTestCase GreenMultipleSizesICOTestCase() +{ + return ImageTestCase("green-multiple-sizes.ico", "image/x-icon", + IntSize(256, 256)); +} + } // namespace image } // namespace mozilla diff --git a/image/test/gtest/Common.h b/image/test/gtest/Common.h index 33fc26e750f8..63b8b9b70026 100644 --- a/image/test/gtest/Common.h +++ b/image/test/gtest/Common.h @@ -414,6 +414,8 @@ ImageTestCase DownscaledTransparentICOWithANDMaskTestCase(); ImageTestCase TruncatedSmallGIFTestCase(); +ImageTestCase GreenMultipleSizesICOTestCase(); + } // namespace image } // namespace mozilla diff --git a/image/test/gtest/TestDecodeToSurface.cpp b/image/test/gtest/TestDecodeToSurface.cpp index dd22d4308d9b..f5762d84c172 100644 --- a/image/test/gtest/TestDecodeToSurface.cpp +++ b/image/test/gtest/TestDecodeToSurface.cpp @@ -27,9 +27,11 @@ class DecodeToSurfaceRunnable : public Runnable public: DecodeToSurfaceRunnable(RefPtr& aSurface, nsIInputStream* aInputStream, + ImageOps::ImageBuffer* aImageBuffer, const ImageTestCase& aTestCase) : mSurface(aSurface) , mInputStream(aInputStream) + , mImageBuffer(aImageBuffer) , mTestCase(aTestCase) { } @@ -41,16 +43,35 @@ public: void Go() { - mSurface = - ImageOps::DecodeToSurface(mInputStream, - nsDependentCString(mTestCase.mMimeType), - imgIContainer::DECODE_FLAGS_DEFAULT); + Maybe outputSize; + if (mTestCase.mOutputSize != mTestCase.mSize) { + outputSize.emplace(mTestCase.mOutputSize); + } + + if (mImageBuffer) { + mSurface = + ImageOps::DecodeToSurface(mImageBuffer, + nsDependentCString(mTestCase.mMimeType), + imgIContainer::DECODE_FLAGS_DEFAULT, + outputSize); + } else { + mSurface = + ImageOps::DecodeToSurface(mInputStream, + nsDependentCString(mTestCase.mMimeType), + imgIContainer::DECODE_FLAGS_DEFAULT, + outputSize); + } ASSERT_TRUE(mSurface != nullptr); EXPECT_TRUE(mSurface->IsDataSourceSurface()); EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::B8G8R8X8 || mSurface->GetFormat() == SurfaceFormat::B8G8R8A8); - EXPECT_EQ(mTestCase.mSize, mSurface->GetSize()); + + if (outputSize) { + EXPECT_EQ(*outputSize, mSurface->GetSize()); + } else { + EXPECT_EQ(mTestCase.mSize, mSurface->GetSize()); + } EXPECT_TRUE(IsSolidColor(mSurface, BGRAColor::Green(), mTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0)); @@ -59,14 +80,19 @@ public: private: RefPtr& mSurface; nsCOMPtr mInputStream; + RefPtr mImageBuffer; ImageTestCase mTestCase; }; static void -RunDecodeToSurface(const ImageTestCase& aTestCase) +RunDecodeToSurface(const ImageTestCase& aTestCase, + ImageOps::ImageBuffer* aImageBuffer = nullptr) { - nsCOMPtr inputStream = LoadFile(aTestCase.mPath); - ASSERT_TRUE(inputStream != nullptr); + nsCOMPtr inputStream; + if (!aImageBuffer) { + inputStream = LoadFile(aTestCase.mPath); + ASSERT_TRUE(inputStream != nullptr); + } nsCOMPtr thread; nsresult rv = @@ -77,7 +103,7 @@ RunDecodeToSurface(const ImageTestCase& aTestCase) // DecodeToSurface doesn't require any main-thread-only code. RefPtr surface; nsCOMPtr runnable = - new DecodeToSurfaceRunnable(surface, inputStream, aTestCase); + new DecodeToSurfaceRunnable(surface, inputStream, aImageBuffer, aTestCase); thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC); thread->Shutdown(); @@ -122,3 +148,43 @@ TEST_F(ImageDecodeToSurface, Corrupt) imgIContainer::DECODE_FLAGS_DEFAULT); EXPECT_TRUE(surface == nullptr); } + +TEST_F(ImageDecodeToSurface, ICOMultipleSizes) +{ + ImageTestCase testCase = GreenMultipleSizesICOTestCase(); + + nsCOMPtr inputStream = LoadFile(testCase.mPath); + ASSERT_TRUE(inputStream != nullptr); + + RefPtr buffer = + ImageOps::CreateImageBuffer(inputStream); + ASSERT_TRUE(buffer != nullptr); + + ImageMetadata metadata; + nsresult rv = ImageOps::DecodeMetadata(buffer, + nsDependentCString(testCase.mMimeType), + metadata); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(metadata.HasSize()); + EXPECT_EQ(testCase.mSize, metadata.GetSize()); + + const nsTArray& nativeSizes = metadata.GetNativeSizes(); + ASSERT_EQ(6u, nativeSizes.Length()); + + IntSize expectedSizes[] = { + IntSize(16, 16), + IntSize(32, 32), + IntSize(64, 64), + IntSize(128, 128), + IntSize(256, 256), + IntSize(256, 128), + }; + + for (int i = 0; i < 6; ++i) { + EXPECT_EQ(expectedSizes[i], nativeSizes[i]); + + // Request decoding at native size + testCase.mOutputSize = nativeSizes[i]; + RunDecodeToSurface(testCase, buffer); + } +} diff --git a/image/test/gtest/TestDecoders.cpp b/image/test/gtest/TestDecoders.cpp index d39b8e404a60..16b17ac63b3f 100644 --- a/image/test/gtest/TestDecoders.cpp +++ b/image/test/gtest/TestDecoders.cpp @@ -672,3 +672,87 @@ TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk) { CheckDecoderSingleChunk(TruncatedSmallGIFTestCase()); } + +TEST_F(ImageDecoders, MultipleSizesICOSingleChunk) +{ + ImageTestCase testCase = GreenMultipleSizesICOTestCase(); + + // Create an image. + RefPtr image = + ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType)); + ASSERT_TRUE(!image->HasError()); + + nsCOMPtr inputStream = LoadFile(testCase.mPath); + ASSERT_TRUE(inputStream); + + // Figure out how much data we have. + uint64_t length; + nsresult rv = inputStream->Available(&length); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + // Write the data into the image. + rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0, + static_cast(length)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + // Let the image know we've sent all the data. + rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + RefPtr tracker = image->GetProgressTracker(); + tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); + + // Use GetFrame() to force a sync decode of the image. + RefPtr surface = + image->GetFrame(imgIContainer::FRAME_CURRENT, + imgIContainer::FLAG_SYNC_DECODE); + + // Ensure that the image's metadata meets our expectations. + IntSize imageSize(0, 0); + rv = image->GetWidth(&imageSize.width); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + rv = image->GetHeight(&imageSize.height); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + + EXPECT_EQ(testCase.mSize.width, imageSize.width); + EXPECT_EQ(testCase.mSize.height, imageSize.height); + + nsTArray nativeSizes; + rv = image->GetNativeSizes(nativeSizes); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_EQ(6u, nativeSizes.Length()); + + IntSize expectedSizes[] = { + IntSize(16, 16), + IntSize(32, 32), + IntSize(64, 64), + IntSize(128, 128), + IntSize(256, 256), + IntSize(256, 128) + }; + + for (int i = 0; i < 6; ++i) { + EXPECT_EQ(expectedSizes[i], nativeSizes[i]); + } + + RefPtr image90 = + ImageOps::Orient(image, Orientation(Angle::D90, Flip::Unflipped)); + rv = image90->GetNativeSizes(nativeSizes); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_EQ(6u, nativeSizes.Length()); + + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(expectedSizes[i], nativeSizes[i]); + } + EXPECT_EQ(IntSize(128, 256), nativeSizes[5]); + + RefPtr image180 = + ImageOps::Orient(image, Orientation(Angle::D180, Flip::Unflipped)); + rv = image180->GetNativeSizes(nativeSizes); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_EQ(6u, nativeSizes.Length()); + + for (int i = 0; i < 6; ++i) { + EXPECT_EQ(expectedSizes[i], nativeSizes[i]); + } +} diff --git a/image/test/gtest/green-multiple-sizes.ico b/image/test/gtest/green-multiple-sizes.ico new file mode 100644 index 000000000000..b9463d0c8971 Binary files /dev/null and b/image/test/gtest/green-multiple-sizes.ico differ diff --git a/image/test/gtest/moz.build b/image/test/gtest/moz.build index ad69e098518c..3e37573dba04 100644 --- a/image/test/gtest/moz.build +++ b/image/test/gtest/moz.build @@ -47,6 +47,7 @@ TEST_HARNESS_FILES.gtest += [ 'first-frame-green.png', 'first-frame-padding.gif', 'green-1x1-truncated.gif', + 'green-multiple-sizes.ico', 'green.bmp', 'green.gif', 'green.ico', diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index ae0e4b678e34..d0f75e88ccc3 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -251,6 +251,12 @@ CheckEdgeIsNotBlackToGray(JSObject* src, const Value& dst) MOZ_ASSERT_IF(IsMarkedBlack(src), JS::ValueIsNotGray(dst)); } +MOZ_ALWAYS_INLINE void +CheckEdgeIsNotBlackToGray(JSObject* src, gc::Cell* dst) +{ + MOZ_ASSERT_IF(IsMarkedBlack(src), JS::CellIsNotGray(dst)); +} + template struct InternalBarrierMethods {}; diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 22839c291ce4..d36594cd24f6 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -2575,6 +2575,17 @@ GCMarker::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const } #ifdef DEBUG + +static bool +IsCrossCompartmentEdge(JSObject* source, const Cell* target) +{ + if (!source->is()) + return false; + + const Value& priv = source->as().private_(); + return priv.isGCThing() && priv.toGCThing() == target; +} + Zone* GCMarker::stackContainsCrossZonePointerTo(const Cell* target) const { @@ -2591,7 +2602,7 @@ GCMarker::stackContainsCrossZonePointerTo(const Cell* target) const if (sourceZone == targetZone) continue; - if ((source->is() && source->as().target() == target) || + if (IsCrossCompartmentEdge(source, target) || Debugger::isDebuggerCrossCompartmentEdge(source, target)) { return sourceZone; diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 8be65b96153f..4b2ca495a280 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -418,6 +418,8 @@ JSCompartment::getNonWrapperObjectForCurrentCompartment(JSContext* cx, MutableHa bool JSCompartment::getOrCreateWrapper(JSContext* cx, HandleObject existing, MutableHandleObject obj) { + MOZ_ASSERT(JS::ObjectIsNotGray(obj)); + // If we already have a wrapper for this value, use it. RootedValue key(cx, ObjectValue(*obj)); if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(CrossCompartmentKey(key))) { diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index 2e21a06840d1..7928e7bd6ee1 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -141,6 +141,7 @@ class JS_FRIEND_API(Wrapper) : public BaseProxyHandler static const Wrapper* wrapperHandler(JSObject* wrapper); static JSObject* wrappedObject(JSObject* wrapper); + static JSObject* wrappedObjectMaybeGray(JSObject* wrapper); unsigned flags() const { return mFlags; diff --git a/js/src/proxy/CrossCompartmentWrapper.cpp b/js/src/proxy/CrossCompartmentWrapper.cpp index ed00594b5386..7e7e3fb558a1 100644 --- a/js/src/proxy/CrossCompartmentWrapper.cpp +++ b/js/src/proxy/CrossCompartmentWrapper.cpp @@ -645,6 +645,8 @@ js::RemapAllWrappersForObject(JSContext* cx, JSObject* oldTargetArg, { MOZ_ASSERT(!IsInsideNursery(oldTargetArg)); MOZ_ASSERT(!IsInsideNursery(newTargetArg)); + MOZ_ASSERT(JS::ObjectIsNotGray(oldTargetArg)); + MOZ_ASSERT(JS::ObjectIsNotGray(newTargetArg)); RootedValue origv(cx, ObjectValue(*oldTargetArg)); RootedObject newTarget(cx, newTargetArg); @@ -699,7 +701,8 @@ js::RecomputeWrappers(JSContext* cx, const CompartmentFilter& sourceFilter, // Recompute all the wrappers in the list. for (const WrapperValue& v : toRecompute) { JSObject* wrapper = &v.toObject(); - JSObject* wrapped = Wrapper::wrappedObject(wrapper); + JSObject* wrapped = Wrapper::wrappedObjectMaybeGray(wrapper); + JS::ExposeObjectToActiveJS(wrapped); RemapWrapper(cx, wrapper, wrapped); } diff --git a/js/src/proxy/Wrapper.cpp b/js/src/proxy/Wrapper.cpp index 35ed461c9041..0c02fc04e195 100644 --- a/js/src/proxy/Wrapper.cpp +++ b/js/src/proxy/Wrapper.cpp @@ -328,13 +328,18 @@ Wrapper::wrapperHandler(JSObject* wrapper) JSObject* Wrapper::wrappedObject(JSObject* wrapper) { - MOZ_ASSERT(wrapper->is()); - JSObject* target = wrapper->as().target(); - if (target) - JS::ExposeObjectToActiveJS(target); + JSObject* target = wrappedObjectMaybeGray(wrapper); + MOZ_ASSERT(JS::ObjectIsNotGray(target)); return target; } +JSObject* +Wrapper::wrappedObjectMaybeGray(JSObject* wrapper) +{ + MOZ_ASSERT(wrapper->is()); + return wrapper->as().target(); +} + JS_FRIEND_API(JSObject*) js::UncheckedUnwrap(JSObject* wrapped, bool stopAtWindowProxy, unsigned* flagsp) { @@ -346,7 +351,7 @@ js::UncheckedUnwrap(JSObject* wrapped, bool stopAtWindowProxy, unsigned* flagsp) break; } flags |= Wrapper::wrapperHandler(wrapped)->flags(); - wrapped = wrapped->as().private_().toObjectOrNull(); + wrapped = wrapped->as().target(); // This can be called from Wrapper::weakmapKeyDelegate() on a wrapper // whose referent has been moved while it is still unmarked. diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h index a760340e2dd9..72805017ba8c 100644 --- a/js/src/vm/NativeObject.h +++ b/js/src/vm/NativeObject.h @@ -1227,6 +1227,7 @@ class NativeObject : public ShapedObject } void setPrivateGCThing(gc::Cell* cell) { + CheckEdgeIsNotBlackToGray(this, cell); void** pprivate = &privateRef(numFixedSlots()); privateWriteBarrierPre(pprivate); *pprivate = reinterpret_cast(cell); diff --git a/js/src/vm/ProxyObject.cpp b/js/src/vm/ProxyObject.cpp index 2bb36c952d02..5fdb6ca774e2 100644 --- a/js/src/vm/ProxyObject.cpp +++ b/js/src/vm/ProxyObject.cpp @@ -101,6 +101,7 @@ ProxyObject::objectMovedDuringMinorGC(TenuringTracer* trc, JSObject* dst, JSObje void ProxyObject::setCrossCompartmentPrivate(const Value& priv) { + CheckEdgeIsNotBlackToGray(this, priv); *slotOfPrivate() = priv; } @@ -108,6 +109,7 @@ void ProxyObject::setSameCompartmentPrivate(const Value& priv) { MOZ_ASSERT(IsObjectValueInCompartment(priv, compartment())); + CheckEdgeIsNotBlackToGray(this, priv); *slotOfPrivate() = priv; } diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index 0daf207897f0..45eb0ffa95c9 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -201,9 +201,12 @@ XPCWrappedNativeXrayTraits::getWN(JSObject* wrapper) } const JSClass XPCWrappedNativeXrayTraits::HolderClass = { - "NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(2) + "NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(HOLDER_SHARED_SLOT_COUNT) }; +const JSClass XrayTraits::HolderClass = { + "XrayHolder", JSCLASS_HAS_RESERVED_SLOTS(HOLDER_SHARED_SLOT_COUNT) +}; const JSClass JSXrayTraits::HolderClass = { "JSXrayHolder", JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT) @@ -1854,7 +1857,7 @@ DOMXrayTraits::preserveWrapper(JSObject* target) JSObject* DOMXrayTraits::createHolder(JSContext* cx, JSObject* wrapper) { - return JS_NewObjectWithGivenProto(cx, nullptr, nullptr); + return JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr); } const JSClass* @@ -2407,16 +2410,35 @@ XrayWrapper::getPrototype(JSContext* cx, JS::HandleObject wrapper, // only if there's been a set. If there's not an expando, or the expando // slot is |undefined|, hand back the default proto, appropriately wrapped. - RootedValue v(cx); if (expando) { - JSAutoCompartment ac(cx, expando); - v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE); + RootedValue v(cx); + { // Scope for JSAutoCompartment + JSAutoCompartment ac(cx, expando); + v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE); + } + if (!v.isUndefined()) { + protop.set(v.toObjectOrNull()); + return JS_WrapObject(cx, protop); + } } - if (v.isUndefined()) - return getPrototypeHelper(cx, wrapper, target, protop); - protop.set(v.toObjectOrNull()); - return JS_WrapObject(cx, protop); + // Check our holder, and cache there if we don't have it cached already. + RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper)); + if (!holder) + return false; + + Value cached = js::GetReservedSlot(holder, + Traits::HOLDER_SLOT_CACHED_PROTO); + if (cached.isUndefined()) { + if (!getPrototypeHelper(cx, wrapper, target, protop)) + return false; + + js::SetReservedSlot(holder, Traits::HOLDER_SLOT_CACHED_PROTO, + ObjectOrNullValue(protop)); + } else { + protop.set(cached.toObjectOrNull()); + } + return true; } template diff --git a/js/xpconnect/wrappers/XrayWrapper.h b/js/xpconnect/wrappers/XrayWrapper.h index 5630982c28c4..4527e3b0a1f0 100644 --- a/js/xpconnect/wrappers/XrayWrapper.h +++ b/js/xpconnect/wrappers/XrayWrapper.h @@ -99,6 +99,12 @@ public: JSObject* ensureExpandoObject(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target); + // Slots for holder objects. + enum { + HOLDER_SLOT_CACHED_PROTO = 0, + HOLDER_SHARED_SLOT_COUNT + }; + JSObject* getHolder(JSObject* wrapper); JSObject* ensureHolder(JSContext* cx, JS::HandleObject wrapper); virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) = 0; @@ -108,6 +114,8 @@ public: bool cloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject src); protected: + static const JSClass HolderClass; + // Get the JSClass we should use for our expando object. virtual const JSClass* getExpandoClass(JSContext* cx, JS::HandleObject target) const; @@ -301,7 +309,7 @@ public: } enum { - SLOT_PROTOKEY = 0, + SLOT_PROTOKEY = HOLDER_SHARED_SLOT_COUNT, SLOT_ISPROTOTYPE, SLOT_CONSTRUCTOR_FOR, SLOT_COUNT @@ -421,7 +429,7 @@ public: virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override { - return JS_NewObjectWithGivenProto(cx, nullptr, nullptr); + return JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr); } static OpaqueXrayTraits singleton; diff --git a/layout/reftests/flexbox/reftest.list b/layout/reftests/flexbox/reftest.list index 9cd46bab54a6..d305a7fb4b57 100644 --- a/layout/reftests/flexbox/reftest.list +++ b/layout/reftests/flexbox/reftest.list @@ -115,4 +115,4 @@ skip-if(gtkWidget) == flexbox-widget-flex-items-3.html flexbox-widget-flex-items fuzzy-if(gtkWidget,1,31) == flexbox-widget-flex-items-4.html flexbox-widget-flex-items-4-ref.html # Tests for table flex items -== flexbox-table-flex-items-1-ref.html flexbox-table-flex-items-1-ref.html +== flexbox-table-flex-items-1.html flexbox-table-flex-items-1-ref.html diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js index a3c3f919770f..227b10d2b42a 100644 --- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -4437,21 +4437,13 @@ Tab.prototype = { this.shouldShowPluginDoorhanger = true; this.clickToPlayPluginsActivated = false; - let documentURI = contentWin.document.documentURIObject.spec; - - // If reader mode, get the base domain for the original url. - let strippedURI = this._stripAboutReaderURL(documentURI); - - // Borrowed from desktop Firefox: https://hg.mozilla.org/mozilla-central/annotate/72835344333f/browser/base/content/urlbarBindings.xml#l236 - let matchedURL = strippedURI.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/); let baseDomain = ""; - if (matchedURL) { - var domain = ""; - [, , domain] = matchedURL; - + // For recognized scheme, get base domain from host. + let principalURI = contentWin.document.nodePrincipal.URI; + if (principalURI && ["http", "https", "ftp"].includes(principalURI.scheme) && principalURI.host) { try { - baseDomain = Services.eTLD.getBaseDomainFromHost(domain); - if (!domain.endsWith(baseDomain)) { + baseDomain = Services.eTLD.getBaseDomainFromHost(principalURI.host); + if (!principalURI.host.endsWith(baseDomain)) { // getBaseDomainFromHost converts its resultant to ACE. let IDNService = Cc["@mozilla.org/network/idn-service;1"].getService(Ci.nsIIDNService); baseDomain = IDNService.convertACEtoUTF8(baseDomain); diff --git a/security/sandbox/chromium-shim/base/MissingBasicTypes.h b/security/sandbox/chromium-shim/base/MissingBasicTypes.h deleted file mode 100644 index 20eef00abcb5..000000000000 --- a/security/sandbox/chromium-shim/base/MissingBasicTypes.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef security_sandbox_MissingBasicTypes_h__ -#define security_sandbox_MissingBasicTypes_h__ - -#include - -// These types are still used by the Chromium sandbox code. When referencing -// Chromium sandbox code from Gecko we can't use the normal base/basictypes.h as -// it clashes with the one from ipc/chromium/src/base/. These types have been -// removed from the one in ipc/chromium/src/base/. -typedef int8_t int8; -typedef uint8_t uint8; -typedef int16_t int16; -typedef uint16_t uint16; -typedef int32_t int32; -typedef uint32_t uint32; -typedef int64_t int64; -typedef uint64_t uint64; - -#endif // security_sandbox_MissingBasicTypes_h__ diff --git a/security/sandbox/chromium-shim/base/debug/activity_tracker.h b/security/sandbox/chromium-shim/base/debug/activity_tracker.h new file mode 100644 index 000000000000..0057090df14e --- /dev/null +++ b/security/sandbox/chromium-shim/base/debug/activity_tracker.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a dummy version of Chromium source file base/debug/activity_tracker.h. +// To provide a class required in base/synchronization/lock_impl_win.cc +// ScopedLockAcquireActivity. We don't use activity tracking. + +#ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ +#define BASE_DEBUG_ACTIVITY_TRACKER_H_ + +#include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/macros.h" + +namespace base { +class PlatformThreadHandle; +class WaitableEvent; + +namespace internal { +class LockImpl; +} + +namespace debug { + +class BASE_EXPORT ScopedLockAcquireActivity +{ + public: + ALWAYS_INLINE + explicit ScopedLockAcquireActivity(const base::internal::LockImpl* lock) {} + DISALLOW_COPY_AND_ASSIGN(ScopedLockAcquireActivity); +}; + +class BASE_EXPORT ScopedEventWaitActivity +{ + public: + ALWAYS_INLINE + explicit ScopedEventWaitActivity(const base::WaitableEvent* event) {} + DISALLOW_COPY_AND_ASSIGN(ScopedEventWaitActivity); +}; + +class BASE_EXPORT ScopedThreadJoinActivity +{ + public: + ALWAYS_INLINE + explicit ScopedThreadJoinActivity(const base::PlatformThreadHandle* thread) {} + DISALLOW_COPY_AND_ASSIGN(ScopedThreadJoinActivity); +}; + + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ diff --git a/security/sandbox/chromium-shim/base/debug/stack_trace.h b/security/sandbox/chromium-shim/base/debug/stack_trace.h new file mode 100644 index 000000000000..775d12cc9113 --- /dev/null +++ b/security/sandbox/chromium-shim/base/debug/stack_trace.h @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a dummy version of Chromium source file base/debug/stack_trace.h. +// To provide a dummy class StackTrace required in base/win/scoped_handle.cc. + +#ifndef BASE_DEBUG_STACK_TRACE_H_ +#define BASE_DEBUG_STACK_TRACE_H_ + +namespace base { +namespace debug { + +class BASE_EXPORT StackTrace { + public: + StackTrace() {}; +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_STACK_TRACE_H_ diff --git a/security/sandbox/chromium-shim/base/file_version_info_win.h b/security/sandbox/chromium-shim/base/file_version_info_win.h index 8276900bd452..788900b4dae8 100644 --- a/security/sandbox/chromium-shim/base/file_version_info_win.h +++ b/security/sandbox/chromium-shim/base/file_version_info_win.h @@ -11,6 +11,8 @@ #ifndef BASE_FILE_VERSION_INFO_WIN_H_ #define BASE_FILE_VERSION_INFO_WIN_H_ +#include "mozilla/Assertions.h" + struct tagVS_FIXEDFILEINFO; typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO; @@ -21,9 +23,9 @@ class FilePath; class FileVersionInfoWin { public: static FileVersionInfoWin* - CreateFileVersionInfo(const base::FilePath& file_path) { return nullptr; } + CreateFileVersionInfo(const base::FilePath& file_path) { MOZ_CRASH(); } - VS_FIXEDFILEINFO* fixed_file_info() { return nullptr; } + VS_FIXEDFILEINFO* fixed_file_info() { MOZ_CRASH(); } }; #endif // BASE_FILE_VERSION_INFO_WIN_H_ diff --git a/security/sandbox/chromium-shim/base/files/file_path.cpp b/security/sandbox/chromium-shim/base/files/file_path.cpp index 245118f9ee55..c5eee683c875 100644 --- a/security/sandbox/chromium-shim/base/files/file_path.cpp +++ b/security/sandbox/chromium-shim/base/files/file_path.cpp @@ -8,9 +8,12 @@ #include "base/files/file_path.h" +#include "mozilla/Assertions.h" + namespace base { FilePath::FilePath(FilePath::StringPieceType path) { + MOZ_CRASH(); } FilePath::~FilePath() { diff --git a/security/sandbox/chromium-shim/base/files/file_util.h b/security/sandbox/chromium-shim/base/files/file_util.h new file mode 100644 index 000000000000..bd6ce0c0a823 --- /dev/null +++ b/security/sandbox/chromium-shim/base/files/file_util.h @@ -0,0 +1,11 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a cut down version of Chromium source file base/files/file_util.h +// This is included in base/memory/shared_memory.h, but it only actually +// requires the include for base/files/file_path.h. + +#include "base/files/file_path.h" diff --git a/security/sandbox/chromium-shim/base/gtest_prod_util.h b/security/sandbox/chromium-shim/base/gtest_prod_util.h index 3eb93fa2a783..b45a1586b0f0 100644 --- a/security/sandbox/chromium-shim/base/gtest_prod_util.h +++ b/security/sandbox/chromium-shim/base/gtest_prod_util.h @@ -4,6 +4,9 @@ * 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/. */ +#ifndef BASE_GTEST_PROD_UTIL_H_ +#define BASE_GTEST_PROD_UTIL_H_ + #ifndef FRIEND_TEST #define FRIEND_TEST(A, B) #endif @@ -15,3 +18,5 @@ #ifndef FORWARD_DECLARE_TEST #define FORWARD_DECLARE_TEST(test_case_name, test_name) #endif + +#endif // BASE_GTEST_PROD_UTIL_H_ diff --git a/security/sandbox/chromium-shim/base/logging.cpp b/security/sandbox/chromium-shim/base/logging.cpp index 9c2113dcbebe..d5811e576e53 100644 --- a/security/sandbox/chromium-shim/base/logging.cpp +++ b/security/sandbox/chromium-shim/base/logging.cpp @@ -28,6 +28,8 @@ #include +#include "mozilla/Unused.h" + namespace logging { namespace { @@ -127,6 +129,7 @@ Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, SystemErrorCode err) : err_(err), log_message_(file, line, severity) { + mozilla::Unused << err_; } Win32ErrorLogMessage::~Win32ErrorLogMessage() { @@ -138,6 +141,7 @@ ErrnoLogMessage::ErrnoLogMessage(const char* file, SystemErrorCode err) : err_(err), log_message_(file, line, severity) { + mozilla::Unused << err_; } ErrnoLogMessage::~ErrnoLogMessage() { diff --git a/security/sandbox/chromium-shim/base/metrics/histogram_macros.h b/security/sandbox/chromium-shim/base/metrics/histogram_macros.h new file mode 100644 index 000000000000..4eedbfa13ec4 --- /dev/null +++ b/security/sandbox/chromium-shim/base/metrics/histogram_macros.h @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a dummy version of Chromium source file base/metrics/histogram_macros.h. +// To provide to histogram macros required in base/memory/shared_memory_win.cc +// UMA_HISTOGRAM_ENUMERATION and UMA_HISTOGRAM_SPARSE_SLOWLY. +// We don't require Chromiums histogram collection code. + +#ifndef BASE_METRICS_HISTOGRAM_MACROS_H_ +#define BASE_METRICS_HISTOGRAM_MACROS_H_ + +#define UMA_HISTOGRAM_ENUMERATION(name, sample, enum_max) do { } while (0) +#define UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample) do { } while (0) + +#endif // BASE_METRICS_HISTOGRAM_MACROS_H_ diff --git a/security/sandbox/chromium-shim/base/scoped_native_library.h b/security/sandbox/chromium-shim/base/scoped_native_library.h new file mode 100644 index 000000000000..d6fdf478ecae --- /dev/null +++ b/security/sandbox/chromium-shim/base/scoped_native_library.h @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a cut down version of Chromium source file base/scoped_native_library.h +// The chromium sandbox only requires ScopedNativeLibrary class to automatically +// unload the library, which we can achieve with UniquePtr. + +#ifndef BASE_SCOPED_NATIVE_LIBRARY_H_ +#define BASE_SCOPED_NATIVE_LIBRARY_H_ + +#include "mozilla/UniquePtr.h" + +namespace base { + +struct HModuleFreePolicy +{ + typedef HMODULE pointer; + void operator()(pointer hModule) + { + ::FreeLibrary(hModule); + } +}; + +typedef mozilla::UniquePtr ScopedNativeLibrary; + +} // namespace base + +#endif // BASE_SCOPED_NATIVE_LIBRARY_H_ diff --git a/security/sandbox/chromium-shim/base/threading/platform_thread_linux.cpp b/security/sandbox/chromium-shim/base/threading/platform_thread_linux.cpp new file mode 100644 index 000000000000..e70bcaa8a076 --- /dev/null +++ b/security/sandbox/chromium-shim/base/threading/platform_thread_linux.cpp @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a cut down version of Chromium source file base/threading/platform_thread_linux.h +// with only the functions required. It also has a dummy implementation of +// SetCurrentThreadPriorityForPlatform, which should not be called. + +#include "base/threading/platform_thread.h" + +#include "base/threading/platform_thread_internal_posix.h" + +#include "mozilla/Assertions.h" + +namespace base { +namespace internal { + +namespace { +const struct sched_param kRealTimePrio = {8}; +} // namespace + +const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { + {ThreadPriority::BACKGROUND, 10}, + {ThreadPriority::NORMAL, 0}, + {ThreadPriority::DISPLAY, -8}, + {ThreadPriority::REALTIME_AUDIO, -10}, +}; + +bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { + MOZ_CRASH(); +} + +bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { + int maybe_sched_rr = 0; + struct sched_param maybe_realtime_prio = {0}; + if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, + &maybe_realtime_prio) == 0 && + maybe_sched_rr == SCHED_RR && + maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { + *priority = ThreadPriority::REALTIME_AUDIO; + return true; + } + return false; +} + +} // namespace internal + +void InitThreading() {} + +void TerminateOnThread() {} + +size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { +#if !defined(THREAD_SANITIZER) + return 0; +#else + // ThreadSanitizer bloats the stack heavily. Evidence has been that the + // default stack size isn't enough for some browser tests. + return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). +#endif +} + +} // namespace base diff --git a/security/sandbox/chromium-shim/base/trace_event/heap_profiler_allocation_context_tracker.h b/security/sandbox/chromium-shim/base/trace_event/heap_profiler_allocation_context_tracker.h new file mode 100644 index 000000000000..bb2cca0ec494 --- /dev/null +++ b/security/sandbox/chromium-shim/base/trace_event/heap_profiler_allocation_context_tracker.h @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a dummy version of Chromium source file base/trace_event/heap_profiler_allocation_context_tracker.h. +// To provide a function required in base/threading/thread_id_name_manager.cc +// SetCurrentThreadName. We don't use the heap profiler. + +#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ +#define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ + +namespace base { +namespace trace_event { + +// The allocation context tracker keeps track of thread-local context for heap +// profiling. It includes a pseudo stack of trace events. On every allocation +// the tracker provides a snapshot of its context in the form of an +// |AllocationContext| that is to be stored together with the allocation +// details. +class BASE_EXPORT AllocationContextTracker { + public: + static void SetCurrentThreadName(const char* name) {} + + DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ diff --git a/security/sandbox/chromium-shim/base/tracked_objects.h b/security/sandbox/chromium-shim/base/tracked_objects.h index 837705ee9f22..092c9533f623 100644 --- a/security/sandbox/chromium-shim/base/tracked_objects.h +++ b/security/sandbox/chromium-shim/base/tracked_objects.h @@ -6,6 +6,9 @@ #ifndef _SECURITY_SANDBOX_TRACKED_OBJECTS_H_ #define _SECURITY_SANDBOX_TRACKED_OBJECTS_H_ + +#include "mozilla/Assertions.h" + namespace tracked_objects { class ThreadData @@ -13,6 +16,7 @@ namespace tracked_objects public: static void InitializeThreadContext(const std::string& name) { + MOZ_CRASH(); } }; } diff --git a/security/sandbox/chromium-shim/base/win/base_features.h b/security/sandbox/chromium-shim/base/win/base_features.h new file mode 100644 index 000000000000..3ee0572b896a --- /dev/null +++ b/security/sandbox/chromium-shim/base/win/base_features.h @@ -0,0 +1,17 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +// This is a dummy version of a file that is generated by the chromium build +// from base/win/BUILD.gn. + +#ifndef BASE_WIN_BASE_FEATURES_H_ +#define BASE_WIN_BASE_FEATURES_H_ + +#include "build/buildflag.h" + +#define BUILDFLAG_INTERNAL_SINGLE_MODULE_MODE_HANDLE_VERIFIER() (false) + +#endif // BASE_WIN_BASE_FEATURES_H_ diff --git a/security/sandbox/chromium-shim/base/win/registry.h b/security/sandbox/chromium-shim/base/win/registry.h index 9fba57277c5d..e5d0f26ed202 100644 --- a/security/sandbox/chromium-shim/base/win/registry.h +++ b/security/sandbox/chromium-shim/base/win/registry.h @@ -7,21 +7,35 @@ // This is a stripped down version of Chromium source file base/win/registry.h // Within our copy of Chromium files this is only used in base/win/windows_version.cc // in OSInfo::processor_model_name, which we don't use. +// It is also used in GetUBR, which is used as the VersionNumber.patch, which +// again is not needed by the sandbox. #ifndef BASE_WIN_REGISTRY_H_ #define BASE_WIN_REGISTRY_H_ +#include + namespace base { namespace win { class BASE_EXPORT RegKey { public: + RegKey() {}; RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) {} ~RegKey() {} + LONG Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) { + return ERROR_CANTOPEN; + } + + LONG ReadValueDW(const wchar_t* name, DWORD* out_value) const + { + return ERROR_CANTREAD; + } + LONG ReadValue(const wchar_t* name, std::wstring* out_value) const { - return 0; + return ERROR_CANTREAD; } private: diff --git a/security/sandbox/chromium-shim/base/win/sdkdecls.h b/security/sandbox/chromium-shim/base/win/sdkdecls.h index e999ab967b72..e2fdda5fe5d6 100644 --- a/security/sandbox/chromium-shim/base/win/sdkdecls.h +++ b/security/sandbox/chromium-shim/base/win/sdkdecls.h @@ -188,4 +188,58 @@ typedef struct _PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY { #endif // NTDDI_WIN8 #endif // (_WIN32_WINNT < 0x0602) + +#if (_WIN32_WINNT < 0x0A00) +// +// Define Font Disable Policy. When enabled, this option will +// block loading Non System Fonts. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_MASK (0x00000003ui64 << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_DEFER (0x00000000ui64 << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_ON (0x00000001ui64 << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_OFF (0x00000002ui64 << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_AUDIT_NONSYSTEM_FONTS (0x00000003ui64 << 48) + +// +// Define remote image load options. When enabled, this option will +// block mapping of images from remote devices. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_MASK (0x00000003ui64 << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_DEFER (0x00000000ui64 << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_ALWAYS_ON (0x00000001ui64 << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_ALWAYS_OFF (0x00000002ui64 << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_RESERVED (0x00000003ui64 << 52) + +// +// Define low IL image load options. When enabled, this option will +// block mapping of images that have the low mandatory label. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_MASK (0x00000003ui64 << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_DEFER (0x00000000ui64 << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_ALWAYS_ON (0x00000001ui64 << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_ALWAYS_OFF (0x00000002ui64 << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_RESERVED (0x00000003ui64 << 56) + +// +// Define Attribute to disable creation of child process +// + +#define PROCESS_CREATION_CHILD_PROCESS_RESTRICTED 0x01 +#define PROCESS_CREATION_CHILD_PROCESS_OVERRIDE 0x02 + +// +// Define Attribute for Desktop Appx Overide. +// + +#define PROCESS_CREATION_DESKTOP_APPX_OVERRIDE 0x04 + +#define ProcThreadAttributeChildProcessPolicy 14 + +#define PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY \ + ProcThreadAttributeValue (ProcThreadAttributeChildProcessPolicy, FALSE, TRUE, FALSE) + +#endif // (_WIN32_WINNT >= 0x0A00) #endif // _SECURITY_SANDBOX_BASE_SHIM_SDKDECLS_H_ diff --git a/security/sandbox/chromium/base/at_exit.cc b/security/sandbox/chromium/base/at_exit.cc index 0fba355698fb..cfe4cf9a587c 100644 --- a/security/sandbox/chromium/base/at_exit.cc +++ b/security/sandbox/chromium/base/at_exit.cc @@ -6,6 +6,7 @@ #include #include +#include #include "base/bind.h" #include "base/callback.h" @@ -21,7 +22,8 @@ namespace base { // this for thread-safe access, since it will only be modified in testing. static AtExitManager* g_top_manager = NULL; -AtExitManager::AtExitManager() : next_manager_(g_top_manager) { +AtExitManager::AtExitManager() + : processing_callbacks_(false), next_manager_(g_top_manager) { // If multiple modules instantiate AtExitManagers they'll end up living in this // module... they have to coexist. #if !defined(COMPONENT_BUILD) @@ -55,7 +57,8 @@ void AtExitManager::RegisterTask(base::Closure task) { } AutoLock lock(g_top_manager->lock_); - g_top_manager->stack_.push(task); + DCHECK(!g_top_manager->processing_callbacks_); + g_top_manager->stack_.push(std::move(task)); } // static @@ -65,16 +68,28 @@ void AtExitManager::ProcessCallbacksNow() { return; } - AutoLock lock(g_top_manager->lock_); - - while (!g_top_manager->stack_.empty()) { - base::Closure task = g_top_manager->stack_.top(); - task.Run(); - g_top_manager->stack_.pop(); + // Callbacks may try to add new callbacks, so run them without holding + // |lock_|. This is an error and caught by the DCHECK in RegisterTask(), but + // handle it gracefully in release builds so we don't deadlock. + std::stack tasks; + { + AutoLock lock(g_top_manager->lock_); + tasks.swap(g_top_manager->stack_); + g_top_manager->processing_callbacks_ = true; } + + while (!tasks.empty()) { + base::Closure task = tasks.top(); + task.Run(); + tasks.pop(); + } + + // Expect that all callbacks have been run. + DCHECK(g_top_manager->stack_.empty()); } -AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) { +AtExitManager::AtExitManager(bool shadow) + : processing_callbacks_(false), next_manager_(g_top_manager) { DCHECK(shadow || !g_top_manager); g_top_manager = this; } diff --git a/security/sandbox/chromium/base/at_exit.h b/security/sandbox/chromium/base/at_exit.h index 04e3f7642224..02e18ed9eb75 100644 --- a/security/sandbox/chromium/base/at_exit.h +++ b/security/sandbox/chromium/base/at_exit.h @@ -59,6 +59,7 @@ class BASE_EXPORT AtExitManager { private: base::Lock lock_; std::stack stack_; + bool processing_callbacks_; AtExitManager* next_manager_; // Stack of managers to allow shadowing. DISALLOW_COPY_AND_ASSIGN(AtExitManager); diff --git a/security/sandbox/chromium/base/atomic_ref_count.h b/security/sandbox/chromium/base/atomic_ref_count.h index 2ab724200203..93c1f0dfd40f 100644 --- a/security/sandbox/chromium/base/atomic_ref_count.h +++ b/security/sandbox/chromium/base/atomic_ref_count.h @@ -12,7 +12,7 @@ namespace base { -typedef subtle::Atomic32 AtomicRefCount; +typedef subtle::AtomicWord AtomicRefCount; // Increment a reference count by "increment", which must exceed 0. inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr, diff --git a/security/sandbox/chromium/base/base_paths.h b/security/sandbox/chromium/base/base_paths.h index 26b2fd4c9a10..ef6aa8283620 100644 --- a/security/sandbox/chromium/base/base_paths.h +++ b/security/sandbox/chromium/base/base_paths.h @@ -32,9 +32,8 @@ enum BasePathKey { DIR_MODULE, // Directory containing FILE_MODULE. DIR_TEMP, // Temporary directory. DIR_HOME, // User's root home directory. On Windows this will look - // like "C:\Users\you" (or on XP - // "C:\Document and Settings\you") which isn't necessarily - // a great place to put files. + // like "C:\Users\" which isn't necessarily a great + // place to put files. FILE_EXE, // Path and filename of the current executable. FILE_MODULE, // Path and filename of the module containing the code for // the PathService (which could differ from FILE_EXE if the diff --git a/security/sandbox/chromium/base/base_paths_win.h b/security/sandbox/chromium/base/base_paths_win.h index d9dbc39f99ab..2db16a62719b 100644 --- a/security/sandbox/chromium/base/base_paths_win.h +++ b/security/sandbox/chromium/base/base_paths_win.h @@ -25,26 +25,25 @@ enum { DIR_PROGRAM_FILESX86, // See table above. DIR_PROGRAM_FILES6432, // See table above. - DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory. - DIR_COMMON_START_MENU, // Usually "C:\Documents and Settings\All Users\ - // Start Menu\Programs" - DIR_START_MENU, // Usually "C:\Documents and Settings\\ - // Start Menu\Programs" - DIR_APP_DATA, // Application Data directory under the user profile. - DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory under - // the user profile. - DIR_COMMON_APP_DATA, // W2K, XP, W2K3: "C:\Documents and Settings\ - // All Users\Application Data". - // Vista, W2K8 and above: "C:\ProgramData". - DIR_APP_SHORTCUTS, // Where tiles on the start screen are stored, only - // for Windows 8. Maps to "Local\AppData\Microsoft\ - // Windows\Application Shortcuts\". - DIR_COMMON_DESKTOP, // Directory for the common desktop (visible - // on all user's Desktop). - DIR_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts. - DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar - // (Win7-8) via base::win::PinShortcutToTaskbar(). - DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts. + DIR_IE_INTERNET_CACHE, // Temporary Internet Files directory. + DIR_COMMON_START_MENU, // Usually "C:\ProgramData\Microsoft\Windows\ + // Start Menu\Programs" + DIR_START_MENU, // Usually "C:\Users\\AppData\Roaming\ + // Microsoft\Windows\Start Menu\Programs" + DIR_APP_DATA, // Application Data directory under the user + // profile. + DIR_LOCAL_APP_DATA, // "Local Settings\Application Data" directory + // under the user profile. + DIR_COMMON_APP_DATA, // Usually "C:\ProgramData". + DIR_APP_SHORTCUTS, // Where tiles on the start screen are stored, + // only for Windows 8. Maps to "Local\AppData\ + // Microsoft\Windows\Application Shortcuts\". + DIR_COMMON_DESKTOP, // Directory for the common desktop (visible + // on all user's Desktop). + DIR_USER_QUICK_LAUNCH, // Directory for the quick launch shortcuts. + DIR_TASKBAR_PINS, // Directory for the shortcuts pinned to taskbar. + DIR_IMPLICIT_APP_SHORTCUTS, // The implicit user pinned shortcut directory. + DIR_WINDOWS_FONTS, // Usually C:\Windows\Fonts. PATH_WIN_END }; diff --git a/security/sandbox/chromium/base/base_switches.cc b/security/sandbox/chromium/base/base_switches.cc index 02b22298850a..f5c6eb3f59bb 100644 --- a/security/sandbox/chromium/base/base_switches.cc +++ b/security/sandbox/chromium/base/base_switches.cc @@ -20,6 +20,10 @@ const char kEnableCrashReporter[] = "enable-crash-reporter"; // the memory-infra category is enabled. const char kEnableHeapProfiling[] = "enable-heap-profiling"; +// Report native (walk the stack) allocation traces. By default pseudo stacks +// derived from trace events are reported. +const char kEnableHeapProfilingModeNative[] = "native"; + // Generates full memory crash dump. const char kFullMemoryCrashReport[] = "full-memory-crash-report"; @@ -46,6 +50,11 @@ const char kNoErrorDialogs[] = "noerrdialogs"; // to the test framework that the current process is a child process. const char kTestChildProcess[] = "test-child-process"; +// When running certain tests that spawn child processes, this switch indicates +// to the test framework that the current process should not initialize ICU to +// avoid creating any scoped handles too early in startup. +const char kTestDoNotInitializeIcu[] = "test-do-not-initialize-icu"; + // Gives the default maximal active V-logging level; 0 is the default. // Normally positive values are used for V-logging levels. const char kV[] = "v"; @@ -80,6 +89,16 @@ const char kProfilerTiming[] = "profiler-timing"; // chrome://profiler. const char kProfilerTimingDisabledValue[] = "0"; +// Specifies a location for profiling output. This will only work if chrome has +// been built with the gyp variable profiling=1 or gn arg enable_profiling=true. +// +// {pid} if present will be replaced by the pid of the process. +// {count} if present will be incremented each time a profile is generated +// for this process. +// The default is chrome-profile-{pid} for the browser and test-profile-{pid} +// for tests. +const char kProfilingFile[] = "profiling-file"; + #if defined(OS_WIN) // Disables the USB keyboard detection for blocking the OSK on Win8+. const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect"; diff --git a/security/sandbox/chromium/base/base_switches.h b/security/sandbox/chromium/base/base_switches.h index c97a629d9fb2..0585186038f6 100644 --- a/security/sandbox/chromium/base/base_switches.h +++ b/security/sandbox/chromium/base/base_switches.h @@ -15,13 +15,16 @@ extern const char kDisableBreakpad[]; extern const char kDisableLowEndDeviceMode[]; extern const char kEnableCrashReporter[]; extern const char kEnableHeapProfiling[]; +extern const char kEnableHeapProfilingModeNative[]; extern const char kEnableLowEndDeviceMode[]; extern const char kForceFieldTrials[]; extern const char kFullMemoryCrashReport[]; extern const char kNoErrorDialogs[]; extern const char kProfilerTiming[]; extern const char kProfilerTimingDisabledValue[]; +extern const char kProfilingFile[]; extern const char kTestChildProcess[]; +extern const char kTestDoNotInitializeIcu[]; extern const char kTraceToFile[]; extern const char kTraceToFileName[]; extern const char kV[]; diff --git a/security/sandbox/chromium/base/bind.h b/security/sandbox/chromium/base/bind.h index 770e45706b02..ce717972e26c 100644 --- a/security/sandbox/chromium/base/bind.h +++ b/security/sandbox/chromium/base/bind.h @@ -6,13 +6,12 @@ #define BASE_BIND_H_ #include "base/bind_internal.h" -#include "base/callback_internal.h" // ----------------------------------------------------------------------------- // Usage documentation // ----------------------------------------------------------------------------- // -// See base/callback.h for documentation. +// See //docs/callback.md for documentation. // // // ----------------------------------------------------------------------------- @@ -22,78 +21,61 @@ // If you're reading the implementation, before proceeding further, you should // read the top comment of base/bind_internal.h for a definition of common // terms and concepts. -// -// RETURN TYPES -// -// Though Bind()'s result is meant to be stored in a Callback<> type, it -// cannot actually return the exact type without requiring a large amount -// of extra template specializations. The problem is that in order to -// discern the correct specialization of Callback<>, Bind would need to -// unwrap the function signature to determine the signature's arity, and -// whether or not it is a method. -// -// Each unique combination of (arity, function_type, num_prebound) where -// function_type is one of {function, method, const_method} would require -// one specialization. We eventually have to do a similar number of -// specializations anyways in the implementation (see the Invoker<>, -// classes). However, it is avoidable in Bind if we return the result -// via an indirection like we do below. -// -// TODO(ajwong): We might be able to avoid this now, but need to test. -// -// It is possible to move most of the static_assert into BindState<>, but it -// feels a little nicer to have the asserts here so people do not need to crack -// open bind_internal.h. On the other hand, it makes Bind() harder to read. namespace base { +// Bind as OnceCallback. template -base::Callback< - typename internal::BindState< - typename internal::FunctorTraits::RunnableType, - typename internal::FunctorTraits::RunType, - typename internal::CallbackParamTraits::StorageType...> - ::UnboundRunType> -Bind(Functor functor, const Args&... args) { - // Type aliases for how to store and run the functor. - using RunnableType = typename internal::FunctorTraits::RunnableType; - using RunType = typename internal::FunctorTraits::RunType; +inline OnceCallback> +BindOnce(Functor&& functor, Args&&... args) { + using BindState = internal::MakeBindStateType; + using UnboundRunType = MakeUnboundRunType; + using Invoker = internal::Invoker; + using CallbackType = OnceCallback; - // Use RunnableType::RunType instead of RunType above because our - // checks below for bound references need to know what the actual - // functor is going to interpret the argument as. - using BoundRunType = typename RunnableType::RunType; + // Store the invoke func into PolymorphicInvoke before casting it to + // InvokeFuncStorage, so that we can ensure its type matches to + // PolymorphicInvoke, to which CallbackType will cast back. + using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke; + PolymorphicInvoke invoke_func = &Invoker::RunOnce; - using BoundArgs = - internal::TakeTypeListItem>; + using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage; + return CallbackType(new BindState( + reinterpret_cast(invoke_func), + std::forward(functor), + std::forward(args)...)); +} - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - static_assert(!internal::HasNonConstReferenceItem::value, - "do not bind functions with nonconst ref"); +// Bind as RepeatingCallback. +template +inline RepeatingCallback> +BindRepeating(Functor&& functor, Args&&... args) { + using BindState = internal::MakeBindStateType; + using UnboundRunType = MakeUnboundRunType; + using Invoker = internal::Invoker; + using CallbackType = RepeatingCallback; - const bool is_method = internal::HasIsMethodTag::value; + // Store the invoke func into PolymorphicInvoke before casting it to + // InvokeFuncStorage, so that we can ensure its type matches to + // PolymorphicInvoke, to which CallbackType will cast back. + using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke; + PolymorphicInvoke invoke_func = &Invoker::Run; - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - static_assert(!internal::BindsArrayToFirstArg::value, - "first bound argument to method cannot be array"); - static_assert( - !internal::HasRefCountedParamAsRawPtr::value, - "a parameter is a refcounted type and needs scoped_refptr"); + using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage; + return CallbackType(new BindState( + reinterpret_cast(invoke_func), + std::forward(functor), + std::forward(args)...)); +} - using BindState = internal::BindState< - RunnableType, RunType, - typename internal::CallbackParamTraits::StorageType...>; - - return Callback( - new BindState(internal::MakeRunnable(functor), args...)); +// Unannotated Bind. +// TODO(tzik): Deprecate this and migrate to OnceCallback and +// RepeatingCallback, once they get ready. +template +inline Callback> +Bind(Functor&& functor, Args&&... args) { + return BindRepeating(std::forward(functor), + std::forward(args)...); } } // namespace base diff --git a/security/sandbox/chromium/base/bind_helpers.h b/security/sandbox/chromium/base/bind_helpers.h index 2add755b4260..c7c7be8ee840 100644 --- a/security/sandbox/chromium/base/bind_helpers.h +++ b/security/sandbox/chromium/base/bind_helpers.h @@ -28,6 +28,9 @@ // argument will CHECK() because the first invocation would have already // transferred ownership to the target function. // +// RetainedRef() accepts a ref counted object and retains a reference to it. +// When the callback is called, the object is passed as a raw pointer. +// // ConstRef() allows binding a constant reference to an argument rather // than a copy. // @@ -71,6 +74,19 @@ // Without Owned(), someone would have to know to delete |pn| when the last // reference to the Callback is deleted. // +// EXAMPLE OF RetainedRef(): +// +// void foo(RefCountedBytes* bytes) {} +// +// scoped_refptr bytes = ...; +// Closure callback = Bind(&foo, base::RetainedRef(bytes)); +// callback.Run(); +// +// Without RetainedRef, the scoped_refptr would try to implicitly convert to +// a raw pointer and fail compilation: +// +// Closure callback = Bind(&foo, bytes); // ERROR! +// // // EXAMPLE OF ConstRef(): // @@ -105,10 +121,11 @@ // // EXAMPLE OF Passed(): // -// void TakesOwnership(scoped_ptr arg) { } -// scoped_ptr CreateFoo() { return scoped_ptr(new Foo()); } +// void TakesOwnership(std::unique_ptr arg) { } +// std::unique_ptr CreateFoo() { return std::unique_ptr(new Foo()); +// } // -// scoped_ptr f(new Foo()); +// std::unique_ptr f(new Foo()); // // // |cb| is given ownership of Foo(). |f| is now NULL. // // You can use std::move(f) in place of &f, but it's more verbose. @@ -150,150 +167,18 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" -#include "base/template_util.h" #include "build/build_config.h" namespace base { + +template +struct IsWeakReceiver; + +template +struct BindUnwrapTraits; + namespace internal { -// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T -// for the existence of AddRef() and Release() functions of the correct -// signature. -// -// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error -// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence -// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison -// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions -// -// The last link in particular show the method used below. -// -// For SFINAE to work with inherited methods, we need to pull some extra tricks -// with multiple inheritance. In the more standard formulation, the overloads -// of Check would be: -// -// template -// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); -// -// template -// No NotTheCheckWeWant(...); -// -// static const bool value = sizeof(NotTheCheckWeWant(0)) == sizeof(Yes); -// -// The problem here is that template resolution will not match -// C::TargetFunc if TargetFunc does not exist directly in C. That is, if -// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, -// |value| will be false. This formulation only checks for whether or -// not TargetFunc exist directly in the class being introspected. -// -// To get around this, we play a dirty trick with multiple inheritance. -// First, We create a class BaseMixin that declares each function that we -// want to probe for. Then we create a class Base that inherits from both T -// (the class we wish to probe) and BaseMixin. Note that the function -// signature in BaseMixin does not need to match the signature of the function -// we are probing for; thus it's easiest to just use void(). -// -// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an -// ambiguous resolution between BaseMixin and T. This lets us write the -// following: -// -// template -// No GoodCheck(Helper<&C::TargetFunc>*); -// -// template -// Yes GoodCheck(...); -// -// static const bool value = sizeof(GoodCheck(0)) == sizeof(Yes); -// -// Notice here that the variadic version of GoodCheck() returns Yes here -// instead of No like the previous one. Also notice that we calculate |value| -// by specializing GoodCheck() on Base instead of T. -// -// We've reversed the roles of the variadic, and Helper overloads. -// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid -// substitution if T::TargetFunc exists. Thus GoodCheck(0) will resolve -// to the variadic version if T has TargetFunc. If T::TargetFunc does not -// exist, then &C::TargetFunc is not ambiguous, and the overload resolution -// will prefer GoodCheck(Helper<&C::TargetFunc>*). -// -// This method of SFINAE will correctly probe for inherited names, but it cannot -// typecheck those names. It's still a good enough sanity check though. -// -// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. -// -// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted -// this works well. -// -// TODO(ajwong): Make this check for Release() as well. -// See http://crbug.com/82038. -template -class SupportsAddRefAndRelease { - using Yes = char[1]; - using No = char[2]; - - struct BaseMixin { - void AddRef(); - }; - -// MSVC warns when you try to use Base if T has a private destructor, the -// common pattern for refcounted types. It does this even though no attempt to -// instantiate Base is made. We disable the warning for this definition. -#if defined(OS_WIN) -#pragma warning(push) -#pragma warning(disable:4624) -#endif - struct Base : public T, public BaseMixin { - }; -#if defined(OS_WIN) -#pragma warning(pop) -#endif - - template struct Helper {}; - - template - static No& Check(Helper<&C::AddRef>*); - - template - static Yes& Check(...); - - public: - enum { value = sizeof(Check(0)) == sizeof(Yes) }; -}; - -// Helpers to assert that arguments of a recounted type are bound with a -// scoped_refptr. -template -struct UnsafeBindtoRefCountedArgHelper : false_type { -}; - -template -struct UnsafeBindtoRefCountedArgHelper - : integral_constant::value> { -}; - -template -struct UnsafeBindtoRefCountedArg : false_type { -}; - -template -struct UnsafeBindtoRefCountedArg - : UnsafeBindtoRefCountedArgHelper::value, T> { -}; - -template -class HasIsMethodTag { - using Yes = char[1]; - using No = char[2]; - - template - static Yes& Check(typename U::IsMethod*); - - template - static No& Check(...); - - public: - enum { value = sizeof(Check(0)) == sizeof(Yes) }; -}; - template class UnretainedWrapper { public: @@ -312,23 +197,27 @@ class ConstRefWrapper { const T* ptr_; }; +template +class RetainedRefWrapper { + public: + explicit RetainedRefWrapper(T* o) : ptr_(o) {} + explicit RetainedRefWrapper(scoped_refptr o) : ptr_(std::move(o)) {} + T* get() const { return ptr_.get(); } + private: + scoped_refptr ptr_; +}; + template struct IgnoreResultHelper { - explicit IgnoreResultHelper(T functor) : functor_(functor) {} + explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {} + explicit operator bool() const { return !!functor_; } T functor_; }; -template -struct IgnoreResultHelper > { - explicit IgnoreResultHelper(const Callback& functor) : functor_(functor) {} - - const Callback& functor_; -}; - // An alternate implementation is to avoid the destructive copy, and instead // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to -// a class that is essentially a scoped_ptr<>. +// a class that is essentially a std::unique_ptr<>. // // The current implementation has the benefit though of leaving ParamTraits<> // fully in callback_internal.h as well as avoiding type conversions during @@ -339,7 +228,7 @@ class OwnedWrapper { explicit OwnedWrapper(T* o) : ptr_(o) {} ~OwnedWrapper() { delete ptr_; } T* get() const { return ptr_; } - OwnedWrapper(const OwnedWrapper& other) { + OwnedWrapper(OwnedWrapper&& other) { ptr_ = other.ptr_; other.ptr_ = NULL; } @@ -376,9 +265,9 @@ class PassedWrapper { public: explicit PassedWrapper(T&& scoper) : is_valid_(true), scoper_(std::move(scoper)) {} - PassedWrapper(const PassedWrapper& other) + PassedWrapper(PassedWrapper&& other) : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} - T Pass() const { + T Take() const { CHECK(is_valid_); is_valid_ = false; return std::move(scoper_); @@ -389,100 +278,13 @@ class PassedWrapper { mutable T scoper_; }; -// Unwrap the stored parameters for the wrappers above. template -struct UnwrapTraits { - using ForwardType = const T&; - static ForwardType Unwrap(const T& o) { return o; } -}; +using Unwrapper = BindUnwrapTraits::type>; template -struct UnwrapTraits > { - using ForwardType = T*; - static ForwardType Unwrap(UnretainedWrapper unretained) { - return unretained.get(); - } -}; - -template -struct UnwrapTraits > { - using ForwardType = const T&; - static ForwardType Unwrap(ConstRefWrapper const_ref) { - return const_ref.get(); - } -}; - -template -struct UnwrapTraits > { - using ForwardType = T*; - static ForwardType Unwrap(const scoped_refptr& o) { return o.get(); } -}; - -template -struct UnwrapTraits > { - using ForwardType = const WeakPtr&; - static ForwardType Unwrap(const WeakPtr& o) { return o; } -}; - -template -struct UnwrapTraits > { - using ForwardType = T*; - static ForwardType Unwrap(const OwnedWrapper& o) { - return o.get(); - } -}; - -template -struct UnwrapTraits > { - using ForwardType = T; - static T Unwrap(PassedWrapper& o) { - return o.Pass(); - } -}; - -// Utility for handling different refcounting semantics in the Bind() -// function. -template -struct MaybeScopedRefPtr; - -template -struct MaybeScopedRefPtr { - MaybeScopedRefPtr() {} -}; - -template -struct MaybeScopedRefPtr { - MaybeScopedRefPtr(const T&, const Rest&...) {} -}; - -template -struct MaybeScopedRefPtr { - MaybeScopedRefPtr(const T*, const Rest&...) {} -}; - -template -struct MaybeScopedRefPtr { - MaybeScopedRefPtr(const T& o, const Rest&...) {} -}; - -template -struct MaybeScopedRefPtr { - MaybeScopedRefPtr(T* o, const Rest&...) : ref_(o) {} - scoped_refptr ref_; -}; - -// No need to additionally AddRef() and Release() since we are storing a -// scoped_refptr<> inside the storage object already. -template -struct MaybeScopedRefPtr, Rest...> { - MaybeScopedRefPtr(const scoped_refptr&, const Rest&...) {} -}; - -template -struct MaybeScopedRefPtr { - MaybeScopedRefPtr(const T* o, const Rest&...) : ref_(o) {} - scoped_refptr ref_; -}; +auto Unwrap(T&& o) -> decltype(Unwrapper::Unwrap(std::forward(o))) { + return Unwrapper::Unwrap(std::forward(o)); +} // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a // method. It is used internally by Bind() to select the correct @@ -491,16 +293,11 @@ struct MaybeScopedRefPtr { // // The first argument should be the type of the object that will be received by // the method. -template -struct IsWeakMethod : public false_type {}; +template +struct IsWeakMethod : std::false_type {}; template -struct IsWeakMethod, Args...> : public true_type {}; - -template -struct IsWeakMethod>, Args...> - : public true_type {}; - +struct IsWeakMethod : IsWeakReceiver {}; // Packs a list of types to hold them in a single type. template @@ -583,19 +380,25 @@ struct MakeFunctionTypeImpl> { template using MakeFunctionType = typename MakeFunctionTypeImpl::Type; -// Used for ExtractArgs. +// Used for ExtractArgs and ExtractReturnType. template struct ExtractArgsImpl; template struct ExtractArgsImpl { - using Type = TypeList; + using ReturnType = R; + using ArgsList = TypeList; }; // A type-level function that extracts function arguments into a TypeList. // E.g. ExtractArgs is evaluated to TypeList. template -using ExtractArgs = typename ExtractArgsImpl::Type; +using ExtractArgs = typename ExtractArgsImpl::ArgsList; + +// A type-level function that extracts the return type of a function. +// E.g. ExtractReturnType is evaluated to R. +template +using ExtractReturnType = typename ExtractArgsImpl::ReturnType; } // namespace internal @@ -604,6 +407,16 @@ static inline internal::UnretainedWrapper Unretained(T* o) { return internal::UnretainedWrapper(o); } +template +static inline internal::RetainedRefWrapper RetainedRef(T* o) { + return internal::RetainedRefWrapper(o); +} + +template +static inline internal::RetainedRefWrapper RetainedRef(scoped_refptr o) { + return internal::RetainedRefWrapper(std::move(o)); +} + template static inline internal::ConstRefWrapper ConstRef(const T& o) { return internal::ConstRefWrapper(o); @@ -622,28 +435,19 @@ static inline internal::OwnedWrapper Owned(T* o) { // Both versions of Passed() prevent T from being an lvalue reference. The first // via use of enable_if, and the second takes a T* which will not bind to T&. template ::value && - !std::is_lvalue_reference::value>::type* = + typename std::enable_if::value>::type* = nullptr> static inline internal::PassedWrapper Passed(T&& scoper) { return internal::PassedWrapper(std::move(scoper)); } -template ::value>::type* = - nullptr> +template static inline internal::PassedWrapper Passed(T* scoper) { return internal::PassedWrapper(std::move(*scoper)); } template static inline internal::IgnoreResultHelper IgnoreResult(T data) { - return internal::IgnoreResultHelper(data); -} - -template -static inline internal::IgnoreResultHelper > -IgnoreResult(const Callback& data) { - return internal::IgnoreResultHelper >(data); + return internal::IgnoreResultHelper(std::move(data)); } BASE_EXPORT void DoNothing(); @@ -653,6 +457,70 @@ void DeletePointer(T* obj) { delete obj; } +// An injection point to control |this| pointer behavior on a method invocation. +// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a +// method, base::Bind cancels the method invocation if the receiver is tested as +// false. +// E.g. Foo::bar() is not called: +// struct Foo : base::SupportsWeakPtr { +// void bar() {} +// }; +// +// WeakPtr oo = nullptr; +// base::Bind(&Foo::bar, oo).Run(); +template +struct IsWeakReceiver : std::false_type {}; + +template +struct IsWeakReceiver> : IsWeakReceiver {}; + +template +struct IsWeakReceiver> : std::true_type {}; + +// An injection point to control how bound objects passed to the target +// function. BindUnwrapTraits<>::Unwrap() is called for each bound objects right +// before the target function is invoked. +template +struct BindUnwrapTraits { + template + static T&& Unwrap(T&& o) { return std::forward(o); } +}; + +template +struct BindUnwrapTraits> { + static T* Unwrap(const internal::UnretainedWrapper& o) { + return o.get(); + } +}; + +template +struct BindUnwrapTraits> { + static const T& Unwrap(const internal::ConstRefWrapper& o) { + return o.get(); + } +}; + +template +struct BindUnwrapTraits> { + static T* Unwrap(const internal::RetainedRefWrapper& o) { + return o.get(); + } +}; + +template +struct BindUnwrapTraits> { + static T* Unwrap(const internal::OwnedWrapper& o) { + return o.get(); + } +}; + +template +struct BindUnwrapTraits> { + static T Unwrap(const internal::PassedWrapper& o) { + return o.Take(); + } +}; + } // namespace base #endif // BASE_BIND_HELPERS_H_ diff --git a/security/sandbox/chromium/base/bind_internal.h b/security/sandbox/chromium/base/bind_internal.h index ac7cd0098787..88e764547f81 100644 --- a/security/sandbox/chromium/base/bind_internal.h +++ b/security/sandbox/chromium/base/bind_internal.h @@ -7,6 +7,7 @@ #include +#include #include #include "base/bind_helpers.h" @@ -17,10 +18,6 @@ #include "base/tuple.h" #include "build/build_config.h" -#if defined(OS_WIN) -#include "base/bind_internal_win.h" -#endif - namespace base { namespace internal { @@ -28,63 +25,87 @@ namespace internal { // // // CONCEPTS: -// Runnable -- A type (really a type class) that has a single Run() method -// and a RunType typedef that corresponds to the type of Run(). -// A Runnable can declare that it should treated like a method -// call by including a typedef named IsMethod. The value of -// this typedef is NOT inspected, only the existence. When a -// Runnable declares itself a method, Bind() will enforce special -// refcounting + WeakPtr handling semantics for the first -// parameter which is expected to be an object. -// Functor -- A copyable type representing something that should be called. -// All function pointers, Callback<>, and Runnables are functors -// even if the invocation syntax differs. +// Functor -- A movable type representing something that should be called. +// All function pointers and Callback<> are functors even if the +// invocation syntax differs. // RunType -- A function type (as opposed to function _pointer_ type) for -// a Run() function. Usually just a convenience typedef. +// a Callback<>::Run(). Usually just a convenience typedef. // (Bound)Args -- A set of types that stores the arguments. // // Types: -// RunnableAdapter<> -- Wraps the various "function" pointer types into an -// object that adheres to the Runnable interface. // ForceVoidReturn<> -- Helper class for translating function signatures to // equivalent forms with a "void" return type. -// FunctorTraits<> -- Type traits used determine the correct RunType and -// RunnableType for a Functor. This is where function +// FunctorTraits<> -- Type traits used to determine the correct RunType and +// invocation manner for a Functor. This is where function // signature adapters are applied. -// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable -// type class that represents the underlying Functor. -// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. +// InvokeHelper<> -- Take a Functor + arguments and actully invokes it. // Handle the differing syntaxes needed for WeakPtr<> -// support, and for ignoring return values. This is separate -// from Invoker to avoid creating multiple version of -// Invoker<>. -// Invoker<> -- Unwraps the curried parameters and executes the Runnable. +// support. This is separate from Invoker to avoid creating +// multiple version of Invoker<>. +// Invoker<> -- Unwraps the curried parameters and executes the Functor. // BindState<> -- Stores the curried parameters, and is the main entry point -// into the Bind() system, doing most of the type resolution. -// There are ARITY BindState types. +// into the Bind() system. -// HasNonConstReferenceParam selects true_type when any of the parameters in -// |Sig| is a non-const reference. -// Implementation note: This non-specialized case handles zero-arity case only. -// Non-zero-arity cases should be handled by the specialization below. -template -struct HasNonConstReferenceItem : false_type {}; +template +struct make_void { + using type = void; +}; -// Implementation note: Select true_type if the first parameter is a non-const -// reference. Otherwise, skip the first parameter and check rest of parameters -// recursively. -template -struct HasNonConstReferenceItem> - : std::conditional::value, - true_type, - HasNonConstReferenceItem>>::type {}; +// A clone of C++17 std::void_t. +// Unlike the original version, we need |make_void| as a helper struct to avoid +// a C++14 defect. +// ref: http://en.cppreference.com/w/cpp/types/void_t +// ref: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558 +template +using void_t = typename make_void::type; + +template +struct ExtractCallableRunTypeImpl; + +template +struct ExtractCallableRunTypeImpl { + using Type = R(Args...); +}; + +// Evaluated to RunType of the given callable type. +// Example: +// auto f = [](int, char*) { return 0.1; }; +// ExtractCallableRunType +// is evaluated to +// double(int, char*); +template +using ExtractCallableRunType = + typename ExtractCallableRunTypeImpl::Type; + +// IsConvertibleToRunType is std::true_type if |Functor| has operator() +// and convertible to the corresponding function pointer. Otherwise, it's +// std::false_type. +// Example: +// IsConvertibleToRunType::value is false. +// +// struct Foo {}; +// IsConvertibleToRunType::value is false. +// +// auto f = []() {}; +// IsConvertibleToRunType::value is true. +// +// int i = 0; +// auto g = [i]() {}; +// IsConvertibleToRunType::value is false. +template +struct IsConvertibleToRunType : std::false_type {}; + +template +struct IsConvertibleToRunType> + : std::is_convertible*> {}; // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw // pointer to a RefCounted type. // Implementation note: This non-specialized case handles zero-arity case only. // Non-zero-arity cases should be handled by the specialization below. template -struct HasRefCountedTypeAsRawPtr : false_type {}; +struct HasRefCountedTypeAsRawPtr : std::false_type {}; // Implementation note: Select true_type if the first parameter is a raw pointer // to a RefCounted type. Otherwise, skip the first parameter and check rest of @@ -92,117 +113,9 @@ struct HasRefCountedTypeAsRawPtr : false_type {}; template struct HasRefCountedTypeAsRawPtr : std::conditional::value, - true_type, + std::true_type, HasRefCountedTypeAsRawPtr>::type {}; -// BindsArrayToFirstArg selects true_type when |is_method| is true and the first -// item of |Args| is an array type. -// Implementation note: This non-specialized case handles !is_method case and -// zero-arity case only. Other cases should be handled by the specialization -// below. -template -struct BindsArrayToFirstArg : false_type {}; - -template -struct BindsArrayToFirstArg : is_array {}; - -// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except -// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument. -// Implementation note: This non-specialized case handles !is_method case and -// zero-arity case only. Other cases should be handled by the specialization -// below. -template -struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr {}; - -template -struct HasRefCountedParamAsRawPtr - : HasRefCountedTypeAsRawPtr {}; - -// RunnableAdapter<> -// -// The RunnableAdapter<> templates provide a uniform interface for invoking -// a function pointer, method pointer, or const method pointer. The adapter -// exposes a Run() method with an appropriate signature. Using this wrapper -// allows for writing code that supports all three pointer types without -// undue repetition. Without it, a lot of code would need to be repeated 3 -// times. -// -// For method pointers and const method pointers the first argument to Run() -// is considered to be the received of the method. This is similar to STL's -// mem_fun(). -// -// This class also exposes a RunType typedef that is the function type of the -// Run() function. -// -// If and only if the wrapper contains a method or const method pointer, an -// IsMethod typedef is exposed. The existence of this typedef (NOT the value) -// marks that the wrapper should be considered a method wrapper. - -template -class RunnableAdapter; - -// Function. -template -class RunnableAdapter { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - explicit RunnableAdapter(R(*function)(Args...)) - : function_(function) { - } - - R Run(typename CallbackParamTraits::ForwardType... args) { - return function_(CallbackForward(args)...); - } - - private: - R (*function_)(Args...); -}; - -// Method. -template -class RunnableAdapter { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(T*, Args...); - using IsMethod = true_type; - - explicit RunnableAdapter(R(T::*method)(Args...)) - : method_(method) { - } - - R Run(T* object, typename CallbackParamTraits::ForwardType... args) { - return (object->*method_)(CallbackForward(args)...); - } - - private: - R (T::*method_)(Args...); -}; - -// Const Method. -template -class RunnableAdapter { - public: - using RunType = R(const T*, Args...); - using IsMethod = true_type; - - explicit RunnableAdapter(R(T::*method)(Args...) const) - : method_(method) { - } - - R Run(const T* object, - typename CallbackParamTraits::ForwardType... args) { - return (object->*method_)(CallbackForward(args)...); - } - - private: - R (T::*method_)(Args...) const; -}; - - // ForceVoidReturn<> // // Set of templates that support forcing the function return type to void. @@ -211,215 +124,435 @@ struct ForceVoidReturn; template struct ForceVoidReturn { - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef void RunType(Args...); + using RunType = void(Args...); }; - // FunctorTraits<> // // See description at top of file. -template -struct FunctorTraits { - using RunnableType = RunnableAdapter; - using RunType = typename RunnableType::RunType; +template +struct FunctorTraits; + +// For a callable type that is convertible to the corresponding function type. +// This specialization is intended to allow binding captureless lambdas by +// base::Bind(), based on the fact that captureless lambdas can be convertible +// to the function type while capturing lambdas can't. +template +struct FunctorTraits< + Functor, + typename std::enable_if::value>::type> { + using RunType = ExtractCallableRunType; + static constexpr bool is_method = false; + static constexpr bool is_nullable = false; + + template + static ExtractReturnType + Invoke(const Functor& functor, RunArgs&&... args) { + return functor(std::forward(args)...); + } }; +// For functions. +template +struct FunctorTraits { + using RunType = R(Args...); + static constexpr bool is_method = false; + static constexpr bool is_nullable = true; + + template + static R Invoke(R (*function)(Args...), RunArgs&&... args) { + return function(std::forward(args)...); + } +}; + +#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64) + +// For functions. +template +struct FunctorTraits { + using RunType = R(Args...); + static constexpr bool is_method = false; + static constexpr bool is_nullable = true; + + template + static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) { + return function(std::forward(args)...); + } +}; + +// For functions. +template +struct FunctorTraits { + using RunType = R(Args...); + static constexpr bool is_method = false; + static constexpr bool is_nullable = true; + + template + static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) { + return function(std::forward(args)...); + } +}; + +#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64) + +// For methods. +template +struct FunctorTraits { + using RunType = R(Receiver*, Args...); + static constexpr bool is_method = true; + static constexpr bool is_nullable = true; + + template + static R Invoke(R (Receiver::*method)(Args...), + ReceiverPtr&& receiver_ptr, + RunArgs&&... args) { + // Clang skips CV qualifier check on a method pointer invocation when the + // receiver is a subclass. Store the receiver into a const reference to + // T to ensure the CV check works. + // https://llvm.org/bugs/show_bug.cgi?id=27037 + Receiver& receiver = *receiver_ptr; + return (receiver.*method)(std::forward(args)...); + } +}; + +// For const methods. +template +struct FunctorTraits { + using RunType = R(const Receiver*, Args...); + static constexpr bool is_method = true; + static constexpr bool is_nullable = true; + + template + static R Invoke(R (Receiver::*method)(Args...) const, + ReceiverPtr&& receiver_ptr, + RunArgs&&... args) { + // Clang skips CV qualifier check on a method pointer invocation when the + // receiver is a subclass. Store the receiver into a const reference to + // T to ensure the CV check works. + // https://llvm.org/bugs/show_bug.cgi?id=27037 + const Receiver& receiver = *receiver_ptr; + return (receiver.*method)(std::forward(args)...); + } +}; + +// For IgnoreResults. template -struct FunctorTraits> { - using RunnableType = typename FunctorTraits::RunnableType; +struct FunctorTraits> : FunctorTraits { using RunType = - typename ForceVoidReturn::RunType; + typename ForceVoidReturn::RunType>::RunType; + + template + static void Invoke(IgnoreResultType&& ignore_result_helper, + RunArgs&&... args) { + FunctorTraits::Invoke( + std::forward(ignore_result_helper).functor_, + std::forward(args)...); + } }; -template -struct FunctorTraits> { - using RunnableType = Callback ; - using RunType = typename Callback::RunType; +// For Callbacks. +template +struct FunctorTraits> { + using RunType = R(Args...); + static constexpr bool is_method = false; + static constexpr bool is_nullable = true; + + template + static R Invoke(CallbackType&& callback, RunArgs&&... args) { + DCHECK(!callback.is_null()); + return std::forward(callback).Run( + std::forward(args)...); + } }; - -// MakeRunnable<> -// -// Converts a passed in functor to a RunnableType using type inference. - -template -typename FunctorTraits::RunnableType MakeRunnable(const T& t) { - return RunnableAdapter(t); -} - -template -typename FunctorTraits::RunnableType -MakeRunnable(const IgnoreResultHelper& t) { - return MakeRunnable(t.functor_); -} - -template -const typename FunctorTraits>::RunnableType& -MakeRunnable(const Callback& t) { - DCHECK(!t.is_null()); - return t; -} - - // InvokeHelper<> // -// There are 3 logical InvokeHelper<> specializations: normal, void-return, -// WeakCalls. +// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls. // // The normal type just calls the underlying runnable. // -// We need a InvokeHelper to handle void return types in order to support -// IgnoreResult(). Normally, if the Runnable's RunType had a void return, -// the template system would just accept "return functor.Run()" ignoring -// the fact that a void function is being used with return. This piece of -// sugar breaks though when the Runnable's RunType is not void. Thus, we -// need a partial specialization to change the syntax to drop the "return" -// from the invocation call. -// -// WeakCalls similarly need special syntax that is applied to the first -// argument to check if they should no-op themselves. -template +// WeakCalls need special syntax that is applied to the first argument to check +// if they should no-op themselves. +template struct InvokeHelper; -template -struct InvokeHelper> { - static ReturnType MakeItSo(Runnable runnable, Args... args) { - return runnable.Run(CallbackForward(args)...); +template +struct InvokeHelper { + template + static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) { + using Traits = FunctorTraits::type>; + return Traits::Invoke(std::forward(functor), + std::forward(args)...); } }; -template -struct InvokeHelper> { - static void MakeItSo(Runnable runnable, Args... args) { - runnable.Run(CallbackForward(args)...); - } -}; - -template -struct InvokeHelper> { - static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) { - if (!weak_ptr.get()) { - return; - } - runnable.Run(weak_ptr.get(), CallbackForward(args)...); - } -}; - -#if !defined(_MSC_VER) - -template -struct InvokeHelper { +template +struct InvokeHelper { // WeakCalls are only supported for functions with a void return type. // Otherwise, the function result would be undefined if the the WeakPtr<> // is invalidated. - static_assert(is_void::value, + static_assert(std::is_void::value, "weak_ptrs can only bind to methods without return values"); -}; -#endif + template + static inline void MakeItSo(Functor&& functor, + BoundWeakPtr&& weak_ptr, + RunArgs&&... args) { + if (!weak_ptr) + return; + using Traits = FunctorTraits::type>; + Traits::Invoke(std::forward(functor), + std::forward(weak_ptr), + std::forward(args)...); + } +}; // Invoker<> // // See description at the top of the file. -template +template struct Invoker; -template -struct Invoker, - StorageType, TypeList, - InvokeHelperType, R(UnboundForwardArgs...)> { - static R Run(BindStateBase* base, - UnboundForwardArgs... unbound_args) { - StorageType* storage = static_cast(base); +template +struct Invoker { + static R RunOnce(BindStateBase* base, UnboundArgs&&... unbound_args) { // Local references to make debugger stepping easier. If in a debugger, // you really want to warp ahead and step through the // InvokeHelper<>::MakeItSo() call below. - return InvokeHelperType::MakeItSo( - storage->runnable_, - Unwrappers::Unwrap(get(storage->bound_args_))..., - CallbackForward(unbound_args)...); + StorageType* storage = static_cast(base); + static constexpr size_t num_bound_args = + std::tuple_sizebound_args_)>::value; + return RunImpl(std::move(storage->functor_), + std::move(storage->bound_args_), + MakeIndexSequence(), + std::forward(unbound_args)...); + } + + static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) { + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + const StorageType* storage = static_cast(base); + static constexpr size_t num_bound_args = + std::tuple_sizebound_args_)>::value; + return RunImpl(storage->functor_, + storage->bound_args_, + MakeIndexSequence(), + std::forward(unbound_args)...); + } + + private: + template + static inline R RunImpl(Functor&& functor, + BoundArgsTuple&& bound, + IndexSequence, + UnboundArgs&&... unbound_args) { + static constexpr bool is_method = + FunctorTraits::type>::is_method; + + using DecayedArgsTuple = typename std::decay::type; + static constexpr bool is_weak_call = + IsWeakMethod::type...>::value; + + return InvokeHelper::MakeItSo( + std::forward(functor), + Unwrap(base::get(std::forward(bound)))..., + std::forward(unbound_args)...); } }; +// Used to implement MakeUnboundRunType. +template +struct MakeUnboundRunTypeImpl { + using RunType = + typename FunctorTraits::type>::RunType; + using ReturnType = ExtractReturnType; + using Args = ExtractArgs; + using UnboundArgs = DropTypeListItem; + using Type = MakeFunctionType; +}; +template +typename std::enable_if::is_nullable, bool>::type +IsNull(const Functor& functor) { + return !functor; +} + +template +typename std::enable_if::is_nullable, bool>::type +IsNull(const Functor&) { + return false; +} + +template +struct BindState; + +template +struct CancellationChecker { + static constexpr bool is_cancellable = false; + static bool Run(const BindStateBase*) { + return false; + } +}; + +template +struct CancellationChecker< + BindState, + typename std::enable_if::is_method, + BoundArgs...>::value>::type> { + static constexpr bool is_cancellable = true; + static bool Run(const BindStateBase* base) { + using BindStateType = BindState; + const BindStateType* bind_state = static_cast(base); + return !base::get<0>(bind_state->bound_args_); + } +}; + +template +struct CancellationChecker< + BindState, BoundArgs...>> { + static constexpr bool is_cancellable = true; + static bool Run(const BindStateBase* base) { + using Functor = Callback; + using BindStateType = BindState; + const BindStateType* bind_state = static_cast(base); + return bind_state->functor_.IsCancelled(); + } +}; + +// Template helpers to detect using Bind() on a base::Callback without any +// additional arguments. In that case, the original base::Callback object should +// just be directly used. +template +struct BindingCallbackWithNoArgs { + static constexpr bool value = false; +}; + +template +struct BindingCallbackWithNoArgs, + BoundArgs...> { + static constexpr bool value = sizeof...(BoundArgs) == 0; +}; // BindState<> // -// This stores all the state passed into Bind() and is also where most -// of the template resolution magic occurs. -// -// Runnable is the functor we are binding arguments to. -// RunType is type of the Run() function that the Invoker<> should use. -// Normally, this is the same as the RunType of the Runnable, but it can -// be different if an adapter like IgnoreResult() has been used. -// -// BoundArgs contains the storage type for all the bound arguments. -template -struct BindState; +// This stores all the state passed into Bind(). +template +struct BindState final : BindStateBase { + using IsCancellable = std::integral_constant< + bool, CancellationChecker::is_cancellable>; -template -struct BindState final - : public BindStateBase { - private: - using StorageType = BindState; - using RunnableType = Runnable; + template + explicit BindState(BindStateBase::InvokeFuncStorage invoke_func, + ForwardFunctor&& functor, + ForwardBoundArgs&&... bound_args) + // IsCancellable is std::false_type if the CancellationChecker<>::Run + // returns always false. Otherwise, it's std::true_type. + : BindState(IsCancellable{}, + invoke_func, + std::forward(functor), + std::forward(bound_args)...) { + static_assert(!BindingCallbackWithNoArgs::value, + "Attempting to bind a base::Callback with no additional " + "arguments: save a heap allocation and use the original " + "base::Callback object"); + } - // true_type if Runnable is a method invocation and the first bound argument - // is a WeakPtr. - using IsWeakCall = - IsWeakMethod::value, BoundArgs...>; - - using BoundIndices = MakeIndexSequence; - using Unwrappers = TypeList...>; - using UnboundForwardArgs = DropTypeListItem< - sizeof...(BoundArgs), - TypeList::ForwardType...>>; - using UnboundForwardRunType = MakeFunctionType; - - using InvokeHelperArgs = ConcatTypeLists< - TypeList::ForwardType...>, - UnboundForwardArgs>; - using InvokeHelperType = - InvokeHelper; - - using UnboundArgs = DropTypeListItem>; - - public: - using InvokerType = Invoker; - using UnboundRunType = MakeFunctionType; - - BindState(const Runnable& runnable, const BoundArgs&... bound_args) - : BindStateBase(&Destroy), - runnable_(runnable), - ref_(bound_args...), - bound_args_(bound_args...) {} - - RunnableType runnable_; - MaybeScopedRefPtr::value, BoundArgs...> ref_; - Tuple bound_args_; + Functor functor_; + std::tuple bound_args_; private: + template + explicit BindState(std::true_type, + BindStateBase::InvokeFuncStorage invoke_func, + ForwardFunctor&& functor, + ForwardBoundArgs&&... bound_args) + : BindStateBase(invoke_func, &Destroy, + &CancellationChecker::Run), + functor_(std::forward(functor)), + bound_args_(std::forward(bound_args)...) { + DCHECK(!IsNull(functor_)); + } + + template + explicit BindState(std::false_type, + BindStateBase::InvokeFuncStorage invoke_func, + ForwardFunctor&& functor, + ForwardBoundArgs&&... bound_args) + : BindStateBase(invoke_func, &Destroy), + functor_(std::forward(functor)), + bound_args_(std::forward(bound_args)...) { + DCHECK(!IsNull(functor_)); + } + ~BindState() {} - static void Destroy(BindStateBase* self) { - delete static_cast(self); + static void Destroy(const BindStateBase* self) { + delete static_cast(self); } }; +// Used to implement MakeBindStateType. +template +struct MakeBindStateTypeImpl; + +template +struct MakeBindStateTypeImpl { + static_assert(!HasRefCountedTypeAsRawPtr::value, + "A parameter is a refcounted type and needs scoped_refptr."); + using Type = BindState::type, + typename std::decay::type...>; +}; + +template +struct MakeBindStateTypeImpl { + using Type = BindState::type>; +}; + +template +struct MakeBindStateTypeImpl { + static_assert( + !std::is_array::type>::value, + "First bound argument to a method cannot be an array."); + static_assert(!HasRefCountedTypeAsRawPtr::value, + "A parameter is a refcounted type and needs scoped_refptr."); + + private: + using DecayedReceiver = typename std::decay::type; + + public: + using Type = BindState< + typename std::decay::type, + typename std::conditional< + std::is_pointer::value, + scoped_refptr::type>, + DecayedReceiver>::type, + typename std::decay::type...>; +}; + +template +using MakeBindStateType = typename MakeBindStateTypeImpl< + FunctorTraits::type>::is_method, + Functor, + BoundArgs...>::Type; + } // namespace internal + +// Returns a RunType of bound functor. +// E.g. MakeUnboundRunType is evaluated to R(C). +template +using MakeUnboundRunType = + typename internal::MakeUnboundRunTypeImpl::Type; + } // namespace base #endif // BASE_BIND_INTERNAL_H_ diff --git a/security/sandbox/chromium/base/bind_internal_win.h b/security/sandbox/chromium/base/bind_internal_win.h deleted file mode 100644 index 2ee12ef214d3..000000000000 --- a/security/sandbox/chromium/base/bind_internal_win.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Specializations of RunnableAdapter<> for Windows specific calling -// conventions. Please see base/bind_internal.h for more info. - -#ifndef BASE_BIND_INTERNAL_WIN_H_ -#define BASE_BIND_INTERNAL_WIN_H_ - -#include "build/build_config.h" - -// In the x64 architecture in Windows, __fastcall, __stdcall, etc, are all -// the same as __cdecl which would turn the following specializations into -// multiple definitions. -#if !defined(ARCH_CPU_X86_64) - -namespace base { -namespace internal { - -template -class RunnableAdapter; - -// __stdcall Function. -template -class RunnableAdapter { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - explicit RunnableAdapter(R(__stdcall *function)(Args...)) - : function_(function) { - } - - R Run(typename CallbackParamTraits::ForwardType... args) { - return function_(args...); - } - - private: - R (__stdcall *function_)(Args...); -}; - -// __fastcall Function. -template -class RunnableAdapter { - public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); - - explicit RunnableAdapter(R(__fastcall *function)(Args...)) - : function_(function) { - } - - R Run(typename CallbackParamTraits::ForwardType... args) { - return function_(args...); - } - - private: - R (__fastcall *function_)(Args...); -}; - -} // namespace internal -} // namespace base - -#endif // !defined(ARCH_CPU_X86_64) - -#endif // BASE_BIND_INTERNAL_WIN_H_ diff --git a/security/sandbox/chromium/base/bit_cast.h b/security/sandbox/chromium/base/bit_cast.h index b548467e7b86..c9514bceef4d 100644 --- a/security/sandbox/chromium/base/bit_cast.h +++ b/security/sandbox/chromium/base/bit_cast.h @@ -6,6 +6,10 @@ #define BASE_BIT_CAST_H_ #include +#include + +#include "base/compiler_specific.h" +#include "build/build_config.h" // bit_cast is a template function that implements the equivalent // of "*reinterpret_cast(&source)". We need this in very low-level @@ -54,15 +58,40 @@ // calls to memcpy() with inline object code when the size argument is a // compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one // load and one store, and memcpy(d,s,8) compiles to two loads and two stores. -// -// WARNING: if Dest or Source is a non-POD type, the result of the memcpy -// is likely to surprise you. template inline Dest bit_cast(const Source& source) { static_assert(sizeof(Dest) == sizeof(Source), "bit_cast requires source and destination to be the same size"); +#if (__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) || \ + (defined(__clang__) && defined(_LIBCPP_VERSION))) + // GCC 5.1 contains the first libstdc++ with is_trivially_copyable. + // Assume libc++ Just Works: is_trivially_copyable added on May 13th 2011. + // However, with libc++ when GCC is the compiler the trait is buggy, see + // crbug.com/607158, so fall back to the less strict variant for non-clang. + static_assert(std::is_trivially_copyable::value, + "non-trivially-copyable bit_cast is undefined"); + static_assert(std::is_trivially_copyable::value, + "non-trivially-copyable bit_cast is undefined"); +#elif HAS_FEATURE(is_trivially_copyable) + // The compiler supports an equivalent intrinsic. + static_assert(__is_trivially_copyable(Dest), + "non-trivially-copyable bit_cast is undefined"); + static_assert(__is_trivially_copyable(Source), + "non-trivially-copyable bit_cast is undefined"); +#elif COMPILER_GCC + // Fallback to compiler intrinsic on GCC and clang (which pretends to be + // GCC). This isn't quite the same as is_trivially_copyable but it'll do for + // our purpose. + static_assert(__has_trivial_copy(Dest), + "non-trivially-copyable bit_cast is undefined"); + static_assert(__has_trivial_copy(Source), + "non-trivially-copyable bit_cast is undefined"); +#else + // Do nothing, let the bots handle it. +#endif + Dest dest; memcpy(&dest, &source, sizeof(dest)); return dest; diff --git a/security/sandbox/chromium/base/callback.h b/security/sandbox/chromium/base/callback.h index 3bf0008b6d33..c6b8ca3c448a 100644 --- a/security/sandbox/chromium/base/callback.h +++ b/security/sandbox/chromium/base/callback.h @@ -7,397 +7,116 @@ #include "base/callback_forward.h" #include "base/callback_internal.h" -#include "base/template_util.h" // NOTE: Header files that do not require the full definition of Callback or // Closure should #include "base/callback_forward.h" instead of this file. // ----------------------------------------------------------------------------- -// Introduction +// Usage documentation // ----------------------------------------------------------------------------- // -// The templated Callback class is a generalized function object. Together -// with the Bind() function in bind.h, they provide a type-safe method for -// performing partial application of functions. -// -// Partial application (or "currying") is the process of binding a subset of -// a function's arguments to produce another function that takes fewer -// arguments. This can be used to pass around a unit of delayed execution, -// much like lexical closures are used in other languages. For example, it -// is used in Chromium code to schedule tasks on different MessageLoops. -// -// A callback with no unbound input parameters (base::Callback) -// is called a base::Closure. Note that this is NOT the same as what other -// languages refer to as a closure -- it does not retain a reference to its -// enclosing environment. -// -// MEMORY MANAGEMENT AND PASSING -// -// The Callback objects themselves should be passed by const-reference, and -// stored by copy. They internally store their state via a refcounted class -// and thus do not need to be deleted. -// -// The reason to pass via a const-reference is to avoid unnecessary -// AddRef/Release pairs to the internal state. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for basic stuff -// ----------------------------------------------------------------------------- -// -// BINDING A BARE FUNCTION -// -// int Return5() { return 5; } -// base::Callback func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(); // Prints 5. -// -// BINDING A CLASS METHOD -// -// The first argument to bind is the member function to call, the second is -// the object on which to call it. -// -// class Ref : public base::RefCountedThreadSafe { -// public: -// int Foo() { return 3; } -// void PrintBye() { LOG(INFO) << "bye."; } -// }; -// scoped_refptr ref = new Ref(); -// base::Callback ref_cb = base::Bind(&Ref::Foo, ref); -// LOG(INFO) << ref_cb.Run(); // Prints out 3. -// -// By default the object must support RefCounted or you will get a compiler -// error. If you're passing between threads, be sure it's -// RefCountedThreadSafe! See "Advanced binding of member functions" below if -// you don't want to use reference counting. -// -// RUNNING A CALLBACK -// -// Callbacks can be run with their "Run" method, which has the same -// signature as the template argument to the callback. -// -// void DoSomething(const base::Callback& callback) { -// callback.Run(5, "hello"); -// } -// -// Callbacks can be run more than once (they don't get deleted or marked when -// run). However, this precludes using base::Passed (see below). -// -// void DoSomething(const base::Callback& callback) { -// double myresult = callback.Run(3.14159); -// myresult += callback.Run(2.71828); -// } -// -// PASSING UNBOUND INPUT PARAMETERS -// -// Unbound parameters are specified at the time a callback is Run(). They are -// specified in the Callback template type: -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc); -// cb.Run(23, "hello, world"); -// -// PASSING BOUND INPUT PARAMETERS -// -// Bound parameters are specified when you create thee callback as arguments -// to Bind(). They will be passed to the function and the Run()ner of the -// callback doesn't see those values or even know that the function it's -// calling. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc, 23, "hello world"); -// cb.Run(); -// -// A callback with no unbound input parameters (base::Callback) -// is called a base::Closure. So we could have also written: -// -// base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); -// -// When calling member functions, bound parameters just go after the object -// pointer. -// -// base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world"); -// -// PARTIAL BINDING OF PARAMETERS -// -// You can specify some parameters when you create the callback, and specify -// the rest when you execute the callback. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc, 23); -// cb.Run("hello world"); -// -// When calling a function bound parameters are first, followed by unbound -// parameters. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for advanced binding -// ----------------------------------------------------------------------------- -// -// BINDING A CLASS METHOD WITH WEAK POINTERS -// -// base::Bind(&MyClass::Foo, GetWeakPtr()); -// -// The callback will not be run if the object has already been destroyed. -// DANGER: weak pointers are not threadsafe, so don't use this -// when passing between threads! -// -// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT -// -// base::Bind(&MyClass::Foo, base::Unretained(this)); -// -// This disables all lifetime management on the object. You're responsible -// for making sure the object is alive at the time of the call. You break it, -// you own it! -// -// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS -// -// MyClass* myclass = new MyClass; -// base::Bind(&MyClass::Foo, base::Owned(myclass)); -// -// The object will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). Potentially useful for -// "fire and forget" cases. -// -// IGNORING RETURN VALUES -// -// Sometimes you want to call a function that returns a value in a callback -// that doesn't expect a return value. -// -// int DoSomething(int arg) { cout << arg << endl; } -// base::Callback cb = -// base::Bind(base::IgnoreResult(&DoSomething)); -// -// -// ----------------------------------------------------------------------------- -// Quick reference for binding parameters to Bind() -// ----------------------------------------------------------------------------- -// -// Bound parameters are specified as arguments to Bind() and are passed to the -// function. A callback with no parameters or no unbound parameters is called a -// Closure (base::Callback and base::Closure are the same thing). -// -// PASSING PARAMETERS OWNED BY THE CALLBACK -// -// void Foo(int* arg) { cout << *arg << endl; } -// int* pn = new int(1); -// base::Closure foo_callback = base::Bind(&foo, base::Owned(pn)); -// -// The parameter will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). -// -// PASSING PARAMETERS AS A scoped_ptr -// -// void TakesOwnership(scoped_ptr arg) {} -// scoped_ptr f(new Foo); -// // f becomes null during the following call. -// base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f)); -// -// Ownership of the parameter will be with the callback until the it is run, -// when ownership is passed to the callback function. This means the callback -// can only be run once. If the callback is never run, it will delete the -// object when it's destroyed. -// -// PASSING PARAMETERS AS A scoped_refptr -// -// void TakesOneRef(scoped_refptr arg) {} -// scoped_refptr f(new Foo) -// base::Closure cb = base::Bind(&TakesOneRef, f); -// -// This should "just work." The closure will take a reference as long as it -// is alive, and another reference will be taken for the called function. -// -// PASSING PARAMETERS BY REFERENCE -// -// Const references are *copied* unless ConstRef is used. Example: -// -// void foo(const int& arg) { printf("%d %p\n", arg, &arg); } -// int n = 1; -// base::Closure has_copy = base::Bind(&foo, n); -// base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); -// n = 2; -// foo(n); // Prints "2 0xaaaaaaaaaaaa" -// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" -// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa" -// -// Normally parameters are copied in the closure. DANGER: ConstRef stores a -// const reference instead, referencing the original parameter. This means -// that you must ensure the object outlives the callback! -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// WHERE IS THIS DESIGN FROM: -// -// The design Callback and Bind is heavily influenced by C++'s -// tr1::function/tr1::bind, and by the "Google Callback" system used inside -// Google. -// -// -// HOW THE IMPLEMENTATION WORKS: -// -// There are three main components to the system: -// 1) The Callback classes. -// 2) The Bind() functions. -// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). -// -// The Callback classes represent a generic function pointer. Internally, -// it stores a refcounted piece of state that represents the target function -// and all its bound parameters. Each Callback specialization has a templated -// constructor that takes an BindState<>*. In the context of the constructor, -// the static type of this BindState<> pointer uniquely identifies the -// function it is representing, all its bound parameters, and a Run() method -// that is capable of invoking the target. -// -// Callback's constructor takes the BindState<>* that has the full static type -// and erases the target function type as well as the types of the bound -// parameters. It does this by storing a pointer to the specific Run() -// function, and upcasting the state of BindState<>* to a -// BindStateBase*. This is safe as long as this BindStateBase pointer -// is only used with the stored Run() pointer. -// -// To BindState<> objects are created inside the Bind() functions. -// These functions, along with a set of internal templates, are responsible for -// -// - Unwrapping the function signature into return type, and parameters -// - Determining the number of parameters that are bound -// - Creating the BindState storing the bound parameters -// - Performing compile-time asserts to avoid error-prone behavior -// - Returning an Callback<> with an arity matching the number of unbound -// parameters and that knows the correct refcounting semantics for the -// target object if we are binding a method. -// -// The Bind functions do the above using type-inference, and template -// specializations. -// -// By default Bind() will store copies of all bound parameters, and attempt -// to refcount a target object if the function being bound is a class method. -// These copies are created even if the function takes parameters as const -// references. (Binding to non-const references is forbidden, see bind.h.) -// -// To change this behavior, we introduce a set of argument wrappers -// (e.g., Unretained(), and ConstRef()). These are simple container templates -// that are passed by value, and wrap a pointer to argument. See the -// file-level comment in base/bind_helpers.h for more info. -// -// These types are passed to the Unwrap() functions, and the MaybeRefcount() -// functions respectively to modify the behavior of Bind(). The Unwrap() -// and MaybeRefcount() functions change behavior by doing partial -// specialization based on whether or not a parameter is a wrapper type. -// -// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. -// -// -// WHY NOT TR1 FUNCTION/BIND? -// -// Direct use of tr1::function and tr1::bind was considered, but ultimately -// rejected because of the number of copy constructors invocations involved -// in the binding of arguments during construction, and the forwarding of -// arguments during invocation. These copies will no longer be an issue in -// C++0x because C++0x will support rvalue reference allowing for the compiler -// to avoid these copies. However, waiting for C++0x is not an option. -// -// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the -// tr1::bind call itself will invoke a non-trivial copy constructor three times -// for each bound parameter. Also, each when passing a tr1::function, each -// bound argument will be copied again. -// -// In addition to the copies taken at binding and invocation, copying a -// tr1::function causes a copy to be made of all the bound parameters and -// state. -// -// Furthermore, in Chromium, it is desirable for the Callback to take a -// reference on a target object when representing a class method call. This -// is not supported by tr1. -// -// Lastly, tr1::function and tr1::bind has a more general and flexible API. -// This includes things like argument reordering by use of -// tr1::bind::placeholder, support for non-const reference parameters, and some -// limited amount of subtyping of the tr1::function object (e.g., -// tr1::function is convertible to tr1::function). -// -// These are not features that are required in Chromium. Some of them, such as -// allowing for reference parameters, and subtyping of functions, may actually -// become a source of errors. Removing support for these features actually -// allows for a simpler implementation, and a terser Currying API. -// -// -// WHY NOT GOOGLE CALLBACKS? -// -// The Google callback system also does not support refcounting. Furthermore, -// its implementation has a number of strange edge cases with respect to type -// conversion of its arguments. In particular, the argument's constness must -// at times match exactly the function signature, or the type-inference might -// break. Given the above, writing a custom solution was easier. -// -// -// MISSING FUNCTIONALITY -// - Invoking the return of Bind. Bind(&foo).Run() does not work; -// - Binding arrays to functions that take a non-const pointer. -// Example: -// void Foo(const char* ptr); -// void Bar(char* ptr); -// Bind(&Foo, "test"); -// Bind(&Bar, "test"); // This fails because ptr is not const. +// See //docs/callback.md for documentation. namespace base { -// First, we forward declare the Callback class template. This informs the -// compiler that the template only has 1 type parameter which is the function -// signature that the Callback is representing. -// -// After this, create template specializations for 0-7 parameters. Note that -// even though the template typelist grows, the specialization still -// only has one type: the function signature. -// -// If you are thinking of forward declaring Callback in your own header file, -// please include "base/callback_forward.h" instead. - namespace internal { -template -struct BindState; + +// RunMixin provides different variants of `Run()` function to `Callback<>` +// based on the type of callback. +template +class RunMixin; + +// Specialization for OnceCallback. +template +class RunMixin> { + private: + using CallbackType = + Callback; + + public: + using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); + + R Run(Args... args) && { + // Move the callback instance into a local variable before the invocation, + // that ensures the internal state is cleared after the invocation. + // It's not safe to touch |this| after the invocation, since running the + // bound function may destroy |this|. + CallbackType cb = static_cast(*this); + PolymorphicInvoke f = + reinterpret_cast(cb.polymorphic_invoke()); + return f(cb.bind_state_.get(), std::forward(args)...); + } +}; + +// Specialization for RepeatingCallback. +template +class RunMixin> { + private: + using CallbackType = Callback; + + public: + using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); + + R Run(Args... args) const { + const CallbackType& cb = static_cast(*this); + PolymorphicInvoke f = + reinterpret_cast(cb.polymorphic_invoke()); + return f(cb.bind_state_.get(), std::forward(args)...); + } +}; + +template +struct IsCallbackConvertible : std::false_type {}; + +template +struct IsCallbackConvertible< + Callback, + Callback> : std::true_type { +}; + } // namespace internal -template -class Callback : public internal::CallbackBase { +template +class Callback + : public internal::CallbackBase, + public internal::RunMixin> { public: - // MSVC 2013 doesn't support Type Alias of function types. - // Revisit this after we update it to newer version. - typedef R RunType(Args...); + static_assert(repeat_mode != internal::RepeatMode::Once || + copy_mode == internal::CopyMode::MoveOnly, + "OnceCallback must be MoveOnly."); - Callback() : CallbackBase(nullptr) { } + using RunType = R(Args...); - template - explicit Callback( - internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &internal::BindState - ::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); + Callback() : internal::CallbackBase(nullptr) {} + + explicit Callback(internal::BindStateBase* bind_state) + : internal::CallbackBase(bind_state) { + } + + template ::value + >::type> + Callback(OtherCallback other) + : internal::CallbackBase(std::move(other)) {} + + template ::value + >::type> + Callback& operator=(OtherCallback other) { + static_cast&>(*this) = std::move(other); + return *this; } bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); + return this->EqualsInternal(other); } - R Run(typename internal::CallbackParamTraits::ForwardType... args) - const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), internal::CallbackForward(args)...); - } - - private: - using PolymorphicInvoke = - R(*)(internal::BindStateBase*, - typename internal::CallbackParamTraits::ForwardType...); + friend class internal::RunMixin; }; } // namespace base diff --git a/security/sandbox/chromium/base/callback_forward.h b/security/sandbox/chromium/base/callback_forward.h index a9a263a50ea7..13eed0eb0d2f 100644 --- a/security/sandbox/chromium/base/callback_forward.h +++ b/security/sandbox/chromium/base/callback_forward.h @@ -6,14 +6,43 @@ #define BASE_CALLBACK_FORWARD_H_ namespace base { +namespace internal { -template +// CopyMode is used to control the copyablity of a Callback. +// MoveOnly indicates the Callback is not copyable but movable, and Copyable +// indicates it is copyable and movable. +enum class CopyMode { + MoveOnly, + Copyable, +}; + +enum class RepeatMode { + Once, + Repeating, +}; + +} // namespace internal + +template class Callback; // Syntactic sugar to make Callback easier to declare since it // will be used in a lot of APIs with delayed execution. using Closure = Callback; +template +using OnceCallback = Callback; +template +using RepeatingCallback = Callback; +using OnceClosure = OnceCallback; +using RepeatingClosure = RepeatingCallback; + } // namespace base #endif // BASE_CALLBACK_FORWARD_H_ diff --git a/security/sandbox/chromium/base/callback_internal.cc b/security/sandbox/chromium/base/callback_internal.cc index 2553fe7e1b64..4afd567f0fe3 100644 --- a/security/sandbox/chromium/base/callback_internal.cc +++ b/security/sandbox/chromium/base/callback_internal.cc @@ -9,38 +9,94 @@ namespace base { namespace internal { -void BindStateBase::AddRef() { +namespace { + +bool ReturnFalse(const BindStateBase*) { + return false; +} + +} // namespace + +BindStateBase::BindStateBase(InvokeFuncStorage polymorphic_invoke, + void (*destructor)(const BindStateBase*)) + : BindStateBase(polymorphic_invoke, destructor, &ReturnFalse) { +} + +BindStateBase::BindStateBase(InvokeFuncStorage polymorphic_invoke, + void (*destructor)(const BindStateBase*), + bool (*is_cancelled)(const BindStateBase*)) + : polymorphic_invoke_(polymorphic_invoke), + ref_count_(0), + destructor_(destructor), + is_cancelled_(is_cancelled) {} + +void BindStateBase::AddRef() const { AtomicRefCountInc(&ref_count_); } -void BindStateBase::Release() { +void BindStateBase::Release() const { if (!AtomicRefCountDec(&ref_count_)) destructor_(this); } -CallbackBase::CallbackBase(const CallbackBase& c) = default; -CallbackBase& CallbackBase::operator=(const CallbackBase& c) = default; +CallbackBase::CallbackBase(CallbackBase&& c) = default; -void CallbackBase::Reset() { - polymorphic_invoke_ = NULL; +CallbackBase& +CallbackBase::operator=(CallbackBase&& c) = default; + +CallbackBase::CallbackBase( + const CallbackBase& c) + : bind_state_(c.bind_state_) {} + +CallbackBase& CallbackBase::operator=( + const CallbackBase& c) { + bind_state_ = c.bind_state_; + return *this; +} + +void CallbackBase::Reset() { // NULL the bind_state_ last, since it may be holding the last ref to whatever // object owns us, and we may be deleted after that. - bind_state_ = NULL; + bind_state_ = nullptr; } -bool CallbackBase::Equals(const CallbackBase& other) const { - return bind_state_.get() == other.bind_state_.get() && - polymorphic_invoke_ == other.polymorphic_invoke_; +bool CallbackBase::IsCancelled() const { + DCHECK(bind_state_); + return bind_state_->IsCancelled(); } -CallbackBase::CallbackBase(BindStateBase* bind_state) - : bind_state_(bind_state), - polymorphic_invoke_(NULL) { +bool CallbackBase::EqualsInternal( + const CallbackBase& other) const { + return bind_state_ == other.bind_state_; +} + +CallbackBase::CallbackBase( + BindStateBase* bind_state) + : bind_state_(bind_state) { DCHECK(!bind_state_.get() || bind_state_->ref_count_ == 1); } -CallbackBase::~CallbackBase() { +CallbackBase::~CallbackBase() {} + +CallbackBase::CallbackBase( + const CallbackBase& c) + : CallbackBase(nullptr) { + bind_state_ = c.bind_state_; } +CallbackBase::CallbackBase(CallbackBase&& c) = default; + +CallbackBase& +CallbackBase::operator=(const CallbackBase& c) { + bind_state_ = c.bind_state_; + return *this; +} + +CallbackBase& +CallbackBase::operator=(CallbackBase&& c) = default; + +template class CallbackBase; +template class CallbackBase; + } // namespace internal } // namespace base diff --git a/security/sandbox/chromium/base/callback_internal.h b/security/sandbox/chromium/base/callback_internal.h index d1d8ab8ec659..f7501f96c5d7 100644 --- a/security/sandbox/chromium/base/callback_internal.h +++ b/security/sandbox/chromium/base/callback_internal.h @@ -8,19 +8,15 @@ #ifndef BASE_CALLBACK_INTERNAL_H_ #define BASE_CALLBACK_INTERNAL_H_ -#include -#include -#include - #include "base/atomic_ref_count.h" #include "base/base_export.h" +#include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/template_util.h" namespace base { namespace internal { +template class CallbackBase; // BindStateBase is used to provide an opaque handle that the Callback @@ -34,199 +30,108 @@ class CallbackBase; // Creating a vtable for every BindState template instantiation results in a lot // of bloat. Its only task is to call the destructor which can be done with a // function pointer. -class BindStateBase { +class BASE_EXPORT BindStateBase { + public: + using InvokeFuncStorage = void(*)(); + protected: - explicit BindStateBase(void (*destructor)(BindStateBase*)) - : ref_count_(0), destructor_(destructor) {} + BindStateBase(InvokeFuncStorage polymorphic_invoke, + void (*destructor)(const BindStateBase*)); + BindStateBase(InvokeFuncStorage polymorphic_invoke, + void (*destructor)(const BindStateBase*), + bool (*is_cancelled)(const BindStateBase*)); ~BindStateBase() = default; private: friend class scoped_refptr; + template friend class CallbackBase; - void AddRef(); - void Release(); + bool IsCancelled() const { + return is_cancelled_(this); + } - AtomicRefCount ref_count_; + void AddRef() const; + void Release() const; + + // In C++, it is safe to cast function pointers to function pointers of + // another type. It is not okay to use void*. We create a InvokeFuncStorage + // that that can store our function pointer, and then cast it back to + // the original type on usage. + InvokeFuncStorage polymorphic_invoke_; + + mutable AtomicRefCount ref_count_; // Pointer to a function that will properly destroy |this|. - void (*destructor_)(BindStateBase*); + void (*destructor_)(const BindStateBase*); + bool (*is_cancelled_)(const BindStateBase*); DISALLOW_COPY_AND_ASSIGN(BindStateBase); }; // Holds the Callback methods that don't require specialization to reduce // template bloat. -class BASE_EXPORT CallbackBase { +// CallbackBase is a direct base class of MoveOnly callbacks, and +// CallbackBase uses CallbackBase for its implementation. +template <> +class BASE_EXPORT CallbackBase { public: - CallbackBase(const CallbackBase& c); - CallbackBase& operator=(const CallbackBase& c); + CallbackBase(CallbackBase&& c); + CallbackBase& operator=(CallbackBase&& c); + + explicit CallbackBase(const CallbackBase& c); + CallbackBase& operator=(const CallbackBase& c); // Returns true if Callback is null (doesn't refer to anything). bool is_null() const { return bind_state_.get() == NULL; } + explicit operator bool() const { return !is_null(); } + + // Returns true if the callback invocation will be nop due to an cancellation. + // It's invalid to call this on uninitialized callback. + bool IsCancelled() const; // Returns the Callback into an uninitialized state. void Reset(); protected: - // In C++, it is safe to cast function pointers to function pointers of - // another type. It is not okay to use void*. We create a InvokeFuncStorage - // that that can store our function pointer, and then cast it back to - // the original type on usage. - using InvokeFuncStorage = void(*)(); + using InvokeFuncStorage = BindStateBase::InvokeFuncStorage; // Returns true if this callback equals |other|. |other| may be null. - bool Equals(const CallbackBase& other) const; + bool EqualsInternal(const CallbackBase& other) const; // Allow initializing of |bind_state_| via the constructor to avoid default - // initialization of the scoped_refptr. We do not also initialize - // |polymorphic_invoke_| here because doing a normal assignment in the - // derived Callback templates makes for much nicer compiler errors. + // initialization of the scoped_refptr. explicit CallbackBase(BindStateBase* bind_state); + InvokeFuncStorage polymorphic_invoke() const { + return bind_state_->polymorphic_invoke_; + } + // Force the destructor to be instantiated inside this translation unit so // that our subclasses will not get inlined versions. Avoids more template // bloat. ~CallbackBase(); scoped_refptr bind_state_; - InvokeFuncStorage polymorphic_invoke_; }; -// A helper template to determine if given type is non-const move-only-type, -// i.e. if a value of the given type should be passed via std::move() in a -// destructive way. Types are considered to be move-only if they have a -// sentinel MoveOnlyTypeForCPP03 member: a class typically gets this from using -// the DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND macro. -// It would be easy to generalize this trait to all move-only types... but this -// confuses template deduction in VS2013 with certain types such as -// std::unique_ptr. -// TODO(dcheng): Revisit this when Windows switches to VS2015 by default. -template struct IsMoveOnlyType { - template - static YesType Test(const typename U::MoveOnlyTypeForCPP03*); - - template - static NoType Test(...); - - static const bool value = sizeof((Test(0))) == sizeof(YesType) && - !is_const::value; +// CallbackBase is a direct base class of Copyable Callbacks. +template <> +class BASE_EXPORT CallbackBase + : public CallbackBase { + public: + CallbackBase(const CallbackBase& c); + CallbackBase(CallbackBase&& c); + CallbackBase& operator=(const CallbackBase& c); + CallbackBase& operator=(CallbackBase&& c); + protected: + explicit CallbackBase(BindStateBase* bind_state) + : CallbackBase(bind_state) {} + ~CallbackBase() {} }; -// Specialization of IsMoveOnlyType so that std::unique_ptr is still considered -// move-only, even without the sentinel member. -template -struct IsMoveOnlyType> : std::true_type {}; - -template -struct CallbackParamTraitsForMoveOnlyType; - -template -struct CallbackParamTraitsForNonMoveOnlyType; - -// TODO(tzik): Use a default parameter once MSVS supports variadic templates -// with default values. -// http://connect.microsoft.com/VisualStudio/feedbackdetail/view/957801/compilation-error-with-variadic-templates -// -// This is a typetraits object that's used to take an argument type, and -// extract a suitable type for storing and forwarding arguments. -// -// In particular, it strips off references, and converts arrays to -// pointers for storage; and it avoids accidentally trying to create a -// "reference of a reference" if the argument is a reference type. -// -// This array type becomes an issue for storage because we are passing bound -// parameters by const reference. In this case, we end up passing an actual -// array type in the initializer list which C++ does not allow. This will -// break passing of C-string literals. -template -struct CallbackParamTraits - : std::conditional::value, - CallbackParamTraitsForMoveOnlyType, - CallbackParamTraitsForNonMoveOnlyType>::type { -}; - -template -struct CallbackParamTraitsForNonMoveOnlyType { - using ForwardType = const T&; - using StorageType = T; -}; - -// The Storage should almost be impossible to trigger unless someone manually -// specifies type of the bind parameters. However, in case they do, -// this will guard against us accidentally storing a reference parameter. -// -// The ForwardType should only be used for unbound arguments. -template -struct CallbackParamTraitsForNonMoveOnlyType { - using ForwardType = T&; - using StorageType = T; -}; - -// Note that for array types, we implicitly add a const in the conversion. This -// means that it is not possible to bind array arguments to functions that take -// a non-const pointer. Trying to specialize the template based on a "const -// T[n]" does not seem to match correctly, so we are stuck with this -// restriction. -template -struct CallbackParamTraitsForNonMoveOnlyType { - using ForwardType = const T*; - using StorageType = const T*; -}; - -// See comment for CallbackParamTraits. -template -struct CallbackParamTraitsForNonMoveOnlyType { - using ForwardType = const T*; - using StorageType = const T*; -}; - -// Parameter traits for movable-but-not-copyable scopers. -// -// Callback<>/Bind() understands movable-but-not-copyable semantics where -// the type cannot be copied but can still have its state destructively -// transferred (aka. moved) to another instance of the same type by calling a -// helper function. When used with Bind(), this signifies transferal of the -// object's state to the target function. -// -// For these types, the ForwardType must not be a const reference, or a -// reference. A const reference is inappropriate, and would break const -// correctness, because we are implementing a destructive move. A non-const -// reference cannot be used with temporaries which means the result of a -// function or a cast would not be usable with Callback<> or Bind(). -template -struct CallbackParamTraitsForMoveOnlyType { - using ForwardType = T; - using StorageType = T; -}; - -// CallbackForward() is a very limited simulation of C++11's std::forward() -// used by the Callback/Bind system for a set of movable-but-not-copyable -// types. It is needed because forwarding a movable-but-not-copyable -// argument to another function requires us to invoke the proper move -// operator to create a rvalue version of the type. The supported types are -// whitelisted below as overloads of the CallbackForward() function. The -// default template compiles out to be a no-op. -// -// In C++11, std::forward would replace all uses of this function. However, it -// is impossible to implement a general std::forward without C++11 due to a lack -// of rvalue references. -// -// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to -// simulate std::forward() and forward the result of one Callback as a -// parameter to another callback. This is to support Callbacks that return -// the movable-but-not-copyable types whitelisted above. -template -typename std::enable_if::value, T>::type& CallbackForward( - T& t) { - return t; -} - -template -typename std::enable_if::value, T>::type CallbackForward( - T& t) { - return std::move(t); -} +extern template class CallbackBase; +extern template class CallbackBase; } // namespace internal } // namespace base diff --git a/security/sandbox/chromium/base/compiler_specific.h b/security/sandbox/chromium/base/compiler_specific.h index 339e9b74e9c2..bb4c52be45e2 100644 --- a/security/sandbox/chromium/base/compiler_specific.h +++ b/security/sandbox/chromium/base/compiler_specific.h @@ -100,6 +100,14 @@ #define NOINLINE #endif +#if COMPILER_GCC && defined(NDEBUG) +#define ALWAYS_INLINE inline __attribute__((__always_inline__)) +#elif COMPILER_MSVC && defined(NDEBUG) +#define ALWAYS_INLINE __forceinline +#else +#define ALWAYS_INLINE inline +#endif + // Specify memory alignment for structs, classes, etc. // Use like: // class ALIGNAS(16) MyClass { ... } @@ -169,6 +177,15 @@ #define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) #endif // MEMORY_SANITIZER +// DISABLE_CFI_PERF -- Disable Control Flow Integrity for perf reasons. +#if !defined(DISABLE_CFI_PERF) +#if defined(__clang__) && defined(OFFICIAL_BUILD) +#define DISABLE_CFI_PERF __attribute__((no_sanitize("cfi"))) +#else +#define DISABLE_CFI_PERF +#endif +#endif + // Macro useful for writing cross-platform function pointers. #if !defined(CDECL) #if defined(OS_WIN) @@ -187,4 +204,20 @@ #endif // defined(COMPILER_GCC) #endif // !defined(UNLIKELY) +#if !defined(LIKELY) +#if defined(COMPILER_GCC) +#define LIKELY(x) __builtin_expect((x), 1) +#else +#define LIKELY(x) (x) +#endif // defined(COMPILER_GCC) +#endif // !defined(LIKELY) + +// Compiler feature-detection. +// clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension +#if defined(__has_feature) +#define HAS_FEATURE(FEATURE) __has_feature(FEATURE) +#else +#define HAS_FEATURE(FEATURE) 0 +#endif + #endif // BASE_COMPILER_SPECIFIC_H_ diff --git a/security/sandbox/chromium/base/containers/adapters.h b/security/sandbox/chromium/base/containers/adapters.h new file mode 100644 index 000000000000..fa671b46d991 --- /dev/null +++ b/security/sandbox/chromium/base/containers/adapters.h @@ -0,0 +1,73 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CONTAINERS_ADAPTERS_H_ +#define BASE_CONTAINERS_ADAPTERS_H_ + +#include + +#include + +#include "base/macros.h" + +namespace base { + +namespace internal { + +// Internal adapter class for implementing base::Reversed. +template +class ReversedAdapter { + public: + using Iterator = decltype(static_cast(nullptr)->rbegin()); + + explicit ReversedAdapter(T& t) : t_(t) {} + ReversedAdapter(const ReversedAdapter& ra) : t_(ra.t_) {} + + // TODO(mdempsky): Once we can use C++14 library features, use std::rbegin + // and std::rend instead, so we can remove the specialization below. + Iterator begin() const { return t_.rbegin(); } + Iterator end() const { return t_.rend(); } + + private: + T& t_; + + DISALLOW_ASSIGN(ReversedAdapter); +}; + +template +class ReversedAdapter { + public: + using Iterator = std::reverse_iterator; + + explicit ReversedAdapter(T (&t)[N]) : t_(t) {} + ReversedAdapter(const ReversedAdapter& ra) : t_(ra.t_) {} + + Iterator begin() const { return Iterator(&t_[N]); } + Iterator end() const { return Iterator(&t_[0]); } + + private: + T (&t_)[N]; + + DISALLOW_ASSIGN(ReversedAdapter); +}; + +} // namespace internal + +// Reversed returns a container adapter usable in a range-based "for" statement +// for iterating a reversible container in reverse order. +// +// Example: +// +// std::vector v = ...; +// for (int i : base::Reversed(v)) { +// // iterates through v from back to front +// } +template +internal::ReversedAdapter Reversed(T& t) { + return internal::ReversedAdapter(t); +} + +} // namespace base + +#endif // BASE_CONTAINERS_ADAPTERS_H_ diff --git a/security/sandbox/chromium/base/containers/hash_tables.h b/security/sandbox/chromium/base/containers/hash_tables.h index c421dddf3e7c..8da7b6726852 100644 --- a/security/sandbox/chromium/base/containers/hash_tables.h +++ b/security/sandbox/chromium/base/containers/hash_tables.h @@ -1,281 +1,75 @@ // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// - -// -// Deal with the differences between Microsoft and GNU implemenations -// of hash_map. Allows all platforms to use |base::hash_map| and -// |base::hash_set|. -// eg: -// base::hash_map my_map; -// base::hash_set my_set; -// -// NOTE: It is an explicit non-goal of this class to provide a generic hash -// function for pointers. If you want to hash a pointers to a particular class, -// please define the template specialization elsewhere (for example, in its -// header file) and keep it specific to just pointers to that class. This is -// because identity hashes are not desirable for all types that might show up -// in containers as pointers. #ifndef BASE_CONTAINERS_HASH_TABLES_H_ #define BASE_CONTAINERS_HASH_TABLES_H_ -#include -#include - -#include - -#include "base/strings/string16.h" -#include "build/build_config.h" - -#if defined(COMPILER_MSVC) +#include #include #include +#include -#define BASE_HASH_NAMESPACE std +#include "base/hash.h" -#elif defined(COMPILER_GCC) +// This header file is deprecated. Use the corresponding C++11 type +// instead. https://crbug.com/576864 +// Use a custom hasher instead. #define BASE_HASH_NAMESPACE base_hash -// This is a hack to disable the gcc 4.4 warning about hash_map and hash_set -// being deprecated. We can get rid of this when we upgrade to VS2008 and we -// can use and . -#ifdef __DEPRECATED -#define CHROME_OLD__DEPRECATED __DEPRECATED -#undef __DEPRECATED -#endif - -#include -#include -#define BASE_HASH_IMPL_NAMESPACE __gnu_cxx - -#include - -#ifdef CHROME_OLD__DEPRECATED -#define __DEPRECATED CHROME_OLD__DEPRECATED -#undef CHROME_OLD__DEPRECATED -#endif - namespace BASE_HASH_NAMESPACE { -// The pre-standard hash behaves like C++11's std::hash, except around pointers. -// const char* is specialized to hash the C string and hash functions for -// general T* are missing. Define a BASE_HASH_NAMESPACE::hash which aligns with -// the C++11 behavior. - +// A separate hasher which, by default, forwards to std::hash. This is so legacy +// uses of BASE_HASH_NAMESPACE with base::hash_map do not interfere with +// std::hash mid-transition. template struct hash { - std::size_t operator()(const T& value) const { - return BASE_HASH_IMPL_NAMESPACE::hash()(value); - } + std::size_t operator()(const T& value) const { return std::hash()(value); } }; -template -struct hash { - std::size_t operator()(T* value) const { - return BASE_HASH_IMPL_NAMESPACE::hash()( - reinterpret_cast(value)); +// Use base::IntPairHash from base/hash.h as a custom hasher instead. +template +struct hash> { + std::size_t operator()(std::pair value) const { + return base::HashInts(value.first, value.second); } }; -// The GNU C++ library provides identity hash functions for many integral types, -// but not for |long long|. This hash function will truncate if |size_t| is -// narrower than |long long|. This is probably good enough for what we will -// use it for. - -#define DEFINE_TRIVIAL_HASH(integral_type) \ - template<> \ - struct hash { \ - std::size_t operator()(integral_type value) const { \ - return static_cast(value); \ - } \ - } - -DEFINE_TRIVIAL_HASH(long long); -DEFINE_TRIVIAL_HASH(unsigned long long); - -#undef DEFINE_TRIVIAL_HASH - -// Implement string hash functions so that strings of various flavors can -// be used as keys in STL maps and sets. The hash algorithm comes from the -// GNU C++ library, in . It is duplicated here because GCC -// versions prior to 4.3.2 are unable to compile when RTTI -// is disabled, as it is in our build. - -#define DEFINE_STRING_HASH(string_type) \ - template<> \ - struct hash { \ - std::size_t operator()(const string_type& s) const { \ - std::size_t result = 0; \ - for (string_type::const_iterator i = s.begin(); i != s.end(); ++i) \ - result = (result * 131) + *i; \ - return result; \ - } \ - } - -DEFINE_STRING_HASH(std::string); -DEFINE_STRING_HASH(base::string16); - -#undef DEFINE_STRING_HASH - } // namespace BASE_HASH_NAMESPACE -#else // COMPILER -#error define BASE_HASH_NAMESPACE for your compiler -#endif // COMPILER - namespace base { -// On MSVC, use the C++11 containers. -#if defined(COMPILER_MSVC) - -template, - class Pred = std::equal_to, - class Alloc = std::allocator>> +// Use std::unordered_map instead. +template , + class Pred = std::equal_to, + class Alloc = std::allocator>> using hash_map = std::unordered_map; -template, - class Pred = std::equal_to, - class Alloc = std::allocator>> +// Use std::unordered_multimap instead. +template , + class Pred = std::equal_to, + class Alloc = std::allocator>> using hash_multimap = std::unordered_multimap; -template, - class Pred = std::equal_to, - class Alloc = std::allocator> +// Use std::unordered_multiset instead. +template , + class Pred = std::equal_to, + class Alloc = std::allocator> using hash_multiset = std::unordered_multiset; -template, - class Pred = std::equal_to, - class Alloc = std::allocator> +// Use std::unordered_set instead. +template , + class Pred = std::equal_to, + class Alloc = std::allocator> using hash_set = std::unordered_set; -#else // !COMPILER_MSVC - -// Otherwise, use the pre-standard ones, but override the default hash to match -// C++11. -template, - class Pred = std::equal_to, - class Alloc = std::allocator>> -using hash_map = BASE_HASH_IMPL_NAMESPACE::hash_map; - -template, - class Pred = std::equal_to, - class Alloc = std::allocator>> -using hash_multimap = - BASE_HASH_IMPL_NAMESPACE::hash_multimap; - -template, - class Pred = std::equal_to, - class Alloc = std::allocator> -using hash_multiset = - BASE_HASH_IMPL_NAMESPACE::hash_multiset; - -template, - class Pred = std::equal_to, - class Alloc = std::allocator> -using hash_set = BASE_HASH_IMPL_NAMESPACE::hash_set; - -#undef BASE_HASH_IMPL_NAMESPACE - -#endif // COMPILER_MSVC - -// Implement hashing for pairs of at-most 32 bit integer values. -// When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using -// multiply-add hashing. This algorithm, as described in -// Theorem 4.3.3 of the thesis "Über die Komplexität der Multiplikation in -// eingeschränkten Branchingprogrammmodellen" by Woelfel, is: -// -// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32 -// -// Contact danakj@chromium.org for any questions. -inline std::size_t HashInts32(uint32_t value1, uint32_t value2) { - uint64_t value1_64 = value1; - uint64_t hash64 = (value1_64 << 32) | value2; - - if (sizeof(std::size_t) >= sizeof(uint64_t)) - return static_cast(hash64); - - uint64_t odd_random = 481046412LL << 32 | 1025306955LL; - uint32_t shift_random = 10121U << 16; - - hash64 = hash64 * odd_random + shift_random; - std::size_t high_bits = static_cast( - hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t)))); - return high_bits; -} - -// Implement hashing for pairs of up-to 64-bit integer values. -// We use the compound integer hash method to produce a 64-bit hash code, by -// breaking the two 64-bit inputs into 4 32-bit values: -// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 -// Then we reduce our result to 32 bits if required, similar to above. -inline std::size_t HashInts64(uint64_t value1, uint64_t value2) { - uint32_t short_random1 = 842304669U; - uint32_t short_random2 = 619063811U; - uint32_t short_random3 = 937041849U; - uint32_t short_random4 = 3309708029U; - - uint32_t value1a = static_cast(value1 & 0xffffffff); - uint32_t value1b = static_cast((value1 >> 32) & 0xffffffff); - uint32_t value2a = static_cast(value2 & 0xffffffff); - uint32_t value2b = static_cast((value2 >> 32) & 0xffffffff); - - uint64_t product1 = static_cast(value1a) * short_random1; - uint64_t product2 = static_cast(value1b) * short_random2; - uint64_t product3 = static_cast(value2a) * short_random3; - uint64_t product4 = static_cast(value2b) * short_random4; - - uint64_t hash64 = product1 + product2 + product3 + product4; - - if (sizeof(std::size_t) >= sizeof(uint64_t)) - return static_cast(hash64); - - uint64_t odd_random = 1578233944LL << 32 | 194370989LL; - uint32_t shift_random = 20591U << 16; - - hash64 = hash64 * odd_random + shift_random; - std::size_t high_bits = static_cast( - hash64 >> (8 * (sizeof(uint64_t) - sizeof(std::size_t)))); - return high_bits; -} - -template -inline std::size_t HashPair(T1 value1, T2 value2) { - // This condition is expected to be compile-time evaluated and optimised away - // in release builds. - if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t))) - return HashInts64(value1, value2); - - return HashInts32(value1, value2); -} - } // namespace base -namespace BASE_HASH_NAMESPACE { - -// Implement methods for hashing a pair of integers, so they can be used as -// keys in STL containers. - -template -struct hash > { - std::size_t operator()(std::pair value) const { - return base::HashPair(value.first, value.second); - } -}; - -} // namespace BASE_HASH_NAMESPACE - -#undef DEFINE_PAIR_HASH_FUNCTION_START -#undef DEFINE_PAIR_HASH_FUNCTION_END - #endif // BASE_CONTAINERS_HASH_TABLES_H_ diff --git a/security/sandbox/chromium/base/cpu.cc b/security/sandbox/chromium/base/cpu.cc index 713544566439..af9c23da1a1e 100644 --- a/security/sandbox/chromium/base/cpu.cc +++ b/security/sandbox/chromium/base/cpu.cc @@ -7,13 +7,11 @@ #include #include #include -#include #include #include #include "base/macros.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) @@ -45,11 +43,11 @@ CPU::CPU() has_ssse3_(false), has_sse41_(false), has_sse42_(false), + has_popcnt_(false), has_avx_(false), has_avx2_(false), has_aesni_(false), has_non_stop_time_stamp_counter_(false), - has_broken_neon_(false), cpu_vendor_("unknown") { Initialize(); } @@ -99,7 +97,7 @@ uint64_t _xgetbv(uint32_t xcr) { #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) class LazyCpuInfoValue { public: - LazyCpuInfoValue() : has_broken_neon_(false) { + LazyCpuInfoValue() { // This function finds the value from /proc/cpuinfo under the key "model // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7 // and later for arm64) and is shown once per CPU. "Processor" is used in @@ -108,21 +106,6 @@ class LazyCpuInfoValue { const char kModelNamePrefix[] = "model name\t: "; const char kProcessorPrefix[] = "Processor\t: "; - // This function also calculates whether we believe that this CPU has a - // broken NEON unit based on these fields from cpuinfo: - unsigned implementer = 0, architecture = 0, variant = 0, part = 0, - revision = 0; - const struct { - const char key[17]; - unsigned int* result; - } kUnsignedValues[] = { - {"CPU implementer", &implementer}, - {"CPU architecture", &architecture}, - {"CPU variant", &variant}, - {"CPU part", &part}, - {"CPU revision", &revision}, - }; - std::string contents; ReadFileToString(FilePath("/proc/cpuinfo"), &contents); DCHECK(!contents.empty()); @@ -138,52 +121,13 @@ class LazyCpuInfoValue { line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0)) { brand_.assign(line.substr(strlen(kModelNamePrefix))); } - - for (size_t i = 0; i < arraysize(kUnsignedValues); i++) { - const char *key = kUnsignedValues[i].key; - const size_t len = strlen(key); - - if (line.compare(0, len, key) == 0 && - line.size() >= len + 1 && - (line[len] == '\t' || line[len] == ' ' || line[len] == ':')) { - size_t colon_pos = line.find(':', len); - if (colon_pos == std::string::npos) { - continue; - } - - const StringPiece line_sp(line); - StringPiece value_sp = line_sp.substr(colon_pos + 1); - while (!value_sp.empty() && - (value_sp[0] == ' ' || value_sp[0] == '\t')) { - value_sp = value_sp.substr(1); - } - - // The string may have leading "0x" or not, so we use strtoul to - // handle that. - char* endptr; - std::string value(value_sp.as_string()); - unsigned long int result = strtoul(value.c_str(), &endptr, 0); - if (*endptr == 0 && result <= UINT_MAX) { - *kUnsignedValues[i].result = result; - } - } - } } - - has_broken_neon_ = - implementer == 0x51 && - architecture == 7 && - variant == 1 && - part == 0x4d && - revision == 0; } const std::string& brand() const { return brand_; } - bool has_broken_neon() const { return has_broken_neon_; } private: std::string brand_; - bool has_broken_neon_; DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue); }; @@ -234,6 +178,8 @@ void CPU::Initialize() { has_ssse3_ = (cpu_info[2] & 0x00000200) != 0; has_sse41_ = (cpu_info[2] & 0x00080000) != 0; has_sse42_ = (cpu_info[2] & 0x00100000) != 0; + has_popcnt_ = (cpu_info[2] & 0x00800000) != 0; + // AVX instructions will generate an illegal instruction exception unless // a) they are supported by the CPU, // b) XSAVE is supported by the CPU and @@ -277,7 +223,6 @@ void CPU::Initialize() { } #elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) cpu_brand_.assign(g_lazy_cpuinfo.Get().brand()); - has_broken_neon_ = g_lazy_cpuinfo.Get().has_broken_neon(); #endif } diff --git a/security/sandbox/chromium/base/cpu.h b/security/sandbox/chromium/base/cpu.h index 8c3c06c04444..0e24df61ddfd 100644 --- a/security/sandbox/chromium/base/cpu.h +++ b/security/sandbox/chromium/base/cpu.h @@ -46,16 +46,13 @@ class BASE_EXPORT CPU { bool has_ssse3() const { return has_ssse3_; } bool has_sse41() const { return has_sse41_; } bool has_sse42() const { return has_sse42_; } + bool has_popcnt() const { return has_popcnt_; } bool has_avx() const { return has_avx_; } bool has_avx2() const { return has_avx2_; } bool has_aesni() const { return has_aesni_; } bool has_non_stop_time_stamp_counter() const { return has_non_stop_time_stamp_counter_; } - // has_broken_neon is only valid on ARM chips. If true, it indicates that we - // believe that the NEON unit on the current CPU is flawed and cannot execute - // some code. See https://code.google.com/p/chromium/issues/detail?id=341598 - bool has_broken_neon() const { return has_broken_neon_; } IntelMicroArchitecture GetIntelMicroArchitecture() const; const std::string& cpu_brand() const { return cpu_brand_; } @@ -78,11 +75,11 @@ class BASE_EXPORT CPU { bool has_ssse3_; bool has_sse41_; bool has_sse42_; + bool has_popcnt_; bool has_avx_; bool has_avx2_; bool has_aesni_; bool has_non_stop_time_stamp_counter_; - bool has_broken_neon_; std::string cpu_vendor_; std::string cpu_brand_; }; diff --git a/security/sandbox/chromium/base/debug/profiler.cc b/security/sandbox/chromium/base/debug/profiler.cc index 75e9aac0cba5..b19e7ecd00fc 100644 --- a/security/sandbox/chromium/base/debug/profiler.cc +++ b/security/sandbox/chromium/base/debug/profiler.cc @@ -13,6 +13,7 @@ #include "build/build_config.h" #if defined(OS_WIN) +#include "base/win/current_module.h" #include "base/win/pe_image.h" #endif // defined(OS_WIN) @@ -56,6 +57,10 @@ void RestartProfilingAfterFork() { ProfilerRegisterThread(); } +bool IsProfilingSupported() { + return true; +} + #else void StartProfiling(const std::string& name) { @@ -74,6 +79,10 @@ bool BeingProfiled() { void RestartProfilingAfterFork() { } +bool IsProfilingSupported() { + return false; +} + #endif #if !defined(OS_WIN) @@ -100,9 +109,6 @@ MoveDynamicSymbol GetProfilerMoveDynamicSymbolFunc() { #else // defined(OS_WIN) -// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx -extern "C" IMAGE_DOS_HEADER __ImageBase; - bool IsBinaryInstrumented() { enum InstrumentationCheckState { UNINITIALIZED, @@ -113,8 +119,7 @@ bool IsBinaryInstrumented() { static InstrumentationCheckState state = UNINITIALIZED; if (state == UNINITIALIZED) { - HMODULE this_module = reinterpret_cast(&__ImageBase); - base::win::PEImage image(this_module); + base::win::PEImage image(CURRENT_MODULE()); // Check to be sure our image is structured as we'd expect. DCHECK(image.VerifyMagic()); @@ -149,8 +154,8 @@ bool FindResolutionFunctionInImports( FunctionSearchContext* context = reinterpret_cast(cookie); - DCHECK_NE(static_cast(NULL), context); - DCHECK_EQ(static_cast(NULL), context->function); + DCHECK(context); + DCHECK(!context->function); // Our import address table contains pointers to the functions we import // at this point. Let's retrieve the first such function and use it to @@ -184,8 +189,7 @@ FunctionType FindFunctionInImports(const char* function_name) { if (!IsBinaryInstrumented()) return NULL; - HMODULE this_module = reinterpret_cast(&__ImageBase); - base::win::PEImage image(this_module); + base::win::PEImage image(CURRENT_MODULE()); FunctionSearchContext ctx = { function_name, NULL }; image.EnumImportChunks(FindResolutionFunctionInImports, &ctx); diff --git a/security/sandbox/chromium/base/debug/profiler.h b/security/sandbox/chromium/base/debug/profiler.h index 7cce7b08f90a..ea81b13c6ae4 100644 --- a/security/sandbox/chromium/base/debug/profiler.h +++ b/security/sandbox/chromium/base/debug/profiler.h @@ -38,6 +38,9 @@ BASE_EXPORT void RestartProfilingAfterFork(); // Returns true iff this executable is instrumented with the Syzygy profiler. BASE_EXPORT bool IsBinaryInstrumented(); +// Returns true iff this executable supports profiling. +BASE_EXPORT bool IsProfilingSupported(); + // There's a class of profilers that use "return address swizzling" to get a // hook on function exits. This class of profilers uses some form of entry hook, // like e.g. binary instrumentation, or a compiler flag, that calls a hook each diff --git a/security/sandbox/chromium/base/environment.h b/security/sandbox/chromium/base/environment.h new file mode 100644 index 000000000000..3a4ed04e4bb5 --- /dev/null +++ b/security/sandbox/chromium/base/environment.h @@ -0,0 +1,90 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ENVIRONMENT_H_ +#define BASE_ENVIRONMENT_H_ + +#include +#include +#include + +#include "base/base_export.h" +#include "base/strings/string16.h" +#include "base/strings/string_piece.h" +#include "build/build_config.h" + +namespace base { + +namespace env_vars { + +#if defined(OS_POSIX) +BASE_EXPORT extern const char kHome[]; +#endif + +} // namespace env_vars + +class BASE_EXPORT Environment { + public: + virtual ~Environment(); + + // Returns the appropriate platform-specific instance. + static std::unique_ptr Create(); + + // Gets an environment variable's value and stores it in |result|. + // Returns false if the key is unset. + virtual bool GetVar(StringPiece variable_name, std::string* result) = 0; + + // Syntactic sugar for GetVar(variable_name, nullptr); + virtual bool HasVar(StringPiece variable_name); + + // Returns true on success, otherwise returns false. + virtual bool SetVar(StringPiece variable_name, + const std::string& new_value) = 0; + + // Returns true on success, otherwise returns false. + virtual bool UnSetVar(StringPiece variable_name) = 0; +}; + + +#if defined(OS_WIN) + +typedef string16 NativeEnvironmentString; +typedef std::map + EnvironmentMap; + +// Returns a modified environment vector constructed from the given environment +// and the list of changes given in |changes|. Each key in the environment is +// matched against the first element of the pairs. In the event of a match, the +// value is replaced by the second of the pair, unless the second is empty, in +// which case the key-value is removed. +// +// This Windows version takes and returns a Windows-style environment block +// which is a concatenated list of null-terminated 16-bit strings. The end is +// marked by a double-null terminator. The size of the returned string will +// include the terminators. +BASE_EXPORT string16 AlterEnvironment(const wchar_t* env, + const EnvironmentMap& changes); + +#elif defined(OS_POSIX) + +typedef std::string NativeEnvironmentString; +typedef std::map + EnvironmentMap; + +// See general comments for the Windows version above. +// +// This Posix version takes and returns a Posix-style environment block, which +// is a null-terminated list of pointers to null-terminated strings. The +// returned array will have appended to it the storage for the array itself so +// there is only one pointer to manage, but this means that you can't copy the +// array without keeping the original around. +BASE_EXPORT std::unique_ptr AlterEnvironment( + const char* const* env, + const EnvironmentMap& changes); + +#endif + +} // namespace base + +#endif // BASE_ENVIRONMENT_H_ diff --git a/security/sandbox/chromium/base/files/file_path.h b/security/sandbox/chromium/base/files/file_path.h index 89e9cbfb1d5c..3234df7bfb69 100644 --- a/security/sandbox/chromium/base/files/file_path.h +++ b/security/sandbox/chromium/base/files/file_path.h @@ -138,6 +138,7 @@ namespace base { class Pickle; class PickleIterator; +class PickleSizer; // An abstraction to isolate users from the differences between native // pathnames on different platforms. @@ -372,11 +373,12 @@ class BASE_EXPORT FilePath { // internally calls SysWideToNativeMB() on POSIX systems other than Mac // and Chrome OS, to mitigate the encoding issue. See the comment at // AsUTF8Unsafe() for details. - static FilePath FromUTF8Unsafe(const std::string& utf8); + static FilePath FromUTF8Unsafe(StringPiece utf8); // Similar to FromUTF8Unsafe, but accepts UTF-16 instead. - static FilePath FromUTF16Unsafe(const string16& utf16); + static FilePath FromUTF16Unsafe(StringPiece16 utf16); + void GetSizeForPickle(PickleSizer* sizer) const; void WriteToPickle(Pickle* pickle) const; bool ReadFromPickle(PickleIterator* iter); diff --git a/security/sandbox/chromium/base/guid.h b/security/sandbox/chromium/base/guid.h index c0a06f8858e3..29c24eacefe6 100644 --- a/security/sandbox/chromium/base/guid.h +++ b/security/sandbox/chromium/base/guid.h @@ -10,23 +10,33 @@ #include #include "base/base_export.h" +#include "base/strings/string_piece.h" #include "build/build_config.h" namespace base { -// Generate a 128-bit random GUID of the form: "%08X-%04X-%04X-%04X-%012llX". +// Generate a 128-bit (pseudo) random GUID in the form of version 4 as described +// in RFC 4122, section 4.4. +// The format of GUID version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, +// where y is one of [8, 9, A, B]. +// The hexadecimal values "a" through "f" are output as lower case characters. // If GUID generation fails an empty string is returned. -// The POSIX implementation uses pseudo random number generation to create -// the GUID. The Windows implementation uses system services. BASE_EXPORT std::string GenerateGUID(); -// Returns true if the input string conforms to the GUID format. -BASE_EXPORT bool IsValidGUID(const std::string& guid); +// Returns true if the input string conforms to the version 4 GUID format. +// Note that this does NOT check if the hexadecimal values "a" through "f" +// are in lower case characters, as Version 4 RFC says onput they're +// case insensitive. (Use IsValidGUIDOutputString for checking if the +// given string is valid output string) +BASE_EXPORT bool IsValidGUID(const base::StringPiece& guid); + +// Returns true if the input string is valid version 4 GUID output string. +// This also checks if the hexadecimal values "a" through "f" are in lower +// case characters. +BASE_EXPORT bool IsValidGUIDOutputString(const base::StringPiece& guid); -#if defined(OS_POSIX) // For unit testing purposes only. Do not use outside of tests. BASE_EXPORT std::string RandomDataToGUIDString(const uint64_t bytes[2]); -#endif } // namespace base diff --git a/security/sandbox/chromium/base/hash.cc b/security/sandbox/chromium/base/hash.cc index d3206f6a6c9c..2f0182592898 100644 --- a/security/sandbox/chromium/base/hash.cc +++ b/security/sandbox/chromium/base/hash.cc @@ -11,8 +11,12 @@ extern "C" uint32_t SuperFastHash(const char* data, int len); namespace base { -uint32_t SuperFastHash(const char* data, int len) { - return ::SuperFastHash(data, len); +uint32_t SuperFastHash(const char* data, size_t length) { + if (length > static_cast(std::numeric_limits::max())) { + NOTREACHED(); + return 0; + } + return ::SuperFastHash(data, static_cast(length)); } } // namespace base diff --git a/security/sandbox/chromium/base/hash.h b/security/sandbox/chromium/base/hash.h index ed8d9fd4cc9b..7c0fba6d39e9 100644 --- a/security/sandbox/chromium/base/hash.h +++ b/security/sandbox/chromium/base/hash.h @@ -10,6 +10,7 @@ #include #include +#include #include "base/base_export.h" #include "base/logging.h" @@ -17,16 +18,12 @@ namespace base { // WARNING: This hash function should not be used for any cryptographic purpose. -BASE_EXPORT uint32_t SuperFastHash(const char* data, int len); +BASE_EXPORT uint32_t SuperFastHash(const char* data, size_t length); // Computes a hash of a memory buffer |data| of a given |length|. // WARNING: This hash function should not be used for any cryptographic purpose. inline uint32_t Hash(const char* data, size_t length) { - if (length > static_cast(std::numeric_limits::max())) { - NOTREACHED(); - return 0; - } - return SuperFastHash(data, static_cast(length)); + return SuperFastHash(data, length); } // Computes a hash of a string |str|. @@ -35,6 +32,87 @@ inline uint32_t Hash(const std::string& str) { return Hash(str.data(), str.size()); } +// Implement hashing for pairs of at-most 32 bit integer values. +// When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using +// multiply-add hashing. This algorithm, as described in +// Theorem 4.3.3 of the thesis "Über die Komplexität der Multiplikation in +// eingeschränkten Branchingprogrammmodellen" by Woelfel, is: +// +// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32 +// +// Contact danakj@chromium.org for any questions. +inline size_t HashInts32(uint32_t value1, uint32_t value2) { + uint64_t value1_64 = value1; + uint64_t hash64 = (value1_64 << 32) | value2; + + if (sizeof(size_t) >= sizeof(uint64_t)) + return static_cast(hash64); + + uint64_t odd_random = 481046412LL << 32 | 1025306955LL; + uint32_t shift_random = 10121U << 16; + + hash64 = hash64 * odd_random + shift_random; + size_t high_bits = + static_cast(hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t)))); + return high_bits; +} + +// Implement hashing for pairs of up-to 64-bit integer values. +// We use the compound integer hash method to produce a 64-bit hash code, by +// breaking the two 64-bit inputs into 4 32-bit values: +// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 +// Then we reduce our result to 32 bits if required, similar to above. +inline size_t HashInts64(uint64_t value1, uint64_t value2) { + uint32_t short_random1 = 842304669U; + uint32_t short_random2 = 619063811U; + uint32_t short_random3 = 937041849U; + uint32_t short_random4 = 3309708029U; + + uint32_t value1a = static_cast(value1 & 0xffffffff); + uint32_t value1b = static_cast((value1 >> 32) & 0xffffffff); + uint32_t value2a = static_cast(value2 & 0xffffffff); + uint32_t value2b = static_cast((value2 >> 32) & 0xffffffff); + + uint64_t product1 = static_cast(value1a) * short_random1; + uint64_t product2 = static_cast(value1b) * short_random2; + uint64_t product3 = static_cast(value2a) * short_random3; + uint64_t product4 = static_cast(value2b) * short_random4; + + uint64_t hash64 = product1 + product2 + product3 + product4; + + if (sizeof(size_t) >= sizeof(uint64_t)) + return static_cast(hash64); + + uint64_t odd_random = 1578233944LL << 32 | 194370989LL; + uint32_t shift_random = 20591U << 16; + + hash64 = hash64 * odd_random + shift_random; + size_t high_bits = + static_cast(hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t)))); + return high_bits; +} + +template +inline size_t HashInts(T1 value1, T2 value2) { + // This condition is expected to be compile-time evaluated and optimised away + // in release builds. + if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t))) + return HashInts64(value1, value2); + + return HashInts32(value1, value2); +} + +// A templated hasher for pairs of integer types. +template +struct IntPairHash; + +template +struct IntPairHash> { + size_t operator()(std::pair value) const { + return HashInts(value.first, value.second); + } +}; + } // namespace base #endif // BASE_HASH_H_ diff --git a/security/sandbox/chromium/base/lazy_instance.h b/security/sandbox/chromium/base/lazy_instance.h index fd0321017df8..1183806bef55 100644 --- a/security/sandbox/chromium/base/lazy_instance.h +++ b/security/sandbox/chromium/base/lazy_instance.h @@ -55,7 +55,7 @@ namespace base { template struct DefaultLazyInstanceTraits { static const bool kRegisterOnExit = true; -#ifndef NDEBUG +#if DCHECK_IS_ON() static const bool kAllowedToAccessOnNonjoinableThread = false; #endif @@ -89,7 +89,7 @@ namespace internal { template struct LeakyLazyInstanceTraits { static const bool kRegisterOnExit = false; -#ifndef NDEBUG +#if DCHECK_IS_ON() static const bool kAllowedToAccessOnNonjoinableThread = true; #endif @@ -102,7 +102,7 @@ struct LeakyLazyInstanceTraits { }; // Our AtomicWord doubles as a spinlock, where a value of -// kBeingCreatedMarker means the spinlock is being held for creation. +// kLazyInstanceStateCreating means the spinlock is being held for creation. static const subtle::AtomicWord kLazyInstanceStateCreating = 1; // Check if instance needs to be created. If so return true otherwise @@ -138,7 +138,7 @@ class LazyInstance { } Type* Pointer() { -#ifndef NDEBUG +#if DCHECK_IS_ON() // Avoid making TLS lookup on release builds. if (!Traits::kAllowedToAccessOnNonjoinableThread) ThreadRestrictions::AssertSingletonAllowed(); diff --git a/security/sandbox/chromium/base/location.h b/security/sandbox/chromium/base/location.h index d3bb23c63ea4..dd78515ce2b0 100644 --- a/security/sandbox/chromium/base/location.h +++ b/security/sandbox/chromium/base/location.h @@ -11,7 +11,7 @@ #include #include "base/base_export.h" -#include "base/containers/hash_tables.h" +#include "base/hash.h" namespace tracked_objects { @@ -59,7 +59,7 @@ class BASE_EXPORT Location { // it comes from __FILE__, so no need to check the contents of the string. // See the definition of FROM_HERE in location.h, and how it is used // elsewhere. - return base::HashPair(reinterpret_cast(location.file_name()), + return base::HashInts(reinterpret_cast(location.file_name()), location.line_number()); } }; @@ -97,7 +97,7 @@ struct BASE_EXPORT LocationSnapshot { BASE_EXPORT const void* GetProgramCounter(); // Define a macro to record the current source location. -#define FROM_HERE FROM_HERE_WITH_EXPLICIT_FUNCTION(__FUNCTION__) +#define FROM_HERE FROM_HERE_WITH_EXPLICIT_FUNCTION(__func__) #define FROM_HERE_WITH_EXPLICIT_FUNCTION(function_name) \ ::tracked_objects::Location(function_name, \ diff --git a/security/sandbox/chromium/base/logging.h b/security/sandbox/chromium/base/logging.h index 300c9b52694b..714545c02bb0 100644 --- a/security/sandbox/chromium/base/logging.h +++ b/security/sandbox/chromium/base/logging.h @@ -11,10 +11,13 @@ #include #include #include +#include +#include #include "base/base_export.h" #include "base/debug/debugger.h" #include "base/macros.h" +#include "base/template_util.h" #include "build/build_config.h" // @@ -306,15 +309,16 @@ const LogSeverity LOG_DFATAL = LOG_FATAL; // by LOG() and LOG_IF, etc. Since these are used all over our code, it's // better to have compact code for these operations. #define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__) -#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__) + ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_INFO, ##__VA_ARGS__) +#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \ + ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_WARNING, \ + ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__) + ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_ERROR, ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__) + ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_FATAL, ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \ - logging::ClassName(__FILE__, __LINE__, logging::LOG_DFATAL , ##__VA_ARGS__) + ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_DFATAL, ##__VA_ARGS__) #define COMPACT_GOOGLE_LOG_INFO \ COMPACT_GOOGLE_LOG_EX_INFO(LogMessage) @@ -373,12 +377,9 @@ const LogSeverity LOG_0 = LOG_ERROR; #define LOG_IF(severity, condition) \ LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition)) -#define SYSLOG(severity) LOG(severity) -#define SYSLOG_IF(severity, condition) LOG_IF(severity, condition) - // The VLOG macros log with negative verbosities. #define VLOG_STREAM(verbose_level) \ - logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream() + ::logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream() #define VLOG(verbose_level) \ LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level)) @@ -389,11 +390,11 @@ const LogSeverity LOG_0 = LOG_ERROR; #if defined (OS_WIN) #define VPLOG_STREAM(verbose_level) \ - logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \ + ::logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \ ::logging::GetLastSystemErrorCode()).stream() #elif defined(OS_POSIX) #define VPLOG_STREAM(verbose_level) \ - logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \ + ::logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \ ::logging::GetLastSystemErrorCode()).stream() #endif @@ -408,8 +409,6 @@ const LogSeverity LOG_0 = LOG_ERROR; #define LOG_ASSERT(condition) \ LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " -#define SYSLOG_ASSERT(condition) \ - SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " #if defined(OS_WIN) #define PLOG_STREAM(severity) \ @@ -435,7 +434,7 @@ const LogSeverity LOG_0 = LOG_ERROR; // boolean. class CheckOpResult { public: - // |message| must be null if and only if the check failed. + // |message| must be non-null if and only if the check failed. CheckOpResult(std::string* message) : message_(message) {} // Returns true if the check succeeded. operator bool() const { return !message_; } @@ -453,22 +452,28 @@ class CheckOpResult { // We make sure CHECK et al. always evaluates their arguments, as // doing CHECK(FunctionWithSideEffect()) is a common idiom. -#if defined(OFFICIAL_BUILD) && defined(NDEBUG) && !defined(OS_ANDROID) +#if defined(OFFICIAL_BUILD) && defined(NDEBUG) // Make all CHECK functions discard their log strings to reduce code -// bloat for official release builds (except Android). +// bloat, and improve performance, for official release builds. -// TODO(akalin): This would be more valuable if there were some way to -// remove BreakDebugger() from the backtrace, perhaps by turning it -// into a macro (like __debugbreak() on Windows). +#if defined(COMPILER_GCC) || __clang__ +#define LOGGING_CRASH() __builtin_trap() +#else +#define LOGGING_CRASH() ((void)(*(volatile char*)0 = 0)) +#endif + +// This is not calling BreakDebugger since this is called frequently, and +// calling an out-of-line function instead of a noreturn inline macro prevents +// compiler optimizations. #define CHECK(condition) \ - !(condition) ? ::base::debug::BreakDebugger() : EAT_STREAM_PARAMETERS + !(condition) ? LOGGING_CRASH() : EAT_STREAM_PARAMETERS #define PCHECK(condition) CHECK(condition) #define CHECK_OP(name, op, val1, val2) CHECK((val1) op (val2)) -#else +#else // !(OFFICIAL_BUILD && NDEBUG) #if defined(_PREFAST_) && defined(OS_WIN) // Use __analysis_assume to tell the VC++ static analysis engine that @@ -491,8 +496,8 @@ class CheckOpResult { #else // _PREFAST_ // Do as much work as possible out of line to reduce inline code size. -#define CHECK(condition) \ - LAZY_STREAM(logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \ +#define CHECK(condition) \ + LAZY_STREAM(::logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \ !(condition)) #define PCHECK(condition) \ @@ -509,14 +514,38 @@ class CheckOpResult { // CHECK_EQ(2, a); #define CHECK_OP(name, op, val1, val2) \ switch (0) case 0: default: \ - if (logging::CheckOpResult true_if_passed = \ - logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2)) \ + if (::logging::CheckOpResult true_if_passed = \ + ::logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2)) \ ; \ else \ - logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream() + ::logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream() -#endif +#endif // !(OFFICIAL_BUILD && NDEBUG) + +// This formats a value for a failing CHECK_XX statement. Ordinarily, +// it uses the definition for operator<<, with a few special cases below. +template +inline typename std::enable_if< + base::internal::SupportsOstreamOperator::value, + void>::type +MakeCheckOpValueString(std::ostream* os, const T& v) { + (*os) << v; +} + +// We need overloads for enums that don't support operator<<. +// (i.e. scoped enums where no operator<< overload was declared). +template +inline typename std::enable_if< + !base::internal::SupportsOstreamOperator::value && + std::is_enum::value, + void>::type +MakeCheckOpValueString(std::ostream* os, const T& v) { + (*os) << static_cast::type>(v); +} + +// We need an explicit overload for std::nullptr_t. +BASE_EXPORT void MakeCheckOpValueString(std::ostream* os, std::nullptr_t p); // Build the error message string. This is separate from the "Impl" // function template because it is not performance critical and so can @@ -525,7 +554,11 @@ class CheckOpResult { template std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { std::ostringstream ss; - ss << names << " (" << v1 << " vs. " << v2 << ")"; + ss << names << " ("; + MakeCheckOpValueString(&ss, v1); + ss << " vs. "; + MakeCheckOpValueString(&ss, v2); + ss << ")"; std::string* msg = new std::string(ss.str()); return msg; } @@ -556,11 +589,11 @@ std::string* MakeCheckOpString( inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ const char* names) { \ if (v1 op v2) return NULL; \ - else return MakeCheckOpString(v1, v2, names); \ + else return ::logging::MakeCheckOpString(v1, v2, names); \ } \ inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ if (v1 op v2) return NULL; \ - else return MakeCheckOpString(v1, v2, names); \ + else return ::logging::MakeCheckOpString(v1, v2, names); \ } DEFINE_CHECK_OP_IMPL(EQ, ==) DEFINE_CHECK_OP_IMPL(NE, !=) @@ -577,12 +610,6 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2) #define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2) -#if defined(NDEBUG) -#define ENABLE_DLOG 0 -#else -#define ENABLE_DLOG 1 -#endif - #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) #define DCHECK_IS_ON() 0 #else @@ -591,7 +618,7 @@ DEFINE_CHECK_OP_IMPL(GT, > ) // Definitions for DLOG et al. -#if ENABLE_DLOG +#if DCHECK_IS_ON() #define DLOG_IS_ON(severity) LOG_IS_ON(severity) #define DLOG_IF(severity, condition) LOG_IF(severity, condition) @@ -600,12 +627,11 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition) #define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition) -#else // ENABLE_DLOG +#else // DCHECK_IS_ON() -// If ENABLE_DLOG is off, we want to avoid emitting any references to -// |condition| (which may reference a variable defined only if NDEBUG -// is not defined). Contrast this with DCHECK et al., which has -// different behavior. +// If !DCHECK_IS_ON(), we want to avoid emitting any references to |condition| +// (which may reference a variable defined only if DCHECK_IS_ON()). +// Contrast this with DCHECK et al., which has different behavior. #define DLOG_IS_ON(severity) false #define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS @@ -614,19 +640,14 @@ DEFINE_CHECK_OP_IMPL(GT, > ) #define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS #define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS -#endif // ENABLE_DLOG +#endif // DCHECK_IS_ON() -// DEBUG_MODE is for uses like +// DEBUG_MODE is for runtime uses like // if (DEBUG_MODE) foo.CheckThatFoo(); -// instead of -// #ifndef NDEBUG -// foo.CheckThatFoo(); -// #endif +// We tie its state to DCHECK_IS_ON(). // -// We tie its state to ENABLE_DLOG. -enum { DEBUG_MODE = ENABLE_DLOG }; - -#undef ENABLE_DLOG +// For compile-time checks, #if DCHECK_IS_ON() can be used. +enum { DEBUG_MODE = DCHECK_IS_ON() }; #define DLOG(severity) \ LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity)) @@ -693,16 +714,16 @@ const LogSeverity LOG_DCHECK = LOG_INFO; // macro is used in an 'if' clause such as: // if (a == 1) // DCHECK_EQ(2, a); -#define DCHECK_OP(name, op, val1, val2) \ - switch (0) case 0: default: \ - if (logging::CheckOpResult true_if_passed = \ - DCHECK_IS_ON() ? \ - logging::Check##name##Impl((val1), (val2), \ - #val1 " " #op " " #val2) : nullptr) \ - ; \ - else \ - logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \ - true_if_passed.message()).stream() +#define DCHECK_OP(name, op, val1, val2) \ + switch (0) case 0: default: \ + if (::logging::CheckOpResult true_if_passed = \ + DCHECK_IS_ON() ? \ + ::logging::Check##name##Impl((val1), (val2), \ + #val1 " " #op " " #val2) : nullptr) \ + ; \ + else \ + ::logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \ + true_if_passed.message()).stream() // Equality/Inequality checks - compare two values, and log a // LOG_DCHECK message including the two values when the result is not @@ -710,7 +731,7 @@ const LogSeverity LOG_DCHECK = LOG_INFO; // defined. // // You may append to the error message like so: -// DCHECK_NE(1, 2) << ": The world must be ending!"; +// DCHECK_NE(1, 2) << "The world must be ending!"; // // We are very careful to ensure that each argument is evaluated exactly // once, and that anything which is legal to pass as a function argument is @@ -719,9 +740,10 @@ const LogSeverity LOG_DCHECK = LOG_INFO; // for example: // DCHECK_EQ(string("abc")[1], 'b'); // -// WARNING: These may not compile correctly if one of the arguments is a pointer -// and the other is NULL. To work around this, simply static_cast NULL to the -// type of the desired pointer. +// WARNING: These don't compile correctly if one of the arguments is a pointer +// and the other is NULL. In new code, prefer nullptr instead. To +// work around this for C++98, simply static_cast NULL to the type of the +// desired pointer. #define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) #define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) @@ -773,6 +795,9 @@ class BASE_EXPORT LogMessage { std::ostream& stream() { return stream_; } + LogSeverity severity() { return severity_; } + std::string str() { return stream_.str(); } + private: void Init(const char* file, int line); @@ -807,12 +832,6 @@ class BASE_EXPORT LogMessage { DISALLOW_COPY_AND_ASSIGN(LogMessage); }; -// A non-macro interface to the log facility; (useful -// when the logging level is not a compile-time constant). -inline void LogAtLevel(int log_level, const std::string& msg) { - LogMessage(__FILE__, __LINE__, log_level).stream() << msg; -} - // This class is used to explicitly ignore values in the conditional // logging macros. This avoids compiler warnings like "value computed // is not used" and "statement has no effect". @@ -886,12 +905,14 @@ BASE_EXPORT void CloseLogFile(); // Async signal safe logging mechanism. BASE_EXPORT void RawLog(int level, const char* message); -#define RAW_LOG(level, message) logging::RawLog(logging::LOG_ ## level, message) +#define RAW_LOG(level, message) \ + ::logging::RawLog(::logging::LOG_##level, message) -#define RAW_CHECK(condition) \ - do { \ - if (!(condition)) \ - logging::RawLog(logging::LOG_FATAL, "Check failed: " #condition "\n"); \ +#define RAW_CHECK(condition) \ + do { \ + if (!(condition)) \ + ::logging::RawLog(::logging::LOG_FATAL, \ + "Check failed: " #condition "\n"); \ } while (0) #if defined(OS_WIN) diff --git a/security/sandbox/chromium/base/macros.h b/security/sandbox/chromium/base/macros.h index 46ee1dadb474..60c5cbd8cb7f 100644 --- a/security/sandbox/chromium/base/macros.h +++ b/security/sandbox/chromium/base/macros.h @@ -20,11 +20,11 @@ #define DISALLOW_ASSIGN(TypeName) \ void operator=(const TypeName&) = delete -// A macro to disallow the copy constructor and operator= functions -// This should be used in the private: declarations for a class +// A macro to disallow the copy constructor and operator= functions. +// This should be used in the private: declarations for a class. #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete // A macro to disallow all the implicit constructors, namely the // default constructor, copy constructor and operator= functions. @@ -52,7 +52,7 @@ template char (&ArraySizeHelper(T (&array)[N]))[N]; // really sure you don't want to do anything with the return value of a function // that has been marked WARN_UNUSED_RESULT, wrap it with this. Example: // -// scoped_ptr my_var = ...; +// std::unique_ptr my_var = ...; // if (TakeOwnership(my_var.get()) == SUCCESS) // ignore_result(my_var.release()); // diff --git a/security/sandbox/chromium/base/memory/aligned_memory.h b/security/sandbox/chromium/base/memory/aligned_memory.h index bb7bd872cfb0..d8290115dbee 100644 --- a/security/sandbox/chromium/base/memory/aligned_memory.h +++ b/security/sandbox/chromium/base/memory/aligned_memory.h @@ -26,9 +26,9 @@ // // ... later, to release the memory: // AlignedFree(my_array); // -// Or using scoped_ptr: +// Or using unique_ptr: // -// scoped_ptr my_array( +// std::unique_ptr my_array( // static_cast(AlignedAlloc(size, alignment))); #ifndef BASE_MEMORY_ALIGNED_MEMORY_H_ @@ -104,8 +104,8 @@ inline void AlignedFree(void* ptr) { #endif } -// Deleter for use with scoped_ptr. E.g., use as -// scoped_ptr foo; +// Deleter for use with unique_ptr. E.g., use as +// std::unique_ptr foo; struct AlignedFreeDeleter { inline void operator()(void* ptr) const { AlignedFree(ptr); diff --git a/security/sandbox/chromium/base/memory/free_deleter.h b/security/sandbox/chromium/base/memory/free_deleter.h new file mode 100644 index 000000000000..560411886582 --- /dev/null +++ b/security/sandbox/chromium/base/memory/free_deleter.h @@ -0,0 +1,25 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_FREE_DELETER_H_ +#define BASE_MEMORY_FREE_DELETER_H_ + +#include + +namespace base { + +// Function object which invokes 'free' on its parameter, which must be +// a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr: +// +// std::unique_ptr foo_ptr( +// static_cast(malloc(sizeof(int)))); +struct FreeDeleter { + inline void operator()(void* ptr) const { + free(ptr); + } +}; + +} // namespace base + +#endif // BASE_MEMORY_FREE_DELETER_H_ diff --git a/security/sandbox/chromium/base/memory/ptr_util.h b/security/sandbox/chromium/base/memory/ptr_util.h new file mode 100644 index 000000000000..8747ac946332 --- /dev/null +++ b/security/sandbox/chromium/base/memory/ptr_util.h @@ -0,0 +1,74 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_PTR_UTIL_H_ +#define BASE_MEMORY_PTR_UTIL_H_ + +#include +#include + +namespace base { + +// Helper to transfer ownership of a raw pointer to a std::unique_ptr. +// Note that std::unique_ptr has very different semantics from +// std::unique_ptr: do not use this helper for array allocations. +template +std::unique_ptr WrapUnique(T* ptr) { + return std::unique_ptr(ptr); +} + +namespace internal { + +template +struct MakeUniqueResult { + using Scalar = std::unique_ptr; +}; + +template +struct MakeUniqueResult { + using Array = std::unique_ptr; +}; + +template +struct MakeUniqueResult { + using Invalid = void; +}; + +} // namespace internal + +// Helper to construct an object wrapped in a std::unique_ptr. This is an +// implementation of C++14's std::make_unique that can be used in Chrome. +// +// MakeUnique(args) should be preferred over WrapUnique(new T(args)): bare +// calls to `new` should be treated with scrutiny. +// +// Usage: +// // ptr is a std::unique_ptr +// auto ptr = MakeUnique("hello world!"); +// +// // arr is a std::unique_ptr +// auto arr = MakeUnique(5); + +// Overload for non-array types. Arguments are forwarded to T's constructor. +template +typename internal::MakeUniqueResult::Scalar MakeUnique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +// Overload for array types of unknown bound, e.g. T[]. The array is allocated +// with `new T[n]()` and value-initialized: note that this is distinct from +// `new T[n]`, which default-initializes. +template +typename internal::MakeUniqueResult::Array MakeUnique(size_t size) { + return std::unique_ptr(new typename std::remove_extent::type[size]()); +} + +// Overload to reject array types of known bound, e.g. T[n]. +template +typename internal::MakeUniqueResult::Invalid MakeUnique(Args&&... args) = + delete; + +} // namespace base + +#endif // BASE_MEMORY_PTR_UTIL_H_ diff --git a/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h b/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h index 09f982b12945..5dbc183acdf3 100644 --- a/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h +++ b/security/sandbox/chromium/base/memory/raw_scoped_refptr_mismatch_checker.h @@ -5,10 +5,10 @@ #ifndef BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ #define BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#include +#include + #include "base/memory/ref_counted.h" -#include "base/template_util.h" -#include "base/tuple.h" -#include "build/build_config.h" // It is dangerous to post a task with a T* argument where T is a subtype of // RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the @@ -25,20 +25,14 @@ namespace internal { template struct NeedsScopedRefptrButGetsRawPtr { -#if defined(OS_WIN) - enum { - value = base::false_type::value - }; -#else enum { // Human readable translation: you needed to be a scoped_refptr if you are a // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) // type. - value = (is_pointer::value && - (is_convertible::value || - is_convertible::value)) + value = (std::is_pointer::value && + (std::is_convertible::value || + std::is_convertible::value)) }; -#endif }; template @@ -47,14 +41,14 @@ struct ParamsUseScopedRefptrCorrectly { }; template <> -struct ParamsUseScopedRefptrCorrectly> { +struct ParamsUseScopedRefptrCorrectly> { enum { value = 1 }; }; template -struct ParamsUseScopedRefptrCorrectly> { +struct ParamsUseScopedRefptrCorrectly> { enum { value = !NeedsScopedRefptrButGetsRawPtr::value && - ParamsUseScopedRefptrCorrectly>::value }; + ParamsUseScopedRefptrCorrectly>::value }; }; } // namespace internal diff --git a/security/sandbox/chromium/base/memory/ref_counted.cc b/security/sandbox/chromium/base/memory/ref_counted.cc index f5924d0fe76e..cd6181b14734 100644 --- a/security/sandbox/chromium/base/memory/ref_counted.cc +++ b/security/sandbox/chromium/base/memory/ref_counted.cc @@ -15,32 +15,32 @@ bool RefCountedThreadSafeBase::HasOneRef() const { } RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) { -#ifndef NDEBUG +#if DCHECK_IS_ON() in_dtor_ = false; #endif } RefCountedThreadSafeBase::~RefCountedThreadSafeBase() { -#ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " "calling Release()"; #endif } void RefCountedThreadSafeBase::AddRef() const { -#ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(!in_dtor_); #endif AtomicRefCountInc(&ref_count_); } bool RefCountedThreadSafeBase::Release() const { -#ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(!in_dtor_); DCHECK(!AtomicRefCountIsZero(&ref_count_)); #endif if (!AtomicRefCountDec(&ref_count_)) { -#ifndef NDEBUG +#if DCHECK_IS_ON() in_dtor_ = true; #endif return true; diff --git a/security/sandbox/chromium/base/memory/ref_counted.h b/security/sandbox/chromium/base/memory/ref_counted.h index a1c12696990d..960c8a284531 100644 --- a/security/sandbox/chromium/base/memory/ref_counted.h +++ b/security/sandbox/chromium/base/memory/ref_counted.h @@ -5,16 +5,17 @@ #ifndef BASE_MEMORY_REF_COUNTED_H_ #define BASE_MEMORY_REF_COUNTED_H_ +#include + #include #include +#include #include "base/atomic_ref_count.h" #include "base/base_export.h" #include "base/compiler_specific.h" -#include "base/macros.h" -#ifndef NDEBUG #include "base/logging.h" -#endif +#include "base/macros.h" #include "base/threading/thread_collision_warner.h" #include "build/build_config.h" @@ -29,16 +30,16 @@ class BASE_EXPORT RefCountedBase { protected: RefCountedBase() : ref_count_(0) - #ifndef NDEBUG - , in_dtor_(false) - #endif - { +#if DCHECK_IS_ON() + , in_dtor_(false) +#endif + { } ~RefCountedBase() { - #ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; - #endif +#endif } @@ -47,9 +48,9 @@ class BASE_EXPORT RefCountedBase { // Current thread books the critical section "AddRelease" // without release it. // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); - #ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(!in_dtor_); - #endif +#endif ++ref_count_; } @@ -59,21 +60,21 @@ class BASE_EXPORT RefCountedBase { // Current thread books the critical section "AddRelease" // without release it. // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); - #ifndef NDEBUG +#if DCHECK_IS_ON() DCHECK(!in_dtor_); - #endif +#endif if (--ref_count_ == 0) { - #ifndef NDEBUG +#if DCHECK_IS_ON() in_dtor_ = true; - #endif +#endif return true; } return false; } private: - mutable int ref_count_; -#ifndef NDEBUG + mutable size_t ref_count_; +#if DCHECK_IS_ON() mutable bool in_dtor_; #endif @@ -97,7 +98,7 @@ class BASE_EXPORT RefCountedThreadSafeBase { private: mutable AtomicRefCount ref_count_; -#ifndef NDEBUG +#if DCHECK_IS_ON() mutable bool in_dtor_; #endif @@ -108,7 +109,7 @@ class BASE_EXPORT RefCountedThreadSafeBase { // // A base class for reference counted classes. Otherwise, known as a cheap -// knock-off of WebKit's RefCounted class. To use this guy just extend your +// knock-off of WebKit's RefCounted class. To use this, just extend your // class from it like so: // // class MyFoo : public base::RefCounted { @@ -123,7 +124,7 @@ class BASE_EXPORT RefCountedThreadSafeBase { template class RefCounted : public subtle::RefCountedBase { public: - RefCounted() {} + RefCounted() = default; void AddRef() const { subtle::RefCountedBase::AddRef(); @@ -136,7 +137,7 @@ class RefCounted : public subtle::RefCountedBase { } protected: - ~RefCounted() {} + ~RefCounted() = default; private: DISALLOW_COPY_AND_ASSIGN(RefCounted); @@ -173,7 +174,7 @@ struct DefaultRefCountedThreadSafeTraits { template > class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { public: - RefCountedThreadSafe() {} + RefCountedThreadSafe() = default; void AddRef() const { subtle::RefCountedThreadSafeBase::AddRef(); @@ -186,7 +187,7 @@ class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { } protected: - ~RefCountedThreadSafe() {} + ~RefCountedThreadSafe() = default; private: friend struct DefaultRefCountedThreadSafeTraits; @@ -210,7 +211,7 @@ class RefCountedData private: friend class base::RefCountedThreadSafe >; - ~RefCountedData() {} + ~RefCountedData() = default; }; } // namespace base @@ -234,7 +235,7 @@ class RefCountedData // void some_other_function() { // scoped_refptr foo = new MyFoo(); // ... -// foo = NULL; // explicitly releases |foo| +// foo = nullptr; // explicitly releases |foo| // ... // if (foo) // foo->Method(param); @@ -249,7 +250,7 @@ class RefCountedData // scoped_refptr b; // // b.swap(a); -// // now, |b| references the MyFoo object, and |a| references NULL. +// // now, |b| references the MyFoo object, and |a| references nullptr. // } // // To make both |a| and |b| in the above example reference the same MyFoo @@ -268,8 +269,7 @@ class scoped_refptr { public: typedef T element_type; - scoped_refptr() : ptr_(NULL) { - } + scoped_refptr() {} scoped_refptr(T* p) : ptr_(p) { if (ptr_) @@ -283,7 +283,9 @@ class scoped_refptr { } // Copy conversion constructor. - template + template ::value>::type> scoped_refptr(const scoped_refptr& r) : ptr_(r.get()) { if (ptr_) AddRef(ptr_); @@ -294,7 +296,9 @@ class scoped_refptr { scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } // Move conversion constructor. - template + template ::value>::type> scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; } @@ -307,12 +311,12 @@ class scoped_refptr { T* get() const { return ptr_; } T& operator*() const { - assert(ptr_ != NULL); + assert(ptr_ != nullptr); return *ptr_; } T* operator->() const { - assert(ptr_ != NULL); + assert(ptr_ != nullptr); return ptr_; } @@ -357,20 +361,7 @@ class scoped_refptr { swap(&r.ptr_); } - private: - template friend class scoped_refptr; - - // Allow scoped_refptr to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - // - // Note that this trick is only safe when the == and != operators - // are declared explicitly, as otherwise "refptr1 == refptr2" - // will compile but do the wrong thing (i.e., convert to Testable - // and then do the comparison). - typedef T* scoped_refptr::*Testable; - - public: - operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : nullptr; } + explicit operator bool() const { return ptr_ != nullptr; } template bool operator==(const scoped_refptr& rhs) const { @@ -388,9 +379,13 @@ class scoped_refptr { } protected: - T* ptr_; + T* ptr_ = nullptr; private: + // Friend required for move constructors that set r.ptr_ to null. + template + friend class scoped_refptr; + // Non-inline helpers to allow: // class Opaque; // extern template class scoped_refptr; @@ -399,11 +394,13 @@ class scoped_refptr { static void Release(T* ptr); }; +// static template void scoped_refptr::AddRef(T* ptr) { ptr->AddRef(); } +// static template void scoped_refptr::Release(T* ptr) { ptr->Release(); @@ -416,8 +413,6 @@ scoped_refptr make_scoped_refptr(T* t) { return scoped_refptr(t); } -// Temporary operator overloads to facilitate the transition. See -// https://crbug.com/110610. template bool operator==(const scoped_refptr& lhs, const U* rhs) { return lhs.get() == rhs; @@ -428,6 +423,16 @@ bool operator==(const T* lhs, const scoped_refptr& rhs) { return lhs == rhs.get(); } +template +bool operator==(const scoped_refptr& lhs, std::nullptr_t null) { + return !static_cast(lhs); +} + +template +bool operator==(std::nullptr_t null, const scoped_refptr& rhs) { + return !static_cast(rhs); +} + template bool operator!=(const scoped_refptr& lhs, const U* rhs) { return !operator==(lhs, rhs); @@ -438,6 +443,16 @@ bool operator!=(const T* lhs, const scoped_refptr& rhs) { return !operator==(lhs, rhs); } +template +bool operator!=(const scoped_refptr& lhs, std::nullptr_t null) { + return !operator==(lhs, null); +} + +template +bool operator!=(std::nullptr_t null, const scoped_refptr& rhs) { + return !operator==(null, rhs); +} + template std::ostream& operator<<(std::ostream& out, const scoped_refptr& p) { return out << p.get(); diff --git a/security/sandbox/chromium/base/memory/scoped_ptr.h b/security/sandbox/chromium/base/memory/scoped_ptr.h deleted file mode 100644 index 282a014869b6..000000000000 --- a/security/sandbox/chromium/base/memory/scoped_ptr.h +++ /dev/null @@ -1,607 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Scopers help you manage ownership of a pointer, helping you easily manage a -// pointer within a scope, and automatically destroying the pointer at the end -// of a scope. There are two main classes you will use, which correspond to the -// operators new/delete and new[]/delete[]. -// -// Example usage (scoped_ptr): -// { -// scoped_ptr foo(new Foo("wee")); -// } // foo goes out of scope, releasing the pointer with it. -// -// { -// scoped_ptr foo; // No pointer managed. -// foo.reset(new Foo("wee")); // Now a pointer is managed. -// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. -// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. -// foo->Method(); // Foo::Method() called. -// foo.get()->Method(); // Foo::Method() called. -// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer -// // manages a pointer. -// foo.reset(new Foo("wee4")); // foo manages a pointer again. -// foo.reset(); // Foo("wee4") destroyed, foo no longer -// // manages a pointer. -// } // foo wasn't managing a pointer, so nothing was destroyed. -// -// Example usage (scoped_ptr): -// { -// scoped_ptr foo(new Foo[100]); -// foo.get()->Method(); // Foo::Method on the 0th element. -// foo[10].Method(); // Foo::Method on the 10th element. -// } -// -// These scopers also implement part of the functionality of C++11 unique_ptr -// in that they are "movable but not copyable." You can use the scopers in -// the parameter and return types of functions to signify ownership transfer -// in to and out of a function. When calling a function that has a scoper -// as the argument type, it must be called with an rvalue of a scoper, which -// can be created by using std::move(), or the result of another function that -// generates a temporary; passing by copy will NOT work. Here is an example -// using scoped_ptr: -// -// void TakesOwnership(scoped_ptr arg) { -// // Do something with arg. -// } -// scoped_ptr CreateFoo() { -// // No need for calling std::move() for returning a move-only value, or -// // when you already have an rvalue as we do here. -// return scoped_ptr(new Foo("new")); -// } -// scoped_ptr PassThru(scoped_ptr arg) { -// return arg; -// } -// -// { -// scoped_ptr ptr(new Foo("yay")); // ptr manages Foo("yay"). -// TakesOwnership(std::move(ptr)); // ptr no longer owns Foo("yay"). -// scoped_ptr ptr2 = CreateFoo(); // ptr2 owns the return Foo. -// scoped_ptr ptr3 = // ptr3 now owns what was in ptr2. -// PassThru(std::move(ptr2)); // ptr2 is correspondingly nullptr. -// } -// -// Notice that if you do not call std::move() when returning from PassThru(), or -// when invoking TakesOwnership(), the code will not compile because scopers -// are not copyable; they only implement move semantics which require calling -// the std::move() function to signify a destructive transfer of state. -// CreateFoo() is different though because we are constructing a temporary on -// the return line and thus can avoid needing to call std::move(). -// -// The conversion move-constructor properly handles upcast in initialization, -// i.e. you can use a scoped_ptr to initialize a scoped_ptr: -// -// scoped_ptr foo(new Foo()); -// scoped_ptr parent(std::move(foo)); - -#ifndef BASE_MEMORY_SCOPED_PTR_H_ -#define BASE_MEMORY_SCOPED_PTR_H_ - -// This is an implementation designed to match the anticipated future TR2 -// implementation of the scoped_ptr class. - -#include -#include -#include - -#include -#include -#include -#include - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/move.h" -#include "base/template_util.h" - -namespace base { - -namespace subtle { -class RefCountedBase; -class RefCountedThreadSafeBase; -} // namespace subtle - -// Function object which invokes 'free' on its parameter, which must be -// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: -// -// scoped_ptr foo_ptr( -// static_cast(malloc(sizeof(int)))); -struct FreeDeleter { - inline void operator()(void* ptr) const { - free(ptr); - } -}; - -namespace internal { - -template struct IsNotRefCounted { - enum { - value = !base::is_convertible::value && - !base::is_convertible:: - value - }; -}; - -// Minimal implementation of the core logic of scoped_ptr, suitable for -// reuse in both scoped_ptr and its specializations. -template -class scoped_ptr_impl { - public: - explicit scoped_ptr_impl(T* p) : data_(p) {} - - // Initializer for deleters that have data parameters. - scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} - - // Templated constructor that destructively takes the value from another - // scoped_ptr_impl. - template - scoped_ptr_impl(scoped_ptr_impl* other) - : data_(other->release(), other->get_deleter()) { - // We do not support move-only deleters. We could modify our move - // emulation to have base::subtle::move() and base::subtle::forward() - // functions that are imperfect emulations of their C++11 equivalents, - // but until there's a requirement, just assume deleters are copyable. - } - - template - void TakeState(scoped_ptr_impl* other) { - // See comment in templated constructor above regarding lack of support - // for move-only deleters. - reset(other->release()); - get_deleter() = other->get_deleter(); - } - - ~scoped_ptr_impl() { - // Match libc++, which calls reset() in its destructor. - // Use nullptr as the new value for three reasons: - // 1. libc++ does it. - // 2. Avoids infinitely recursing into destructors if two classes are owned - // in a reference cycle (see ScopedPtrTest.ReferenceCycle). - // 3. If |this| is accessed in the future, in a use-after-free bug, attempts - // to dereference |this|'s pointer should cause either a failure or a - // segfault closer to the problem. If |this| wasn't reset to nullptr, - // the access would cause the deleted memory to be read or written - // leading to other more subtle issues. - reset(nullptr); - } - - void reset(T* p) { - // Match C++11's definition of unique_ptr::reset(), which requires changing - // the pointer before invoking the deleter on the old pointer. This prevents - // |this| from being accessed after the deleter is run, which may destroy - // |this|. - T* old = data_.ptr; - data_.ptr = p; - if (old != nullptr) - static_cast(data_)(old); - } - - T* get() const { return data_.ptr; } - - D& get_deleter() { return data_; } - const D& get_deleter() const { return data_; } - - void swap(scoped_ptr_impl& p2) { - // Standard swap idiom: 'using std::swap' ensures that std::swap is - // present in the overload set, but we call swap unqualified so that - // any more-specific overloads can be used, if available. - using std::swap; - swap(static_cast(data_), static_cast(p2.data_)); - swap(data_.ptr, p2.data_.ptr); - } - - T* release() { - T* old_ptr = data_.ptr; - data_.ptr = nullptr; - return old_ptr; - } - - private: - // Needed to allow type-converting constructor. - template friend class scoped_ptr_impl; - - // Use the empty base class optimization to allow us to have a D - // member, while avoiding any space overhead for it when D is an - // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good - // discussion of this technique. - struct Data : public D { - explicit Data(T* ptr_in) : ptr(ptr_in) {} - Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} - T* ptr; - }; - - Data data_; - - DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl); -}; - -} // namespace internal - -} // namespace base - -// A scoped_ptr is like a T*, except that the destructor of scoped_ptr -// automatically deletes the pointer it holds (if any). -// That is, scoped_ptr owns the T object that it points to. -// Like a T*, a scoped_ptr may hold either nullptr or a pointer to a T -// object. Also like T*, scoped_ptr is thread-compatible, and once you -// dereference it, you get the thread safety guarantees of T. -// -// The size of scoped_ptr is small. On most compilers, when using the -// std::default_delete, sizeof(scoped_ptr) == sizeof(T*). Custom deleters -// will increase the size proportional to whatever state they need to have. See -// comments inside scoped_ptr_impl<> for details. -// -// Current implementation targets having a strict subset of C++11's -// unique_ptr<> features. Known deficiencies include not supporting move-only -// deleteres, function pointers as deleters, and deleters with reference -// types. -template > -class scoped_ptr { - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr) - - static_assert(!std::is_array::value, - "scoped_ptr doesn't support array with size"); - static_assert(base::internal::IsNotRefCounted::value, - "T is a refcounted type and needs a scoped_refptr"); - - public: - // The element and deleter types. - using element_type = T; - using deleter_type = D; - - // Constructor. Defaults to initializing with nullptr. - scoped_ptr() : impl_(nullptr) {} - - // Constructor. Takes ownership of p. - explicit scoped_ptr(element_type* p) : impl_(p) {} - - // Constructor. Allows initialization of a stateful deleter. - scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} - - // Constructor. Allows construction from a nullptr. - scoped_ptr(std::nullptr_t) : impl_(nullptr) {} - - // Move constructor. - // - // IMPLEMENTATION NOTE: Clang requires a move constructor to be defined (and - // not just the conversion constructor) in order to warn on pessimizing moves. - // The requirements for the move constructor are specified in C++11 - // 20.7.1.2.1.15-17, which has some subtleties around reference deleters. As - // we don't support reference (or move-only) deleters, the post conditions are - // trivially true: we always copy construct the deleter from other's deleter. - scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} - - // Conversion constructor. Allows construction from a scoped_ptr rvalue for a - // convertible type and deleter. - // - // IMPLEMENTATION NOTE: C++ 20.7.1.2.1.19 requires this constructor to only - // participate in overload resolution if all the following are true: - // - U is implicitly convertible to T: this is important for 2 reasons: - // 1. So type traits don't incorrectly return true, e.g. - // std::is_convertible, scoped_ptr>::value - // should be false. - // 2. To make sure code like this compiles: - // void F(scoped_ptr); - // void F(scoped_ptr); - // // Ambiguous since both conversion constructors match. - // F(scoped_ptr()); - // - U is not an array type: to prevent conversions from scoped_ptr to - // scoped_ptr. - // - D is a reference type and E is the same type, or D is not a reference - // type and E is implicitly convertible to D: again, we don't support - // reference deleters, so we only worry about the latter requirement. - template ::value && - std::is_convertible::value && - std::is_convertible::value>::type* = - nullptr> - scoped_ptr(scoped_ptr&& other) - : impl_(&other.impl_) {} - - // operator=. - // - // IMPLEMENTATION NOTE: Unlike the move constructor, Clang does not appear to - // require a move assignment operator to trigger the pessimizing move warning: - // in this case, the warning triggers when moving a temporary. For consistency - // with the move constructor, we define it anyway. C++11 20.7.1.2.3.1-3 - // defines several requirements around this: like the move constructor, the - // requirements are simplified by the fact that we don't support move-only or - // reference deleters. - scoped_ptr& operator=(scoped_ptr&& rhs) { - impl_.TakeState(&rhs.impl_); - return *this; - } - - // operator=. Allows assignment from a scoped_ptr rvalue for a convertible - // type and deleter. - // - // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from - // the normal move assignment operator. C++11 20.7.1.2.3.4-7 contains the - // requirement for this operator, but like the conversion constructor, the - // requirements are greatly simplified by not supporting move-only or - // reference deleters. - template ::value && - std::is_convertible::value && - // Note that this really should be - // std::is_assignable, but - // appears to be missing this on some - // platforms. This is close enough (though - // it's not the same). - std::is_convertible::value>::type* = - nullptr> - scoped_ptr& operator=(scoped_ptr&& rhs) { - impl_.TakeState(&rhs.impl_); - return *this; - } - - // operator=. Allows assignment from a nullptr. Deletes the currently owned - // object, if any. - scoped_ptr& operator=(std::nullptr_t) { - reset(); - return *this; - } - - // Reset. Deletes the currently owned object, if any. - // Then takes ownership of a new object, if given. - void reset(element_type* p = nullptr) { impl_.reset(p); } - - // Accessors to get the owned object. - // operator* and operator-> will assert() if there is no current object. - element_type& operator*() const { - assert(impl_.get() != nullptr); - return *impl_.get(); - } - element_type* operator->() const { - assert(impl_.get() != nullptr); - return impl_.get(); - } - element_type* get() const { return impl_.get(); } - - // Access to the deleter. - deleter_type& get_deleter() { return impl_.get_deleter(); } - const deleter_type& get_deleter() const { return impl_.get_deleter(); } - - // Allow scoped_ptr to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - // - // Note that this trick is only safe when the == and != operators - // are declared explicitly, as otherwise "scoped_ptr1 == - // scoped_ptr2" will compile but do the wrong thing (i.e., convert - // to Testable and then do the comparison). - private: - typedef base::internal::scoped_ptr_impl - scoped_ptr::*Testable; - - public: - operator Testable() const { - return impl_.get() ? &scoped_ptr::impl_ : nullptr; - } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - impl_.swap(p2.impl_); - } - - // Release a pointer. - // The return value is the current pointer held by this object. If this object - // holds a nullptr, the return value is nullptr. After this operation, this - // object will hold a nullptr, and will not own the object any more. - element_type* release() WARN_UNUSED_RESULT { - return impl_.release(); - } - - private: - // Needed to reach into |impl_| in the constructor. - template friend class scoped_ptr; - base::internal::scoped_ptr_impl impl_; - - // Forbidden for API compatibility with std::unique_ptr. - explicit scoped_ptr(int disallow_construction_from_null); -}; - -template -class scoped_ptr { - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(scoped_ptr) - - public: - // The element and deleter types. - using element_type = T; - using deleter_type = D; - - // Constructor. Defaults to initializing with nullptr. - scoped_ptr() : impl_(nullptr) {} - - // Constructor. Stores the given array. Note that the argument's type - // must exactly match T*. In particular: - // - it cannot be a pointer to a type derived from T, because it is - // inherently unsafe in the general case to access an array through a - // pointer whose dynamic type does not match its static type (eg., if - // T and the derived types had different sizes access would be - // incorrectly calculated). Deletion is also always undefined - // (C++98 [expr.delete]p3). If you're doing this, fix your code. - // - it cannot be const-qualified differently from T per unique_ptr spec - // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting - // to work around this may use const_cast(). - explicit scoped_ptr(element_type* array) : impl_(array) {} - - // Constructor. Allows construction from a nullptr. - scoped_ptr(std::nullptr_t) : impl_(nullptr) {} - - // Constructor. Allows construction from a scoped_ptr rvalue. - scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {} - - // operator=. Allows assignment from a scoped_ptr rvalue. - scoped_ptr& operator=(scoped_ptr&& rhs) { - impl_.TakeState(&rhs.impl_); - return *this; - } - - // operator=. Allows assignment from a nullptr. Deletes the currently owned - // array, if any. - scoped_ptr& operator=(std::nullptr_t) { - reset(); - return *this; - } - - // Reset. Deletes the currently owned array, if any. - // Then takes ownership of a new object, if given. - void reset(element_type* array = nullptr) { impl_.reset(array); } - - // Accessors to get the owned array. - element_type& operator[](size_t i) const { - assert(impl_.get() != nullptr); - return impl_.get()[i]; - } - element_type* get() const { return impl_.get(); } - - // Access to the deleter. - deleter_type& get_deleter() { return impl_.get_deleter(); } - const deleter_type& get_deleter() const { return impl_.get_deleter(); } - - // Allow scoped_ptr to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - private: - typedef base::internal::scoped_ptr_impl - scoped_ptr::*Testable; - - public: - operator Testable() const { - return impl_.get() ? &scoped_ptr::impl_ : nullptr; - } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - impl_.swap(p2.impl_); - } - - // Release a pointer. - // The return value is the current pointer held by this object. If this object - // holds a nullptr, the return value is nullptr. After this operation, this - // object will hold a nullptr, and will not own the object any more. - element_type* release() WARN_UNUSED_RESULT { - return impl_.release(); - } - - private: - // Force element_type to be a complete type. - enum { type_must_be_complete = sizeof(element_type) }; - - // Actually hold the data. - base::internal::scoped_ptr_impl impl_; - - // Disable initialization from any type other than element_type*, by - // providing a constructor that matches such an initialization, but is - // private and has no definition. This is disabled because it is not safe to - // call delete[] on an array whose static type does not match its dynamic - // type. - template explicit scoped_ptr(U* array); - explicit scoped_ptr(int disallow_construction_from_null); - - // Disable reset() from any type other than element_type*, for the same - // reasons as the constructor above. - template void reset(U* array); - void reset(int disallow_reset_from_null); -}; - -// Free functions -template -void swap(scoped_ptr& p1, scoped_ptr& p2) { - p1.swap(p2); -} - -template -bool operator==(const scoped_ptr& p1, const scoped_ptr& p2) { - return p1.get() == p2.get(); -} -template -bool operator==(const scoped_ptr& p, std::nullptr_t) { - return p.get() == nullptr; -} -template -bool operator==(std::nullptr_t, const scoped_ptr& p) { - return p.get() == nullptr; -} - -template -bool operator!=(const scoped_ptr& p1, const scoped_ptr& p2) { - return !(p1 == p2); -} -template -bool operator!=(const scoped_ptr& p, std::nullptr_t) { - return !(p == nullptr); -} -template -bool operator!=(std::nullptr_t, const scoped_ptr& p) { - return !(p == nullptr); -} - -template -bool operator<(const scoped_ptr& p1, const scoped_ptr& p2) { - return p1.get() < p2.get(); -} -template -bool operator<(const scoped_ptr& p, std::nullptr_t) { - return p.get() < nullptr; -} -template -bool operator<(std::nullptr_t, const scoped_ptr& p) { - return nullptr < p.get(); -} - -template -bool operator>(const scoped_ptr& p1, const scoped_ptr& p2) { - return p2 < p1; -} -template -bool operator>(const scoped_ptr& p, std::nullptr_t) { - return nullptr < p; -} -template -bool operator>(std::nullptr_t, const scoped_ptr& p) { - return p < nullptr; -} - -template -bool operator<=(const scoped_ptr& p1, const scoped_ptr& p2) { - return !(p1 > p2); -} -template -bool operator<=(const scoped_ptr& p, std::nullptr_t) { - return !(p > nullptr); -} -template -bool operator<=(std::nullptr_t, const scoped_ptr& p) { - return !(nullptr > p); -} - -template -bool operator>=(const scoped_ptr& p1, const scoped_ptr& p2) { - return !(p1 < p2); -} -template -bool operator>=(const scoped_ptr& p, std::nullptr_t) { - return !(p < nullptr); -} -template -bool operator>=(std::nullptr_t, const scoped_ptr& p) { - return !(nullptr < p); -} - -// A function to convert T* into scoped_ptr -// Doing e.g. make_scoped_ptr(new FooBarBaz(arg)) is a shorter notation -// for scoped_ptr >(new FooBarBaz(arg)) -template -scoped_ptr make_scoped_ptr(T* ptr) { - return scoped_ptr(ptr); -} - -template -std::ostream& operator<<(std::ostream& out, const scoped_ptr& p) { - return out << p.get(); -} - -#endif // BASE_MEMORY_SCOPED_PTR_H_ diff --git a/security/sandbox/chromium/base/memory/shared_memory.h b/security/sandbox/chromium/base/memory/shared_memory.h new file mode 100644 index 000000000000..f68c861647c8 --- /dev/null +++ b/security/sandbox/chromium/base/memory/shared_memory.h @@ -0,0 +1,292 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_SHARED_MEMORY_H_ +#define BASE_MEMORY_SHARED_MEMORY_H_ + +#include + +#include + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/memory/shared_memory_handle.h" +#include "base/process/process_handle.h" +#include "build/build_config.h" + +#if defined(OS_POSIX) +#include +#include +#include +#include "base/file_descriptor_posix.h" +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" +#endif + +#if defined(OS_WIN) +#include "base/win/scoped_handle.h" +#endif + +namespace base { + +class FilePath; + +// Options for creating a shared memory object. +struct BASE_EXPORT SharedMemoryCreateOptions { +#if !(defined(OS_MACOSX) && !defined(OS_IOS)) + // DEPRECATED (crbug.com/345734): + // If NULL, the object is anonymous. This pointer is owned by the caller + // and must live through the call to Create(). + const std::string* name_deprecated = nullptr; + + // DEPRECATED (crbug.com/345734): + // If true, and the shared memory already exists, Create() will open the + // existing shared memory and ignore the size parameter. If false, + // shared memory must not exist. This flag is meaningless unless + // name_deprecated is non-NULL. + bool open_existing_deprecated = false; +#endif // !(defined(OS_MACOSX) && !defined(OS_IOS)) + + // Size of the shared memory object to be created. + // When opening an existing object, this has no effect. + size_t size = 0; + + // If true, mappings might need to be made executable later. + bool executable = false; + + // If true, the file can be shared read-only to a process. + bool share_read_only = false; +}; + +// Platform abstraction for shared memory. Provides a C++ wrapper +// around the OS primitive for a memory mapped file. +class BASE_EXPORT SharedMemory { + public: + SharedMemory(); + +#if defined(OS_WIN) + // Similar to the default constructor, except that this allows for + // calling LockDeprecated() to acquire the named mutex before either Create or + // Open are called on Windows. + explicit SharedMemory(const std::wstring& name); +#endif + + // Create a new SharedMemory object from an existing, open + // shared memory file. + // + // WARNING: This does not reduce the OS-level permissions on the handle; it + // only affects how the SharedMemory will be mmapped. Use + // ShareReadOnlyToProcess to drop permissions. TODO(jln,jyasskin): DCHECK + // that |read_only| matches the permissions of the handle. + SharedMemory(const SharedMemoryHandle& handle, bool read_only); + + // Closes any open files. + ~SharedMemory(); + + // Return true iff the given handle is valid (i.e. not the distingished + // invalid value; NULL for a HANDLE and -1 for a file descriptor) + static bool IsHandleValid(const SharedMemoryHandle& handle); + + // Returns invalid handle (see comment above for exact definition). + static SharedMemoryHandle NULLHandle(); + + // Closes a shared memory handle. + static void CloseHandle(const SharedMemoryHandle& handle); + + // Returns the maximum number of handles that can be open at once per process. + static size_t GetHandleLimit(); + + // Duplicates The underlying OS primitive. Returns NULLHandle() on failure. + // The caller is responsible for destroying the duplicated OS primitive. + static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle); + +#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS)) + // This method requires that the SharedMemoryHandle is backed by a POSIX fd. + static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle); +#endif + +#if defined(OS_POSIX) && !defined(OS_ANDROID) + // Gets the size of the shared memory region referred to by |handle|. + // Returns false on a failure to determine the size. On success, populates the + // output variable |size|. + static bool GetSizeFromSharedMemoryHandle(const SharedMemoryHandle& handle, + size_t* size); +#endif // defined(OS_POSIX) && !defined(OS_ANDROID) + + // Creates a shared memory object as described by the options struct. + // Returns true on success and false on failure. + bool Create(const SharedMemoryCreateOptions& options); + + // Creates and maps an anonymous shared memory segment of size size. + // Returns true on success and false on failure. + bool CreateAndMapAnonymous(size_t size); + + // Creates an anonymous shared memory segment of size size. + // Returns true on success and false on failure. + bool CreateAnonymous(size_t size) { + SharedMemoryCreateOptions options; + options.size = size; + return Create(options); + } + +#if !defined(OS_MACOSX) || defined(OS_IOS) + // DEPRECATED (crbug.com/345734): + // Creates or opens a shared memory segment based on a name. + // If open_existing is true, and the shared memory already exists, + // opens the existing shared memory and ignores the size parameter. + // If open_existing is false, shared memory must not exist. + // size is the size of the block to be created. + // Returns true on success, false on failure. + bool CreateNamedDeprecated( + const std::string& name, bool open_existing, size_t size) { + SharedMemoryCreateOptions options; + options.name_deprecated = &name; + options.open_existing_deprecated = open_existing; + options.size = size; + return Create(options); + } + + // Deletes resources associated with a shared memory segment based on name. + // Not all platforms require this call. + bool Delete(const std::string& name); + + // Opens a shared memory segment based on a name. + // If read_only is true, opens for read-only access. + // Returns true on success, false on failure. + bool Open(const std::string& name, bool read_only); +#endif // !defined(OS_MACOSX) || defined(OS_IOS) + + // Maps the shared memory into the caller's address space. + // Returns true on success, false otherwise. The memory address + // is accessed via the memory() accessor. The mapped address is guaranteed to + // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail + // if this object is currently mapped. + bool Map(size_t bytes) { + return MapAt(0, bytes); + } + + // Same as above, but with |offset| to specify from begining of the shared + // memory block to map. + // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|. + bool MapAt(off_t offset, size_t bytes); + enum { MAP_MINIMUM_ALIGNMENT = 32 }; + + // Unmaps the shared memory from the caller's address space. + // Returns true if successful; returns false on error or if the + // memory is not mapped. + bool Unmap(); + + // The size requested when the map is first created. + size_t requested_size() const { return requested_size_; } + + // The actual size of the mapped memory (may be larger than requested). + size_t mapped_size() const { return mapped_size_; } + + // Gets a pointer to the opened memory space if it has been + // Mapped via Map(). Returns NULL if it is not mapped. + void* memory() const { return memory_; } + + // Returns the underlying OS handle for this segment. + // Use of this handle for anything other than an opaque + // identifier is not portable. + SharedMemoryHandle handle() const; + + // Returns the underlying OS handle for this segment. The caller also gets + // ownership of the handle. This is logically equivalent to: + // SharedMemoryHandle dup = DuplicateHandle(handle()); + // Close(); + // return dup; + SharedMemoryHandle TakeHandle(); + + // Closes the open shared memory segment. The memory will remain mapped if + // it was previously mapped. + // It is safe to call Close repeatedly. + void Close(); + + // Shares the shared memory to another process. Attempts to create a + // platform-specific new_handle which can be used in a remote process to read + // the shared memory file. new_handle is an output parameter to receive the + // handle for use in the remote process. + // + // |*this| must have been initialized using one of the Create*() or Open() + // methods with share_read_only=true. If it was constructed from a + // SharedMemoryHandle, this call will CHECK-fail. + // + // Returns true on success, false otherwise. + bool ShareReadOnlyToProcess(ProcessHandle process, + SharedMemoryHandle* new_handle) { + return ShareToProcessCommon(process, new_handle, false, SHARE_READONLY); + } + + // Logically equivalent to: + // bool ok = ShareReadOnlyToProcess(process, new_handle); + // Close(); + // return ok; + // Note that the memory is unmapped by calling this method, regardless of the + // return value. + bool GiveReadOnlyToProcess(ProcessHandle process, + SharedMemoryHandle* new_handle) { + return ShareToProcessCommon(process, new_handle, true, SHARE_READONLY); + } + + // Shares the shared memory to another process. Attempts + // to create a platform-specific new_handle which can be + // used in a remote process to access the shared memory + // file. new_handle is an output parameter to receive + // the handle for use in the remote process. + // Returns true on success, false otherwise. + bool ShareToProcess(ProcessHandle process, + SharedMemoryHandle* new_handle) { + return ShareToProcessCommon(process, new_handle, false, SHARE_CURRENT_MODE); + } + + // Logically equivalent to: + // bool ok = ShareToProcess(process, new_handle); + // Close(); + // return ok; + // Note that the memory is unmapped by calling this method, regardless of the + // return value. + bool GiveToProcess(ProcessHandle process, + SharedMemoryHandle* new_handle) { + return ShareToProcessCommon(process, new_handle, true, SHARE_CURRENT_MODE); + } + + private: +#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \ + !(defined(OS_MACOSX) && !defined(OS_IOS)) + bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly); + bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); +#endif + enum ShareMode { + SHARE_READONLY, + SHARE_CURRENT_MODE, + }; + bool ShareToProcessCommon(ProcessHandle process, + SharedMemoryHandle* new_handle, + bool close_self, + ShareMode); + +#if defined(OS_WIN) + // If true indicates this came from an external source so needs extra checks + // before being mapped. + bool external_section_; + std::wstring name_; + win::ScopedHandle mapped_file_; +#elif defined(OS_MACOSX) && !defined(OS_IOS) + // The OS primitive that backs the shared memory region. + SharedMemoryHandle shm_; +#elif defined(OS_POSIX) + int mapped_file_; + int readonly_mapped_file_; +#endif + size_t mapped_size_; + void* memory_; + bool read_only_; + size_t requested_size_; + + DISALLOW_COPY_AND_ASSIGN(SharedMemory); +}; +} // namespace base + +#endif // BASE_MEMORY_SHARED_MEMORY_H_ diff --git a/security/sandbox/chromium/base/memory/shared_memory_handle.h b/security/sandbox/chromium/base/memory/shared_memory_handle.h new file mode 100644 index 000000000000..c3fd7ae34bfe --- /dev/null +++ b/security/sandbox/chromium/base/memory/shared_memory_handle.h @@ -0,0 +1,162 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ +#define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ + +#include + +#include "build/build_config.h" + +#if defined(OS_WIN) +#include +#include "base/process/process_handle.h" +#elif defined(OS_MACOSX) && !defined(OS_IOS) +#include +#include "base/base_export.h" +#include "base/macros.h" +#include "base/process/process_handle.h" +#elif defined(OS_POSIX) +#include +#include "base/file_descriptor_posix.h" +#endif + +namespace base { + +// SharedMemoryHandle is a platform specific type which represents +// the underlying OS handle to a shared memory segment. +#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS)) +typedef FileDescriptor SharedMemoryHandle; +#elif defined(OS_WIN) +class BASE_EXPORT SharedMemoryHandle { + public: + // The default constructor returns an invalid SharedMemoryHandle. + SharedMemoryHandle(); + SharedMemoryHandle(HANDLE h, base::ProcessId pid); + + // Standard copy constructor. The new instance shares the underlying OS + // primitives. + SharedMemoryHandle(const SharedMemoryHandle& handle); + + // Standard assignment operator. The updated instance shares the underlying + // OS primitives. + SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); + + // Comparison operators. + bool operator==(const SharedMemoryHandle& handle) const; + bool operator!=(const SharedMemoryHandle& handle) const; + + // Closes the underlying OS resources. + void Close() const; + + // Whether the underlying OS primitive is valid. + bool IsValid() const; + + // Whether |pid_| is the same as the current process's id. + bool BelongsToCurrentProcess() const; + + // Whether handle_ needs to be duplicated into the destination process when + // an instance of this class is passed over a Chrome IPC channel. + bool NeedsBrokering() const; + + void SetOwnershipPassesToIPC(bool ownership_passes); + bool OwnershipPassesToIPC() const; + + HANDLE GetHandle() const; + base::ProcessId GetPID() const; + + private: + HANDLE handle_; + + // The process in which |handle_| is valid and can be used. If |handle_| is + // invalid, this will be kNullProcessId. + base::ProcessId pid_; + + // Whether passing this object as a parameter to an IPC message passes + // ownership of |handle_| to the IPC stack. This is meant to mimic the + // behavior of the |auto_close| parameter of FileDescriptor. This member only + // affects attachment-brokered SharedMemoryHandles. + // Defaults to |false|. + bool ownership_passes_to_ipc_; +}; +#else +class BASE_EXPORT SharedMemoryHandle { + public: + // The default constructor returns an invalid SharedMemoryHandle. + SharedMemoryHandle(); + + // Makes a Mach-based SharedMemoryHandle of the given size. On error, + // subsequent calls to IsValid() return false. + explicit SharedMemoryHandle(mach_vm_size_t size); + + // Makes a Mach-based SharedMemoryHandle from |memory_object|, a named entry + // in the task with process id |pid|. The memory region has size |size|. + SharedMemoryHandle(mach_port_t memory_object, + mach_vm_size_t size, + base::ProcessId pid); + + // Standard copy constructor. The new instance shares the underlying OS + // primitives. + SharedMemoryHandle(const SharedMemoryHandle& handle); + + // Standard assignment operator. The updated instance shares the underlying + // OS primitives. + SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); + + // Duplicates the underlying OS resources. + SharedMemoryHandle Duplicate() const; + + // Comparison operators. + bool operator==(const SharedMemoryHandle& handle) const; + bool operator!=(const SharedMemoryHandle& handle) const; + + // Whether the underlying OS primitive is valid. Once the SharedMemoryHandle + // is backed by a valid OS primitive, it becomes immutable. + bool IsValid() const; + + // Exposed so that the SharedMemoryHandle can be transported between + // processes. + mach_port_t GetMemoryObject() const; + + // Returns false on a failure to determine the size. On success, populates the + // output variable |size|. Returns 0 if the handle is invalid. + bool GetSize(size_t* size) const; + + // The SharedMemoryHandle must be valid. + // Returns whether the SharedMemoryHandle was successfully mapped into memory. + // On success, |memory| is an output variable that contains the start of the + // mapped memory. + bool MapAt(off_t offset, size_t bytes, void** memory, bool read_only); + + // Closes the underlying OS primitive. + void Close() const; + + void SetOwnershipPassesToIPC(bool ownership_passes); + bool OwnershipPassesToIPC() const; + + private: + // Shared code between copy constructor and operator=. + void CopyRelevantData(const SharedMemoryHandle& handle); + + mach_port_t memory_object_ = MACH_PORT_NULL; + + // The size of the shared memory region when |type_| is MACH. Only + // relevant if |memory_object_| is not |MACH_PORT_NULL|. + mach_vm_size_t size_ = 0; + + // The pid of the process in which |memory_object_| is usable. Only + // relevant if |memory_object_| is not |MACH_PORT_NULL|. + base::ProcessId pid_ = 0; + + // Whether passing this object as a parameter to an IPC message passes + // ownership of |memory_object_| to the IPC stack. This is meant to mimic + // the behavior of the |auto_close| parameter of FileDescriptor. + // Defaults to |false|. + bool ownership_passes_to_ipc_ = false; +}; +#endif + +} // namespace base + +#endif // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ diff --git a/security/sandbox/chromium/base/memory/shared_memory_handle_win.cc b/security/sandbox/chromium/base/memory/shared_memory_handle_win.cc new file mode 100644 index 000000000000..a2ff91abd2c6 --- /dev/null +++ b/security/sandbox/chromium/base/memory/shared_memory_handle_win.cc @@ -0,0 +1,79 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/shared_memory_handle.h" + +#include "base/logging.h" + +namespace base { + +SharedMemoryHandle::SharedMemoryHandle() + : handle_(nullptr), pid_(kNullProcessId), ownership_passes_to_ipc_(false) {} + +SharedMemoryHandle::SharedMemoryHandle(HANDLE h, base::ProcessId pid) + : handle_(h), pid_(pid), ownership_passes_to_ipc_(false) {} + +SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) + : handle_(handle.handle_), + pid_(handle.pid_), + ownership_passes_to_ipc_(handle.ownership_passes_to_ipc_) {} + +SharedMemoryHandle& SharedMemoryHandle::operator=( + const SharedMemoryHandle& handle) { + if (this == &handle) + return *this; + + handle_ = handle.handle_; + pid_ = handle.pid_; + ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_; + return *this; +} + +bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { + // Invalid handles are always equal. + if (!IsValid() && !handle.IsValid()) + return true; + + return handle_ == handle.handle_ && pid_ == handle.pid_; +} + +bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { + return !(*this == handle); +} + +void SharedMemoryHandle::Close() const { + DCHECK(handle_ != nullptr); + DCHECK(BelongsToCurrentProcess()); + ::CloseHandle(handle_); +} + +bool SharedMemoryHandle::IsValid() const { + return handle_ != nullptr; +} + +bool SharedMemoryHandle::BelongsToCurrentProcess() const { + return pid_ == base::GetCurrentProcId(); +} + +bool SharedMemoryHandle::NeedsBrokering() const { + return BelongsToCurrentProcess(); +} + +HANDLE SharedMemoryHandle::GetHandle() const { + return handle_; +} + +base::ProcessId SharedMemoryHandle::GetPID() const { + return pid_; +} + +void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { + ownership_passes_to_ipc_ = ownership_passes; +} + +bool SharedMemoryHandle::OwnershipPassesToIPC() const { + return ownership_passes_to_ipc_; +} + +} // namespace base diff --git a/security/sandbox/chromium/base/memory/shared_memory_win.cc b/security/sandbox/chromium/base/memory/shared_memory_win.cc new file mode 100644 index 000000000000..1eba23b846b8 --- /dev/null +++ b/security/sandbox/chromium/base/memory/shared_memory_win.cc @@ -0,0 +1,395 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/shared_memory.h" + +#include +#include +#include + +#include "base/logging.h" +#include "base/metrics/histogram_macros.h" +#include "base/rand_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" + +namespace { + +// Errors that can occur during Shared Memory construction. +// These match tools/metrics/histograms/histograms.xml. +// This enum is append-only. +enum CreateError { + SUCCESS = 0, + SIZE_ZERO = 1, + SIZE_TOO_LARGE = 2, + INITIALIZE_ACL_FAILURE = 3, + INITIALIZE_SECURITY_DESC_FAILURE = 4, + SET_SECURITY_DESC_FAILURE = 5, + CREATE_FILE_MAPPING_FAILURE = 6, + REDUCE_PERMISSIONS_FAILURE = 7, + ALREADY_EXISTS = 8, + CREATE_ERROR_LAST = ALREADY_EXISTS +}; + +// Emits UMA metrics about encountered errors. Pass zero (0) for |winerror| +// if there is no associated Windows error. +void LogError(CreateError error, DWORD winerror) { + UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error, + CREATE_ERROR_LAST + 1); + static_assert(ERROR_SUCCESS == 0, "Windows error code changed!"); + if (winerror != ERROR_SUCCESS) + UMA_HISTOGRAM_SPARSE_SLOWLY("SharedMemory.CreateWinError", winerror); +} + +typedef enum _SECTION_INFORMATION_CLASS { + SectionBasicInformation, +} SECTION_INFORMATION_CLASS; + +typedef struct _SECTION_BASIC_INFORMATION { + PVOID BaseAddress; + ULONG Attributes; + LARGE_INTEGER Size; +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; + +typedef ULONG(__stdcall* NtQuerySectionType)( + HANDLE SectionHandle, + SECTION_INFORMATION_CLASS SectionInformationClass, + PVOID SectionInformation, + ULONG SectionInformationLength, + PULONG ResultLength); + +// Returns the length of the memory section starting at the supplied address. +size_t GetMemorySectionSize(void* address) { + MEMORY_BASIC_INFORMATION memory_info; + if (!::VirtualQuery(address, &memory_info, sizeof(memory_info))) + return 0; + return memory_info.RegionSize - (static_cast(address) - + static_cast(memory_info.AllocationBase)); +} + +// Checks if the section object is safe to map. At the moment this just means +// it's not an image section. +bool IsSectionSafeToMap(HANDLE handle) { + static NtQuerySectionType nt_query_section_func; + if (!nt_query_section_func) { + nt_query_section_func = reinterpret_cast( + ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection")); + DCHECK(nt_query_section_func); + } + + // The handle must have SECTION_QUERY access for this to succeed. + SECTION_BASIC_INFORMATION basic_information = {}; + ULONG status = + nt_query_section_func(handle, SectionBasicInformation, &basic_information, + sizeof(basic_information), nullptr); + if (status) + return false; + return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; +} + +// Returns a HANDLE on success and |nullptr| on failure. +// This function is similar to CreateFileMapping, but removes the permissions +// WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE. +// +// A newly created file mapping has two sets of permissions. It has access +// control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and +// file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). ::DuplicateHandle() +// with the parameter DUPLICATE_SAME_ACCESS copies both sets of permissions. +// +// The Chrome sandbox prevents HANDLEs with the WRITE_DAC permission from being +// duplicated into unprivileged processes. But the only way to copy file +// permissions is with the parameter DUPLICATE_SAME_ACCESS. This means that +// there is no way for a privileged process to duplicate a file mapping into an +// unprivileged process while maintaining the previous file permissions. +// +// By removing all access control permissions of a file mapping immediately +// after creation, ::DuplicateHandle() effectively only copies the file +// permissions. +HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa, + size_t rounded_size, + LPCWSTR name) { + HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0, + static_cast(rounded_size), name); + if (!h) { + LogError(CREATE_FILE_MAPPING_FAILURE, GetLastError()); + return nullptr; + } + + HANDLE h2; + BOOL success = ::DuplicateHandle( + GetCurrentProcess(), h, GetCurrentProcess(), &h2, + FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0); + BOOL rv = ::CloseHandle(h); + DCHECK(rv); + + if (!success) { + LogError(REDUCE_PERMISSIONS_FAILURE, GetLastError()); + return nullptr; + } + + return h2; +} + +} // namespace. + +namespace base { + +SharedMemory::SharedMemory() + : external_section_(false), + mapped_size_(0), + memory_(NULL), + read_only_(false), + requested_size_(0) {} + +SharedMemory::SharedMemory(const std::wstring& name) + : external_section_(false), + name_(name), + mapped_size_(0), + memory_(NULL), + read_only_(false), + requested_size_(0) {} + +SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) + : external_section_(true), + mapped_size_(0), + memory_(NULL), + read_only_(read_only), + requested_size_(0) { + DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess()); + mapped_file_.Set(handle.GetHandle()); +} + +SharedMemory::~SharedMemory() { + Unmap(); + Close(); +} + +// static +bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { + return handle.IsValid(); +} + +// static +SharedMemoryHandle SharedMemory::NULLHandle() { + return SharedMemoryHandle(); +} + +// static +void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { + handle.Close(); +} + +// static +size_t SharedMemory::GetHandleLimit() { + // Rounded down from value reported here: + // http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx + return static_cast(1 << 23); +} + +// static +SharedMemoryHandle SharedMemory::DuplicateHandle( + const SharedMemoryHandle& handle) { + DCHECK(handle.BelongsToCurrentProcess()); + HANDLE duped_handle; + ProcessHandle process = GetCurrentProcess(); + BOOL success = + ::DuplicateHandle(process, handle.GetHandle(), process, &duped_handle, 0, + FALSE, DUPLICATE_SAME_ACCESS); + if (success) { + base::SharedMemoryHandle handle(duped_handle, GetCurrentProcId()); + handle.SetOwnershipPassesToIPC(true); + return handle; + } + return SharedMemoryHandle(); +} + +bool SharedMemory::CreateAndMapAnonymous(size_t size) { + return CreateAnonymous(size) && Map(size); +} + +bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { + // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, + // wasting 32k per mapping on average. + static const size_t kSectionMask = 65536 - 1; + DCHECK(!options.executable); + DCHECK(!mapped_file_.Get()); + if (options.size == 0) { + LogError(SIZE_ZERO, 0); + return false; + } + + // Check maximum accounting for overflow. + if (options.size > + static_cast(std::numeric_limits::max()) - kSectionMask) { + LogError(SIZE_TOO_LARGE, 0); + return false; + } + + size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; + name_ = options.name_deprecated ? + ASCIIToUTF16(*options.name_deprecated) : L""; + SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; + SECURITY_DESCRIPTOR sd; + ACL dacl; + + if (name_.empty()) { + // Add an empty DACL to enforce anonymous read-only sections. + sa.lpSecurityDescriptor = &sd; + if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) { + LogError(INITIALIZE_ACL_FAILURE, GetLastError()); + return false; + } + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { + LogError(INITIALIZE_SECURITY_DESC_FAILURE, GetLastError()); + return false; + } + if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) { + LogError(SET_SECURITY_DESC_FAILURE, GetLastError()); + return false; + } + + // Windows ignores DACLs on certain unnamed objects (like shared sections). + // So, we generate a random name when we need to enforce read-only. + uint64_t rand_values[4]; + RandBytes(&rand_values, sizeof(rand_values)); + name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", + rand_values[0], rand_values[1], + rand_values[2], rand_values[3]); + } + mapped_file_.Set(CreateFileMappingWithReducedPermissions( + &sa, rounded_size, name_.empty() ? nullptr : name_.c_str())); + if (!mapped_file_.IsValid()) { + // The error is logged within CreateFileMappingWithReducedPermissions(). + return false; + } + + requested_size_ = options.size; + + // Check if the shared memory pre-exists. + if (GetLastError() == ERROR_ALREADY_EXISTS) { + // If the file already existed, set requested_size_ to 0 to show that + // we don't know the size. + requested_size_ = 0; + external_section_ = true; + if (!options.open_existing_deprecated) { + Close(); + // From "if" above: GetLastError() == ERROR_ALREADY_EXISTS. + LogError(ALREADY_EXISTS, ERROR_ALREADY_EXISTS); + return false; + } + } + + LogError(SUCCESS, ERROR_SUCCESS); + return true; +} + +bool SharedMemory::Delete(const std::string& name) { + // intentionally empty -- there is nothing for us to do on Windows. + return true; +} + +bool SharedMemory::Open(const std::string& name, bool read_only) { + DCHECK(!mapped_file_.Get()); + DWORD access = FILE_MAP_READ | SECTION_QUERY; + if (!read_only) + access |= FILE_MAP_WRITE; + name_ = ASCIIToUTF16(name); + read_only_ = read_only; + mapped_file_.Set( + OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str())); + if (!mapped_file_.IsValid()) + return false; + // If a name specified assume it's an external section. + if (!name_.empty()) + external_section_ = true; + // Note: size_ is not set in this case. + return true; +} + +bool SharedMemory::MapAt(off_t offset, size_t bytes) { + if (!mapped_file_.Get()) + return false; + + if (bytes > static_cast(std::numeric_limits::max())) + return false; + + if (memory_) + return false; + + if (external_section_ && !IsSectionSafeToMap(mapped_file_.Get())) + return false; + + memory_ = MapViewOfFile( + mapped_file_.Get(), + read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, + static_cast(offset) >> 32, static_cast(offset), bytes); + if (memory_ != NULL) { + DCHECK_EQ(0U, reinterpret_cast(memory_) & + (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); + mapped_size_ = GetMemorySectionSize(memory_); + return true; + } + return false; +} + +bool SharedMemory::Unmap() { + if (memory_ == NULL) + return false; + + UnmapViewOfFile(memory_); + memory_ = NULL; + return true; +} + +bool SharedMemory::ShareToProcessCommon(ProcessHandle process, + SharedMemoryHandle* new_handle, + bool close_self, + ShareMode share_mode) { + *new_handle = SharedMemoryHandle(); + DWORD access = FILE_MAP_READ | SECTION_QUERY; + DWORD options = 0; + HANDLE mapped_file = mapped_file_.Get(); + HANDLE result; + if (share_mode == SHARE_CURRENT_MODE && !read_only_) + access |= FILE_MAP_WRITE; + if (close_self) { + // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. + options = DUPLICATE_CLOSE_SOURCE; + HANDLE detached_handle = mapped_file_.Take(); + DCHECK_EQ(detached_handle, mapped_file); + Unmap(); + } + + if (process == GetCurrentProcess() && close_self) { + *new_handle = SharedMemoryHandle(mapped_file, base::GetCurrentProcId()); + return true; + } + + if (!::DuplicateHandle(GetCurrentProcess(), mapped_file, process, &result, + access, FALSE, options)) { + return false; + } + *new_handle = SharedMemoryHandle(result, base::GetProcId(process)); + new_handle->SetOwnershipPassesToIPC(true); + return true; +} + + +void SharedMemory::Close() { + mapped_file_.Close(); +} + +SharedMemoryHandle SharedMemory::handle() const { + return SharedMemoryHandle(mapped_file_.Get(), base::GetCurrentProcId()); +} + +SharedMemoryHandle SharedMemory::TakeHandle() { + SharedMemoryHandle handle(mapped_file_.Take(), base::GetCurrentProcId()); + handle.SetOwnershipPassesToIPC(true); + memory_ = nullptr; + mapped_size_ = 0; + return handle; +} + +} // namespace base diff --git a/security/sandbox/chromium/base/memory/singleton.h b/security/sandbox/chromium/base/memory/singleton.h index 79e4441a8ed8..cfdff7831f9f 100644 --- a/security/sandbox/chromium/base/memory/singleton.h +++ b/security/sandbox/chromium/base/memory/singleton.h @@ -22,6 +22,7 @@ #include "base/at_exit.h" #include "base/atomicops.h" #include "base/base_export.h" +#include "base/logging.h" #include "base/macros.h" #include "base/memory/aligned_memory.h" #include "base/threading/thread_restrictions.h" @@ -63,7 +64,7 @@ struct DefaultSingletonTraits { // exit. See below for the required call that makes this happen. static const bool kRegisterAtExit = true; -#ifndef NDEBUG +#if DCHECK_IS_ON() // Set to false to disallow access on a non-joinable thread. This is // different from kRegisterAtExit because StaticMemorySingletonTraits allows // access on non-joinable threads, and gracefully handles this. @@ -78,7 +79,7 @@ struct DefaultSingletonTraits { template struct LeakySingletonTraits : public DefaultSingletonTraits { static const bool kRegisterAtExit = false; -#ifndef NDEBUG +#if DCHECK_IS_ON() static const bool kAllowedToAccessOnNonjoinableThread = true; #endif }; @@ -227,7 +228,7 @@ class Singleton { // Return a pointer to the one true instance of the class. static Type* get() { -#ifndef NDEBUG +#if DCHECK_IS_ON() // Avoid making TLS lookup on release builds. if (!Traits::kAllowedToAccessOnNonjoinableThread) ThreadRestrictions::AssertSingletonAllowed(); diff --git a/security/sandbox/chromium/base/memory/weak_ptr.h b/security/sandbox/chromium/base/memory/weak_ptr.h index 33d1e4736245..3544439dd3ca 100644 --- a/security/sandbox/chromium/base/memory/weak_ptr.h +++ b/security/sandbox/chromium/base/memory/weak_ptr.h @@ -3,7 +3,7 @@ // found in the LICENSE file. // Weak pointers are pointers to an object that do not affect its lifetime, -// and which may be invalidated (i.e. reset to NULL) by the object, or its +// and which may be invalidated (i.e. reset to nullptr) by the object, or its // owner, at any time, most commonly when the object is about to be deleted. // Weak pointers are useful when an object needs to be accessed safely by one @@ -70,12 +70,14 @@ #ifndef BASE_MEMORY_WEAK_PTR_H_ #define BASE_MEMORY_WEAK_PTR_H_ +#include +#include + #include "base/base_export.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/sequence_checker.h" -#include "base/template_util.h" namespace base { @@ -110,6 +112,11 @@ class BASE_EXPORT WeakReference { explicit WeakReference(const Flag* flag); ~WeakReference(); + WeakReference(WeakReference&& other); + WeakReference(const WeakReference& other); + WeakReference& operator=(WeakReference&& other) = default; + WeakReference& operator=(const WeakReference& other) = default; + bool is_valid() const; private: @@ -142,6 +149,11 @@ class BASE_EXPORT WeakPtrBase { WeakPtrBase(); ~WeakPtrBase(); + WeakPtrBase(const WeakPtrBase& other) = default; + WeakPtrBase(WeakPtrBase&& other) = default; + WeakPtrBase& operator=(const WeakPtrBase& other) = default; + WeakPtrBase& operator=(WeakPtrBase&& other) = default; + protected: explicit WeakPtrBase(const WeakReference& ref); @@ -159,10 +171,9 @@ class SupportsWeakPtrBase { // function that makes calling this easier. template static WeakPtr StaticAsWeakPtr(Derived* t) { - typedef - is_convertible convertible; - static_assert(convertible::value, - "AsWeakPtr argument must inherit from SupportsWeakPtr"); + static_assert( + std::is_base_of::value, + "AsWeakPtr argument must inherit from SupportsWeakPtr"); return AsWeakPtrImpl(t, *t); } @@ -198,50 +209,39 @@ template class WeakPtrFactory; template class WeakPtr : public internal::WeakPtrBase { public: - WeakPtr() : ptr_(NULL) { - } + WeakPtr() : ptr_(nullptr) {} + + WeakPtr(std::nullptr_t) : ptr_(nullptr) {} // Allow conversion from U to T provided U "is a" T. Note that this - // is separate from the (implicit) copy constructor. + // is separate from the (implicit) copy and move constructors. template WeakPtr(const WeakPtr& other) : WeakPtrBase(other), ptr_(other.ptr_) { } + template + WeakPtr(WeakPtr&& other) + : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} - T* get() const { return ref_.is_valid() ? ptr_ : NULL; } + T* get() const { return ref_.is_valid() ? ptr_ : nullptr; } T& operator*() const { - DCHECK(get() != NULL); + DCHECK(get() != nullptr); return *get(); } T* operator->() const { - DCHECK(get() != NULL); + DCHECK(get() != nullptr); return get(); } - // Allow WeakPtr to be used in boolean expressions, but not - // implicitly convertible to a real bool (which is dangerous). - // - // Note that this trick is only safe when the == and != operators - // are declared explicitly, as otherwise "weak_ptr1 == weak_ptr2" - // will compile but do the wrong thing (i.e., convert to Testable - // and then do the comparison). - private: - typedef T* WeakPtr::*Testable; - - public: - operator Testable() const { return get() ? &WeakPtr::ptr_ : NULL; } - void reset() { ref_ = internal::WeakReference(); - ptr_ = NULL; + ptr_ = nullptr; } - private: - // Explicitly declare comparison operators as required by the bool - // trick, but keep them private. - template bool operator==(WeakPtr const&) const; - template bool operator!=(WeakPtr const&) const; + // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; + explicit operator bool() const { return get() != nullptr; } + private: friend class internal::SupportsWeakPtrBase; template friend class WeakPtr; friend class SupportsWeakPtr; @@ -253,10 +253,28 @@ class WeakPtr : public internal::WeakPtrBase { } // This pointer is only valid when ref_.is_valid() is true. Otherwise, its - // value is undefined (as opposed to NULL). + // value is undefined (as opposed to nullptr). T* ptr_; }; +// Allow callers to compare WeakPtrs against nullptr to test validity. +template +bool operator!=(const WeakPtr& weak_ptr, std::nullptr_t) { + return !(weak_ptr == nullptr); +} +template +bool operator!=(std::nullptr_t, const WeakPtr& weak_ptr) { + return weak_ptr != nullptr; +} +template +bool operator==(const WeakPtr& weak_ptr, std::nullptr_t) { + return weak_ptr.get() == nullptr; +} +template +bool operator==(std::nullptr_t, const WeakPtr& weak_ptr) { + return weak_ptr == nullptr; +} + // A class may be composed of a WeakPtrFactory and thereby // control how it exposes weak pointers to itself. This is helpful if you only // need weak pointers within the implementation of a class. This class is also @@ -268,9 +286,7 @@ class WeakPtrFactory { explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { } - ~WeakPtrFactory() { - ptr_ = NULL; - } + ~WeakPtrFactory() { ptr_ = nullptr; } WeakPtr GetWeakPtr() { DCHECK(ptr_); diff --git a/security/sandbox/chromium/base/move.h b/security/sandbox/chromium/base/move.h deleted file mode 100644 index 0af416e00e17..000000000000 --- a/security/sandbox/chromium/base/move.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MOVE_H_ -#define BASE_MOVE_H_ - -#include - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "build/build_config.h" - -// TODO(crbug.com/566182): DEPRECATED! -// Use DISALLOW_COPY_AND_ASSIGN instead, or if your type will be used in -// Callbacks, use DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND instead. -#define MOVE_ONLY_TYPE_FOR_CPP_03(type) \ - DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) - -// A macro to disallow the copy constructor and copy assignment functions. -// This should be used in the private: declarations for a class. -// -// Use this macro instead of DISALLOW_COPY_AND_ASSIGN if you want to pass -// ownership of the type through a base::Callback without heap-allocating it -// into a scoped_ptr. The class must define a move constructor and move -// assignment operator to make this work. -// -// This version of the macro adds a Pass() function and a cryptic -// MoveOnlyTypeForCPP03 typedef for the base::Callback implementation to use. -// See IsMoveOnlyType template and its usage in base/callback_internal.h -// for more details. -// TODO(crbug.com/566182): Remove this macro and use DISALLOW_COPY_AND_ASSIGN -// everywhere instead. -#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_MACOSX) -#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \ - private: \ - type(const type&) = delete; \ - void operator=(const type&) = delete; \ - \ - public: \ - typedef void MoveOnlyTypeForCPP03; \ - \ - private: -#else -#define DISALLOW_COPY_AND_ASSIGN_WITH_MOVE_FOR_BIND(type) \ - private: \ - type(const type&) = delete; \ - void operator=(const type&) = delete; \ - \ - public: \ - type&& Pass() WARN_UNUSED_RESULT { return std::move(*this); } \ - typedef void MoveOnlyTypeForCPP03; \ - \ - private: -#endif - -#endif // BASE_MOVE_H_ diff --git a/security/sandbox/chromium/base/numerics/safe_conversions.h b/security/sandbox/chromium/base/numerics/safe_conversions.h index baac188fd2a7..4f45caf9c520 100644 --- a/security/sandbox/chromium/base/numerics/safe_conversions.h +++ b/security/sandbox/chromium/base/numerics/safe_conversions.h @@ -18,7 +18,7 @@ namespace base { // Convenience function that returns true if the supplied value is in range // for the destination type. template -inline bool IsValueInRangeForNumericType(Src value) { +constexpr bool IsValueInRangeForNumericType(Src value) { return internal::DstRangeRelationToSrcRange(value) == internal::RANGE_VALID; } @@ -26,7 +26,7 @@ inline bool IsValueInRangeForNumericType(Src value) { // Convenience function for determining if a numeric value is negative without // throwing compiler warnings on: unsigned(value) < 0. template -typename std::enable_if::is_signed, bool>::type +constexpr typename std::enable_if::is_signed, bool>::type IsValueNegative(T value) { static_assert(std::numeric_limits::is_specialized, "Argument must be numeric."); @@ -34,39 +34,62 @@ IsValueNegative(T value) { } template -typename std::enable_if::is_signed, bool>::type - IsValueNegative(T) { +constexpr typename std::enable_if::is_signed, + bool>::type IsValueNegative(T) { static_assert(std::numeric_limits::is_specialized, "Argument must be numeric."); return false; } -// checked_cast<> is analogous to static_cast<> for numeric types, -// except that it CHECKs that the specified numeric conversion will not -// overflow or underflow. NaN source will always trigger a CHECK. -template -inline Dst checked_cast(Src value) { - CHECK(IsValueInRangeForNumericType(value)); - return static_cast(value); -} - -// HandleNaN will cause this class to CHECK(false). -struct SaturatedCastNaNBehaviorCheck { +// Just fires a CHECK(false). Used for numeric boundary errors. +struct CheckOnFailure { template - static T HandleNaN() { + static T HandleFailure() { CHECK(false); return T(); } }; +// checked_cast<> is analogous to static_cast<> for numeric types, +// except that it CHECKs that the specified numeric conversion will not +// overflow or underflow. NaN source will always trigger a CHECK. +template +constexpr Dst checked_cast(Src value) { + // This throws a compile-time error on evaluating the constexpr if it can be + // determined at compile-time as failing, otherwise it will CHECK at runtime. + return IsValueInRangeForNumericType(value) + ? static_cast(value) + : CheckHandler::template HandleFailure(); +} + // HandleNaN will return 0 in this case. struct SaturatedCastNaNBehaviorReturnZero { template - static T HandleNaN() { + static constexpr T HandleFailure() { return T(); } }; +namespace internal { +// This wrapper is used for C++11 constexpr support by avoiding the declaration +// of local variables in the saturated_cast template function. +template +constexpr Dst saturated_cast_impl(const Src value, + const RangeConstraint constraint) { + return constraint == RANGE_VALID + ? static_cast(value) + : (constraint == RANGE_UNDERFLOW + ? std::numeric_limits::min() + : (constraint == RANGE_OVERFLOW + ? std::numeric_limits::max() + : (constraint == RANGE_INVALID + ? NaNHandler::template HandleFailure() + : (NOTREACHED(), static_cast(value))))); +} +} // namespace internal + // saturated_cast<> is analogous to static_cast<> for numeric types, except // that the specified numeric conversion will saturate rather than overflow or // underflow. NaN assignment to an integral will defer the behavior to a @@ -74,35 +97,18 @@ struct SaturatedCastNaNBehaviorReturnZero { template -inline Dst saturated_cast(Src value) { - // Optimization for floating point values, which already saturate. - if (std::numeric_limits::is_iec559) - return static_cast(value); - - switch (internal::DstRangeRelationToSrcRange(value)) { - case internal::RANGE_VALID: - return static_cast(value); - - case internal::RANGE_UNDERFLOW: - return std::numeric_limits::min(); - - case internal::RANGE_OVERFLOW: - return std::numeric_limits::max(); - - // Should fail only on attempting to assign NaN to a saturated integer. - case internal::RANGE_INVALID: - return NaNHandler::template HandleNaN(); - } - - NOTREACHED(); - return static_cast(value); +constexpr Dst saturated_cast(Src value) { + return std::numeric_limits::is_iec559 + ? static_cast(value) // Floating point optimization. + : internal::saturated_cast_impl( + value, internal::DstRangeRelationToSrcRange(value)); } // strict_cast<> is analogous to static_cast<> for numeric types, except that // it will cause a compile failure if the destination type is not large enough // to contain any value in the source type. It performs no runtime checking. template -inline Dst strict_cast(Src value) { +constexpr Dst strict_cast(Src value) { static_assert(std::numeric_limits::is_specialized, "Argument must be numeric."); static_assert(std::numeric_limits::is_specialized, @@ -128,33 +134,33 @@ inline Dst strict_cast(Src value) { // compiles cleanly with truncation warnings enabled. // This template should introduce no runtime overhead, but it also provides no // runtime checking of any of the associated mathematical operations. Use -// CheckedNumeric for runtime range checks of tha actual value being assigned. +// CheckedNumeric for runtime range checks of the actual value being assigned. template class StrictNumeric { public: typedef T type; - StrictNumeric() : value_(0) {} + constexpr StrictNumeric() : value_(0) {} // Copy constructor. template - StrictNumeric(const StrictNumeric& rhs) + constexpr StrictNumeric(const StrictNumeric& rhs) : value_(strict_cast(rhs.value_)) {} // This is not an explicit constructor because we implicitly upgrade regular // numerics to StrictNumerics to make them easier to use. template - StrictNumeric(Src value) + constexpr StrictNumeric(Src value) : value_(strict_cast(value)) {} // The numeric cast operator basically handles all the magic. template - operator Dst() const { + constexpr operator Dst() const { return strict_cast(value_); } private: - T value_; + const T value_; }; // Explicitly make a shorter size_t typedef for convenience. diff --git a/security/sandbox/chromium/base/numerics/safe_conversions_impl.h b/security/sandbox/chromium/base/numerics/safe_conversions_impl.h index 02e68e25de9d..bdce1675700e 100644 --- a/security/sandbox/chromium/base/numerics/safe_conversions_impl.h +++ b/security/sandbox/chromium/base/numerics/safe_conversions_impl.h @@ -8,9 +8,9 @@ #include #include +#include #include - -#include "base/template_util.h" +#include namespace base { namespace internal { @@ -20,9 +20,11 @@ namespace internal { // for accurate range comparisons between floating point and integer types. template struct MaxExponent { + static_assert(std::is_arithmetic::value, + "Argument must be numeric."); static const int value = std::numeric_limits::is_iec559 ? std::numeric_limits::max_exponent - : (sizeof(NumericType) * 8 + 1 - + : (sizeof(NumericType) * CHAR_BIT + 1 - std::numeric_limits::is_signed); }; @@ -96,17 +98,18 @@ enum RangeConstraint { }; // Helper function for coercing an int back to a RangeContraint. -inline RangeConstraint GetRangeConstraint(int integer_range_constraint) { - DCHECK(integer_range_constraint >= RANGE_VALID && - integer_range_constraint <= RANGE_INVALID); +constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint) { + // TODO(jschuh): Once we get full C++14 support we want this + // assert(integer_range_constraint >= RANGE_VALID && + // integer_range_constraint <= RANGE_INVALID) return static_cast(integer_range_constraint); } // This function creates a RangeConstraint from an upper and lower bound // check by taking advantage of the fact that only NaN can be out of range in // both directions at once. -inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, - bool is_in_lower_bound) { +constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, + bool is_in_lower_bound) { return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) | (is_in_lower_bound ? 0 : RANGE_UNDERFLOW)); } @@ -136,25 +139,24 @@ template struct NarrowingRange { typedef typename std::numeric_limits SrcLimits; typedef typename std::numeric_limits DstLimits; + // The following logic avoids warnings where the max function is + // instantiated with invalid values for a bit shift (even though + // such a function can never be called). + static const int shift = (MaxExponent::value > MaxExponent::value && + SrcLimits::digits < DstLimits::digits && + SrcLimits::is_iec559 && + DstLimits::is_integer) + ? (DstLimits::digits - SrcLimits::digits) + : 0; - static Dst max() { - // The following logic avoids warnings where the max function is - // instantiated with invalid values for a bit shift (even though - // such a function can never be called). - static const int shift = - (MaxExponent::value > MaxExponent::value && - SrcLimits::digits < DstLimits::digits && SrcLimits::is_iec559 && - DstLimits::is_integer) - ? (DstLimits::digits - SrcLimits::digits) - : 0; - + static constexpr Dst max() { // We use UINTMAX_C below to avoid compiler warnings about shifting floating // points. Since it's a compile time calculation, it shouldn't have any // performance impact. return DstLimits::max() - static_cast((UINTMAX_C(1) << shift) - 1); } - static Dst min() { + static constexpr Dst min() { return std::numeric_limits::is_iec559 ? -DstLimits::max() : DstLimits::min(); } @@ -187,7 +189,7 @@ struct DstRangeRelationToSrcRangeImpl { - static RangeConstraint Check(Src value) { return RANGE_VALID; } + static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; } }; // Signed to signed narrowing: Both the upper and lower boundaries may be @@ -198,7 +200,7 @@ struct DstRangeRelationToSrcRangeImpl { - static RangeConstraint Check(Src value) { + static constexpr RangeConstraint Check(Src value) { return GetRangeConstraint((value <= NarrowingRange::max()), (value >= NarrowingRange::min())); } @@ -211,7 +213,7 @@ struct DstRangeRelationToSrcRangeImpl { - static RangeConstraint Check(Src value) { + static constexpr RangeConstraint Check(Src value) { return GetRangeConstraint(value <= NarrowingRange::max(), true); } }; @@ -223,7 +225,7 @@ struct DstRangeRelationToSrcRangeImpl { - static RangeConstraint Check(Src value) { + static constexpr RangeConstraint Check(Src value) { return sizeof(Dst) > sizeof(Src) ? RANGE_VALID : GetRangeConstraint( @@ -240,7 +242,7 @@ struct DstRangeRelationToSrcRangeImpl { - static RangeConstraint Check(Src value) { + static constexpr RangeConstraint Check(Src value) { return (MaxExponent::value >= MaxExponent::value) ? GetRangeConstraint(true, value >= static_cast(0)) : GetRangeConstraint( @@ -250,7 +252,7 @@ struct DstRangeRelationToSrcRangeImpl -inline RangeConstraint DstRangeRelationToSrcRange(Src value) { +constexpr RangeConstraint DstRangeRelationToSrcRange(Src value) { static_assert(std::numeric_limits::is_specialized, "Argument must be numeric."); static_assert(std::numeric_limits::is_specialized, diff --git a/security/sandbox/chromium/base/numerics/safe_math.h b/security/sandbox/chromium/base/numerics/safe_math.h index d169690a8278..511eb23f7876 100644 --- a/security/sandbox/chromium/base/numerics/safe_math.h +++ b/security/sandbox/chromium/base/numerics/safe_math.h @@ -7,6 +7,10 @@ #include +#include +#include + +#include "base/logging.h" #include "base/numerics/safe_math_impl.h" namespace base { @@ -44,6 +48,9 @@ namespace internal { // Do stuff... template class CheckedNumeric { + static_assert(std::is_arithmetic::value, + "CheckedNumeric: T must be a numeric type."); + public: typedef T type; @@ -52,16 +59,15 @@ class CheckedNumeric { // Copy constructor. template CheckedNumeric(const CheckedNumeric& rhs) - : state_(rhs.ValueUnsafe(), rhs.validity()) {} + : state_(rhs.ValueUnsafe(), rhs.IsValid()) {} template - CheckedNumeric(Src value, RangeConstraint validity) - : state_(value, validity) {} + CheckedNumeric(Src value, bool is_valid) : state_(value, is_valid) {} // This is not an explicit constructor because we implicitly upgrade regular // numerics to CheckedNumerics to make them easier to use. template - CheckedNumeric(Src value) + CheckedNumeric(Src value) // NOLINT(runtime/explicit) : state_(value) { static_assert(std::numeric_limits::is_specialized, "Argument must be numeric."); @@ -70,12 +76,12 @@ class CheckedNumeric { // This is not an explicit constructor because we want a seamless conversion // from StrictNumeric types. template - CheckedNumeric(StrictNumeric value) + CheckedNumeric(StrictNumeric value) // NOLINT(runtime/explicit) : state_(static_cast(value)) { } // IsValid() is the public API to test if a CheckedNumeric is currently valid. - bool IsValid() const { return validity() == RANGE_VALID; } + bool IsValid() const { return state_.is_valid(); } // ValueOrDie() The primary accessor for the underlying value. If the current // state is not valid it will CHECK and crash. @@ -99,51 +105,42 @@ class CheckedNumeric { return CheckedNumeric::cast(*this).ValueUnsafe(); } - // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for - // tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: current validity state (i.e. valid, overflow, underflow, nan). - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - RangeConstraint validity() const { return state_.validity(); } - // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now // for tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. + // values it returns are unintuitive and likely to change in the future. // Returns: the raw numeric value, regardless of the current state. - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. T ValueUnsafe() const { return state_.value(); } // Prototypes for the supported arithmetic operator overloads. - template CheckedNumeric& operator+=(Src rhs); - template CheckedNumeric& operator-=(Src rhs); - template CheckedNumeric& operator*=(Src rhs); - template CheckedNumeric& operator/=(Src rhs); - template CheckedNumeric& operator%=(Src rhs); + template + CheckedNumeric& operator+=(Src rhs); + template + CheckedNumeric& operator-=(Src rhs); + template + CheckedNumeric& operator*=(Src rhs); + template + CheckedNumeric& operator/=(Src rhs); + template + CheckedNumeric& operator%=(Src rhs); + template + CheckedNumeric& operator<<=(Src rhs); + template + CheckedNumeric& operator>>=(Src rhs); CheckedNumeric operator-() const { - RangeConstraint validity; - T value = CheckedNeg(state_.value(), &validity); // Negation is always valid for floating point. - if (std::numeric_limits::is_iec559) - return CheckedNumeric(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric(value, validity); + T value = 0; + bool is_valid = (std::numeric_limits::is_iec559 || IsValid()) && + CheckedNeg(state_.value(), &value); + return CheckedNumeric(value, is_valid); } CheckedNumeric Abs() const { - RangeConstraint validity; - T value = CheckedAbs(state_.value(), &validity); // Absolute value is always valid for floating point. - if (std::numeric_limits::is_iec559) - return CheckedNumeric(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric(value, validity); + T value = 0; + bool is_valid = (std::numeric_limits::is_iec559 || IsValid()) && + CheckedAbs(state_.value(), &value); + return CheckedNumeric(value, is_valid); } // This function is available only for integral types. It returns an unsigned @@ -151,7 +148,7 @@ class CheckedNumeric { // of the source, and properly handling signed min. CheckedNumeric::type> UnsignedAbs() const { return CheckedNumeric::type>( - CheckedUnsignedAbs(state_.value()), state_.validity()); + SafeUnsignedAbs(state_.value()), state_.is_valid()); } CheckedNumeric& operator++() { @@ -190,23 +187,13 @@ class CheckedNumeric { template static CheckedNumeric cast( const CheckedNumeric& u, - typename std::enable_if::value, int>::type = 0) { + typename std::enable_if::value, int>::type = 0) { return u; } static const CheckedNumeric& cast(const CheckedNumeric& u) { return u; } private: - template - struct UnderlyingType { - using type = NumericType; - }; - - template - struct UnderlyingType> { - using type = NumericType; - }; - CheckedNumericState state_; }; @@ -217,76 +204,53 @@ class CheckedNumeric { // * We skip range checks for floating points. // * We skip range checks for destination integers with sufficient range. // TODO(jschuh): extract these out into templates. -#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ +#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP, PROMOTION) \ /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ - template \ - CheckedNumeric::type> operator OP( \ - const CheckedNumeric& lhs, const CheckedNumeric& rhs) { \ - typedef typename ArithmeticPromotion::type Promotion; \ + template \ + CheckedNumeric::type> \ + operator OP(const CheckedNumeric& lhs, const CheckedNumeric& rhs) { \ + using P = typename ArithmeticPromotion::type; \ + if (!rhs.IsValid() || !lhs.IsValid()) \ + return CheckedNumeric

(0, false); \ /* Floating point always takes the fast path */ \ - if (std::numeric_limits::is_iec559) \ - return CheckedNumeric(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ - if (IsIntegerArithmeticSafe::value) \ - return CheckedNumeric( \ - lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - RangeConstraint validity = RANGE_VALID; \ - T result = static_cast(Checked##NAME( \ - static_cast(lhs.ValueUnsafe()), \ - static_cast(rhs.ValueUnsafe()), \ - &validity)); \ - return CheckedNumeric( \ - result, \ - GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \ + if (std::is_floating_point::value || std::is_floating_point::value) \ + return CheckedNumeric

(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ + P result = 0; \ + bool is_valid = \ + Checked##NAME(lhs.ValueUnsafe(), rhs.ValueUnsafe(), &result); \ + return CheckedNumeric

(result, is_valid); \ } \ /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ - template \ - template \ - CheckedNumeric& CheckedNumeric::operator COMPOUND_OP(Src rhs) { \ - *this = CheckedNumeric::cast(*this) \ - OP CheckedNumeric::type>::cast(rhs); \ + template \ + template \ + CheckedNumeric& CheckedNumeric::operator COMPOUND_OP(R rhs) { \ + *this = *this OP rhs; \ return *this; \ } \ - /* Binary arithmetic operator for CheckedNumeric of different type. */ \ - template \ - CheckedNumeric::type> operator OP( \ - const CheckedNumeric& lhs, const CheckedNumeric& rhs) { \ - typedef typename ArithmeticPromotion::type Promotion; \ - if (IsIntegerArithmeticSafe::value) \ - return CheckedNumeric( \ - lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - return CheckedNumeric::cast(lhs) \ - OP CheckedNumeric::cast(rhs); \ - } \ /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ - template \ - CheckedNumeric::type> operator OP( \ - const CheckedNumeric& lhs, Src rhs) { \ - typedef typename ArithmeticPromotion::type Promotion; \ - if (IsIntegerArithmeticSafe::value) \ - return CheckedNumeric(lhs.ValueUnsafe() OP rhs, \ - lhs.validity()); \ - return CheckedNumeric::cast(lhs) \ - OP CheckedNumeric::cast(rhs); \ + template ::value>::type* = \ + nullptr> \ + CheckedNumeric::type> \ + operator OP(const CheckedNumeric& lhs, R rhs) { \ + return lhs OP CheckedNumeric(rhs); \ } \ - /* Binary arithmetic operator for right numeric and left CheckedNumeric. */ \ - template \ - CheckedNumeric::type> operator OP( \ - Src lhs, const CheckedNumeric& rhs) { \ - typedef typename ArithmeticPromotion::type Promotion; \ - if (IsIntegerArithmeticSafe::value) \ - return CheckedNumeric(lhs OP rhs.ValueUnsafe(), \ - rhs.validity()); \ - return CheckedNumeric::cast(lhs) \ - OP CheckedNumeric::cast(rhs); \ + /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \ + template ::value>::type* = \ + nullptr> \ + CheckedNumeric::type> \ + operator OP(L lhs, const CheckedNumeric& rhs) { \ + return CheckedNumeric(lhs) OP rhs; \ } -BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= ) +BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=, MAX_EXPONENT_PROMOTION) +BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=, MAX_EXPONENT_PROMOTION) +BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=, MAX_EXPONENT_PROMOTION) +BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=, MAX_EXPONENT_PROMOTION) +BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=, MAX_EXPONENT_PROMOTION) +BASE_NUMERIC_ARITHMETIC_OPERATORS(LeftShift, <<, <<=, LEFT_PROMOTION) +BASE_NUMERIC_ARITHMETIC_OPERATORS(RightShift, >>, >>=, LEFT_PROMOTION) #undef BASE_NUMERIC_ARITHMETIC_OPERATORS diff --git a/security/sandbox/chromium/base/numerics/safe_math_impl.h b/security/sandbox/chromium/base/numerics/safe_math_impl.h index 4fbcc045b840..71fc278b297c 100644 --- a/security/sandbox/chromium/base/numerics/safe_math_impl.h +++ b/security/sandbox/chromium/base/numerics/safe_math_impl.h @@ -8,13 +8,13 @@ #include #include +#include #include #include #include #include #include "base/numerics/safe_conversions.h" -#include "base/template_util.h" namespace base { namespace internal { @@ -90,12 +90,12 @@ template struct PositionOfSignBit { static const typename std::enable_if::is_integer, size_t>::type value = - 8 * sizeof(Integer) - 1; + CHAR_BIT * sizeof(Integer) - 1; }; // This is used for UnsignedAbs, where we need to support floating-point // template instantiations even though we don't actually support the operations. -// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, +// However, there is no corresponding implementation of e.g. SafeUnsignedAbs, // so the float versions will not compile. template ::is_integer, @@ -115,7 +115,7 @@ struct UnsignedOrFloatForSize { // Helper templates for integer manipulations. template -bool HasSignBit(T x) { +constexpr bool HasSignBit(T x) { // Cast to unsigned since right shift on signed is undefined. return !!(static_cast::type>(x) >> PositionOfSignBit::value); @@ -123,58 +123,226 @@ bool HasSignBit(T x) { // This wrapper undoes the standard integer promotions. template -T BinaryComplement(T x) { - return ~x; +constexpr T BinaryComplement(T x) { + return static_cast(~x); } +// Return if a numeric value is negative regardless of type. +template ::value && + std::is_signed::value>::type* = nullptr> +constexpr bool IsNegative(T x) { + return x < 0; +} + +template ::value && + !std::is_signed::value>::type* = nullptr> +constexpr bool IsNegative(T x) { + return false; +} + +enum ArithmeticPromotionCategory { + LEFT_PROMOTION, // Use the type of the left-hand argument. + RIGHT_PROMOTION, // Use the type of the right-hand argument. + MAX_EXPONENT_PROMOTION, // Use the type supporting the largest exponent. + BIG_ENOUGH_PROMOTION // Attempt to find a big enough type. +}; + +template +struct ArithmeticPromotion; + +template ::value > MaxExponent::value) + ? LEFT_PROMOTION + : RIGHT_PROMOTION> +struct MaxExponentPromotion; + +template +struct MaxExponentPromotion { + using type = Lhs; +}; + +template +struct MaxExponentPromotion { + using type = Rhs; +}; + +template ::type>::value && + sizeof(typename MaxExponentPromotion::type) == + sizeof(intmax_t), + bool is_max_exponent = + StaticDstRangeRelationToSrcRange< + typename MaxExponentPromotion::type, + Lhs>::value == + NUMERIC_RANGE_CONTAINED&& StaticDstRangeRelationToSrcRange< + typename MaxExponentPromotion::type, + Rhs>::value == NUMERIC_RANGE_CONTAINED> +struct BigEnoughPromotion; + +// The side with the max exponent is big enough. +template +struct BigEnoughPromotion { + using type = typename MaxExponentPromotion::type; + static const bool is_contained = true; +}; + +// We can use a twice wider type to fit. +template +struct BigEnoughPromotion { + using type = typename IntegerForSizeAndSign< + sizeof(typename MaxExponentPromotion::type) * 2, + std::is_signed::value || std::is_signed::value>::type; + static const bool is_contained = true; +}; + +// No type is large enough. +template +struct BigEnoughPromotion { + using type = typename MaxExponentPromotion::type; + static const bool is_contained = false; +}; + +// These are the four supported promotion types. + +// Use the type of the left-hand argument. +template +struct ArithmeticPromotion { + using type = Lhs; + static const bool is_contained = true; +}; + +// Use the type of the right-hand argument. +template +struct ArithmeticPromotion { + using type = Rhs; + static const bool is_contained = true; +}; + +// Use the type supporting the largest exponent. +template +struct ArithmeticPromotion { + using type = typename MaxExponentPromotion::type; + static const bool is_contained = true; +}; + +// Attempt to find a big enough type. +template +struct ArithmeticPromotion { + using type = typename BigEnoughPromotion::type; + static const bool is_contained = BigEnoughPromotion::is_contained; +}; + +// We can statically check if operations on the provided types can wrap, so we +// can skip the checked operations if they're not needed. So, for an integer we +// care if the destination type preserves the sign and is twice the width of +// the source. +template +struct IsIntegerArithmeticSafe { + static const bool value = !std::numeric_limits::is_iec559 && + StaticDstRangeRelationToSrcRange::value == + NUMERIC_RANGE_CONTAINED && + sizeof(T) >= (2 * sizeof(Lhs)) && + StaticDstRangeRelationToSrcRange::value != + NUMERIC_RANGE_CONTAINED && + sizeof(T) >= (2 * sizeof(Rhs)); +}; + // Here are the actual portable checked integer math implementations. // TODO(jschuh): Break this code out from the enable_if pattern and find a clean // way to coalesce things into the CheckedNumericState specializations below. template -typename std::enable_if::is_integer, T>::type -CheckedAdd(T x, T y, RangeConstraint* validity) { +typename std::enable_if::is_integer, bool>::type +CheckedAddImpl(T x, T y, T* result) { // Since the value of x+y is undefined if we have a signed type, we compute // it using the unsigned type of the same size. typedef typename UnsignedIntegerForSize::type UnsignedDst; UnsignedDst ux = static_cast(x); UnsignedDst uy = static_cast(y); - UnsignedDst uresult = ux + uy; + UnsignedDst uresult = static_cast(ux + uy); + *result = static_cast(uresult); // Addition is valid if the sign of (x + y) is equal to either that of x or // that of y. - if (std::numeric_limits::is_signed) { - if (HasSignBit(BinaryComplement((uresult ^ ux) & (uresult ^ uy)))) - *validity = RANGE_VALID; - else // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; + return (std::numeric_limits::is_signed) + ? HasSignBit(BinaryComplement( + static_cast((uresult ^ ux) & (uresult ^ uy)))) + : (BinaryComplement(x) >= + y); // Unsigned is either valid or underflow. +} - } else { // Unsigned is either valid or overflow. - *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW; +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedAdd(T x, U y, V* result) { + using Promotion = + typename ArithmeticPromotion::type; + Promotion presult; + // Fail if either operand is out of range for the promoted type. + // TODO(jschuh): This could be made to work for a broader range of values. + bool is_valid = IsValueInRangeForNumericType(x) && + IsValueInRangeForNumericType(y); + + if (IsIntegerArithmeticSafe::value) { + presult = static_cast(x) + static_cast(y); + } else { + is_valid &= CheckedAddImpl(static_cast(x), + static_cast(y), &presult); } - return static_cast(uresult); + *result = static_cast(presult); + return is_valid && IsValueInRangeForNumericType(presult); } template -typename std::enable_if::is_integer, T>::type -CheckedSub(T x, T y, RangeConstraint* validity) { +typename std::enable_if::is_integer, bool>::type +CheckedSubImpl(T x, T y, T* result) { // Since the value of x+y is undefined if we have a signed type, we compute // it using the unsigned type of the same size. typedef typename UnsignedIntegerForSize::type UnsignedDst; UnsignedDst ux = static_cast(x); UnsignedDst uy = static_cast(y); - UnsignedDst uresult = ux - uy; + UnsignedDst uresult = static_cast(ux - uy); + *result = static_cast(uresult); // Subtraction is valid if either x and y have same sign, or (x-y) and x have // the same sign. - if (std::numeric_limits::is_signed) { - if (HasSignBit(BinaryComplement((uresult ^ ux) & (ux ^ uy)))) - *validity = RANGE_VALID; - else // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; + return (std::numeric_limits::is_signed) + ? HasSignBit(BinaryComplement( + static_cast((uresult ^ ux) & (ux ^ uy)))) + : (x >= y); +} - } else { // Unsigned is either valid or underflow. - *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW; +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedSub(T x, U y, V* result) { + using Promotion = + typename ArithmeticPromotion::type; + Promotion presult; + // Fail if either operand is out of range for the promoted type. + // TODO(jschuh): This could be made to work for a broader range of values. + bool is_valid = IsValueInRangeForNumericType(x) && + IsValueInRangeForNumericType(y); + + if (IsIntegerArithmeticSafe::value) { + presult = static_cast(x) - static_cast(y); + } else { + is_valid &= CheckedSubImpl(static_cast(x), + static_cast(y), &presult); } - return static_cast(uresult); + *result = static_cast(presult); + return is_valid && IsValueInRangeForNumericType(presult); } // Integer multiplication is a bit complicated. In the fast case we just @@ -184,139 +352,243 @@ CheckedSub(T x, T y, RangeConstraint* validity) { template typename std::enable_if::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { + bool>::type +CheckedMulImpl(T x, T y, T* result) { typedef typename TwiceWiderInteger::type IntermediateType; IntermediateType tmp = static_cast(x) * static_cast(y); - *validity = DstRangeRelationToSrcRange(tmp); - return static_cast(tmp); + *result = static_cast(tmp); + return DstRangeRelationToSrcRange(tmp) == RANGE_VALID; } template typename std::enable_if::is_integer && std::numeric_limits::is_signed && (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - // If either side is zero then the result will be zero. - if (!x || !y) { - return RANGE_VALID; - - } else if (x > 0) { - if (y > 0) - *validity = - x <= std::numeric_limits::max() / y ? RANGE_VALID : RANGE_OVERFLOW; - else - *validity = y >= std::numeric_limits::min() / x ? RANGE_VALID - : RANGE_UNDERFLOW; - - } else { - if (y > 0) - *validity = x >= std::numeric_limits::min() / y ? RANGE_VALID - : RANGE_UNDERFLOW; - else - *validity = - y >= std::numeric_limits::max() / x ? RANGE_VALID : RANGE_OVERFLOW; + bool>::type +CheckedMulImpl(T x, T y, T* result) { + if (x && y) { + if (x > 0) { + if (y > 0) { + if (x > std::numeric_limits::max() / y) + return false; + } else { + if (y < std::numeric_limits::min() / x) + return false; + } + } else { + if (y > 0) { + if (x < std::numeric_limits::min() / y) + return false; + } else { + if (y < std::numeric_limits::max() / x) + return false; + } + } } - - return x * y; + *result = x * y; + return true; } template typename std::enable_if::is_integer && !std::numeric_limits::is_signed && (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - *validity = (y == 0 || x <= std::numeric_limits::max() / y) - ? RANGE_VALID - : RANGE_OVERFLOW; - return x * y; + bool>::type +CheckedMulImpl(T x, T y, T* result) { + *result = x * y; + return (y == 0 || x <= std::numeric_limits::max() / y); } -// Division just requires a check for an invalid negation on signed min/-1. -template -T CheckedDiv(T x, - T y, - RangeConstraint* validity, - typename std::enable_if::is_integer, - int>::type = 0) { - if (std::numeric_limits::is_signed && x == std::numeric_limits::min() && - y == static_cast(-1)) { - *validity = RANGE_OVERFLOW; - return std::numeric_limits::min(); +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedMul(T x, U y, V* result) { + using Promotion = + typename ArithmeticPromotion::type; + Promotion presult; + // Fail if either operand is out of range for the promoted type. + // TODO(jschuh): This could be made to work for a broader range of values. + bool is_valid = IsValueInRangeForNumericType(x) && + IsValueInRangeForNumericType(y); + + if (IsIntegerArithmeticSafe::value) { + presult = static_cast(x) * static_cast(y); + } else { + is_valid &= CheckedMulImpl(static_cast(x), + static_cast(y), &presult); } + *result = static_cast(presult); + return is_valid && IsValueInRangeForNumericType(presult); +} - *validity = RANGE_VALID; - return x / y; +// Division just requires a check for a zero denominator or an invalid negation +// on signed min/-1. +template +typename std::enable_if::is_integer, bool>::type +CheckedDivImpl(T x, T y, T* result) { + if (y && (!std::numeric_limits::is_signed || + x != std::numeric_limits::min() || y != static_cast(-1))) { + *result = x / y; + return true; + } + return false; +} + +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedDiv(T x, U y, V* result) { + using Promotion = + typename ArithmeticPromotion::type; + Promotion presult; + // Fail if either operand is out of range for the promoted type. + // TODO(jschuh): This could be made to work for a broader range of values. + bool is_valid = IsValueInRangeForNumericType(x) && + IsValueInRangeForNumericType(y); + is_valid &= CheckedDivImpl(static_cast(x), + static_cast(y), &presult); + *result = static_cast(presult); + return is_valid && IsValueInRangeForNumericType(presult); } template typename std::enable_if::is_integer && std::numeric_limits::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint* validity) { - *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; - return x % y; + bool>::type +CheckedModImpl(T x, T y, T* result) { + if (y > 0) { + *result = static_cast(x % y); + return true; + } + return false; } template typename std::enable_if::is_integer && !std::numeric_limits::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint* validity) { - *validity = RANGE_VALID; - return x % y; + bool>::type +CheckedModImpl(T x, T y, T* result) { + if (y != 0) { + *result = static_cast(x % y); + return true; + } + return false; +} + +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedMod(T x, U y, V* result) { + using Promotion = + typename ArithmeticPromotion::type; + Promotion presult; + bool is_valid = CheckedModImpl(static_cast(x), + static_cast(y), &presult); + *result = static_cast(presult); + return is_valid && IsValueInRangeForNumericType(presult); +} + +// Left shift. Shifts less than 0 or greater than or equal to the number +// of bits in the promoted type are undefined. Shifts of negative values +// are undefined. Otherwise it is defined when the result fits. +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedLeftShift(T x, U shift, V* result) { + using ShiftType = typename UnsignedIntegerForSize::type; + static const ShiftType kBitWidth = CHAR_BIT * sizeof(T); + const ShiftType real_shift = static_cast(shift); + // Signed shift is not legal on negative values. + if (!IsNegative(x) && real_shift < kBitWidth) { + // Just use a multiplication because it's easy. + // TODO(jschuh): This could probably be made more efficient. + if (!std::is_signed::value || real_shift != kBitWidth - 1) + return CheckedMul(x, static_cast(1) << shift, result); + return !x; // Special case zero for a full width signed shift. + } + return false; +} + +// Right shift. Shifts less than 0 or greater than or equal to the number +// of bits in the promoted type are undefined. Otherwise, it is always defined, +// but a right shift of a negative value is implementation-dependent. +template +typename std::enable_if::is_integer && + std::numeric_limits::is_integer && + std::numeric_limits::is_integer, + bool>::type +CheckedRightShift(T x, U shift, V* result) { + // Use the type conversion push negative values out of range. + using ShiftType = typename UnsignedIntegerForSize::type; + if (static_cast(shift) < (CHAR_BIT * sizeof(T))) { + T tmp = x >> shift; + *result = static_cast(tmp); + return IsValueInRangeForNumericType(tmp); + } + return false; } template typename std::enable_if::is_integer && std::numeric_limits::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint* validity) { - *validity = - value != std::numeric_limits::min() ? RANGE_VALID : RANGE_OVERFLOW; + bool>::type +CheckedNeg(T value, T* result) { // The negation of signed min is min, so catch that one. - return -value; + if (value != std::numeric_limits::min()) { + *result = static_cast(-value); + return true; + } + return false; } template typename std::enable_if::is_integer && !std::numeric_limits::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint* validity) { - // The only legal unsigned negation is zero. - *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; - return static_cast( - -static_cast::type>(value)); + bool>::type +CheckedNeg(T value, T* result) { + if (!value) { // The only legal unsigned negation is zero. + *result = static_cast(0); + return true; + } + return false; } template typename std::enable_if::is_integer && std::numeric_limits::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint* validity) { - *validity = - value != std::numeric_limits::min() ? RANGE_VALID : RANGE_OVERFLOW; - return static_cast(std::abs(value)); + bool>::type +CheckedAbs(T value, T* result) { + if (value != std::numeric_limits::min()) { + *result = std::abs(value); + return true; + } + return false; } template typename std::enable_if::is_integer && !std::numeric_limits::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint* validity) { + bool>::type +CheckedAbs(T value, T* result) { // T is unsigned, so |value| must already be positive. - *validity = RANGE_VALID; - return value; + *result = value; + return true; } template typename std::enable_if::is_integer && std::numeric_limits::is_signed, typename UnsignedIntegerForSize::type>::type -CheckedUnsignedAbs(T value) { +SafeUnsignedAbs(T value) { typedef typename UnsignedIntegerForSize::type UnsignedT; return value == std::numeric_limits::min() ? static_cast(std::numeric_limits::max()) + 1 @@ -327,19 +599,36 @@ template typename std::enable_if::is_integer && !std::numeric_limits::is_signed, T>::type -CheckedUnsignedAbs(T value) { +SafeUnsignedAbs(T value) { // T is unsigned, so |value| must already be positive. - return value; + return static_cast(value); } -// These are the floating point stubs that the compiler needs to see. Only the -// negation operation is ever called. -#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ - template \ - typename std::enable_if::is_iec559, T>::type \ - Checked##NAME(T, T, RangeConstraint*) { \ - NOTREACHED(); \ - return 0; \ +template +typename std::enable_if::is_iec559, T>::type CheckedNeg( + T value, + bool*) { + NOTREACHED(); + return static_cast(-value); +} + +template +typename std::enable_if::is_iec559, T>::type CheckedAbs( + T value, + bool*) { + NOTREACHED(); + return static_cast(std::abs(value)); +} + +// These are the floating point stubs that the compiler needs to see. +#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ + template \ + typename std::enable_if::is_iec559 || \ + std::numeric_limits::is_iec559 || \ + std::numeric_limits::is_iec559, \ + bool>::type Checked##NAME(T, U, V*) { \ + NOTREACHED(); \ + return static_cast(false); \ } BASE_FLOAT_ARITHMETIC_STUBS(Add) @@ -351,17 +640,17 @@ BASE_FLOAT_ARITHMETIC_STUBS(Mod) #undef BASE_FLOAT_ARITHMETIC_STUBS template -typename std::enable_if::is_iec559, T>::type CheckedNeg( - T value, - RangeConstraint*) { - return -value; +typename std::enable_if::is_iec559, bool>::type +CheckedNeg(T value, T* result) { + *result = static_cast(-value); + return true; } template -typename std::enable_if::is_iec559, T>::type CheckedAbs( - T value, - RangeConstraint*) { - return std::abs(value); +typename std::enable_if::is_iec559, bool>::type +CheckedAbs(T value, T* result) { + *result = static_cast(std::abs(value)); + return true; } // Floats carry around their validity state with them, but integers do not. So, @@ -391,19 +680,19 @@ template class CheckedNumericState { private: T value_; - RangeConstraint validity_; + bool is_valid_; public: template friend class CheckedNumericState; - CheckedNumericState() : value_(0), validity_(RANGE_VALID) {} + CheckedNumericState() : value_(0), is_valid_(true) {} template - CheckedNumericState(Src value, RangeConstraint validity) + CheckedNumericState(Src value, bool is_valid) : value_(static_cast(value)), - validity_(GetRangeConstraint(validity | - DstRangeRelationToSrcRange(value))) { + is_valid_(is_valid && + (DstRangeRelationToSrcRange(value) == RANGE_VALID)) { static_assert(std::numeric_limits::is_specialized, "Argument must be numeric."); } @@ -411,9 +700,7 @@ class CheckedNumericState { // Copy constructor. template CheckedNumericState(const CheckedNumericState& rhs) - : value_(static_cast(rhs.value())), - validity_(GetRangeConstraint( - rhs.validity() | DstRangeRelationToSrcRange(rhs.value()))) {} + : value_(static_cast(rhs.value())), is_valid_(rhs.IsValid()) {} template explicit CheckedNumericState( @@ -421,9 +708,9 @@ class CheckedNumericState { typename std::enable_if::is_specialized, int>::type = 0) : value_(static_cast(value)), - validity_(DstRangeRelationToSrcRange(value)) {} + is_valid_(DstRangeRelationToSrcRange(value) == RANGE_VALID) {} - RangeConstraint validity() const { return validity_; } + bool is_valid() const { return is_valid_; } T value() const { return value_; } }; @@ -442,29 +729,12 @@ class CheckedNumericState { template CheckedNumericState( Src value, - RangeConstraint validity, + bool is_valid, typename std::enable_if::is_integer, int>::type = 0) { - switch (DstRangeRelationToSrcRange(value)) { - case RANGE_VALID: - value_ = static_cast(value); - break; - - case RANGE_UNDERFLOW: - value_ = -std::numeric_limits::infinity(); - break; - - case RANGE_OVERFLOW: - value_ = std::numeric_limits::infinity(); - break; - - case RANGE_INVALID: - value_ = std::numeric_limits::quiet_NaN(); - break; - - default: - NOTREACHED(); - } + value_ = (is_valid && (DstRangeRelationToSrcRange(value) == RANGE_VALID)) + ? static_cast(value) + : std::numeric_limits::quiet_NaN(); } template @@ -479,66 +749,10 @@ class CheckedNumericState { CheckedNumericState(const CheckedNumericState& rhs) : value_(static_cast(rhs.value())) {} - RangeConstraint validity() const { - return GetRangeConstraint(value_ <= std::numeric_limits::max(), - value_ >= -std::numeric_limits::max()); - } + bool is_valid() const { return std::isfinite(value_); } T value() const { return value_; } }; -// For integers less than 128-bit and floats 32-bit or larger, we can distil -// C/C++ arithmetic promotions down to two simple rules: -// 1. The type with the larger maximum exponent always takes precedence. -// 2. The resulting type must be promoted to at least an int. -// The following template specializations implement that promotion logic. -enum ArithmeticPromotionCategory { - LEFT_PROMOTION, - RIGHT_PROMOTION, - DEFAULT_PROMOTION -}; - -template ::value > MaxExponent::value) - ? (MaxExponent::value > MaxExponent::value - ? LEFT_PROMOTION - : DEFAULT_PROMOTION) - : (MaxExponent::value > MaxExponent::value - ? RIGHT_PROMOTION - : DEFAULT_PROMOTION) > -struct ArithmeticPromotion; - -template -struct ArithmeticPromotion { - typedef Lhs type; -}; - -template -struct ArithmeticPromotion { - typedef Rhs type; -}; - -template -struct ArithmeticPromotion { - typedef int type; -}; - -// We can statically check if operations on the provided types can wrap, so we -// can skip the checked operations if they're not needed. So, for an integer we -// care if the destination type preserves the sign and is twice the width of -// the source. -template -struct IsIntegerArithmeticSafe { - static const bool value = !std::numeric_limits::is_iec559 && - StaticDstRangeRelationToSrcRange::value == - NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Lhs)) && - StaticDstRangeRelationToSrcRange::value != - NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Rhs)); -}; - } // namespace internal } // namespace base diff --git a/security/sandbox/chromium/base/process/kill.h b/security/sandbox/chromium/base/process/kill.h new file mode 100644 index 000000000000..6d410e02a0d1 --- /dev/null +++ b/security/sandbox/chromium/base/process/kill.h @@ -0,0 +1,146 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file contains routines to kill processes and get the exit code and +// termination status. + +#ifndef BASE_PROCESS_KILL_H_ +#define BASE_PROCESS_KILL_H_ + +#include "base/files/file_path.h" +#include "base/process/process.h" +#include "base/process/process_handle.h" +#include "base/time/time.h" +#include "build/build_config.h" + +namespace base { + +class ProcessFilter; + +#if defined(OS_WIN) +namespace win { + +// See definition in sandbox/win/src/sandbox_types.h +const DWORD kSandboxFatalMemoryExceeded = 7012; + +} // namespace win + +#endif // OS_WIN + +// Return status values from GetTerminationStatus. Don't use these as +// exit code arguments to KillProcess*(), use platform/application +// specific values instead. +enum TerminationStatus { + TERMINATION_STATUS_NORMAL_TERMINATION, // zero exit status + TERMINATION_STATUS_ABNORMAL_TERMINATION, // non-zero exit status + TERMINATION_STATUS_PROCESS_WAS_KILLED, // e.g. SIGKILL or task manager kill + TERMINATION_STATUS_PROCESS_CRASHED, // e.g. Segmentation fault + TERMINATION_STATUS_STILL_RUNNING, // child hasn't exited yet +#if defined(OS_CHROMEOS) + // Used for the case when oom-killer kills a process on ChromeOS. + TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, +#endif +#if defined(OS_ANDROID) + // On Android processes are spawned from the system Zygote and we do not get + // the termination status. We can't know if the termination was a crash or an + // oom kill for sure, but we can use status of the strong process bindings as + // a hint. + TERMINATION_STATUS_OOM_PROTECTED, // child was protected from oom kill +#endif + TERMINATION_STATUS_LAUNCH_FAILED, // child process never launched + TERMINATION_STATUS_OOM, // Process died due to oom + TERMINATION_STATUS_MAX_ENUM +}; + +// Attempts to kill all the processes on the current machine that were launched +// from the given executable name, ending them with the given exit code. If +// filter is non-null, then only processes selected by the filter are killed. +// Returns true if all processes were able to be killed off, false if at least +// one couldn't be killed. +BASE_EXPORT bool KillProcesses(const FilePath::StringType& executable_name, + int exit_code, + const ProcessFilter* filter); + +#if defined(OS_POSIX) +// Attempts to kill the process group identified by |process_group_id|. Returns +// true on success. +BASE_EXPORT bool KillProcessGroup(ProcessHandle process_group_id); +#endif // defined(OS_POSIX) + +// Get the termination status of the process by interpreting the +// circumstances of the child process' death. |exit_code| is set to +// the status returned by waitpid() on POSIX, and from +// GetExitCodeProcess() on Windows. |exit_code| may be NULL if the +// caller is not interested in it. Note that on Linux, this function +// will only return a useful result the first time it is called after +// the child exits (because it will reap the child and the information +// will no longer be available). +BASE_EXPORT TerminationStatus GetTerminationStatus(ProcessHandle handle, + int* exit_code); + +#if defined(OS_POSIX) +// Send a kill signal to the process and then wait for the process to exit +// and get the termination status. +// +// This is used in situations where it is believed that the process is dead +// or dying (because communication with the child process has been cut). +// In order to avoid erroneously returning that the process is still running +// because the kernel is still cleaning it up, this will wait for the process +// to terminate. In order to avoid the risk of hanging while waiting for the +// process to terminate, send a SIGKILL to the process before waiting for the +// termination status. +// +// Note that it is not an option to call WaitForExitCode and then +// GetTerminationStatus as the child will be reaped when WaitForExitCode +// returns, and this information will be lost. +// +BASE_EXPORT TerminationStatus GetKnownDeadTerminationStatus( + ProcessHandle handle, int* exit_code); +#endif // defined(OS_POSIX) + +// Wait for all the processes based on the named executable to exit. If filter +// is non-null, then only processes selected by the filter are waited on. +// Returns after all processes have exited or wait_milliseconds have expired. +// Returns true if all the processes exited, false otherwise. +BASE_EXPORT bool WaitForProcessesToExit( + const FilePath::StringType& executable_name, + base::TimeDelta wait, + const ProcessFilter* filter); + +// Waits a certain amount of time (can be 0) for all the processes with a given +// executable name to exit, then kills off any of them that are still around. +// If filter is non-null, then only processes selected by the filter are waited +// on. Killed processes are ended with the given exit code. Returns false if +// any processes needed to be killed, true if they all exited cleanly within +// the wait_milliseconds delay. +BASE_EXPORT bool CleanupProcesses(const FilePath::StringType& executable_name, + base::TimeDelta wait, + int exit_code, + const ProcessFilter* filter); + +// This method ensures that the specified process eventually terminates, and +// then it closes the given process handle. +// +// It assumes that the process has already been signalled to exit, and it +// begins by waiting a small amount of time for it to exit. If the process +// does not appear to have exited, then this function starts to become +// aggressive about ensuring that the process terminates. +// +// On Linux this method does not block the calling thread. +// On OS X this method may block for up to 2 seconds. +// +// NOTE: The process must have been opened with the PROCESS_TERMINATE and +// SYNCHRONIZE permissions. +// +BASE_EXPORT void EnsureProcessTerminated(Process process); + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +// The nicer version of EnsureProcessTerminated() that is patient and will +// wait for |pid| to finish and then reap it. +BASE_EXPORT void EnsureProcessGetsReaped(ProcessId pid); +#endif + +} // namespace base + +#endif // BASE_PROCESS_KILL_H_ diff --git a/security/sandbox/chromium/base/process/launch.h b/security/sandbox/chromium/base/process/launch.h new file mode 100644 index 000000000000..be8f6e73b9fe --- /dev/null +++ b/security/sandbox/chromium/base/process/launch.h @@ -0,0 +1,319 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file contains functions for launching subprocesses. + +#ifndef BASE_PROCESS_LAUNCH_H_ +#define BASE_PROCESS_LAUNCH_H_ + +#include + +#include +#include +#include + +#include "base/base_export.h" +#include "base/environment.h" +#include "base/macros.h" +#include "base/process/process.h" +#include "base/process/process_handle.h" +#include "base/strings/string_piece.h" +#include "build/build_config.h" + +#if defined(OS_POSIX) +#include "base/posix/file_descriptor_shuffle.h" +#elif defined(OS_WIN) +#include +#endif + +namespace base { + +class CommandLine; + +#if defined(OS_WIN) +typedef std::vector HandlesToInheritVector; +#endif +// TODO(viettrungluu): Only define this on POSIX? +typedef std::vector > FileHandleMappingVector; + +// Options for launching a subprocess that are passed to LaunchProcess(). +// The default constructor constructs the object with default options. +struct BASE_EXPORT LaunchOptions { +#if defined(OS_POSIX) + // Delegate to be run in between fork and exec in the subprocess (see + // pre_exec_delegate below) + class BASE_EXPORT PreExecDelegate { + public: + PreExecDelegate() {} + virtual ~PreExecDelegate() {} + + // Since this is to be run between fork and exec, and fork may have happened + // while multiple threads were running, this function needs to be async + // safe. + virtual void RunAsyncSafe() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(PreExecDelegate); + }; +#endif // defined(OS_POSIX) + + LaunchOptions(); + LaunchOptions(const LaunchOptions&); + ~LaunchOptions(); + + // If true, wait for the process to complete. + bool wait = false; + + // If not empty, change to this directory before executing the new process. + base::FilePath current_directory; + +#if defined(OS_WIN) + bool start_hidden = false; + + // If non-null, inherit exactly the list of handles in this vector (these + // handles must be inheritable). + HandlesToInheritVector* handles_to_inherit = nullptr; + + // If true, the new process inherits handles from the parent. In production + // code this flag should be used only when running short-lived, trusted + // binaries, because open handles from other libraries and subsystems will + // leak to the child process, causing errors such as open socket hangs. + // Note: If |handles_to_inherit| is non-null, this flag is ignored and only + // those handles will be inherited. + bool inherit_handles = false; + + // If non-null, runs as if the user represented by the token had launched it. + // Whether the application is visible on the interactive desktop depends on + // the token belonging to an interactive logon session. + // + // To avoid hard to diagnose problems, when specified this loads the + // environment variables associated with the user and if this operation fails + // the entire call fails as well. + UserTokenHandle as_user = nullptr; + + // If true, use an empty string for the desktop name. + bool empty_desktop_name = false; + + // If non-null, launches the application in that job object. The process will + // be terminated immediately and LaunchProcess() will fail if assignment to + // the job object fails. + HANDLE job_handle = nullptr; + + // Handles for the redirection of stdin, stdout and stderr. The handles must + // be inheritable. Caller should either set all three of them or none (i.e. + // there is no way to redirect stderr without redirecting stdin). The + // |inherit_handles| flag must be set to true when redirecting stdio stream. + HANDLE stdin_handle = nullptr; + HANDLE stdout_handle = nullptr; + HANDLE stderr_handle = nullptr; + + // If set to true, ensures that the child process is launched with the + // CREATE_BREAKAWAY_FROM_JOB flag which allows it to breakout of the parent + // job if any. + bool force_breakaway_from_job_ = false; +#else // !defined(OS_WIN) + // Set/unset environment variables. These are applied on top of the parent + // process environment. Empty (the default) means to inherit the same + // environment. See AlterEnvironment(). + EnvironmentMap environ; + + // Clear the environment for the new process before processing changes from + // |environ|. + bool clear_environ = false; + + // If non-null, remap file descriptors according to the mapping of + // src fd->dest fd to propagate FDs into the child process. + // This pointer is owned by the caller and must live through the + // call to LaunchProcess(). + const FileHandleMappingVector* fds_to_remap = nullptr; + + // Each element is an RLIMIT_* constant that should be raised to its + // rlim_max. This pointer is owned by the caller and must live through + // the call to LaunchProcess(). + const std::vector* maximize_rlimits = nullptr; + + // If true, start the process in a new process group, instead of + // inheriting the parent's process group. The pgid of the child process + // will be the same as its pid. + bool new_process_group = false; + +#if defined(OS_LINUX) + // If non-zero, start the process using clone(), using flags as provided. + // Unlike in clone, clone_flags may not contain a custom termination signal + // that is sent to the parent when the child dies. The termination signal will + // always be set to SIGCHLD. + int clone_flags = 0; + + // By default, child processes will have the PR_SET_NO_NEW_PRIVS bit set. If + // true, then this bit will not be set in the new child process. + bool allow_new_privs = false; + + // Sets parent process death signal to SIGKILL. + bool kill_on_parent_death = false; +#endif // defined(OS_LINUX) + +#if defined(OS_POSIX) + // If not empty, launch the specified executable instead of + // cmdline.GetProgram(). This is useful when it is necessary to pass a custom + // argv[0]. + base::FilePath real_path; + + // If non-null, a delegate to be run immediately prior to executing the new + // program in the child process. + // + // WARNING: If LaunchProcess is called in the presence of multiple threads, + // code running in this delegate essentially needs to be async-signal safe + // (see man 7 signal for a list of allowed functions). + PreExecDelegate* pre_exec_delegate = nullptr; +#endif // defined(OS_POSIX) + +#if defined(OS_CHROMEOS) + // If non-negative, the specified file descriptor will be set as the launched + // process' controlling terminal. + int ctrl_terminal_fd = -1; +#endif // defined(OS_CHROMEOS) +#endif // !defined(OS_WIN) +}; + +// Launch a process via the command line |cmdline|. +// See the documentation of LaunchOptions for details on |options|. +// +// Returns a valid Process upon success. +// +// Unix-specific notes: +// - All file descriptors open in the parent process will be closed in the +// child process except for any preserved by options::fds_to_remap, and +// stdin, stdout, and stderr. If not remapped by options::fds_to_remap, +// stdin is reopened as /dev/null, and the child is allowed to inherit its +// parent's stdout and stderr. +// - If the first argument on the command line does not contain a slash, +// PATH will be searched. (See man execvp.) +BASE_EXPORT Process LaunchProcess(const CommandLine& cmdline, + const LaunchOptions& options); + +#if defined(OS_WIN) +// Windows-specific LaunchProcess that takes the command line as a +// string. Useful for situations where you need to control the +// command line arguments directly, but prefer the CommandLine version +// if launching Chrome itself. +// +// The first command line argument should be the path to the process, +// and don't forget to quote it. +// +// Example (including literal quotes) +// cmdline = "c:\windows\explorer.exe" -foo "c:\bar\" +BASE_EXPORT Process LaunchProcess(const string16& cmdline, + const LaunchOptions& options); + +// Launches a process with elevated privileges. This does not behave exactly +// like LaunchProcess as it uses ShellExecuteEx instead of CreateProcess to +// create the process. This means the process will have elevated privileges +// and thus some common operations like OpenProcess will fail. Currently the +// only supported LaunchOptions are |start_hidden| and |wait|. +BASE_EXPORT Process LaunchElevatedProcess(const CommandLine& cmdline, + const LaunchOptions& options); + +#elif defined(OS_POSIX) +// A POSIX-specific version of LaunchProcess that takes an argv array +// instead of a CommandLine. Useful for situations where you need to +// control the command line arguments directly, but prefer the +// CommandLine version if launching Chrome itself. +BASE_EXPORT Process LaunchProcess(const std::vector& argv, + const LaunchOptions& options); + +// Close all file descriptors, except those which are a destination in the +// given multimap. Only call this function in a child process where you know +// that there aren't any other threads. +BASE_EXPORT void CloseSuperfluousFds(const InjectiveMultimap& saved_map); +#endif // defined(OS_POSIX) + +#if defined(OS_WIN) +// Set |job_object|'s JOBOBJECT_EXTENDED_LIMIT_INFORMATION +// BasicLimitInformation.LimitFlags to |limit_flags|. +BASE_EXPORT bool SetJobObjectLimitFlags(HANDLE job_object, DWORD limit_flags); + +// Output multi-process printf, cout, cerr, etc to the cmd.exe console that ran +// chrome. This is not thread-safe: only call from main thread. +BASE_EXPORT void RouteStdioToConsole(bool create_console_if_not_found); +#endif // defined(OS_WIN) + +// Executes the application specified by |cl| and wait for it to exit. Stores +// the output (stdout) in |output|. Redirects stderr to /dev/null. Returns true +// on success (application launched and exited cleanly, with exit code +// indicating success). +BASE_EXPORT bool GetAppOutput(const CommandLine& cl, std::string* output); + +// Like GetAppOutput, but also includes stderr. +BASE_EXPORT bool GetAppOutputAndError(const CommandLine& cl, + std::string* output); + +#if defined(OS_WIN) +// A Windows-specific version of GetAppOutput that takes a command line string +// instead of a CommandLine object. Useful for situations where you need to +// control the command line arguments directly. +BASE_EXPORT bool GetAppOutput(const StringPiece16& cl, std::string* output); +#endif + +#if defined(OS_POSIX) +// A POSIX-specific version of GetAppOutput that takes an argv array +// instead of a CommandLine. Useful for situations where you need to +// control the command line arguments directly. +BASE_EXPORT bool GetAppOutput(const std::vector& argv, + std::string* output); + +// A version of |GetAppOutput()| which also returns the exit code of the +// executed command. Returns true if the application runs and exits cleanly. If +// this is the case the exit code of the application is available in +// |*exit_code|. +BASE_EXPORT bool GetAppOutputWithExitCode(const CommandLine& cl, + std::string* output, int* exit_code); +#endif // defined(OS_POSIX) + +// If supported on the platform, and the user has sufficent rights, increase +// the current process's scheduling priority to a high priority. +BASE_EXPORT void RaiseProcessToHighPriority(); + +#if defined(OS_MACOSX) +// An implementation of LaunchProcess() that uses posix_spawn() instead of +// fork()+exec(). This does not support the |pre_exec_delegate| and +// |current_directory| options. +Process LaunchProcessPosixSpawn(const std::vector& argv, + const LaunchOptions& options); + +// Restore the default exception handler, setting it to Apple Crash Reporter +// (ReportCrash). When forking and execing a new process, the child will +// inherit the parent's exception ports, which may be set to the Breakpad +// instance running inside the parent. The parent's Breakpad instance should +// not handle the child's exceptions. Calling RestoreDefaultExceptionHandler +// in the child after forking will restore the standard exception handler. +// See http://crbug.com/20371/ for more details. +void RestoreDefaultExceptionHandler(); +#endif // defined(OS_MACOSX) + +// Creates a LaunchOptions object suitable for launching processes in a test +// binary. This should not be called in production/released code. +BASE_EXPORT LaunchOptions LaunchOptionsForTest(); + +#if defined(OS_LINUX) || defined(OS_NACL_NONSFI) +// A wrapper for clone with fork-like behavior, meaning that it returns the +// child's pid in the parent and 0 in the child. |flags|, |ptid|, and |ctid| are +// as in the clone system call (the CLONE_VM flag is not supported). +// +// This function uses the libc clone wrapper (which updates libc's pid cache) +// internally, so callers may expect things like getpid() to work correctly +// after in both the child and parent. An exception is when this code is run +// under Valgrind. Valgrind does not support the libc clone wrapper, so the libc +// pid cache may be incorrect after this function is called under Valgrind. +// +// As with fork(), callers should be extremely careful when calling this while +// multiple threads are running, since at the time the fork happened, the +// threads could have been in any state (potentially holding locks, etc.). +// Callers should most likely call execve() in the child soon after calling +// this. +BASE_EXPORT pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid); +#endif + +} // namespace base + +#endif // BASE_PROCESS_LAUNCH_H_ diff --git a/security/sandbox/chromium/base/process/process.h b/security/sandbox/chromium/base/process/process.h new file mode 100644 index 000000000000..5538475863b0 --- /dev/null +++ b/security/sandbox/chromium/base/process/process.h @@ -0,0 +1,182 @@ +// Copyright 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_PROCESS_PROCESS_H_ +#define BASE_PROCESS_PROCESS_H_ + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/process/process_handle.h" +#include "base/time/time.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include "base/win/scoped_handle.h" +#endif + +#if defined(OS_MACOSX) +#include "base/feature_list.h" +#include "base/process/port_provider_mac.h" +#endif + +namespace base { + +#if defined(OS_MACOSX) +extern const Feature kMacAllowBackgroundingProcesses; +#endif + +// Provides a move-only encapsulation of a process. +// +// This object is not tied to the lifetime of the underlying process: the +// process may be killed and this object may still around, and it will still +// claim to be valid. The actual behavior in that case is OS dependent like so: +// +// Windows: The underlying ProcessHandle will be valid after the process dies +// and can be used to gather some information about that process, but most +// methods will obviously fail. +// +// POSIX: The underlying PorcessHandle is not guaranteed to remain valid after +// the process dies, and it may be reused by the system, which means that it may +// end up pointing to the wrong process. +class BASE_EXPORT Process { + public: + explicit Process(ProcessHandle handle = kNullProcessHandle); + + Process(Process&& other); + + // The destructor does not terminate the process. + ~Process(); + + Process& operator=(Process&& other); + + // Returns an object for the current process. + static Process Current(); + + // Returns a Process for the given |pid|. + static Process Open(ProcessId pid); + + // Returns a Process for the given |pid|. On Windows the handle is opened + // with more access rights and must only be used by trusted code (can read the + // address space and duplicate handles). + static Process OpenWithExtraPrivileges(ProcessId pid); + +#if defined(OS_WIN) + // Returns a Process for the given |pid|, using some |desired_access|. + // See ::OpenProcess documentation for valid |desired_access|. + static Process OpenWithAccess(ProcessId pid, DWORD desired_access); +#endif + + // Creates an object from a |handle| owned by someone else. + // Don't use this for new code. It is only intended to ease the migration to + // a strict ownership model. + // TODO(rvargas) crbug.com/417532: Remove this code. + static Process DeprecatedGetProcessFromHandle(ProcessHandle handle); + + // Returns true if processes can be backgrounded. + static bool CanBackgroundProcesses(); + + // Returns true if this objects represents a valid process. + bool IsValid() const; + + // Returns a handle for this process. There is no guarantee about when that + // handle becomes invalid because this object retains ownership. + ProcessHandle Handle() const; + + // Returns a second object that represents this process. + Process Duplicate() const; + + // Get the PID for this process. + ProcessId Pid() const; + + // Returns true if this process is the current process. + bool is_current() const; + + // Close the process handle. This will not terminate the process. + void Close(); + + // Terminates the process with extreme prejudice. The given |exit_code| will + // be the exit code of the process. If |wait| is true, this method will wait + // for up to one minute for the process to actually terminate. + // Returns true if the process terminates within the allowed time. + // NOTE: On POSIX |exit_code| is ignored. + bool Terminate(int exit_code, bool wait) const; + + // Waits for the process to exit. Returns true on success. + // On POSIX, if the process has been signaled then |exit_code| is set to -1. + // On Linux this must be a child process, however on Mac and Windows it can be + // any process. + // NOTE: |exit_code| is optional, nullptr can be passed if the exit code is + // not required. + bool WaitForExit(int* exit_code); + + // Same as WaitForExit() but only waits for up to |timeout|. + // NOTE: |exit_code| is optional, nullptr can be passed if the exit code + // is not required. + bool WaitForExitWithTimeout(TimeDelta timeout, int* exit_code); + +#if defined(OS_MACOSX) + // The Mac needs a Mach port in order to manipulate a process's priority, + // and there's no good way to get that from base given the pid. These Mac + // variants of the IsProcessBackgrounded and SetProcessBackgrounded API take + // a port provider for this reason. See crbug.com/460102 + // + // A process is backgrounded when its task priority is + // |TASK_BACKGROUND_APPLICATION|. + // + // Returns true if the port_provider can locate a task port for the process + // and it is backgrounded. If port_provider is null, returns false. + bool IsProcessBackgrounded(PortProvider* port_provider) const; + + // Set the process as backgrounded. If value is + // true, the priority of the associated task will be set to + // TASK_BACKGROUND_APPLICATION. If value is false, the + // priority of the process will be set to TASK_FOREGROUND_APPLICATION. + // + // Returns true if the priority was changed, false otherwise. If + // |port_provider| is null, this is a no-op and it returns false. + bool SetProcessBackgrounded(PortProvider* port_provider, bool value); +#else + // A process is backgrounded when it's priority is lower than normal. + // Return true if this process is backgrounded, false otherwise. + bool IsProcessBackgrounded() const; + + // Set a process as backgrounded. If value is true, the priority of the + // process will be lowered. If value is false, the priority of the process + // will be made "normal" - equivalent to default process priority. + // Returns true if the priority was changed, false otherwise. + bool SetProcessBackgrounded(bool value); +#endif // defined(OS_MACOSX) + // Returns an integer representing the priority of a process. The meaning + // of this value is OS dependent. + int GetPriority() const; + +#if defined(OS_CHROMEOS) + // Get the PID in its PID namespace. + // If the process is not in a PID namespace or /proc//status does not + // report NSpid, kNullProcessId is returned. + ProcessId GetPidInNamespace() const; +#endif + + private: +#if defined(OS_WIN) + bool is_current_process_; + win::ScopedHandle process_; +#else + ProcessHandle process_; +#endif + + DISALLOW_COPY_AND_ASSIGN(Process); +}; + +#if defined(OS_CHROMEOS) +// Exposed for testing. +// Given the contents of the /proc//cgroup file, determine whether the +// process is backgrounded or not. +BASE_EXPORT bool IsProcessBackgroundedCGroup( + const StringPiece& cgroup_contents); +#endif // defined(OS_CHROMEOS) + +} // namespace base + +#endif // BASE_PROCESS_PROCESS_H_ diff --git a/security/sandbox/chromium/base/process/process_handle_win.cc b/security/sandbox/chromium/base/process/process_handle_win.cc new file mode 100644 index 000000000000..b8136d1e8cce --- /dev/null +++ b/security/sandbox/chromium/base/process/process_handle_win.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/process/process_handle.h" + +#include +#include + +#include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" + +namespace base { + +ProcessId GetCurrentProcId() { + return ::GetCurrentProcessId(); +} + +ProcessHandle GetCurrentProcessHandle() { + return ::GetCurrentProcess(); +} + +ProcessId GetProcId(ProcessHandle process) { + // This returns 0 if we have insufficient rights to query the process handle. + return GetProcessId(process); +} + +ProcessId GetParentProcessId(ProcessHandle process) { + ProcessId child_pid = GetProcId(process); + PROCESSENTRY32 process_entry; + process_entry.dwSize = sizeof(PROCESSENTRY32); + + win::ScopedHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); + if (snapshot.IsValid() && Process32First(snapshot.Get(), &process_entry)) { + do { + if (process_entry.th32ProcessID == child_pid) + return process_entry.th32ParentProcessID; + } while (Process32Next(snapshot.Get(), &process_entry)); + } + + return 0u; +} + +} // namespace base diff --git a/security/sandbox/chromium/base/rand_util_win.cc b/security/sandbox/chromium/base/rand_util_win.cc new file mode 100644 index 000000000000..22fdd4da72c8 --- /dev/null +++ b/security/sandbox/chromium/base/rand_util_win.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/rand_util.h" + +#include +#include +#include + +// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the +// "Community Additions" comment on MSDN here: +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx +#define SystemFunction036 NTAPI SystemFunction036 +#include +#undef SystemFunction036 + +#include +#include + +#include "base/logging.h" + +namespace base { + +// NOTE: This function must be cryptographically secure. http://crbug.com/140076 +uint64_t RandUint64() { + uint64_t number; + RandBytes(&number, sizeof(number)); + return number; +} + +void RandBytes(void* output, size_t output_length) { + char* output_ptr = static_cast(output); + while (output_length > 0) { + const ULONG output_bytes_this_pass = static_cast(std::min( + output_length, static_cast(std::numeric_limits::max()))); + const bool success = + RtlGenRandom(output_ptr, output_bytes_this_pass) != FALSE; + CHECK(success); + output_length -= output_bytes_this_pass; + output_ptr += output_bytes_this_pass; + } +} + +} // namespace base diff --git a/security/sandbox/chromium/base/sequence_checker.h b/security/sandbox/chromium/base/sequence_checker.h index ad0182825c24..471631844ba7 100644 --- a/security/sandbox/chromium/base/sequence_checker.h +++ b/security/sandbox/chromium/base/sequence_checker.h @@ -5,13 +5,6 @@ #ifndef BASE_SEQUENCE_CHECKER_H_ #define BASE_SEQUENCE_CHECKER_H_ -// See comments for the similar block in thread_checker.h. -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define ENABLE_SEQUENCE_CHECKER 1 -#else -#define ENABLE_SEQUENCE_CHECKER 0 -#endif - #include "base/sequence_checker_impl.h" namespace base { @@ -22,23 +15,22 @@ namespace base { // the right version for your build configuration. class SequenceCheckerDoNothing { public: - bool CalledOnValidSequencedThread() const { - return true; - } + bool CalledOnValidSequence() const { return true; } void DetachFromSequence() {} }; -// SequenceChecker is a helper class used to help verify that some -// methods of a class are called in sequence -- that is, called from -// the same SequencedTaskRunner. It is a generalization of -// ThreadChecker; see comments in sequence_checker_impl.h for details. +// SequenceChecker is a helper class to verify that calls to some methods of a +// class are sequenced. Calls are sequenced when they are issued: +// - From tasks posted to SequencedTaskRunners or SingleThreadTaskRunners bound +// to the same sequence, or, +// - From a single thread outside of any task. // // Example: // class MyClass { // public: // void Foo() { -// DCHECK(sequence_checker_.CalledOnValidSequencedThread()); +// DCHECK(sequence_checker_.CalledOnValidSequence()); // ... (do stuff) ... // } // @@ -46,16 +38,14 @@ class SequenceCheckerDoNothing { // SequenceChecker sequence_checker_; // } // -// In Release mode, CalledOnValidSequencedThread() will always return true. -#if ENABLE_SEQUENCE_CHECKER +// In Release mode, CalledOnValidSequence() will always return true. +#if DCHECK_IS_ON() class SequenceChecker : public SequenceCheckerImpl { }; #else class SequenceChecker : public SequenceCheckerDoNothing { }; -#endif // ENABLE_SEQUENCE_CHECKER - -#undef ENABLE_SEQUENCE_CHECKER +#endif // DCHECK_IS_ON() } // namespace base diff --git a/security/sandbox/chromium/base/sequence_checker_impl.h b/security/sandbox/chromium/base/sequence_checker_impl.h index e3c5fed508c4..74039718f62d 100644 --- a/security/sandbox/chromium/base/sequence_checker_impl.h +++ b/security/sandbox/chromium/base/sequence_checker_impl.h @@ -6,30 +6,32 @@ #define BASE_SEQUENCE_CHECKER_IMPL_H_ #include "base/base_export.h" +#include "base/compiler_specific.h" #include "base/macros.h" +#include "base/sequence_token.h" #include "base/synchronization/lock.h" #include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread_checker_impl.h" namespace base { -// SequenceCheckerImpl is used to help verify that some methods of a -// class are called in sequence -- that is, called from the same -// SequencedTaskRunner. It is a generalization of ThreadChecker; in -// particular, it behaves exactly like ThreadChecker if constructed -// on a thread that is not part of a SequencedWorkerPool. +// Real implementation of SequenceChecker for use in debug mode or for temporary +// use in release mode (e.g. to CHECK on a threading issue seen only in the +// wild). +// +// Note: You should almost always use the SequenceChecker class to get the right +// version for your build configuration. class BASE_EXPORT SequenceCheckerImpl { public: SequenceCheckerImpl(); ~SequenceCheckerImpl(); - // Returns whether the we are being called on the same sequence token - // as previous calls. If there is no associated sequence, then returns - // whether we are being called on the underlying ThreadChecker's thread. - bool CalledOnValidSequencedThread() const; + // Returns true if called in sequence with previous calls to this method and + // the constructor. + bool CalledOnValidSequence() const WARN_UNUSED_RESULT; - // Unbinds the checker from the currently associated sequence. The - // checker will be re-bound on the next call to CalledOnValidSequence(). + // Unbinds the checker from the currently associated sequence. The checker + // will be re-bound on the next call to CalledOnValidSequence(). void DetachFromSequence(); private: @@ -38,11 +40,17 @@ class BASE_EXPORT SequenceCheckerImpl { // Guards all variables below. mutable Lock lock_; - // Used if |sequence_token_| is not valid. - ThreadCheckerImpl thread_checker_; - mutable bool sequence_token_assigned_; + // True when the SequenceChecker is bound to a sequence or a thread. + mutable bool is_assigned_ = false; - mutable SequencedWorkerPool::SequenceToken sequence_token_; + mutable SequenceToken sequence_token_; + + // TODO(gab): Remove this when SequencedWorkerPool is deprecated in favor of + // TaskScheduler. crbug.com/622400 + mutable SequencedWorkerPool::SequenceToken sequenced_worker_pool_token_; + + // Used when |sequenced_worker_pool_token_| and |sequence_token_| are invalid. + ThreadCheckerImpl thread_checker_; DISALLOW_COPY_AND_ASSIGN(SequenceCheckerImpl); }; diff --git a/security/sandbox/chromium/base/sequence_token.h b/security/sandbox/chromium/base/sequence_token.h new file mode 100644 index 000000000000..6e7d191ae8a8 --- /dev/null +++ b/security/sandbox/chromium/base/sequence_token.h @@ -0,0 +1,115 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SEQUENCE_TOKEN_H_ +#define BASE_SEQUENCE_TOKEN_H_ + +#include "base/base_export.h" +#include "base/macros.h" + +namespace base { + +// A token that identifies a series of sequenced tasks (i.e. tasks that run one +// at a time in posting order). +class BASE_EXPORT SequenceToken { + public: + // Instantiates an invalid SequenceToken. + SequenceToken() = default; + + // Explicitly allow copy. + SequenceToken(const SequenceToken& other) = default; + SequenceToken& operator=(const SequenceToken& other) = default; + + // An invalid SequenceToken is not equal to any other SequenceToken, including + // other invalid SequenceTokens. + bool operator==(const SequenceToken& other) const; + bool operator!=(const SequenceToken& other) const; + + // Returns true if this is a valid SequenceToken. + bool IsValid() const; + + // Returns the integer uniquely representing this SequenceToken. This method + // should only be used for tracing and debugging. + int ToInternalValue() const; + + // Returns a valid SequenceToken which isn't equal to any previously returned + // SequenceToken. + static SequenceToken Create(); + + // Returns the SequenceToken associated with the task running on the current + // thread, as determined by the active ScopedSetSequenceTokenForCurrentThread + // if any. + static SequenceToken GetForCurrentThread(); + + private: + explicit SequenceToken(int token) : token_(token) {} + + static constexpr int kInvalidSequenceToken = -1; + int token_ = kInvalidSequenceToken; +}; + +// A token that identifies a task. +// +// This is used by ThreadCheckerImpl to determine whether calls to +// CalledOnValidThread() come from the same task and hence are deterministically +// single-threaded (vs. calls coming from different sequenced or parallel tasks, +// which may or may not run on the same thread). +class BASE_EXPORT TaskToken { + public: + // Instantiates an invalid TaskToken. + TaskToken() = default; + + // Explicitly allow copy. + TaskToken(const TaskToken& other) = default; + TaskToken& operator=(const TaskToken& other) = default; + + // An invalid TaskToken is not equal to any other TaskToken, including + // other invalid TaskTokens. + bool operator==(const TaskToken& other) const; + bool operator!=(const TaskToken& other) const; + + // Returns true if this is a valid TaskToken. + bool IsValid() const; + + // In the scope of a ScopedSetSequenceTokenForCurrentThread, returns a valid + // TaskToken which isn't equal to any TaskToken returned in the scope of a + // different ScopedSetSequenceTokenForCurrentThread. Otherwise, returns an + // invalid TaskToken. + static TaskToken GetForCurrentThread(); + + private: + friend class ScopedSetSequenceTokenForCurrentThread; + + explicit TaskToken(int token) : token_(token) {} + + // Returns a valid TaskToken which isn't equal to any previously returned + // TaskToken. This is private as it only meant to be instantiated by + // ScopedSetSequenceTokenForCurrentThread. + static TaskToken Create(); + + static constexpr int kInvalidTaskToken = -1; + int token_ = kInvalidTaskToken; +}; + +// Instantiate this in the scope where a single task runs. +class BASE_EXPORT ScopedSetSequenceTokenForCurrentThread { + public: + // Throughout the lifetime of the constructed object, + // SequenceToken::GetForCurrentThread() will return |sequence_token| and + // TaskToken::GetForCurrentThread() will return a TaskToken which is not equal + // to any TaskToken returned in the scope of another + // ScopedSetSequenceTokenForCurrentThread. + ScopedSetSequenceTokenForCurrentThread(const SequenceToken& sequence_token); + ~ScopedSetSequenceTokenForCurrentThread(); + + private: + const SequenceToken sequence_token_; + const TaskToken task_token_; + + DISALLOW_COPY_AND_ASSIGN(ScopedSetSequenceTokenForCurrentThread); +}; + +} // namespace base + +#endif // BASE_SEQUENCE_TOKEN_H_ diff --git a/security/sandbox/chromium/base/sequenced_task_runner.h b/security/sandbox/chromium/base/sequenced_task_runner.h index 6bb3f2b8717b..0bedf2e1b925 100644 --- a/security/sandbox/chromium/base/sequenced_task_runner.h +++ b/security/sandbox/chromium/base/sequenced_task_runner.h @@ -154,6 +154,24 @@ class BASE_EXPORT SequencedTaskRunner : public TaskRunner { const void* object); }; +struct BASE_EXPORT OnTaskRunnerDeleter { + explicit OnTaskRunnerDeleter(scoped_refptr task_runner); + ~OnTaskRunnerDeleter(); + + OnTaskRunnerDeleter(OnTaskRunnerDeleter&&); + OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&); + + template + void operator()(const T* ptr) { + if (task_runner_->RunsTasksOnCurrentThread()) + delete ptr; + else if (ptr) + task_runner_->DeleteSoon(FROM_HERE, ptr); + } + + scoped_refptr task_runner_; +}; + } // namespace base #endif // BASE_SEQUENCED_TASK_RUNNER_H_ diff --git a/security/sandbox/chromium/base/stl_util.h b/security/sandbox/chromium/base/stl_util.h index 12e226a9db9b..3f7555dde545 100644 --- a/security/sandbox/chromium/base/stl_util.h +++ b/security/sandbox/chromium/base/stl_util.h @@ -15,6 +15,8 @@ #include "base/logging.h" +namespace base { + // Clears internal memory of an STL object. // STL clear()/reserve(0) does not always free internal memory allocated // This function uses swap/destructor to ensure the internal memory is freed. @@ -27,69 +29,6 @@ void STLClearObject(T* obj) { obj->reserve(0); } -// For a range within a container of pointers, calls delete (non-array version) -// on these pointers. -// NOTE: for these three functions, we could just implement a DeleteObject -// functor and then call for_each() on the range and functor, but this -// requires us to pull in all of algorithm.h, which seems expensive. -// For hash_[multi]set, it is important that this deletes behind the iterator -// because the hash_set may call the hash function on the iterator when it is -// advanced, which could result in the hash function trying to deference a -// stale pointer. -template -void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete *temp; - } -} - -// For a range within a container of pairs, calls delete (non-array version) on -// BOTH items in the pairs. -// NOTE: Like STLDeleteContainerPointers, it is important that this deletes -// behind the iterator because if both the key and value are deleted, the -// container may call the hash function on the iterator when it is advanced, -// which could result in the hash function trying to dereference a stale -// pointer. -template -void STLDeleteContainerPairPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->first; - delete temp->second; - } -} - -// For a range within a container of pairs, calls delete (non-array version) on -// the FIRST item in the pairs. -// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. -template -void STLDeleteContainerPairFirstPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->first; - } -} - -// For a range within a container of pairs, calls delete. -// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. -// Deleting the value does not always invalidate the iterator, but it may -// do so if the key is a pointer into the value object. -template -void STLDeleteContainerPairSecondPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->second; - } -} - // Counts the number of instances of val in a container. template typename std::iterator_traits< @@ -124,15 +63,17 @@ inline char* string_as_array(std::string* str) { // and clear() methods. // // If container is NULL, this function is a no-op. -// -// As an alternative to calling STLDeleteElements() directly, consider -// STLElementDeleter (defined below), which ensures that your container's -// elements are deleted when the STLElementDeleter goes out of scope. template void STLDeleteElements(T* container) { if (!container) return; - STLDeleteContainerPointers(container->begin(), container->end()); + + for (auto it = container->begin(); it != container->end();) { + auto temp = it; + ++it; + delete *temp; + } + container->clear(); } @@ -143,46 +84,16 @@ template void STLDeleteValues(T* container) { if (!container) return; - STLDeleteContainerPairSecondPointers(container->begin(), container->end()); + + for (auto it = container->begin(); it != container->end();) { + auto temp = it; + ++it; + delete temp->second; + } + container->clear(); } - -// The following classes provide a convenient way to delete all elements or -// values from STL containers when they goes out of scope. This greatly -// simplifies code that creates temporary objects and has multiple return -// statements. Example: -// -// vector tmp_proto; -// STLElementDeleter > d(&tmp_proto); -// if (...) return false; -// ... -// return success; - -// Given a pointer to an STL container this class will delete all the element -// pointers when it goes out of scope. -template -class STLElementDeleter { - public: - STLElementDeleter(T* container) : container_(container) {} - ~STLElementDeleter() { STLDeleteElements(container_); } - - private: - T* container_; -}; - -// Given a pointer to an STL container this class will delete all the value -// pointers when it goes out of scope. -template -class STLValueDeleter { - public: - STLValueDeleter(T* container) : container_(container) {} - ~STLValueDeleter() { STLDeleteValues(container_); } - - private: - T* container_; -}; - // Test to see if a set, map, hash_set or hash_map contains a particular key. // Returns true if the key is in the collection. template @@ -198,8 +109,6 @@ bool ContainsValue(const Collection& collection, const Value& value) { collection.end(); } -namespace base { - // Returns true if the container is sorted. template bool STLIsSorted(const Container& cont) { diff --git a/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc b/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc index 931ace8b1245..1a21728a8e5f 100644 --- a/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc +++ b/security/sandbox/chromium/base/strings/safe_sprintf_unittest.cc @@ -10,10 +10,10 @@ #include #include +#include #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -205,7 +205,7 @@ TEST(SafeSPrintfTest, ASANFriendlyBufferTest) { // There is a more complicated test in PrintLongString() that covers a lot // more edge case, but it is also harder to debug in case of a failure. const char kTestString[] = "This is a test"; - scoped_ptr buf(new char[sizeof(kTestString)]); + std::unique_ptr buf(new char[sizeof(kTestString)]); EXPECT_EQ(static_cast(sizeof(kTestString) - 1), SafeSNPrintf(buf.get(), sizeof(kTestString), kTestString)); EXPECT_EQ(std::string(kTestString), std::string(buf.get())); @@ -369,7 +369,7 @@ void PrintLongString(char* buf, size_t sz) { // Allocate slightly more space, so that we can verify that SafeSPrintf() // never writes past the end of the buffer. - scoped_ptr tmp(new char[sz+2]); + std::unique_ptr tmp(new char[sz + 2]); memset(tmp.get(), 'X', sz+2); // Use SafeSPrintf() to output a complex list of arguments: @@ -383,7 +383,7 @@ void PrintLongString(char* buf, size_t sz) { char* out = tmp.get(); size_t out_sz = sz; size_t len; - for (scoped_ptr perfect_buf;;) { + for (std::unique_ptr perfect_buf;;) { size_t needed = SafeSNPrintf(out, out_sz, #if defined(NDEBUG) "A%2cong %s: %d %010X %d %p%7s", 'l', "string", "", diff --git a/security/sandbox/chromium/base/strings/string16.h b/security/sandbox/chromium/base/strings/string16.h index e47669c1b565..30f4e3eec0ce 100644 --- a/security/sandbox/chromium/base/strings/string16.h +++ b/security/sandbox/chromium/base/strings/string16.h @@ -29,6 +29,8 @@ #include #include #include + +#include #include #include "base/base_export.h" @@ -46,6 +48,8 @@ typedef std::char_traits string16_char_traits; #elif defined(WCHAR_T_IS_UTF32) +#include // for mbstate_t + namespace base { typedef uint16_t char16; @@ -182,6 +186,21 @@ BASE_EXPORT extern void PrintTo(const string16& str, std::ostream* out); extern template class BASE_EXPORT std::basic_string; +// Specialize std::hash for base::string16. Although the style guide forbids +// this in general, it is necessary for consistency with WCHAR_T_IS_UTF16 +// platforms, where base::string16 is a type alias for std::wstring. +namespace std { +template <> +struct hash { + std::size_t operator()(const base::string16& s) const { + std::size_t result = 0; + for (base::char16 c : s) + result = (result * 131) + c; + return result; + } +}; +} // namespace std + #endif // WCHAR_T_IS_UTF32 #endif // BASE_STRINGS_STRING16_H_ diff --git a/security/sandbox/chromium/base/strings/string_number_conversions.cc b/security/sandbox/chromium/base/strings/string_number_conversions.cc index 07248501e315..755811ded7e3 100644 --- a/security/sandbox/chromium/base/strings/string_number_conversions.cc +++ b/security/sandbox/chromium/base/strings/string_number_conversions.cc @@ -12,10 +12,8 @@ #include #include "base/logging.h" -#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" #include "base/scoped_clear_errno.h" -#include "base/strings/utf_string_conversions.h" #include "base/third_party/dmg_fp/dmg_fp.h" namespace base { @@ -146,6 +144,7 @@ class IteratorRangeToNumber { if (begin != end && *begin == '-') { if (!std::numeric_limits::is_signed) { + *output = 0; valid = false; } else if (!Negative::Invoke(begin + 1, end, output)) { valid = false; diff --git a/security/sandbox/chromium/base/strings/string_number_conversions.h b/security/sandbox/chromium/base/strings/string_number_conversions.h index 1265f0dcba3a..a3b876aa155c 100644 --- a/security/sandbox/chromium/base/strings/string_number_conversions.h +++ b/security/sandbox/chromium/base/strings/string_number_conversions.h @@ -25,6 +25,14 @@ // Please do not add "convenience" functions for converting strings to integers // that return the value and ignore success/failure. That encourages people to // write code that doesn't properly handle the error conditions. +// +// DO NOT use these functions in any UI unless it's NOT localized on purpose. +// Instead, use base::MessageFormatter for a complex message with numbers +// (integer, float, double) embedded or base::Format{Number,Double,Percent} to +// just format a single number/percent. Note that some languages use native +// digits instead of ASCII digits while others use a group separator or decimal +// point different from ',' and '.'. Using these functions in the UI would lead +// numbers to be formatted in a non-native way. // ---------------------------------------------------------------------------- namespace base { diff --git a/security/sandbox/chromium/base/strings/string_piece.h b/security/sandbox/chromium/base/strings/string_piece.h index 31e7596d119c..eaec14de5da7 100644 --- a/security/sandbox/chromium/base/strings/string_piece.h +++ b/security/sandbox/chromium/base/strings/string_piece.h @@ -28,7 +28,6 @@ #include #include "base/base_export.h" -#include "base/containers/hash_tables.h" #include "base/logging.h" #include "base/strings/string16.h" @@ -224,6 +223,8 @@ template class BasicStringPiece { } value_type operator[](size_type i) const { return ptr_[i]; } + value_type front() const { return ptr_[0]; } + value_type back() const { return ptr_[length_ - 1]; } void remove_prefix(size_type n) { ptr_ += n; @@ -432,38 +433,32 @@ inline bool operator>=(const StringPiece16& x, const StringPiece16& y) { BASE_EXPORT std::ostream& operator<<(std::ostream& o, const StringPiece& piece); -} // namespace base - // Hashing --------------------------------------------------------------------- // We provide appropriate hash functions so StringPiece and StringPiece16 can // be used as keys in hash sets and maps. -// This hash function is copied from base/containers/hash_tables.h. We don't -// use the ones already defined for string and string16 directly because it -// would require the string constructors to be called, which we don't want. -#define HASH_STRING_PIECE(StringPieceType, string_piece) \ - std::size_t result = 0; \ - for (StringPieceType::const_iterator i = string_piece.begin(); \ - i != string_piece.end(); ++i) \ - result = (result * 131) + *i; \ - return result; \ +// This hash function is copied from base/strings/string16.h. We don't use the +// ones already defined for string and string16 directly because it would +// require the string constructors to be called, which we don't want. +#define HASH_STRING_PIECE(StringPieceType, string_piece) \ + std::size_t result = 0; \ + for (StringPieceType::const_iterator i = string_piece.begin(); \ + i != string_piece.end(); ++i) \ + result = (result * 131) + *i; \ + return result; -namespace BASE_HASH_NAMESPACE { - -template<> -struct hash { - std::size_t operator()(const base::StringPiece& sp) const { - HASH_STRING_PIECE(base::StringPiece, sp); +struct StringPieceHash { + std::size_t operator()(const StringPiece& sp) const { + HASH_STRING_PIECE(StringPiece, sp); } }; -template<> -struct hash { - std::size_t operator()(const base::StringPiece16& sp16) const { - HASH_STRING_PIECE(base::StringPiece16, sp16); +struct StringPiece16Hash { + std::size_t operator()(const StringPiece16& sp16) const { + HASH_STRING_PIECE(StringPiece16, sp16); } }; -} // namespace BASE_HASH_NAMESPACE +} // namespace base #endif // BASE_STRINGS_STRING_PIECE_H_ diff --git a/security/sandbox/chromium/base/strings/string_split.cc b/security/sandbox/chromium/base/strings/string_split.cc index 6c949b989a9b..a8180b24d367 100644 --- a/security/sandbox/chromium/base/strings/string_split.cc +++ b/security/sandbox/chromium/base/strings/string_split.cc @@ -227,18 +227,22 @@ bool SplitStringIntoKeyValuePairs(StringPiece input, return success; } -void SplitStringUsingSubstr(StringPiece16 input, - StringPiece16 delimiter, - std::vector* result) { - SplitStringUsingSubstrT(input, delimiter, TRIM_WHITESPACE, SPLIT_WANT_ALL, - result); +std::vector SplitStringUsingSubstr(StringPiece16 input, + StringPiece16 delimiter, + WhitespaceHandling whitespace, + SplitResult result_type) { + std::vector result; + SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); + return result; } -void SplitStringUsingSubstr(StringPiece input, - StringPiece delimiter, - std::vector* result) { - SplitStringUsingSubstrT(input, delimiter, TRIM_WHITESPACE, SPLIT_WANT_ALL, - result); +std::vector SplitStringUsingSubstr(StringPiece input, + StringPiece delimiter, + WhitespaceHandling whitespace, + SplitResult result_type) { + std::vector result; + SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); + return result; } std::vector SplitStringPieceUsingSubstr( diff --git a/security/sandbox/chromium/base/strings/string_split.h b/security/sandbox/chromium/base/strings/string_split.h index ec9f24604a63..24b9dfa1e9fb 100644 --- a/security/sandbox/chromium/base/strings/string_split.h +++ b/security/sandbox/chromium/base/strings/string_split.h @@ -90,16 +90,16 @@ BASE_EXPORT bool SplitStringIntoKeyValuePairs(StringPiece input, // Similar to SplitString, but use a substring delimiter instead of a list of // characters that are all possible delimiters. -// -// TODO(brettw) this should probably be changed and expanded to provide a -// mirror of the SplitString[Piece] API above, just with the different -// delimiter handling. -BASE_EXPORT void SplitStringUsingSubstr(StringPiece16 input, - StringPiece16 delimiter, - std::vector* result); -BASE_EXPORT void SplitStringUsingSubstr(StringPiece input, - StringPiece delimiter, - std::vector* result); +BASE_EXPORT std::vector SplitStringUsingSubstr( + StringPiece16 input, + StringPiece16 delimiter, + WhitespaceHandling whitespace, + SplitResult result_type); +BASE_EXPORT std::vector SplitStringUsingSubstr( + StringPiece input, + StringPiece delimiter, + WhitespaceHandling whitespace, + SplitResult result_type); // Like SplitStringUsingSubstr above except it returns a vector of StringPieces // which reference the original buffer without copying. Although you have to be diff --git a/security/sandbox/chromium/base/strings/string_util.cc b/security/sandbox/chromium/base/strings/string_util.cc index e8000abd40bc..cb668ed7fff4 100644 --- a/security/sandbox/chromium/base/strings/string_util.cc +++ b/security/sandbox/chromium/base/strings/string_util.cc @@ -23,7 +23,6 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/singleton.h" -#include "base/strings/string_split.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/strings/utf_string_conversions.h" #include "base/third_party/icu/icu_utf.h" @@ -888,6 +887,7 @@ OutStringType DoReplaceStringPlaceholders( const std::vector& subst, std::vector* offsets) { size_t substitutions = subst.size(); + DCHECK_LT(substitutions, 10U); size_t sub_length = 0; for (const auto& cur : subst) @@ -901,7 +901,6 @@ OutStringType DoReplaceStringPlaceholders( if ('$' == *i) { if (i + 1 != format_string.end()) { ++i; - DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; if ('$' == *i) { while (i != format_string.end() && '$' == *i) { formatted.push_back('$'); @@ -909,14 +908,11 @@ OutStringType DoReplaceStringPlaceholders( } --i; } else { - uintptr_t index = 0; - while (i != format_string.end() && '0' <= *i && *i <= '9') { - index *= 10; - index += *i - '0'; - ++i; + if (*i < '1' || *i > '9') { + DLOG(ERROR) << "Invalid placeholder: $" << *i; + continue; } - --i; - index -= 1; + uintptr_t index = *i - '1'; if (offsets) { ReplacementOffset r_offset(index, static_cast(formatted.size())); diff --git a/security/sandbox/chromium/base/strings/string_util.h b/security/sandbox/chromium/base/strings/string_util.h index e369f294d0ba..31c900362d57 100644 --- a/security/sandbox/chromium/base/strings/string_util.h +++ b/security/sandbox/chromium/base/strings/string_util.h @@ -337,7 +337,15 @@ inline bool IsAsciiWhitespace(Char c) { } template inline bool IsAsciiAlpha(Char c) { - return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')); + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} +template +inline bool IsAsciiUpper(Char c) { + return c >= 'A' && c <= 'Z'; +} +template +inline bool IsAsciiLower(Char c) { + return c >= 'a' && c <= 'z'; } template inline bool IsAsciiDigit(Char c) { @@ -429,7 +437,7 @@ BASE_EXPORT std::string JoinString(const std::vector& parts, BASE_EXPORT string16 JoinString(const std::vector& parts, StringPiece16 separator); -// Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively. +// Replace $1-$2-$3..$9 in the format string with values from |subst|. // Additionally, any number of consecutive '$' characters is replaced by that // number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be // NULL. This only allows you to use up to nine replacements. diff --git a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h b/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h index c7164045390e..2d95870c5808 100644 --- a/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h +++ b/security/sandbox/chromium/base/strings/utf_string_conversion_utils.h @@ -5,7 +5,8 @@ #ifndef BASE_STRINGS_UTF_STRING_CONVERSION_UTILS_H_ #define BASE_STRINGS_UTF_STRING_CONVERSION_UTILS_H_ -// This should only be used by the various UTF string conversion files. +// Low-level UTF handling functions. Most code will want to use the functions +// in utf_string_conversions.h #include #include diff --git a/security/sandbox/chromium/base/synchronization/condition_variable.h b/security/sandbox/chromium/base/synchronization/condition_variable.h index a41b2ba5a781..b5677511728a 100644 --- a/security/sandbox/chromium/base/synchronization/condition_variable.h +++ b/security/sandbox/chromium/base/synchronization/condition_variable.h @@ -75,9 +75,12 @@ #include #endif +#if defined(OS_WIN) +#include +#endif + namespace base { -class ConditionVarImpl; class TimeDelta; class BASE_EXPORT ConditionVariable { @@ -88,11 +91,13 @@ class BASE_EXPORT ConditionVariable { ~ConditionVariable(); // Wait() releases the caller's critical section atomically as it starts to - // sleep, and the reacquires it when it is signaled. + // sleep, and the reacquires it when it is signaled. The wait functions are + // susceptible to spurious wakeups. (See usage note 1 for more details.) void Wait(); void TimedWait(const TimeDelta& max_time); - // Broadcast() revives all waiting threads. + // Broadcast() revives all waiting threads. (See usage note 2 for more + // details.) void Broadcast(); // Signal() revives one waiting thread. void Signal(); @@ -100,14 +105,15 @@ class BASE_EXPORT ConditionVariable { private: #if defined(OS_WIN) - ConditionVarImpl* impl_; + CONDITION_VARIABLE cv_; + SRWLOCK* const srwlock_; #elif defined(OS_POSIX) pthread_cond_t condition_; pthread_mutex_t* user_mutex_; -#if DCHECK_IS_ON() - base::Lock* user_lock_; // Needed to adjust shadow lock state on wait. #endif +#if DCHECK_IS_ON() && (defined(OS_WIN) || defined(OS_POSIX)) + base::Lock* const user_lock_; // Needed to adjust shadow lock state on wait. #endif DISALLOW_COPY_AND_ASSIGN(ConditionVariable); diff --git a/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc b/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc index d86fd180ec7f..d07c67181030 100644 --- a/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc +++ b/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc @@ -118,6 +118,8 @@ void ConditionVariable::TimedWait(const TimeDelta& max_time) { #endif // OS_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC #endif // OS_MACOSX + // On failure, we only expect the CV to timeout. Any other error value means + // that we've unexpectedly woken up. DCHECK(rv == 0 || rv == ETIMEDOUT); #if DCHECK_IS_ON() user_lock_->CheckUnheldAndMark(); diff --git a/security/sandbox/chromium/base/synchronization/lock.h b/security/sandbox/chromium/base/synchronization/lock.h index f7dd35dccba3..599984e8b6dc 100644 --- a/security/sandbox/chromium/base/synchronization/lock.h +++ b/security/sandbox/chromium/base/synchronization/lock.h @@ -38,9 +38,9 @@ class BASE_EXPORT Lock { Lock(); ~Lock(); - // NOTE: Although windows critical sections support recursive locks, we do not - // allow this, and we will commonly fire a DCHECK() if a thread attempts to - // acquire the lock a second time (while already holding it). + // NOTE: We do not permit recursive locks and will commonly fire a DCHECK() if + // a thread attempts to acquire the lock a second time (while already holding + // it). void Acquire() { lock_.Lock(); CheckUnheldAndMark(); @@ -61,15 +61,28 @@ class BASE_EXPORT Lock { void AssertAcquired() const; #endif // DCHECK_IS_ON() + // Whether Lock mitigates priority inversion when used from different thread + // priorities. + static bool HandlesMultipleThreadPriorities() { #if defined(OS_POSIX) - // The posix implementation of ConditionVariable needs to be able - // to see our lock and tweak our debugging counters, as it releases - // and acquires locks inside of pthread_cond_{timed,}wait. - friend class ConditionVariable; + // POSIX mitigates priority inversion by setting the priority of a thread + // holding a Lock to the maximum priority of any other thread waiting on it. + return internal::LockImpl::PriorityInheritanceAvailable(); #elif defined(OS_WIN) - // The Windows Vista implementation of ConditionVariable needs the - // native handle of the critical section. - friend class WinVistaCondVar; + // Windows mitigates priority inversion by randomly boosting the priority of + // ready threads. + // https://msdn.microsoft.com/library/windows/desktop/ms684831.aspx + return true; +#else +#error Unsupported platform +#endif + } + +#if defined(OS_POSIX) || defined(OS_WIN) + // Both Windows and POSIX implementations of ConditionVariable need to be + // able to see our lock and tweak our debugging counters, as they release and + // acquire locks inside of their condition variable APIs. + friend class ConditionVariable; #endif private: diff --git a/security/sandbox/chromium/base/synchronization/lock_impl.h b/security/sandbox/chromium/base/synchronization/lock_impl.h index ed85987b39e1..603585a05041 100644 --- a/security/sandbox/chromium/base/synchronization/lock_impl.h +++ b/security/sandbox/chromium/base/synchronization/lock_impl.h @@ -24,9 +24,9 @@ namespace internal { class BASE_EXPORT LockImpl { public: #if defined(OS_WIN) - typedef CRITICAL_SECTION NativeHandle; + using NativeHandle = SRWLOCK; #elif defined(OS_POSIX) - typedef pthread_mutex_t NativeHandle; + using NativeHandle = pthread_mutex_t; #endif LockImpl(); @@ -48,6 +48,11 @@ class BASE_EXPORT LockImpl { // unnecessary. NativeHandle* native_handle() { return &native_handle_; } +#if defined(OS_POSIX) + // Whether this lock will attempt to use priority inheritance. + static bool PriorityInheritanceAvailable(); +#endif + private: NativeHandle native_handle_; diff --git a/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc b/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc index 5619adaf5d82..e54595b87f10 100644 --- a/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc +++ b/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc @@ -7,27 +7,45 @@ #include #include +#include "base/debug/activity_tracker.h" #include "base/logging.h" +#include "base/synchronization/lock.h" namespace base { namespace internal { +// Determines which platforms can consider using priority inheritance locks. Use +// this define for platform code that may not compile if priority inheritance +// locks aren't available. For this platform code, +// PRIORITY_INHERITANCE_LOCKS_POSSIBLE() is a necessary but insufficient check. +// Lock::PriorityInheritanceAvailable still must be checked as the code may +// compile but the underlying platform still may not correctly support priority +// inheritance locks. +#if defined(OS_NACL) || defined(OS_ANDROID) +#define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 0 +#else +#define PRIORITY_INHERITANCE_LOCKS_POSSIBLE() 1 +#endif + LockImpl::LockImpl() { -#ifndef NDEBUG - // In debug, setup attributes for lock error checking. pthread_mutexattr_t mta; int rv = pthread_mutexattr_init(&mta); DCHECK_EQ(rv, 0) << ". " << strerror(rv); +#if PRIORITY_INHERITANCE_LOCKS_POSSIBLE() + if (PriorityInheritanceAvailable()) { + rv = pthread_mutexattr_setprotocol(&mta, PTHREAD_PRIO_INHERIT); + DCHECK_EQ(rv, 0) << ". " << strerror(rv); + } +#endif +#ifndef NDEBUG + // In debug, setup attributes for lock error checking. rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); DCHECK_EQ(rv, 0) << ". " << strerror(rv); +#endif rv = pthread_mutex_init(&native_handle_, &mta); DCHECK_EQ(rv, 0) << ". " << strerror(rv); rv = pthread_mutexattr_destroy(&mta); DCHECK_EQ(rv, 0) << ". " << strerror(rv); -#else - // In release, go with the default lock attributes. - pthread_mutex_init(&native_handle_, NULL); -#endif } LockImpl::~LockImpl() { @@ -42,6 +60,7 @@ bool LockImpl::Try() { } void LockImpl::Lock() { + base::debug::ScopedLockAcquireActivity lock_activity(this); int rv = pthread_mutex_lock(&native_handle_); DCHECK_EQ(rv, 0) << ". " << strerror(rv); } @@ -51,5 +70,29 @@ void LockImpl::Unlock() { DCHECK_EQ(rv, 0) << ". " << strerror(rv); } +// static +bool LockImpl::PriorityInheritanceAvailable() { +#if PRIORITY_INHERITANCE_LOCKS_POSSIBLE() && defined(OS_MACOSX) + return true; +#else + // Security concerns prevent the use of priority inheritance mutexes on Linux. + // * CVE-2010-0622 - wake_futex_pi unlocks incorrect, possible DoS. + // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0622 + // * CVE-2012-6647 - Linux < 3.5.1, futex_wait_requeue_pi possible DoS. + // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6647 + // * CVE-2014-3153 - Linux <= 3.14.5, futex_requeue, privilege escalation. + // https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3153 + // + // If the above were all addressed, we still need a runtime check to deal with + // the bug below. + // * glibc Bug 14652: https://sourceware.org/bugzilla/show_bug.cgi?id=14652 + // Fixed in glibc 2.17. + // Priority inheritance mutexes may deadlock with condition variables + // during recacquisition of the mutex after the condition variable is + // signalled. + return false; +#endif +} + } // namespace internal } // namespace base diff --git a/security/sandbox/chromium/base/synchronization/lock_impl_win.cc b/security/sandbox/chromium/base/synchronization/lock_impl_win.cc index fbc1bdd464b0..31f95f4e394b 100644 --- a/security/sandbox/chromium/base/synchronization/lock_impl_win.cc +++ b/security/sandbox/chromium/base/synchronization/lock_impl_win.cc @@ -4,32 +4,26 @@ #include "base/synchronization/lock_impl.h" +#include "base/debug/activity_tracker.h" + namespace base { namespace internal { -LockImpl::LockImpl() { - // The second parameter is the spin count, for short-held locks it avoid the - // contending thread from going to sleep which helps performance greatly. - ::InitializeCriticalSectionAndSpinCount(&native_handle_, 2000); -} +LockImpl::LockImpl() : native_handle_(SRWLOCK_INIT) {} -LockImpl::~LockImpl() { - ::DeleteCriticalSection(&native_handle_); -} +LockImpl::~LockImpl() = default; bool LockImpl::Try() { - if (::TryEnterCriticalSection(&native_handle_) != FALSE) { - return true; - } - return false; + return !!::TryAcquireSRWLockExclusive(&native_handle_); } void LockImpl::Lock() { - ::EnterCriticalSection(&native_handle_); + base::debug::ScopedLockAcquireActivity lock_activity(this); + ::AcquireSRWLockExclusive(&native_handle_); } void LockImpl::Unlock() { - ::LeaveCriticalSection(&native_handle_); + ::ReleaseSRWLockExclusive(&native_handle_); } } // namespace internal diff --git a/security/sandbox/chromium/base/synchronization/waitable_event.h b/security/sandbox/chromium/base/synchronization/waitable_event.h index b5d91d00b51f..3863e98455ee 100644 --- a/security/sandbox/chromium/base/synchronization/waitable_event.h +++ b/security/sandbox/chromium/base/synchronization/waitable_event.h @@ -43,11 +43,18 @@ class TimeDelta; // be better off just using an Windows event directly. class BASE_EXPORT WaitableEvent { public: - // If manual_reset is true, then to set the event state to non-signaled, a - // consumer must call the Reset method. If this parameter is false, then the - // system automatically resets the event state to non-signaled after a single - // waiting thread has been released. - WaitableEvent(bool manual_reset, bool initially_signaled); + // Indicates whether a WaitableEvent should automatically reset the event + // state after a single waiting thread has been released or remain signaled + // until Reset() is manually invoked. + enum class ResetPolicy { MANUAL, AUTOMATIC }; + + // Indicates whether a new WaitableEvent should start in a signaled state or + // not. + enum class InitialState { SIGNALED, NOT_SIGNALED }; + + // Constructs a WaitableEvent with policy and initial state as detailed in + // the above enums. + WaitableEvent(ResetPolicy reset_policy, InitialState initial_state); #if defined(OS_WIN) // Create a WaitableEvent from an Event HANDLE which has already been @@ -150,7 +157,7 @@ class BASE_EXPORT WaitableEvent { struct WaitableEventKernel : public RefCountedThreadSafe { public: - WaitableEventKernel(bool manual_reset, bool initially_signaled); + WaitableEventKernel(ResetPolicy reset_policy, InitialState initial_state); bool Dequeue(Waiter* waiter, void* tag); diff --git a/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc b/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc index 64d4376fe565..a8b686b88ce8 100644 --- a/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc +++ b/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc @@ -7,6 +7,7 @@ #include #include +#include "base/debug/activity_tracker.h" #include "base/logging.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" @@ -39,12 +40,11 @@ namespace base { // ----------------------------------------------------------------------------- // This is just an abstract base class for waking the two types of waiters // ----------------------------------------------------------------------------- -WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) - : kernel_(new WaitableEventKernel(manual_reset, initially_signaled)) { -} +WaitableEvent::WaitableEvent(ResetPolicy reset_policy, + InitialState initial_state) + : kernel_(new WaitableEventKernel(reset_policy, initial_state)) {} -WaitableEvent::~WaitableEvent() { -} +WaitableEvent::~WaitableEvent() = default; void WaitableEvent::Reset() { base::AutoLock locked(kernel_->lock_); @@ -158,6 +158,9 @@ void WaitableEvent::Wait() { } bool WaitableEvent::TimedWait(const TimeDelta& max_time) { + // Record the event that this thread is blocking upon (for hang diagnosis). + base::debug::ScopedEventWaitActivity event_activity(this); + base::ThreadRestrictions::AssertWaitAllowed(); const TimeTicks end_time(TimeTicks::Now() + max_time); const bool finite_time = max_time.ToInternalValue() >= 0; @@ -233,6 +236,9 @@ size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables, base::ThreadRestrictions::AssertWaitAllowed(); DCHECK(count) << "Cannot wait on no events"; + // Record an event (the first) that this thread is blocking upon. + base::debug::ScopedEventWaitActivity event_activity(raw_waitables[0]); + // We need to acquire the locks in a globally consistent order. Thus we sort // the array of waitables by address. We actually sort a pairs so that we can // map back to the original index values later. @@ -348,14 +354,13 @@ size_t WaitableEvent::EnqueueMany // ----------------------------------------------------------------------------- // Private functions... -WaitableEvent::WaitableEventKernel::WaitableEventKernel(bool manual_reset, - bool initially_signaled) - : manual_reset_(manual_reset), - signaled_(initially_signaled) { -} +WaitableEvent::WaitableEventKernel::WaitableEventKernel( + ResetPolicy reset_policy, + InitialState initial_state) + : manual_reset_(reset_policy == ResetPolicy::MANUAL), + signaled_(initial_state == InitialState::SIGNALED) {} -WaitableEvent::WaitableEventKernel::~WaitableEventKernel() { -} +WaitableEvent::WaitableEventKernel::~WaitableEventKernel() = default; // ----------------------------------------------------------------------------- // Wake all waiting waiters. Called with lock held. diff --git a/security/sandbox/chromium/base/task_runner.h b/security/sandbox/chromium/base/task_runner.h index 6dd82ccaca99..9593835eebbd 100644 --- a/security/sandbox/chromium/base/task_runner.h +++ b/security/sandbox/chromium/base/task_runner.h @@ -9,13 +9,10 @@ #include "base/base_export.h" #include "base/callback_forward.h" +#include "base/location.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" -namespace tracked_objects { -class Location; -} // namespace tracked_objects - namespace base { struct TaskRunnerTraits; diff --git a/security/sandbox/chromium/base/task_scheduler/task_traits.h b/security/sandbox/chromium/base/task_scheduler/task_traits.h new file mode 100644 index 000000000000..93b6d71e9c7c --- /dev/null +++ b/security/sandbox/chromium/base/task_scheduler/task_traits.h @@ -0,0 +1,132 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TASK_SCHEDULER_TASK_TRAITS_H_ +#define BASE_TASK_SCHEDULER_TASK_TRAITS_H_ + +#include + +#include + +#include "base/base_export.h" +#include "build/build_config.h" + +namespace base { + +// Valid priorities supported by the task scheduler. Note: internal algorithms +// depend on priorities being expressed as a continuous zero-based list from +// lowest to highest priority. Users of this API shouldn't otherwise care about +// nor use the underlying values. +enum class TaskPriority { + // This will always be equal to the lowest priority available. + LOWEST = 0, + // User won't notice if this task takes an arbitrarily long time to complete. + BACKGROUND = LOWEST, + // This task affects UI or responsiveness of future user interactions. It is + // not an immediate response to a user interaction. + // Examples: + // - Updating the UI to reflect progress on a long task. + // - Loading data that might be shown in the UI after a future user + // interaction. + USER_VISIBLE, + // This task affects UI immediately after a user interaction. + // Example: Generating data shown in the UI immediately after a click. + USER_BLOCKING, + // This will always be equal to the highest priority available. + HIGHEST = USER_BLOCKING, +}; + +// Valid shutdown behaviors supported by the task scheduler. +enum class TaskShutdownBehavior { + // Tasks posted with this mode which have not started executing before + // shutdown is initiated will never run. Tasks with this mode running at + // shutdown will be ignored (the worker will not be joined). + // + // This option provides a nice way to post stuff you don't want blocking + // shutdown. For example, you might be doing a slow DNS lookup and if it's + // blocked on the OS, you may not want to stop shutdown, since the result + // doesn't really matter at that point. + // + // However, you need to be very careful what you do in your callback when you + // use this option. Since the thread will continue to run until the OS + // terminates the process, the app can be in the process of tearing down when + // you're running. This means any singletons or global objects you use may + // suddenly become invalid out from under you. For this reason, it's best to + // use this only for slow but simple operations like the DNS example. + CONTINUE_ON_SHUTDOWN, + + // Tasks posted with this mode that have not started executing at + // shutdown will never run. However, any task that has already begun + // executing when shutdown is invoked will be allowed to continue and + // will block shutdown until completion. + // + // Note: Because TaskScheduler::Shutdown() may block while these tasks are + // executing, care must be taken to ensure that they do not block on the + // thread that called TaskScheduler::Shutdown(), as this may lead to deadlock. + SKIP_ON_SHUTDOWN, + + // Tasks posted with this mode before shutdown is complete will block shutdown + // until they're executed. Generally, this should be used only to save + // critical user data. + // + // Note: Tasks with BACKGROUND priority that block shutdown will be promoted + // to USER_VISIBLE priority during shutdown. + BLOCK_SHUTDOWN, +}; + +// Describes metadata for a single task or a group of tasks. +class BASE_EXPORT TaskTraits { + public: + // Constructs a default TaskTraits for tasks with + // (1) no I/O, + // (2) low priority, and + // (3) may block shutdown or be skipped on shutdown. + // Tasks that require stricter guarantees should highlight those by requesting + // explicit traits below. + TaskTraits(); + TaskTraits(const TaskTraits& other) = default; + TaskTraits& operator=(const TaskTraits& other) = default; + ~TaskTraits(); + + // Allows tasks with these traits to do file I/O. + TaskTraits& WithFileIO(); + + // Applies |priority| to tasks with these traits. + TaskTraits& WithPriority(TaskPriority priority); + + // Applies |shutdown_behavior| to tasks with these traits. + TaskTraits& WithShutdownBehavior(TaskShutdownBehavior shutdown_behavior); + + // Returns true if file I/O is allowed by these traits. + bool with_file_io() const { return with_file_io_; } + + // Returns the priority of tasks with these traits. + TaskPriority priority() const { return priority_; } + + // Returns the shutdown behavior of tasks with these traits. + TaskShutdownBehavior shutdown_behavior() const { return shutdown_behavior_; } + + private: + bool with_file_io_; + TaskPriority priority_; + TaskShutdownBehavior shutdown_behavior_; +}; + +// Returns string literals for the enums defined in this file. These methods +// should only be used for tracing and debugging. +BASE_EXPORT const char* TaskPriorityToString(TaskPriority task_priority); +BASE_EXPORT const char* TaskShutdownBehaviorToString( + TaskShutdownBehavior task_priority); + +// Stream operators so that the enums defined in this file can be used in +// DCHECK and EXPECT statements. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, + const TaskPriority& shutdown_behavior); +BASE_EXPORT std::ostream& operator<<( + std::ostream& os, + const TaskShutdownBehavior& shutdown_behavior); + +} // namespace base + +#endif // BASE_TASK_SCHEDULER_TASK_TRAITS_H_ diff --git a/security/sandbox/chromium/base/template_util.h b/security/sandbox/chromium/base/template_util.h index d58807a77ce7..1bfc1ac814a2 100644 --- a/security/sandbox/chromium/base/template_util.h +++ b/security/sandbox/chromium/base/template_util.h @@ -6,117 +6,128 @@ #define BASE_TEMPLATE_UTIL_H_ #include +#include +#include +#include #include "build/build_config.h" +// This hacks around libstdc++ 4.6 missing stuff in type_traits, while we need +// to support it. +#define CR_GLIBCXX_4_7_0 20120322 +#define CR_GLIBCXX_4_5_4 20120702 +#define CR_GLIBCXX_4_6_4 20121127 +#if defined(__GLIBCXX__) && \ + (__GLIBCXX__ < CR_GLIBCXX_4_7_0 || __GLIBCXX__ == CR_GLIBCXX_4_5_4 || \ + __GLIBCXX__ == CR_GLIBCXX_4_6_4) +#define CR_USE_FALLBACKS_FOR_OLD_GLIBCXX +#endif + namespace base { -// template definitions from tr1 +template struct is_non_const_reference : std::false_type {}; +template struct is_non_const_reference : std::true_type {}; +template struct is_non_const_reference : std::false_type {}; -template -struct integral_constant { - static const T value = v; - typedef T value_type; - typedef integral_constant type; -}; - -template const T integral_constant::value; - -typedef integral_constant true_type; -typedef integral_constant false_type; - -template struct is_pointer : false_type {}; -template struct is_pointer : true_type {}; - -// Member function pointer detection. This is built-in to C++ 11's stdlib, and -// we can remove this when we switch to it. -template -struct is_member_function_pointer : false_type {}; - -template -struct is_member_function_pointer : true_type {}; -template -struct is_member_function_pointer : true_type {}; - - -template struct is_same : public false_type {}; -template struct is_same : true_type {}; - -template struct is_array : public false_type {}; -template struct is_array : public true_type {}; -template struct is_array : public true_type {}; - -template struct is_non_const_reference : false_type {}; -template struct is_non_const_reference : true_type {}; -template struct is_non_const_reference : false_type {}; - -template struct is_const : false_type {}; -template struct is_const : true_type {}; - -template struct is_void : false_type {}; -template <> struct is_void : true_type {}; +// is_assignable namespace internal { -// Types YesType and NoType are guaranteed such that sizeof(YesType) < -// sizeof(NoType). -typedef char YesType; - -struct NoType { - YesType dummy[2]; +template +struct SelectSecond { + using type = Second; }; -// This class is an implementation detail for is_convertible, and you -// don't need to know how it works to use is_convertible. For those -// who care: we declare two different functions, one whose argument is -// of type To and one with a variadic argument list. We give them -// return types of different size, so we can use sizeof to trick the -// compiler into telling us which function it would have chosen if we -// had called it with an argument of type From. See Alexandrescu's -// _Modern C++ Design_ for more details on this sort of trick. - -struct ConvertHelper { - template - static YesType Test(To); - - template - static NoType Test(...); - - template - static From& Create(); +struct Any { + Any(...); }; -// Used to determine if a type is a struct/union/class. Inspired by Boost's -// is_class type_trait implementation. -struct IsClassHelper { - template - static YesType Test(void(C::*)(void)); +// True case: If |Lvalue| can be assigned to from |Rvalue|, then the return +// value is a true_type. +template +typename internal::SelectSecond< + decltype((std::declval() = std::declval())), + std::true_type>::type +IsAssignableTest(Lvalue&&, Rvalue&&); - template - static NoType Test(...); -}; +// False case: Otherwise the return value is a false_type. +template +std::false_type IsAssignableTest(internal::Any, Rvalue&&); + +// Default case: Neither Lvalue nor Rvalue is void. Uses IsAssignableTest to +// determine the type of IsAssignableImpl. +template ::value || std::is_void::value> +struct IsAssignableImpl + : public std::common_type(), + std::declval()))>::type {}; + +// Void case: Either Lvalue or Rvalue is void. Then the type of IsAssignableTest +// is false_type. +template +struct IsAssignableImpl : public std::false_type {}; + +// Uses expression SFINAE to detect whether using operator<< would work. +template +struct SupportsOstreamOperator : std::false_type {}; +template +struct SupportsOstreamOperator() + << std::declval()))> + : std::true_type {}; } // namespace internal -// Inherits from true_type if From is convertible to To, false_type otherwise. -// -// Note that if the type is convertible, this will be a true_type REGARDLESS -// of whether or not the conversion would emit a warning. -template -struct is_convertible - : integral_constant( - internal::ConvertHelper::Create())) == - sizeof(internal::YesType)> { +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +template +struct is_assignable : public internal::IsAssignableImpl {}; + +// is_copy_assignable is true if a T const& is assignable to a T&. +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +template +struct is_copy_assignable + : public is_assignable::type, + typename std::add_lvalue_reference< + typename std::add_const::type>::type> {}; + +// is_move_assignable is true if a T&& is assignable to a T&. +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +template +struct is_move_assignable + : public is_assignable::type, + const typename std::add_rvalue_reference::type> { }; +// underlying_type produces the integer type backing an enum type. +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +#if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) template -struct is_class - : integral_constant(0)) == - sizeof(internal::YesType)> { +struct underlying_type { + using type = __underlying_type(T); }; +#else +template +using underlying_type = std::underlying_type; +#endif + +// TODO(crbug.com/554293): Remove this when all platforms have this in the std +// namespace. +#if defined(CR_USE_FALLBACKS_FOR_OLD_GLIBCXX) +template +using is_trivially_destructible = std::has_trivial_destructor; +#else +template +using is_trivially_destructible = std::is_trivially_destructible; +#endif } // namespace base +#undef CR_USE_FALLBACKS_FOR_OLD_GLIBCXX + #endif // BASE_TEMPLATE_UTIL_H_ diff --git a/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc b/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc index 502c16cc72f3..19dbdebd63cc 100644 --- a/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc +++ b/security/sandbox/chromium/base/third_party/dmg_fp/dtoa.cc @@ -32,6 +32,7 @@ */ /* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * (Note that IEEE arithmetic is disabled by gcc's -ffast-math flag.) * * This strtod returns a nearest machine number to the input decimal * string (or sets errno to ERANGE). With IEEE arithmetic, ties are @@ -70,7 +71,8 @@ * #define IBM for IBM mainframe-style floating-point arithmetic. * #define VAX for VAX-style floating-point arithmetic (D_floating). * #define No_leftright to omit left-right logic in fast floating-point - * computation of dtoa. + * computation of dtoa. This will cause dtoa modes 4 and 5 to be + * treated the same as modes 2 and 3 for some inputs. * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 * and strtod and dtoa should round accordingly. Unless Trust_FLT_ROUNDS * is also #defined, fegetround() will be queried for the rounding mode. @@ -78,13 +80,18 @@ * standard (and are specified to be consistent, with fesetround() * affecting the value of FLT_ROUNDS), but that some (Linux) systems * do not work correctly in this regard, so using fegetround() is more - * portable than using FLT_FOUNDS directly. + * portable than using FLT_ROUNDS directly. * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 * and Honor_FLT_ROUNDS is not #defined. * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines * that use extended-precision instructions to compute rounded * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic + * that rounds toward +Infinity. + * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased + * rounding when the underlying floating-point arithmetic uses + * unbiased rounding. This prevent using ordinary floating-point + * arithmetic when the result could be computed with one rounding error. * #define Inaccurate_Divide for IEEE-format with correctly rounded * products but inaccurate quotients, e.g., for Intel i860. * #define NO_LONG_LONG on machines that do not have a "long long" @@ -458,6 +465,11 @@ extern int strtod_diglim; #ifndef IEEE_Arith #define ROUND_BIASED +#else +#ifdef ROUND_BIASED_without_Round_Up +#undef ROUND_BIASED +#define ROUND_BIASED +#endif #endif #ifdef RND_PRODQUOT @@ -663,7 +675,7 @@ s2b #ifdef KR_headers (s, nd0, nd, y9, dplen) CONST char *s; int nd0, nd, dplen; ULong y9; #else - (CONST char *s, int nd0, int nd, ULong y9, int dplen) + (const char *s, int nd0, int nd, ULong y9, int dplen) #endif { Bigint *b; @@ -1500,14 +1512,11 @@ static CONST double tinytens[] = { 1e-16, 1e-32 }; #endif #ifdef Need_Hexdig /*{*/ +#if 0 static unsigned char hexdig[256]; static void -#ifdef KR_headers -htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; -#else htinit(unsigned char *h, unsigned char *s, int inc) -#endif { int i, j; for(i = 0; (j = s[i]) !=0; i++) @@ -1515,17 +1524,34 @@ htinit(unsigned char *h, unsigned char *s, int inc) } static void -#ifdef KR_headers -hexdig_init() -#else -hexdig_init(void) -#endif +hexdig_init(void) /* Use of hexdig_init omitted 20121220 to avoid a */ + /* race condition when multiple threads are used. */ { #define USC (unsigned char *) htinit(hexdig, USC "0123456789", 0x10); htinit(hexdig, USC "abcdef", 0x10 + 10); htinit(hexdig, USC "ABCDEF", 0x10 + 10); } +#else +static const unsigned char hexdig[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 16,17,18,19,20,21,22,23,24,25,0,0,0,0,0,0, + 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,26,27,28,29,30,31,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; +#endif #endif /* } Need_Hexdig */ #ifdef INFNAN_CHECK @@ -1543,7 +1569,7 @@ match #ifdef KR_headers (sp, t) char **sp, *t; #else - (CONST char **sp, CONST char *t) + (const char **sp, const char *t) #endif { int c, d; @@ -1565,15 +1591,14 @@ hexnan #ifdef KR_headers (rvp, sp) U *rvp; CONST char **sp; #else - (U *rvp, CONST char **sp) + (U *rvp, const char **sp) #endif { ULong c, x[2]; CONST char *s; int c1, havedig, udx0, xshift; - if (!hexdig['0']) - hexdig_init(); + /**** if (!hexdig['0']) hexdig_init(); ****/ x[0] = x[1] = 0; havedig = xshift = 0; udx0 = 1; @@ -1640,6 +1665,41 @@ hexnan #define kshift 4 #define kmask 15 #endif + +#if !defined(NO_HEX_FP) || defined(Honor_FLT_ROUNDS) /*{*/ + static Bigint * +#ifdef KR_headers +increment(b) Bigint *b; +#else +increment(Bigint *b) +#endif +{ + ULong *x, *xe; + Bigint *b1; + + x = b->x; + xe = x + b->wds; + do { + if (*x < (ULong)0xffffffffL) { + ++*x; + return b; + } + *x++ = 0; + } while(x < xe); + { + if (b->wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1,b); + Bfree(b); + b = b1; + } + b->x[b->wds++] = 1; + } + return b; + } + +#endif /*}*/ + #ifndef NO_HEX_FP /*{*/ static void @@ -1712,37 +1772,6 @@ enum { /* rounding values: same as FLT_ROUNDS */ Round_down = 3 }; - static Bigint * -#ifdef KR_headers -increment(b) Bigint *b; -#else -increment(Bigint *b) -#endif -{ - ULong *x, *xe; - Bigint *b1; - - x = b->x; - xe = x + b->wds; - do { - if (*x < (ULong)0xffffffffL) { - ++*x; - return b; - } - *x++ = 0; - } while(x < xe); - { - if (b->wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1,b); - Bfree(b); - b = b1; - } - b->x[b->wds++] = 1; - } - return b; - } - void #ifdef KR_headers gethex(sp, rvp, rounding, sign) @@ -1793,8 +1822,7 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) #endif #endif - if (!hexdig['0']) - hexdig_init(); + /**** if (!hexdig['0']) hexdig_init(); ****/ havedig = 0; s0 = *(CONST unsigned char **)sp + 2; while(s0[havedig] == '0') @@ -1894,6 +1922,8 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) #endif goto retz; #ifdef IEEE_Arith + ret_tinyf: + Bfree(b); ret_tiny: #ifndef NO_ERRNO errno = ERANGE; @@ -1994,15 +2024,15 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) switch (rounding) { case Round_near: if (n == nbits && (n < 2 || any_on(b,n-1))) - goto ret_tiny; + goto ret_tinyf; break; case Round_up: if (!sign) - goto ret_tiny; + goto ret_tinyf; break; case Round_down: if (sign) - goto ret_tiny; + goto ret_tinyf; } #endif /* } IEEE_Arith */ Bfree(b); @@ -2102,7 +2132,7 @@ gethex( CONST char **sp, U *rvp, int rounding, int sign) #endif Bfree(b); } -#endif /*}!NO_HEX_FP*/ +#endif /*!NO_HEX_FP}*/ static int #ifdef KR_headers @@ -2149,7 +2179,13 @@ quorem bxe = bx + n; q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ #ifdef DEBUG +#ifdef NO_STRTOD_BIGCOMP /*debug*/ if (q > 9) +#else + /* An oversized q is possible when quorem is called from bigcomp and */ + /* the input is near, e.g., twice the smallest denormalized number. */ + /*debug*/ if (q > 15) +#endif /*debug*/ Bug("oversized quotient in quorem"); #endif if (q) { @@ -2235,15 +2271,36 @@ quorem return q; } -#ifndef NO_STRTOD_BIGCOMP +#if defined(Avoid_Underflow) || !defined(NO_STRTOD_BIGCOMP) /*{*/ + static double +sulp +#ifdef KR_headers + (x, bc) U *x; BCinfo *bc; +#else + (U *x, BCinfo *bc) +#endif +{ + U u; + double rv; + int i; + rv = ulp(x); + if (!bc->scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0) + return rv; /* Is there an example where i <= 0 ? */ + word0(&u) = Exp_1 + (i << Exp_shift); + word1(&u) = 0; + return rv * u.d; + } +#endif /*}*/ + +#ifndef NO_STRTOD_BIGCOMP static void bigcomp #ifdef KR_headers (rv, s0, bc) U *rv; CONST char *s0; BCinfo *bc; #else - (U *rv, CONST char *s0, BCinfo *bc) + (U *rv, const char *s0, BCinfo *bc) #endif { Bigint *b, *d; @@ -2375,7 +2432,7 @@ bigcomp b = multadd(b, 10, 0); dig = quorem(b,d); } - if (b->x[0] || b->wds > 1) + if (dig > 0 || b->x[0] || b->wds > 1) dd = -1; ret: Bfree(b); @@ -2398,7 +2455,7 @@ bigcomp } if (!dsign) goto rethi1; - dval(rv) += 2.*ulp(rv); + dval(rv) += 2.*sulp(rv,bc); } else { bc->inexact = 0; @@ -2415,17 +2472,27 @@ bigcomp else if (dd < 0) { if (!dsign) /* does not happen for round-near */ retlow1: - dval(rv) -= ulp(rv); + dval(rv) -= sulp(rv,bc); } else if (dd > 0) { if (dsign) { rethi1: - dval(rv) += ulp(rv); + dval(rv) += sulp(rv,bc); } } else { /* Exact half-way case: apply round-even rule. */ - if (word1(rv) & 1) { + if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) { + i = 1 - j; + if (i <= 31) { + if (word1(rv) & (0x1 << i)) + goto odd; + } + else if (word0(rv) & (0x1 << (i-32))) + goto odd; + } + else if (word1(rv) & 1) { + odd: if (dsign) goto rethi1; goto retlow1; @@ -2444,21 +2511,27 @@ strtod #ifdef KR_headers (s00, se) CONST char *s00; char **se; #else - (CONST char *s00, char **se) + (const char *s00, char **se) #endif { int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1; - int esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + int esign, i, j, k, nd, nd0, nf, nz, nz0, nz1, sign; CONST char *s, *s0, *s1; double aadj, aadj1; Long L; U aadj2, adj, rv, rv0; ULong y, z; BCinfo bc; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; + Bigint *bb = nullptr, *bb1, *bd = nullptr, *bd0, *bs = nullptr, *delta = nullptr; +#ifdef Avoid_Underflow + ULong Lsb, Lsb1; +#endif #ifdef SET_INEXACT int oldinexact; #endif +#ifndef NO_STRTOD_BIGCOMP + int req_bigcomp = 0; +#endif #ifdef Honor_FLT_ROUNDS /*{*/ #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ bc.rounding = Flt_Rounds; @@ -2475,7 +2548,7 @@ strtod CONST char *s2; #endif - sign = nz0 = nz = bc.dplen = bc.uflchk = 0; + sign = nz0 = nz1 = nz = bc.dplen = bc.uflchk = 0; dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': @@ -2521,10 +2594,12 @@ strtod for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) if (nd < 9) y = 10*y + c - '0'; - else if (nd < 16) + else if (nd < DBL_DIG + 2) z = 10*z + c - '0'; nd0 = nd; bc.dp0 = bc.dp1 = s - s0; + for(s1 = s; s1 > s0 && *--s1 == '0'; ) + ++nz1; #ifdef USE_LOCALE s1 = localeconv()->decimal_point; if (c == *s1) { @@ -2552,6 +2627,8 @@ strtod for(; c == '0'; c = *++s) nz++; if (c > '0' && c <= '9') { + bc.dp0 = s0 - s; + bc.dp1 = bc.dp0 + bc.dplen; s0 = s; nf += nz; nz = 0; @@ -2567,13 +2644,13 @@ strtod for(i = 1; i < nz; i++) if (nd++ < 9) y *= 10; - else if (nd <= DBL_DIG + 1) + else if (nd <= DBL_DIG + 2) z *= 10; if (nd++ < 9) y = 10*y + c; - else if (nd <= DBL_DIG + 1) + else if (nd <= DBL_DIG + 2) z = 10*z + c; - nz = 0; + nz = nz1 = 0; } } } @@ -2597,8 +2674,11 @@ strtod if (c > '0' && c <= '9') { L = c - '0'; s1 = s; - while((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; + while((c = *++s) >= '0' && c <= '9') { + if (L < (INT_MAX - 10) / 10) { + L = 10*L + (c - '0'); + } + } if (s - s1 > 8 || L > 19999) /* Avoid confusion from exponents * so large that e might overflow. @@ -2660,7 +2740,7 @@ strtod if (!nd0) nd0 = nd; - k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + k = nd < DBL_DIG + 2 ? nd : DBL_DIG + 2; dval(&rv) = y; if (k > 9) { #ifdef SET_INEXACT @@ -2679,6 +2759,7 @@ strtod ) { if (!e) goto ret; +#ifndef ROUND_BIASED_without_Round_Up if (e > 0) { if (e <= Ten_pmax) { #ifdef VAX @@ -2739,6 +2820,7 @@ strtod goto ret; } #endif +#endif /* ROUND_BIASED_without_Round_Up */ } e1 += nd - k; @@ -2771,9 +2853,6 @@ strtod if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: -#ifndef NO_ERRNO - errno = ERANGE; -#endif /* Can't trust HUGE_VAL */ #ifdef IEEE_Arith #ifdef Honor_FLT_ROUNDS @@ -2800,6 +2879,17 @@ strtod word0(&rv) = Big0; word1(&rv) = Big1; #endif /*IEEE_Arith*/ + range_err: + if (bd0) { + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + } +#ifndef NO_ERRNO + errno = ERANGE; +#endif goto ret; } e1 >>= 4; @@ -2840,6 +2930,8 @@ strtod >> Exp_shift)) > 0) { /* scaled rv is denormal; clear j low bits */ if (j >= 32) { + if (j > 54) + goto undfl; word1(&rv) = 0; if (j >= 53) word0(&rv) = (P+2)*Exp_msk1; @@ -2863,10 +2955,7 @@ strtod if (!dval(&rv)) { undfl: dval(&rv) = 0.; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - goto ret; + goto range_err; } #ifndef Avoid_Underflow word0(&rv) = Tiny0; @@ -2883,7 +2972,7 @@ strtod /* Put digits into bd: true value = bd * 10^e */ - bc.nd = nd; + bc.nd = nd - nz1; #ifndef NO_STRTOD_BIGCOMP bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */ /* to silence an erroneous warning about bc.nd0 */ @@ -2896,7 +2985,7 @@ strtod if (i > nd0) j += bc.dplen; for(;;) { - if (--j <= bc.dp1 && j >= bc.dp0) + if (--j < bc.dp1 && j >= bc.dp0) j = bc.dp0 - 1; if (s0[j] != '0') break; @@ -2941,12 +3030,21 @@ strtod bs2++; #endif #ifdef Avoid_Underflow + Lsb = LSB; + Lsb1 = 0; j = bbe - bc.scale; i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; + j = P + 1 - bbbits; + if (i < Emin) { /* denormal */ + i = Emin - i; + j -= i; + if (i < 32) + Lsb <<= i; + else if (i < 52) + Lsb1 = Lsb << (i-32); + else + Lsb1 = Exp_mask; + } #else /*Avoid_Underflow*/ #ifdef Sudden_Underflow #ifdef IBM @@ -2994,24 +3092,26 @@ strtod bc.dsign = delta->sign; delta->sign = 0; i = cmp(delta, bs); -#ifndef NO_STRTOD_BIGCOMP +#ifndef NO_STRTOD_BIGCOMP /*{*/ if (bc.nd > nd && i <= 0) { - if (bc.dsign) - break; /* Must use bigcomp(). */ + if (bc.dsign) { + /* Must use bigcomp(). */ + req_bigcomp = 1; + break; + } #ifdef Honor_FLT_ROUNDS if (bc.rounding != 1) { - if (i < 0) + if (i < 0) { + req_bigcomp = 1; break; + } } else #endif - { - bc.nd = nd; i = -1; /* Discarded digits make delta smaller. */ - } } -#endif -#ifdef Honor_FLT_ROUNDS +#endif /*}*/ +#ifdef Honor_FLT_ROUNDS /*{*/ if (bc.rounding != 1) { if (i < 0) { /* Error is less than an ulp */ @@ -3045,7 +3145,7 @@ strtod } } apply_adj: -#ifdef Avoid_Underflow +#ifdef Avoid_Underflow /*{*/ if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) word0(&adj) += (2*P+1)*Exp_msk1 - y; @@ -3059,7 +3159,7 @@ strtod } else #endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ +#endif /*Avoid_Underflow}*/ dval(&rv) += adj.d*ulp(&rv); } break; @@ -3076,7 +3176,7 @@ strtod adj.d = y; } } -#ifdef Avoid_Underflow +#ifdef Avoid_Underflow /*{*/ if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) word0(&adj) += (2*P+1)*Exp_msk1 - y; #else @@ -3092,7 +3192,7 @@ strtod goto cont; } #endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ +#endif /*Avoid_Underflow}*/ adj.d *= ulp(&rv); if (bc.dsign) { if (word0(&rv) == Big0 && word1(&rv) == Big1) @@ -3103,20 +3203,20 @@ strtod dval(&rv) -= adj.d; goto cont; } -#endif /*Honor_FLT_ROUNDS*/ +#endif /*}Honor_FLT_ROUNDS*/ if (i < 0) { /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask -#ifdef IEEE_Arith +#ifdef IEEE_Arith /*{*/ #ifdef Avoid_Underflow || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 #else || (word0(&rv) & Exp_mask) <= Exp_msk1 #endif -#endif +#endif /*}*/ ) { #ifdef SET_INEXACT if (!delta->x[0] && delta->wds <= 1) @@ -3147,6 +3247,8 @@ strtod #endif 0xffffffff)) { /*boundary case -- increment exponent*/ + if (word0(&rv) == Big0 && word1(&rv) == Big1) + goto ovfl; word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1 #ifdef IBM @@ -3207,18 +3309,39 @@ strtod #ifdef IBM goto cont; #else +#ifndef NO_STRTOD_BIGCOMP + if (bc.nd > nd) + goto cont; +#endif break; #endif } #ifndef ROUND_BIASED +#ifdef Avoid_Underflow + if (Lsb1) { + if (!(word0(&rv) & Lsb1)) + break; + } + else if (!(word1(&rv) & Lsb)) + break; +#else if (!(word1(&rv) & LSB)) break; +#endif #endif if (bc.dsign) +#ifdef Avoid_Underflow + dval(&rv) += sulp(&rv, &bc); +#else dval(&rv) += ulp(&rv); +#endif #ifndef ROUND_BIASED else { +#ifdef Avoid_Underflow + dval(&rv) -= sulp(&rv, &bc); +#else dval(&rv) -= ulp(&rv); +#endif #ifndef Sudden_Underflow if (!dval(&rv)) { if (bc.nd >nd) { @@ -3311,9 +3434,22 @@ strtod dval(&aadj2) = aadj1; word0(&aadj2) += (2*P+1)*Exp_msk1 - y; aadj1 = dval(&aadj2); + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; + if (rv.d == 0.) +#ifdef NO_STRTOD_BIGCOMP + goto undfl; +#else + { + req_bigcomp = 1; + break; + } +#endif + } + else { + adj.d = aadj1 * ulp(&rv); + dval(&rv) += adj.d; } - adj.d = aadj1 * ulp(&rv); - dval(&rv) += adj.d; #else #ifdef Sudden_Underflow if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { @@ -3396,8 +3532,16 @@ strtod Bfree(bd0); Bfree(delta); #ifndef NO_STRTOD_BIGCOMP - if (bc.nd > nd) + if (req_bigcomp) { + bd0 = 0; + bc.e0 += nz1; bigcomp(&rv, s0, &bc); + y = word0(&rv) & Exp_mask; + if (y == Exp_mask) + goto ovfl; + if (y == 0 && rv.d == 0.) + goto undfl; + } #endif #ifdef SET_INEXACT if (bc.inexact) { @@ -3470,7 +3614,7 @@ rv_alloc(int i) #ifdef KR_headers nrv_alloc(s, rve, n) char *s, **rve; int n; #else -nrv_alloc(CONST char *s, char **rve, int n) +nrv_alloc(const char *s, char **rve, int n) #endif { char *rv, *t; @@ -3582,7 +3726,7 @@ dtoa */ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + j, j1 = 0, k, k0, k_check, leftright, m2, m5, s2, s5, spec_case, try_quick; Long L; #ifndef Sudden_Underflow @@ -3593,6 +3737,11 @@ dtoa U d2, eps, u; double ds; char *s, *s0; +#ifndef No_leftright +#ifdef IEEE_Arith + U eps1; +#endif +#endif #ifdef SET_INEXACT int inexact, oldinexact; #endif @@ -3858,14 +4007,26 @@ dtoa * generating digits needed. */ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); +#ifdef IEEE_Arith + if (k0 < 0 && j1 >= 307) { + eps1.d = 1.01e256; /* 1.01 allows roundoff in the next few lines */ + word0(&eps1) -= Exp_msk1 * (Bias+P-1); + dval(&eps1) *= tens[j1 & 0xf]; + for(i = 0, j = (j1-256) >> 4; j; j >>= 1, i++) + if (j & 1) + dval(&eps1) *= bigtens[i]; + if (eps.d < eps1.d) + eps.d = eps1.d; + } +#endif for(i = 0;;) { - L = (long)dval(&u); + L = dval(&u); dval(&u) -= L; - *s++ = '0' + (char)L; - if (dval(&u) < dval(&eps)) - goto ret1; + *s++ = '0' + (int)L; if (1. - dval(&u) < dval(&eps)) goto bump_up; + if (dval(&u) < dval(&eps)) + goto ret1; if (++i >= ilim) break; dval(&eps) *= 10.; @@ -3913,7 +4074,7 @@ dtoa goto no_digits; goto one_digit; } - for(i = 1; i <= k + 1; i++, dval(&u) *= 10.) { + for(i = 1;; i++, dval(&u) *= 10.) { L = (Long)(dval(&u) / ds); dval(&u) -= L*ds; #ifdef Check_FLT_ROUNDS @@ -3939,7 +4100,12 @@ dtoa } #endif dval(&u) += dval(&u); - if (dval(&u) > ds || (dval(&u) == ds && L & 1)) { +#ifdef ROUND_BIASED + if (dval(&u) >= ds) +#else + if (dval(&u) > ds || (dval(&u) == ds && L & 1)) +#endif + { bump_up: while(*--s == '9') if (s == s0) { @@ -4024,16 +4190,6 @@ dtoa * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ -#ifdef Pack_32 - i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f; - if (i) - i = 32 - i; -#define iInc 28 -#else - if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) - i = 16 - i; -#define iInc 12 -#endif i = dshift(S, s2); b2 += i; m2 += i; @@ -4126,7 +4282,11 @@ dtoa if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); +#ifdef ROUND_BIASED + if (j1 >= 0 /*)*/ +#else if ((j1 > 0 || (j1 == 0 && dig & 1)) +#endif && dig++ == '9') goto round_9_up; } @@ -4187,7 +4347,12 @@ dtoa #endif b = lshift(b, 1); j = cmp(b, S); - if (j > 0 || (j == 0 && dig & 1)) { +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { roundoff: while(*--s == '9') if (s == s0) { diff --git a/security/sandbox/chromium/base/threading/platform_thread.h b/security/sandbox/chromium/base/threading/platform_thread.h index e2b09bcb5bfd..0b34cce25f95 100644 --- a/security/sandbox/chromium/base/threading/platform_thread.h +++ b/security/sandbox/chromium/base/threading/platform_thread.h @@ -99,7 +99,7 @@ const PlatformThreadId kInvalidThreadId(0); // Valid values for priority of Thread::Options and SimpleThread::Options, and // SetCurrentThreadPriority(), listed in increasing order of importance. -enum class ThreadPriority { +enum class ThreadPriority : int { // Suitable for threads that shouldn't disrupt high priority work. BACKGROUND, // Default priority level. @@ -142,8 +142,8 @@ class BASE_EXPORT PlatformThread { // Sleeps for the specified duration. static void Sleep(base::TimeDelta duration); - // Sets the thread name visible to debuggers/tools. This has no effect - // otherwise. + // Sets the thread name visible to debuggers/tools. This will try to + // initialize the context for current thread unless it's a WorkerThread. static void SetName(const std::string& name); // Gets the thread name, if previously set by SetName. @@ -175,14 +175,29 @@ class BASE_EXPORT PlatformThread { // PlatformThreadHandle. static bool CreateNonJoinable(size_t stack_size, Delegate* delegate); + // CreateNonJoinableWithPriority() does the same thing as CreateNonJoinable() + // except the priority of the thread is set based on |priority|. + static bool CreateNonJoinableWithPriority(size_t stack_size, + Delegate* delegate, + ThreadPriority priority); + // Joins with a thread created via the Create function. This function blocks // the caller until the designated thread exits. This will invalidate // |thread_handle|. static void Join(PlatformThreadHandle thread_handle); + // Detaches and releases the thread handle. The thread is no longer joinable + // and |thread_handle| is invalidated after this call. + static void Detach(PlatformThreadHandle thread_handle); + + // Returns true if SetCurrentThreadPriority() can be used to increase the + // priority of the current thread. + static bool CanIncreaseCurrentThreadPriority(); + // Toggles the current thread's priority at runtime. A thread may not be able // to raise its priority back up after lowering it if the process does not - // have a proper permission, e.g. CAP_SYS_NICE on Linux. + // have a proper permission, e.g. CAP_SYS_NICE on Linux. A thread may not be + // able to lower its priority back down after raising it to REALTIME_AUDIO. // Since changing other threads' priority is not permitted in favor of // security, this interface is restricted to change only the current thread // priority (https://crbug.com/399473). @@ -190,6 +205,20 @@ class BASE_EXPORT PlatformThread { static ThreadPriority GetCurrentThreadPriority(); +#if defined(OS_LINUX) + // Toggles a specific thread's priority at runtime. This can be used to + // change the priority of a thread in a different process and will fail + // if the calling process does not have proper permissions. The + // SetCurrentThreadPriority() function above is preferred in favor of + // security but on platforms where sandboxed processes are not allowed to + // change priority this function exists to allow a non-sandboxed process + // to change the priority of sandboxed threads for improved performance. + // Warning: Don't use this for a main thread because that will change the + // whole thread group's (i.e. process) priority. + static void SetThreadPriority(PlatformThreadId thread_id, + ThreadPriority priority); +#endif + private: DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread); }; diff --git a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc b/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc index 9af02044fcee..378a24d0d1d8 100644 --- a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc +++ b/security/sandbox/chromium/base/threading/platform_thread_internal_posix.cc @@ -4,6 +4,7 @@ #include "base/threading/platform_thread_internal_posix.h" +#include "base/containers/adapters.h" #include "base/logging.h" namespace base { @@ -11,8 +12,7 @@ namespace base { namespace internal { int ThreadPriorityToNiceValue(ThreadPriority priority) { - for (const ThreadPriorityToNiceValuePair& pair : - kThreadPriorityToNiceValueMap) { + for (const auto& pair : kThreadPriorityToNiceValueMap) { if (pair.priority == priority) return pair.nice_value; } @@ -21,13 +21,17 @@ int ThreadPriorityToNiceValue(ThreadPriority priority) { } ThreadPriority NiceValueToThreadPriority(int nice_value) { - for (const ThreadPriorityToNiceValuePair& pair : - kThreadPriorityToNiceValueMap) { - if (pair.nice_value == nice_value) + // Try to find a priority that best describes |nice_value|. If there isn't + // an exact match, this method returns the closest priority whose nice value + // is higher (lower priority) than |nice_value|. + for (const auto& pair : Reversed(kThreadPriorityToNiceValueMap)) { + if (pair.nice_value >= nice_value) return pair.priority; } - NOTREACHED() << "Unknown nice value"; - return ThreadPriority::NORMAL; + + // Reaching here means |nice_value| is more than any of the defined + // priorities. The lowest priority is suitable in this case. + return ThreadPriority::BACKGROUND; } } // namespace internal diff --git a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h b/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h index 05a8d1e26e78..5f4a215968b6 100644 --- a/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h +++ b/security/sandbox/chromium/base/threading/platform_thread_internal_posix.h @@ -5,6 +5,7 @@ #ifndef BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ #define BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_ +#include "base/base_export.h" #include "base/threading/platform_thread.h" namespace base { @@ -15,7 +16,11 @@ struct ThreadPriorityToNiceValuePair { ThreadPriority priority; int nice_value; }; -extern const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4]; +// The elements must be listed in the order of increasing priority (lowest +// priority first), that is, in the order of decreasing nice values (highest +// nice value first). +BASE_EXPORT extern +const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4]; // Returns the nice value matching |priority| based on the platform-specific // implementation of kThreadPriorityToNiceValueMap. @@ -23,7 +28,7 @@ int ThreadPriorityToNiceValue(ThreadPriority priority); // Returns the ThreadPrioirty matching |nice_value| based on the platform- // specific implementation of kThreadPriorityToNiceValueMap. -ThreadPriority NiceValueToThreadPriority(int nice_value); +BASE_EXPORT ThreadPriority NiceValueToThreadPriority(int nice_value); // Allows platform specific tweaks to the generic POSIX solution for // SetCurrentThreadPriority. Returns true if the platform-specific diff --git a/security/sandbox/chromium/base/threading/platform_thread_linux.cc b/security/sandbox/chromium/base/threading/platform_thread_linux.cc deleted file mode 100644 index 4057ede947e2..000000000000 --- a/security/sandbox/chromium/base/threading/platform_thread_linux.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/platform_thread.h" - -#include -#include -#include - -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/platform_thread_internal_posix.h" -#include "base/threading/thread_id_name_manager.h" -#include "base/tracked_objects.h" -#include "build/build_config.h" - -#if !defined(OS_NACL) -#include -#include -#include -#include -#endif - -namespace base { - -namespace internal { - -namespace { -#if !defined(OS_NACL) -const struct sched_param kRealTimePrio = {8}; -const struct sched_param kResetPrio = {0}; -#endif -} // namespace - -const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { - {ThreadPriority::BACKGROUND, 10}, - {ThreadPriority::NORMAL, 0}, - {ThreadPriority::DISPLAY, -6}, - {ThreadPriority::REALTIME_AUDIO, -10}, -}; - -bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { -#if !defined(OS_NACL) - ThreadPriority current_priority; - if (priority != ThreadPriority::REALTIME_AUDIO && - GetCurrentThreadPriorityForPlatform(¤t_priority) && - current_priority == ThreadPriority::REALTIME_AUDIO) { - // If the pthread's round-robin scheduler is already enabled, and the new - // priority will use setpriority() instead, the pthread scheduler should be - // reset to use SCHED_OTHER so that setpriority() just works. - pthread_setschedparam(pthread_self(), SCHED_OTHER, &kResetPrio); - return false; - } - return priority == ThreadPriority::REALTIME_AUDIO && - pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0; -#else - return false; -#endif -} - -bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) { -#if !defined(OS_NACL) - int maybe_sched_rr = 0; - struct sched_param maybe_realtime_prio = {0}; - if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, - &maybe_realtime_prio) == 0 && - maybe_sched_rr == SCHED_RR && - maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { - *priority = ThreadPriority::REALTIME_AUDIO; - return true; - } -#endif - return false; -} - -} // namespace internal - -// static -void PlatformThread::SetName(const std::string& name) { - ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name); - tracked_objects::ThreadData::InitializeThreadContext(name); - -#if !defined(OS_NACL) - // On linux we can get the thread names to show up in the debugger by setting - // the process name for the LWP. We don't want to do this for the main - // thread because that would rename the process, causing tools like killall - // to stop working. - if (PlatformThread::CurrentId() == getpid()) - return; - - // http://0pointer.de/blog/projects/name-your-threads.html - // Set the name for the LWP (which gets truncated to 15 characters). - // Note that glibc also has a 'pthread_setname_np' api, but it may not be - // available everywhere and it's only benefit over using prctl directly is - // that it can set the name of threads other than the current thread. - int err = prctl(PR_SET_NAME, name.c_str()); - // We expect EPERM failures in sandboxed processes, just ignore those. - if (err < 0 && errno != EPERM) - DPLOG(ERROR) << "prctl(PR_SET_NAME)"; -#endif // !defined(OS_NACL) -} - -void InitThreading() {} - -void InitOnThread() {} - -void TerminateOnThread() {} - -size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { -#if !defined(THREAD_SANITIZER) - return 0; -#else - // ThreadSanitizer bloats the stack heavily. Evidence has been that the - // default stack size isn't enough for some browser tests. - return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). -#endif -} - -} // namespace base diff --git a/security/sandbox/chromium/base/threading/platform_thread_posix.cc b/security/sandbox/chromium/base/threading/platform_thread_posix.cc index 39a007316f78..9a6a2bb999c4 100644 --- a/security/sandbox/chromium/base/threading/platform_thread_posix.cc +++ b/security/sandbox/chromium/base/threading/platform_thread_posix.cc @@ -11,10 +11,14 @@ #include #include #include +#include +#include +#include + +#include "base/debug/activity_tracker.h" #include "base/lazy_instance.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/threading/platform_thread_internal_posix.h" #include "base/threading/thread_id_name_manager.h" #include "base/threading/thread_restrictions.h" @@ -22,14 +26,11 @@ #if defined(OS_LINUX) #include -#elif defined(OS_ANDROID) -#include #endif namespace base { void InitThreading(); -void InitOnThread(); void TerminateOnThread(); size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes); @@ -45,19 +46,22 @@ struct ThreadParams { }; void* ThreadFunc(void* params) { - base::InitOnThread(); - PlatformThread::Delegate* delegate = nullptr; { - scoped_ptr thread_params(static_cast(params)); + std::unique_ptr thread_params( + static_cast(params)); delegate = thread_params->delegate; if (!thread_params->joinable) base::ThreadRestrictions::SetSingletonAllowed(false); - if (thread_params->priority != ThreadPriority::NORMAL) - PlatformThread::SetCurrentThreadPriority(thread_params->priority); +#if !defined(OS_NACL) + // Threads on linux/android may inherit their priority from the thread + // where they were created. This explicitly sets the priority of all new + // threads. + PlatformThread::SetCurrentThreadPriority(thread_params->priority); +#endif } ThreadIdNameManager::GetInstance()->RegisterThread( @@ -97,7 +101,7 @@ bool CreateThread(size_t stack_size, if (stack_size > 0) pthread_attr_setstacksize(&attributes, stack_size); - scoped_ptr params(new ThreadParams); + std::unique_ptr params(new ThreadParams); params->delegate = delegate; params->joinable = joinable; params->priority = priority; @@ -184,21 +188,32 @@ const char* PlatformThread::GetName() { bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, PlatformThreadHandle* thread_handle, ThreadPriority priority) { - return CreateThread(stack_size, true, // joinable thread - delegate, thread_handle, priority); + return CreateThread(stack_size, true /* joinable thread */, delegate, + thread_handle, priority); } // static bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { + return CreateNonJoinableWithPriority(stack_size, delegate, + ThreadPriority::NORMAL); +} + +// static +bool PlatformThread::CreateNonJoinableWithPriority(size_t stack_size, + Delegate* delegate, + ThreadPriority priority) { PlatformThreadHandle unused; bool result = CreateThread(stack_size, false /* non-joinable thread */, - delegate, &unused, ThreadPriority::NORMAL); + delegate, &unused, priority); return result; } // static void PlatformThread::Join(PlatformThreadHandle thread_handle) { + // Record the event that this thread is blocking upon (for hang diagnosis). + base::debug::ScopedThreadJoinActivity thread_activity(&thread_handle); + // Joining another thread may block the current thread for a long time, since // the thread referred to by |thread_handle| may still be running long-lived / // blocking tasks. @@ -206,9 +221,26 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), NULL)); } +// static +void PlatformThread::Detach(PlatformThreadHandle thread_handle) { + CHECK_EQ(0, pthread_detach(thread_handle.platform_handle())); +} + // Mac has its own Set/GetCurrentThreadPriority() implementations. #if !defined(OS_MACOSX) +// static +bool PlatformThread::CanIncreaseCurrentThreadPriority() { +#if defined(OS_NACL) + return false; +#else + // Only root can raise thread priority on POSIX environment. On Linux, users + // who have CAP_SYS_NICE permission also can raise the thread priority, but + // libcap.so would be needed to check the capability. + return geteuid() == 0; +#endif // defined(OS_NACL) +} + // static void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { #if defined(OS_NACL) diff --git a/security/sandbox/chromium/base/threading/platform_thread_win.cc b/security/sandbox/chromium/base/threading/platform_thread_win.cc index d5bd9bed08e7..2644eee520b8 100644 --- a/security/sandbox/chromium/base/threading/platform_thread_win.cc +++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc @@ -6,6 +6,7 @@ #include +#include "base/debug/activity_tracker.h" #include "base/debug/alias.h" #include "base/debug/profiler.h" #include "base/logging.h" @@ -13,7 +14,6 @@ #include "base/threading/thread_restrictions.h" #include "base/tracked_objects.h" #include "base/win/scoped_handle.h" -#include "base/win/windows_version.h" namespace base { @@ -100,10 +100,8 @@ bool CreateThreadInternal(size_t stack_size, PlatformThreadHandle* out_thread_handle, ThreadPriority priority) { unsigned int flags = 0; - if (stack_size > 0 && base::win::GetVersion() >= base::win::VERSION_XP) { + if (stack_size > 0) { flags = STACK_SIZE_PARAM_IS_A_RESERVATION; - } else { - stack_size = 0; } ThreadParams* params = new ThreadParams; @@ -199,12 +197,23 @@ bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate, // static bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) { - return CreateThreadInternal(stack_size, delegate, nullptr, - ThreadPriority::NORMAL); + return CreateNonJoinableWithPriority(stack_size, delegate, + ThreadPriority::NORMAL); +} + +// static +bool PlatformThread::CreateNonJoinableWithPriority(size_t stack_size, + Delegate* delegate, + ThreadPriority priority) { + return CreateThreadInternal(stack_size, delegate, nullptr /* non-joinable */, + priority); } // static void PlatformThread::Join(PlatformThreadHandle thread_handle) { + // Record the event that this thread is blocking upon (for hang diagnosis). + base::debug::ScopedThreadJoinActivity thread_activity(&thread_handle); + DCHECK(thread_handle.platform_handle()); // TODO(willchan): Enable this check once I can get it to work for Windows // shutdown. @@ -217,18 +226,21 @@ void PlatformThread::Join(PlatformThreadHandle thread_handle) { // Wait for the thread to exit. It should already have terminated but make // sure this assumption is valid. - DWORD result = WaitForSingleObject(thread_handle.platform_handle(), INFINITE); - if (result != WAIT_OBJECT_0) { - // Debug info for bug 127931. - DWORD error = GetLastError(); - debug::Alias(&error); - debug::Alias(&result); - CHECK(false); - } - + CHECK_EQ(WAIT_OBJECT_0, + WaitForSingleObject(thread_handle.platform_handle(), INFINITE)); CloseHandle(thread_handle.platform_handle()); } +// static +void PlatformThread::Detach(PlatformThreadHandle thread_handle) { + CloseHandle(thread_handle.platform_handle()); +} + +// static +bool PlatformThread::CanIncreaseCurrentThreadPriority() { + return true; +} + // static void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { int desired_priority = THREAD_PRIORITY_ERROR_RETURN; @@ -251,7 +263,7 @@ void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) { } DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN); -#ifndef NDEBUG +#if DCHECK_IS_ON() const BOOL success = #endif ::SetThreadPriority(PlatformThread::CurrentHandle().platform_handle(), diff --git a/security/sandbox/chromium/base/threading/sequenced_worker_pool.h b/security/sandbox/chromium/base/threading/sequenced_worker_pool.h index ba0e444210fe..252d511d3f2b 100644 --- a/security/sandbox/chromium/base/threading/sequenced_worker_pool.h +++ b/security/sandbox/chromium/base/threading/sequenced_worker_pool.h @@ -8,15 +8,16 @@ #include #include +#include #include #include "base/base_export.h" #include "base/callback_forward.h" +#include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/single_thread_task_runner.h" #include "base/task_runner.h" +#include "base/task_scheduler/task_traits.h" namespace tracked_objects { class Location; @@ -24,12 +25,10 @@ class Location; namespace base { -class SingleThreadTaskRunner; +class SequencedTaskRunner; template class DeleteHelper; -class SequencedTaskRunner; - // A worker thread pool that enforces ordering between sets of tasks. It also // allows you to specify what should happen to your tasks on shutdown. // @@ -47,8 +46,7 @@ class SequencedTaskRunner; // destruction will be visible to T2. // // Example: -// SequencedWorkerPool::SequenceToken token = -// SequencedWorkerPool::GetSequenceToken(); +// SequencedWorkerPool::SequenceToken token = pool.GetSequenceToken(); // pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN, // FROM_HERE, base::Bind(...)); // pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN, @@ -164,36 +162,61 @@ class BASE_EXPORT SequencedWorkerPool : public TaskRunner { // an unsequenced task, returns an invalid SequenceToken. static SequenceToken GetSequenceTokenForCurrentThread(); - // Gets a SequencedTaskRunner for the current thread. If the current thread is - // running an unsequenced task, a new SequenceToken will be generated and set, - // so that the returned SequencedTaskRunner is guaranteed to run tasks after - // the current task has finished running. - static scoped_refptr - GetSequencedTaskRunnerForCurrentThread(); + // Returns the SequencedWorkerPool that owns this thread, or null if the + // current thread is not a SequencedWorkerPool worker thread. + // + // Always returns nullptr when SequencedWorkerPool is redirected to + // TaskScheduler. + // + // DEPRECATED. Use SequencedTaskRunnerHandle::Get() instead. Consequentially + // the only remaining use case is in sequenced_task_runner_handle.cc to + // implement that and will soon be removed along with SequencedWorkerPool: + // http://crbug.com/622400. + static scoped_refptr GetWorkerPoolForCurrentThread(); // Returns a unique token that can be used to sequence tasks posted to // PostSequencedWorkerTask(). Valid tokens are always nonzero. - // TODO(bauerb): Rename this to better differentiate from - // GetSequenceTokenForCurrentThread(). static SequenceToken GetSequenceToken(); - // Returns the SequencedWorkerPool that owns this thread, or null if the - // current thread is not a SequencedWorkerPool worker thread. - static scoped_refptr GetWorkerPoolForCurrentThread(); + // Starts redirecting tasks posted to this process' SequencedWorkerPools to + // the registered TaskScheduler. This cannot be called after a task has been + // posted to a SequencedWorkerPool. This is not thread-safe; proper + // synchronization is required to use any SequencedWorkerPool method after + // calling this. There must be a registered TaskScheduler when this is called. + // Ideally, call this on the main thread of a process, before any other + // threads are created and before any tasks are posted to that process' + // SequencedWorkerPools. + // TODO(gab): Remove this if http://crbug.com/622400 fails + // (SequencedWorkerPool will be phased out completely otherwise). + static void RedirectToTaskSchedulerForProcess(); + + // Stops redirecting tasks posted to this process' SequencedWorkerPools to the + // registered TaskScheduler and allows RedirectToTaskSchedulerForProcess() to + // be called even if tasks have already posted to a SequencedWorkerPool in + // this process. Calling this while there are active SequencedWorkerPools is + // not supported. This is not thread-safe; proper synchronization is required + // to use any SequencedWorkerPool method after calling this. + static void ResetRedirectToTaskSchedulerForProcessForTesting(); // When constructing a SequencedWorkerPool, there must be a // ThreadTaskRunnerHandle on the current thread unless you plan to // deliberately leak it. - // Pass the maximum number of threads (they will be lazily created as needed) - // and a prefix for the thread name to aid in debugging. + // Constructs a SequencedWorkerPool which will lazily create up to + // |max_threads| and a prefix for the thread name to aid in debugging. + // |max_threads| must be greater than 1. |task_priority| will be used to hint + // base::TaskScheduler for an experiment in which all SequencedWorkerPool + // tasks will be redirected to it in processes where a base::TaskScheduler was + // instantiated. SequencedWorkerPool(size_t max_threads, - const std::string& thread_name_prefix); + const std::string& thread_name_prefix, + base::TaskPriority task_priority); // Like above, but with |observer| for testing. Does not take ownership of // |observer|. SequencedWorkerPool(size_t max_threads, const std::string& thread_name_prefix, + base::TaskPriority task_priority, TestingObserver* observer); // Returns the sequence token associated with the given name. Calling this @@ -207,7 +230,7 @@ class BASE_EXPORT SequencedWorkerPool : public TaskRunner { // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay // are posted with BLOCK_SHUTDOWN behavior. scoped_refptr GetSequencedTaskRunner( - SequenceToken token); + SequenceToken token) WARN_UNUSED_RESULT; // Returns a SequencedTaskRunner wrapper which posts to this // SequencedWorkerPool using the given sequence token. Tasks with nonzero @@ -215,14 +238,14 @@ class BASE_EXPORT SequencedWorkerPool : public TaskRunner { // are posted with the given shutdown behavior. scoped_refptr GetSequencedTaskRunnerWithShutdownBehavior( SequenceToken token, - WorkerShutdown shutdown_behavior); + WorkerShutdown shutdown_behavior) WARN_UNUSED_RESULT; // Returns a TaskRunner wrapper which posts to this SequencedWorkerPool using // the given shutdown behavior. Tasks with nonzero delay are posted with // SKIP_ON_SHUTDOWN behavior and tasks with zero delay are posted with the // given shutdown behavior. scoped_refptr GetTaskRunnerWithShutdownBehavior( - WorkerShutdown shutdown_behavior); + WorkerShutdown shutdown_behavior) WARN_UNUSED_RESULT; // Posts the given task for execution in the worker pool. Tasks posted with // this function will execute in an unspecified order on a background thread. @@ -316,23 +339,21 @@ class BASE_EXPORT SequencedWorkerPool : public TaskRunner { TimeDelta delay) override; bool RunsTasksOnCurrentThread() const override; - // Returns true if the current thread is processing a task with the given - // sequence_token. - bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; - - // Returns true if any thread is currently processing a task with the given - // sequence token. Should only be called with a valid sequence token. - bool IsRunningSequence(SequenceToken sequence_token) const; - // Blocks until all pending tasks are complete. This should only be called in // unit tests when you want to validate something that should have happened. - // This will not flush delayed tasks; delayed tasks get deleted. + // Does not wait for delayed tasks. If redirection to TaskScheduler is + // disabled, delayed tasks are deleted. If redirection to TaskScheduler is + // enabled, this will wait for all tasks posted to TaskScheduler (not just + // tasks posted to this SequencedWorkerPool). // // Note that calling this will not prevent other threads from posting work to // the queue while the calling thread is waiting on Flush(). In this case, // Flush will return only when there's no more work in the queue. Normally, // this doesn't come up since in a test, all the work is being posted from // the main thread. + // + // TODO(gab): Remove mentions of TaskScheduler in this comment if + // http://crbug.com/622400 fails. void FlushForTesting(); // Spuriously signal that there is work to be done. @@ -368,13 +389,18 @@ class BASE_EXPORT SequencedWorkerPool : public TaskRunner { friend class DeleteHelper; class Inner; + class PoolSequencedTaskRunner; class Worker; - const scoped_refptr constructor_task_runner_; + // Returns true if the current thread is processing a task with the given + // sequence_token. + bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const; + + const scoped_refptr constructor_task_runner_; // Avoid pulling in too many headers by putting (almost) everything // into |inner_|. - const scoped_ptr inner_; + const std::unique_ptr inner_; DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool); }; diff --git a/security/sandbox/chromium/base/threading/thread_checker_impl.h b/security/sandbox/chromium/base/threading/thread_checker_impl.h index c92e143db0c3..13193d129932 100644 --- a/security/sandbox/chromium/base/threading/thread_checker_impl.h +++ b/security/sandbox/chromium/base/threading/thread_checker_impl.h @@ -7,17 +7,18 @@ #include "base/base_export.h" #include "base/compiler_specific.h" +#include "base/sequence_token.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" namespace base { -// Real implementation of ThreadChecker, for use in debug mode, or -// for temporary use in release mode (e.g. to CHECK on a threading issue -// seen only in the wild). +// Real implementation of ThreadChecker, for use in debug mode, or for temporary +// use in release mode (e.g. to CHECK on a threading issue seen only in the +// wild). // -// Note: You should almost always use the ThreadChecker class to get the -// right version for your build configuration. +// Note: You should almost always use the ThreadChecker class to get the right +// version for your build configuration. class BASE_EXPORT ThreadCheckerImpl { public: ThreadCheckerImpl(); @@ -31,12 +32,29 @@ class BASE_EXPORT ThreadCheckerImpl { void DetachFromThread(); private: - void EnsureThreadIdAssigned() const; + void EnsureAssigned() const; + // Members are mutable so that CalledOnValidThread() can set them. + + // Synchronizes access to all members. mutable base::Lock lock_; - // This is mutable so that CalledOnValidThread can set it. - // It's guarded by |lock_|. - mutable PlatformThreadRef valid_thread_id_; + + // Thread on which CalledOnValidThread() may return true. + mutable PlatformThreadRef thread_id_; + + // TaskToken for which CalledOnValidThread() always returns true. This allows + // CalledOnValidThread() to return true when called multiple times from the + // same task, even if it's not running in a single-threaded context itself + // (allowing usage of ThreadChecker/NonThreadSafe objects on the stack in the + // scope of one-off tasks). Note: CalledOnValidThread() may return true even + // if the current TaskToken is not equal to this. + mutable TaskToken task_token_; + + // SequenceToken for which CalledOnValidThread() may return true. Used to + // ensure that CalledOnValidThread() doesn't return true for TaskScheduler + // tasks that happen to run on the same thread but weren't posted to the same + // SingleThreadTaskRunner. + mutable SequenceToken sequence_token_; }; } // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_id_name_manager.cc b/security/sandbox/chromium/base/threading/thread_id_name_manager.cc index 56cfa273a87d..107e0dc49857 100644 --- a/security/sandbox/chromium/base/threading/thread_id_name_manager.cc +++ b/security/sandbox/chromium/base/threading/thread_id_name_manager.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/memory/singleton.h" #include "base/strings/string_util.h" +#include "base/trace_event/heap_profiler_allocation_context_tracker.h" namespace base { namespace { @@ -50,27 +51,37 @@ void ThreadIdNameManager::RegisterThread(PlatformThreadHandle::Handle handle, void ThreadIdNameManager::SetName(PlatformThreadId id, const std::string& name) { - AutoLock locked(lock_); - NameToInternedNameMap::iterator iter = name_to_interned_name_.find(name); std::string* leaked_str = NULL; - if (iter != name_to_interned_name_.end()) { - leaked_str = iter->second; - } else { - leaked_str = new std::string(name); - name_to_interned_name_[name] = leaked_str; + { + AutoLock locked(lock_); + NameToInternedNameMap::iterator iter = name_to_interned_name_.find(name); + if (iter != name_to_interned_name_.end()) { + leaked_str = iter->second; + } else { + leaked_str = new std::string(name); + name_to_interned_name_[name] = leaked_str; + } + + ThreadIdToHandleMap::iterator id_to_handle_iter = + thread_id_to_handle_.find(id); + + // The main thread of a process will not be created as a Thread object which + // means there is no PlatformThreadHandler registered. + if (id_to_handle_iter == thread_id_to_handle_.end()) { + main_process_name_ = leaked_str; + main_process_id_ = id; + return; + } + thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; } - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); - - // The main thread of a process will not be created as a Thread object which - // means there is no PlatformThreadHandler registered. - if (id_to_handle_iter == thread_id_to_handle_.end()) { - main_process_name_ = leaked_str; - main_process_id_ = id; - return; - } - thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str; + // Add the leaked thread name to heap profiler context tracker. The name added + // is valid for the lifetime of the process. AllocationContextTracker cannot + // call GetName(which holds a lock) during the first allocation because it can + // cause a deadlock when the first allocation happens in the + // ThreadIdNameManager itself when holding the lock. + trace_event::AllocationContextTracker::SetCurrentThreadName( + leaked_str->c_str()); } const char* ThreadIdNameManager::GetName(PlatformThreadId id) { diff --git a/security/sandbox/chromium/base/threading/thread_local.h b/security/sandbox/chromium/base/threading/thread_local.h index f40420cd2f8b..cad9add3a9ca 100644 --- a/security/sandbox/chromium/base/threading/thread_local.h +++ b/security/sandbox/chromium/base/threading/thread_local.h @@ -2,35 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// WARNING: Thread local storage is a bit tricky to get right. Please make -// sure that this is really the proper solution for what you're trying to -// achieve. Don't prematurely optimize, most likely you can just use a Lock. +// WARNING: Thread local storage is a bit tricky to get right. Please make sure +// that this is really the proper solution for what you're trying to achieve. +// Don't prematurely optimize, most likely you can just use a Lock. // -// These classes implement a wrapper around the platform's TLS storage -// mechanism. On construction, they will allocate a TLS slot, and free the -// TLS slot on destruction. No memory management (creation or destruction) is -// handled. This means for uses of ThreadLocalPointer, you must correctly -// manage the memory yourself, these classes will not destroy the pointer for -// you. There are no at-thread-exit actions taken by these classes. +// These classes implement a wrapper around ThreadLocalStorage::Slot. On +// construction, they will allocate a TLS slot, and free the TLS slot on +// destruction. No memory management (creation or destruction) is handled. This +// means for uses of ThreadLocalPointer, you must correctly manage the memory +// yourself, these classes will not destroy the pointer for you. There are no +// at-thread-exit actions taken by these classes. // -// ThreadLocalPointer wraps a Type*. It performs no creation or -// destruction, so memory management must be handled elsewhere. The first call -// to Get() on a thread will return NULL. You can update the pointer with a -// call to Set(). +// ThreadLocalPointer wraps a Type*. It performs no creation or +// destruction, so memory management must be handled elsewhere. The first call +// to Get() on a thread will return NULL. You can update the pointer with a call +// to Set(). // -// ThreadLocalBoolean wraps a bool. It will default to false if it has never +// ThreadLocalBoolean wraps a bool. It will default to false if it has never // been set otherwise with Set(). // -// Thread Safety: An instance of ThreadLocalStorage is completely thread safe -// once it has been created. If you want to dynamically create an instance, -// you must of course properly deal with safety and race conditions. This -// means a function-level static initializer is generally inappropiate. +// Thread Safety: An instance of ThreadLocalStorage is completely thread safe +// once it has been created. If you want to dynamically create an instance, you +// must of course properly deal with safety and race conditions. This means a +// function-level static initializer is generally inappropiate. // -// In Android, the system TLS is limited, the implementation is backed with -// ThreadLocalStorage. +// In Android, the system TLS is limited. // // Example usage: -// // My class is logically attached to a single thread. We cache a pointer +// // My class is logically attached to a single thread. We cache a pointer // // on the thread it was created on, so we can implement current(). // MyClass::MyClass() { // DCHECK(Singleton >::get()->Get() == NULL); @@ -51,76 +50,42 @@ #ifndef BASE_THREADING_THREAD_LOCAL_H_ #define BASE_THREADING_THREAD_LOCAL_H_ -#include "base/base_export.h" #include "base/macros.h" #include "base/threading/thread_local_storage.h" -#include "build/build_config.h" - -#if defined(OS_POSIX) -#include -#endif namespace base { -namespace internal { - -// Helper functions that abstract the cross-platform APIs. Do not use directly. -struct BASE_EXPORT ThreadLocalPlatform { -#if defined(OS_WIN) - typedef unsigned long SlotType; -#elif defined(OS_ANDROID) - typedef ThreadLocalStorage::StaticSlot SlotType; -#elif defined(OS_POSIX) - typedef pthread_key_t SlotType; -#endif - - static void AllocateSlot(SlotType* slot); - static void FreeSlot(SlotType slot); - static void* GetValueFromSlot(SlotType slot); - static void SetValueInSlot(SlotType slot, void* value); -}; - -} // namespace internal template class ThreadLocalPointer { public: - ThreadLocalPointer() : slot_() { - internal::ThreadLocalPlatform::AllocateSlot(&slot_); - } - - ~ThreadLocalPointer() { - internal::ThreadLocalPlatform::FreeSlot(slot_); - } + ThreadLocalPointer() = default; + ~ThreadLocalPointer() = default; Type* Get() { - return static_cast( - internal::ThreadLocalPlatform::GetValueFromSlot(slot_)); + return static_cast(slot_.Get()); } void Set(Type* ptr) { - internal::ThreadLocalPlatform::SetValueInSlot( - slot_, const_cast(static_cast(ptr))); + slot_.Set(const_cast(static_cast(ptr))); } private: - typedef internal::ThreadLocalPlatform::SlotType SlotType; - - SlotType slot_; + ThreadLocalStorage::Slot slot_; DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer); }; class ThreadLocalBoolean { public: - ThreadLocalBoolean() {} - ~ThreadLocalBoolean() {} + ThreadLocalBoolean() = default; + ~ThreadLocalBoolean() = default; bool Get() { - return tlp_.Get() != NULL; + return tlp_.Get() != nullptr; } void Set(bool val) { - tlp_.Set(val ? this : NULL); + tlp_.Set(val ? this : nullptr); } private: diff --git a/security/sandbox/chromium/base/threading/thread_local_posix.cc b/security/sandbox/chromium/base/threading/thread_local_posix.cc deleted file mode 100644 index 8bc46ad1902d..000000000000 --- a/security/sandbox/chromium/base/threading/thread_local_posix.cc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_local.h" - -#include - -#include "base/logging.h" -#include "build/build_config.h" - -#if !defined(OS_ANDROID) - -namespace base { -namespace internal { - -// static -void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { - int error = pthread_key_create(slot, NULL); - CHECK_EQ(error, 0); -} - -// static -void ThreadLocalPlatform::FreeSlot(SlotType slot) { - int error = pthread_key_delete(slot); - DCHECK_EQ(0, error); -} - -// static -void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { - return pthread_getspecific(slot); -} - -// static -void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { - int error = pthread_setspecific(slot, value); - DCHECK_EQ(error, 0); -} - -} // namespace internal -} // namespace base - -#endif // !defined(OS_ANDROID) diff --git a/security/sandbox/chromium/base/threading/thread_local_storage.cc b/security/sandbox/chromium/base/threading/thread_local_storage.cc new file mode 100644 index 000000000000..15a1d5e2dbb4 --- /dev/null +++ b/security/sandbox/chromium/base/threading/thread_local_storage.cc @@ -0,0 +1,345 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/thread_local_storage.h" + +#include "base/atomicops.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/synchronization/lock.h" +#include "build/build_config.h" + +using base::internal::PlatformThreadLocalStorage; + +// Chrome Thread Local Storage (TLS) +// +// This TLS system allows Chrome to use a single OS level TLS slot process-wide, +// and allows us to control the slot limits instead of being at the mercy of the +// platform. To do this, Chrome TLS replicates an array commonly found in the OS +// thread metadata. +// +// Overview: +// +// OS TLS Slots Per-Thread Per-Process Global +// ... +// [] Chrome TLS Array Chrome TLS Metadata +// [] ----------> [][][][][ ][][][][] [][][][][ ][][][][] +// [] | | +// ... V V +// Metadata Version Slot Information +// Your Data! +// +// Using a single OS TLS slot, Chrome TLS allocates an array on demand for the +// lifetime of each thread that requests Chrome TLS data. Each per-thread TLS +// array matches the length of the per-process global metadata array. +// +// A per-process global TLS metadata array tracks information about each item in +// the per-thread array: +// * Status: Tracks if the slot is allocated or free to assign. +// * Destructor: An optional destructor to call on thread destruction for that +// specific slot. +// * Version: Tracks the current version of the TLS slot. Each TLS slot +// allocation is associated with a unique version number. +// +// Most OS TLS APIs guarantee that a newly allocated TLS slot is +// initialized to 0 for all threads. The Chrome TLS system provides +// this guarantee by tracking the version for each TLS slot here +// on each per-thread Chrome TLS array entry. Threads that access +// a slot with a mismatched version will receive 0 as their value. +// The metadata version is incremented when the client frees a +// slot. The per-thread metadata version is updated when a client +// writes to the slot. This scheme allows for constant time +// invalidation and avoids the need to iterate through each Chrome +// TLS array to mark the slot as zero. +// +// Just like an OS TLS API, clients of the Chrome TLS are responsible for +// managing any necessary lifetime of the data in their slots. The only +// convenience provided is automatic destruction when a thread ends. If a client +// frees a slot, that client is responsible for destroying the data in the slot. + +namespace { +// In order to make TLS destructors work, we need to keep around a function +// pointer to the destructor for each slot. We keep this array of pointers in a +// global (static) array. +// We use the single OS-level TLS slot (giving us one pointer per thread) to +// hold a pointer to a per-thread array (table) of slots that we allocate to +// Chromium consumers. + +// g_native_tls_key is the one native TLS that we use. It stores our table. +base::subtle::Atomic32 g_native_tls_key = + PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES; + +// The maximum number of slots in our thread local storage stack. +constexpr int kThreadLocalStorageSize = 256; +constexpr int kInvalidSlotValue = -1; + +enum TlsStatus { + FREE, + IN_USE, +}; + +struct TlsMetadata { + TlsStatus status; + base::ThreadLocalStorage::TLSDestructorFunc destructor; + uint32_t version; +}; + +struct TlsVectorEntry { + void* data; + uint32_t version; +}; + +// This LazyInstance isn't needed until after we've constructed the per-thread +// TLS vector, so it's safe to use. +base::LazyInstance::Leaky g_tls_metadata_lock; +TlsMetadata g_tls_metadata[kThreadLocalStorageSize]; +size_t g_last_assigned_slot = 0; + +// The maximum number of times to try to clear slots by calling destructors. +// Use pthread naming convention for clarity. +constexpr int kMaxDestructorIterations = kThreadLocalStorageSize; + +// This function is called to initialize our entire Chromium TLS system. +// It may be called very early, and we need to complete most all of the setup +// (initialization) before calling *any* memory allocator functions, which may +// recursively depend on this initialization. +// As a result, we use Atomics, and avoid anything (like a singleton) that might +// require memory allocations. +TlsVectorEntry* ConstructTlsVector() { + PlatformThreadLocalStorage::TLSKey key = + base::subtle::NoBarrier_Load(&g_native_tls_key); + if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES) { + CHECK(PlatformThreadLocalStorage::AllocTLS(&key)); + + // The TLS_KEY_OUT_OF_INDEXES is used to find out whether the key is set or + // not in NoBarrier_CompareAndSwap, but Posix doesn't have invalid key, we + // define an almost impossible value be it. + // If we really get TLS_KEY_OUT_OF_INDEXES as value of key, just alloc + // another TLS slot. + if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES) { + PlatformThreadLocalStorage::TLSKey tmp = key; + CHECK(PlatformThreadLocalStorage::AllocTLS(&key) && + key != PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES); + PlatformThreadLocalStorage::FreeTLS(tmp); + } + // Atomically test-and-set the tls_key. If the key is + // TLS_KEY_OUT_OF_INDEXES, go ahead and set it. Otherwise, do nothing, as + // another thread already did our dirty work. + if (PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES != + static_cast( + base::subtle::NoBarrier_CompareAndSwap( + &g_native_tls_key, + PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES, key))) { + // We've been shortcut. Another thread replaced g_native_tls_key first so + // we need to destroy our index and use the one the other thread got + // first. + PlatformThreadLocalStorage::FreeTLS(key); + key = base::subtle::NoBarrier_Load(&g_native_tls_key); + } + } + CHECK(!PlatformThreadLocalStorage::GetTLSValue(key)); + + // Some allocators, such as TCMalloc, make use of thread local storage. As a + // result, any attempt to call new (or malloc) will lazily cause such a system + // to initialize, which will include registering for a TLS key. If we are not + // careful here, then that request to create a key will call new back, and + // we'll have an infinite loop. We avoid that as follows: Use a stack + // allocated vector, so that we don't have dependence on our allocator until + // our service is in place. (i.e., don't even call new until after we're + // setup) + TlsVectorEntry stack_allocated_tls_data[kThreadLocalStorageSize]; + memset(stack_allocated_tls_data, 0, sizeof(stack_allocated_tls_data)); + // Ensure that any rentrant calls change the temp version. + PlatformThreadLocalStorage::SetTLSValue(key, stack_allocated_tls_data); + + // Allocate an array to store our data. + TlsVectorEntry* tls_data = new TlsVectorEntry[kThreadLocalStorageSize]; + memcpy(tls_data, stack_allocated_tls_data, sizeof(stack_allocated_tls_data)); + PlatformThreadLocalStorage::SetTLSValue(key, tls_data); + return tls_data; +} + +void OnThreadExitInternal(TlsVectorEntry* tls_data) { + DCHECK(tls_data); + // Some allocators, such as TCMalloc, use TLS. As a result, when a thread + // terminates, one of the destructor calls we make may be to shut down an + // allocator. We have to be careful that after we've shutdown all of the known + // destructors (perchance including an allocator), that we don't call the + // allocator and cause it to resurrect itself (with no possibly destructor + // call to follow). We handle this problem as follows: Switch to using a stack + // allocated vector, so that we don't have dependence on our allocator after + // we have called all g_tls_metadata destructors. (i.e., don't even call + // delete[] after we're done with destructors.) + TlsVectorEntry stack_allocated_tls_data[kThreadLocalStorageSize]; + memcpy(stack_allocated_tls_data, tls_data, sizeof(stack_allocated_tls_data)); + // Ensure that any re-entrant calls change the temp version. + PlatformThreadLocalStorage::TLSKey key = + base::subtle::NoBarrier_Load(&g_native_tls_key); + PlatformThreadLocalStorage::SetTLSValue(key, stack_allocated_tls_data); + delete[] tls_data; // Our last dependence on an allocator. + + // Snapshot the TLS Metadata so we don't have to lock on every access. + TlsMetadata tls_metadata[kThreadLocalStorageSize]; + { + base::AutoLock auto_lock(g_tls_metadata_lock.Get()); + memcpy(tls_metadata, g_tls_metadata, sizeof(g_tls_metadata)); + } + + int remaining_attempts = kMaxDestructorIterations; + bool need_to_scan_destructors = true; + while (need_to_scan_destructors) { + need_to_scan_destructors = false; + // Try to destroy the first-created-slot (which is slot 1) in our last + // destructor call. That user was able to function, and define a slot with + // no other services running, so perhaps it is a basic service (like an + // allocator) and should also be destroyed last. If we get the order wrong, + // then we'll iterate several more times, so it is really not that critical + // (but it might help). + for (int slot = 0; slot < kThreadLocalStorageSize ; ++slot) { + void* tls_value = stack_allocated_tls_data[slot].data; + if (!tls_value || tls_metadata[slot].status == TlsStatus::FREE || + stack_allocated_tls_data[slot].version != tls_metadata[slot].version) + continue; + + base::ThreadLocalStorage::TLSDestructorFunc destructor = + tls_metadata[slot].destructor; + if (!destructor) + continue; + stack_allocated_tls_data[slot].data = nullptr; // pre-clear the slot. + destructor(tls_value); + // Any destructor might have called a different service, which then set a + // different slot to a non-null value. Hence we need to check the whole + // vector again. This is a pthread standard. + need_to_scan_destructors = true; + } + if (--remaining_attempts <= 0) { + NOTREACHED(); // Destructors might not have been called. + break; + } + } + + // Remove our stack allocated vector. + PlatformThreadLocalStorage::SetTLSValue(key, nullptr); +} + +} // namespace + +namespace base { + +namespace internal { + +#if defined(OS_WIN) +void PlatformThreadLocalStorage::OnThreadExit() { + PlatformThreadLocalStorage::TLSKey key = + base::subtle::NoBarrier_Load(&g_native_tls_key); + if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES) + return; + void *tls_data = GetTLSValue(key); + // Maybe we have never initialized TLS for this thread. + if (!tls_data) + return; + OnThreadExitInternal(static_cast(tls_data)); +} +#elif defined(OS_POSIX) +void PlatformThreadLocalStorage::OnThreadExit(void* value) { + OnThreadExitInternal(static_cast(value)); +} +#endif // defined(OS_WIN) + +} // namespace internal + +void ThreadLocalStorage::StaticSlot::Initialize(TLSDestructorFunc destructor) { + PlatformThreadLocalStorage::TLSKey key = + base::subtle::NoBarrier_Load(&g_native_tls_key); + if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES || + !PlatformThreadLocalStorage::GetTLSValue(key)) { + ConstructTlsVector(); + } + + // Grab a new slot. + slot_ = kInvalidSlotValue; + version_ = 0; + { + base::AutoLock auto_lock(g_tls_metadata_lock.Get()); + for (int i = 0; i < kThreadLocalStorageSize; ++i) { + // Tracking the last assigned slot is an attempt to find the next + // available slot within one iteration. Under normal usage, slots remain + // in use for the lifetime of the process (otherwise before we reclaimed + // slots, we would have run out of slots). This makes it highly likely the + // next slot is going to be a free slot. + size_t slot_candidate = + (g_last_assigned_slot + 1 + i) % kThreadLocalStorageSize; + if (g_tls_metadata[slot_candidate].status == TlsStatus::FREE) { + g_tls_metadata[slot_candidate].status = TlsStatus::IN_USE; + g_tls_metadata[slot_candidate].destructor = destructor; + g_last_assigned_slot = slot_candidate; + slot_ = slot_candidate; + version_ = g_tls_metadata[slot_candidate].version; + break; + } + } + } + CHECK_NE(slot_, kInvalidSlotValue); + CHECK_LT(slot_, kThreadLocalStorageSize); + + // Setup our destructor. + base::subtle::Release_Store(&initialized_, 1); +} + +void ThreadLocalStorage::StaticSlot::Free() { + DCHECK_NE(slot_, kInvalidSlotValue); + DCHECK_LT(slot_, kThreadLocalStorageSize); + { + base::AutoLock auto_lock(g_tls_metadata_lock.Get()); + g_tls_metadata[slot_].status = TlsStatus::FREE; + g_tls_metadata[slot_].destructor = nullptr; + ++(g_tls_metadata[slot_].version); + } + slot_ = kInvalidSlotValue; + base::subtle::Release_Store(&initialized_, 0); +} + +void* ThreadLocalStorage::StaticSlot::Get() const { + TlsVectorEntry* tls_data = static_cast( + PlatformThreadLocalStorage::GetTLSValue( + base::subtle::NoBarrier_Load(&g_native_tls_key))); + if (!tls_data) + tls_data = ConstructTlsVector(); + DCHECK_NE(slot_, kInvalidSlotValue); + DCHECK_LT(slot_, kThreadLocalStorageSize); + // Version mismatches means this slot was previously freed. + if (tls_data[slot_].version != version_) + return nullptr; + return tls_data[slot_].data; +} + +void ThreadLocalStorage::StaticSlot::Set(void* value) { + TlsVectorEntry* tls_data = static_cast( + PlatformThreadLocalStorage::GetTLSValue( + base::subtle::NoBarrier_Load(&g_native_tls_key))); + if (!tls_data) + tls_data = ConstructTlsVector(); + DCHECK_NE(slot_, kInvalidSlotValue); + DCHECK_LT(slot_, kThreadLocalStorageSize); + tls_data[slot_].data = value; + tls_data[slot_].version = version_; +} + +ThreadLocalStorage::Slot::Slot(TLSDestructorFunc destructor) { + tls_slot_.Initialize(destructor); +} + +ThreadLocalStorage::Slot::~Slot() { + tls_slot_.Free(); +} + +void* ThreadLocalStorage::Slot::Get() const { + return tls_slot_.Get(); +} + +void ThreadLocalStorage::Slot::Set(void* value) { + tls_slot_.Set(value); +} + +} // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_local_storage.h b/security/sandbox/chromium/base/threading/thread_local_storage.h index 013b0aeffbbe..fd2a789d0152 100644 --- a/security/sandbox/chromium/base/threading/thread_local_storage.h +++ b/security/sandbox/chromium/base/threading/thread_local_storage.h @@ -5,6 +5,8 @@ #ifndef BASE_THREADING_THREAD_LOCAL_STORAGE_H_ #define BASE_THREADING_THREAD_LOCAL_STORAGE_H_ +#include + #include "base/atomicops.h" #include "base/base_export.h" #include "base/macros.h" @@ -20,9 +22,12 @@ namespace base { namespace internal { -// WARNING: You should *NOT* be using this class directly. -// PlatformThreadLocalStorage is low-level abstraction to the OS's TLS -// interface, you should instead be using ThreadLocalStorage::StaticSlot/Slot. +// WARNING: You should *NOT* use this class directly. +// PlatformThreadLocalStorage is a low-level abstraction of the OS's TLS +// interface. Instead, you should use one of the following: +// * ThreadLocalBoolean (from thread_local.h) for booleans. +// * ThreadLocalPointer (from thread_local.h) for pointers. +// * ThreadLocalStorage::StaticSlot/Slot for more direct control of the slot. class BASE_EXPORT PlatformThreadLocalStorage { public: @@ -123,18 +128,25 @@ class BASE_EXPORT ThreadLocalStorage { // The internals of this struct should be considered private. base::subtle::Atomic32 initialized_; int slot_; + uint32_t version_; }; // A convenience wrapper around StaticSlot with a constructor. Can be used // as a member variable. - class BASE_EXPORT Slot : public StaticSlot { + class BASE_EXPORT Slot { public: - // Calls StaticSlot::Initialize(). explicit Slot(TLSDestructorFunc destructor = NULL); + ~Slot(); + + // Get the thread-local value stored in this slot. + // Values are guaranteed to initially be zero. + void* Get() const; + + // Set the slot's thread-local value to |value|. + void Set(void* value); private: - using StaticSlot::initialized_; - using StaticSlot::slot_; + StaticSlot tls_slot_; DISALLOW_COPY_AND_ASSIGN(Slot); }; diff --git a/security/sandbox/chromium/base/threading/thread_local_storage_posix.cc b/security/sandbox/chromium/base/threading/thread_local_storage_posix.cc new file mode 100644 index 000000000000..ebaf4005d331 --- /dev/null +++ b/security/sandbox/chromium/base/threading/thread_local_storage_posix.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/thread_local_storage.h" + +#include "base/logging.h" + +namespace base { + +namespace internal { + +bool PlatformThreadLocalStorage::AllocTLS(TLSKey* key) { + return !pthread_key_create(key, + base::internal::PlatformThreadLocalStorage::OnThreadExit); +} + +void PlatformThreadLocalStorage::FreeTLS(TLSKey key) { + int ret = pthread_key_delete(key); + DCHECK_EQ(ret, 0); +} + +void* PlatformThreadLocalStorage::GetTLSValue(TLSKey key) { + return pthread_getspecific(key); +} + +void PlatformThreadLocalStorage::SetTLSValue(TLSKey key, void* value) { + int ret = pthread_setspecific(key, value); + DCHECK_EQ(ret, 0); +} + +} // namespace internal + +} // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_local_storage_win.cc b/security/sandbox/chromium/base/threading/thread_local_storage_win.cc new file mode 100644 index 000000000000..42a7d016fdd1 --- /dev/null +++ b/security/sandbox/chromium/base/threading/thread_local_storage_win.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/thread_local_storage.h" + +#include + +#include "base/logging.h" + +namespace base { + +namespace internal { + +bool PlatformThreadLocalStorage::AllocTLS(TLSKey* key) { + TLSKey value = TlsAlloc(); + if (value != TLS_OUT_OF_INDEXES) { + *key = value; + return true; + } + return false; +} + +void PlatformThreadLocalStorage::FreeTLS(TLSKey key) { + BOOL ret = TlsFree(key); + DCHECK(ret); +} + +void* PlatformThreadLocalStorage::GetTLSValue(TLSKey key) { + return TlsGetValue(key); +} + +void PlatformThreadLocalStorage::SetTLSValue(TLSKey key, void* value) { + BOOL ret = TlsSetValue(key, value); + DCHECK(ret); +} + +} // namespace internal + +} // namespace base + +// Thread Termination Callbacks. +// Windows doesn't support a per-thread destructor with its +// TLS primitives. So, we build it manually by inserting a +// function to be called on each thread's exit. +// This magic is from http://www.codeproject.com/threads/tls.asp +// and it works for VC++ 7.0 and later. + +// Force a reference to _tls_used to make the linker create the TLS directory +// if it's not already there. (e.g. if __declspec(thread) is not used). +// Force a reference to p_thread_callback_base to prevent whole program +// optimization from discarding the variable. +#ifdef _WIN64 + +#pragma comment(linker, "/INCLUDE:_tls_used") +#pragma comment(linker, "/INCLUDE:p_thread_callback_base") + +#else // _WIN64 + +#pragma comment(linker, "/INCLUDE:__tls_used") +#pragma comment(linker, "/INCLUDE:_p_thread_callback_base") + +#endif // _WIN64 + +// Static callback function to call with each thread termination. +void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved) { + // On XP SP0 & SP1, the DLL_PROCESS_ATTACH is never seen. It is sent on SP2+ + // and on W2K and W2K3. So don't assume it is sent. + if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) + base::internal::PlatformThreadLocalStorage::OnThreadExit(); +} + +// .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are +// called automatically by the OS loader code (not the CRT) when the module is +// loaded and on thread creation. They are NOT called if the module has been +// loaded by a LoadLibrary() call. It must have implicitly been loaded at +// process startup. +// By implicitly loaded, I mean that it is directly referenced by the main EXE +// or by one of its dependent DLLs. Delay-loaded DLL doesn't count as being +// implicitly loaded. +// +// See VC\crt\src\tlssup.c for reference. + +// extern "C" suppresses C++ name mangling so we know the symbol name for the +// linker /INCLUDE:symbol pragma above. +extern "C" { +// The linker must not discard p_thread_callback_base. (We force a reference +// to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If +// this variable is discarded, the OnThreadExit function will never be called. +#ifdef _WIN64 + +// .CRT section is merged with .rdata on x64 so it must be constant data. +#pragma const_seg(".CRT$XLB") +// When defining a const variable, it must have external linkage to be sure the +// linker doesn't discard it. +extern const PIMAGE_TLS_CALLBACK p_thread_callback_base; +const PIMAGE_TLS_CALLBACK p_thread_callback_base = OnThreadExit; + +// Reset the default section. +#pragma const_seg() + +#else // _WIN64 + +#pragma data_seg(".CRT$XLB") +PIMAGE_TLS_CALLBACK p_thread_callback_base = OnThreadExit; + +// Reset the default section. +#pragma data_seg() + +#endif // _WIN64 +} // extern "C" diff --git a/security/sandbox/chromium/base/threading/thread_local_win.cc b/security/sandbox/chromium/base/threading/thread_local_win.cc deleted file mode 100644 index 1c74e4213871..000000000000 --- a/security/sandbox/chromium/base/threading/thread_local_win.cc +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/threading/thread_local.h" - -#include - -#include "base/logging.h" - -namespace base { -namespace internal { - -// static -void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { - *slot = TlsAlloc(); - CHECK_NE(*slot, TLS_OUT_OF_INDEXES); -} - -// static -void ThreadLocalPlatform::FreeSlot(SlotType slot) { - if (!TlsFree(slot)) { - NOTREACHED() << "Failed to deallocate tls slot with TlsFree()."; - } -} - -// static -void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) { - return TlsGetValue(slot); -} - -// static -void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) { - if (!TlsSetValue(slot, value)) { - LOG(FATAL) << "Failed to TlsSetValue()."; - } -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/threading/thread_restrictions.cc b/security/sandbox/chromium/base/threading/thread_restrictions.cc index 00306c5ae7d6..8dd77433325f 100644 --- a/security/sandbox/chromium/base/threading/thread_restrictions.cc +++ b/security/sandbox/chromium/base/threading/thread_restrictions.cc @@ -4,7 +4,7 @@ #include "base/threading/thread_restrictions.h" -#if ENABLE_THREAD_RESTRICTIONS +#if DCHECK_IS_ON() #include "base/lazy_instance.h" #include "base/logging.h" @@ -35,7 +35,7 @@ bool ThreadRestrictions::SetIOAllowed(bool allowed) { // static void ThreadRestrictions::AssertIOAllowed() { if (g_io_disallowed.Get().Get()) { - LOG(FATAL) << + NOTREACHED() << "Function marked as IO-only was called from a thread that " "disallows IO! If this thread really should be allowed to " "make IO calls, adjust the call to " @@ -54,10 +54,14 @@ bool ThreadRestrictions::SetSingletonAllowed(bool allowed) { // static void ThreadRestrictions::AssertSingletonAllowed() { if (g_singleton_disallowed.Get().Get()) { - LOG(FATAL) << "LazyInstance/Singleton is not allowed to be used on this " - << "thread. Most likely it's because this thread is not " - << "joinable, so AtExitManager may have deleted the object " - << "on shutdown, leading to a potential shutdown crash."; + NOTREACHED() << "LazyInstance/Singleton is not allowed to be used on this " + << "thread. Most likely it's because this thread is not " + << "joinable (or the current task is running with " + << "TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN semantics), so " + << "AtExitManager may have deleted the object on shutdown, " + << "leading to a potential shutdown crash. If you need to use " + << "the object from this context, it'll have to be updated to " + << "use Leaky traits."; } } @@ -69,8 +73,8 @@ void ThreadRestrictions::DisallowWaiting() { // static void ThreadRestrictions::AssertWaitAllowed() { if (g_wait_disallowed.Get().Get()) { - LOG(FATAL) << "Waiting is not allowed to be used on this thread to prevent " - << "jank and deadlock."; + NOTREACHED() << "Waiting is not allowed to be used on this thread to " + << "prevent jank and deadlock."; } } @@ -82,4 +86,4 @@ bool ThreadRestrictions::SetWaitAllowed(bool allowed) { } // namespace base -#endif // ENABLE_THREAD_RESTRICTIONS +#endif // DCHECK_IS_ON() diff --git a/security/sandbox/chromium/base/threading/thread_restrictions.h b/security/sandbox/chromium/base/threading/thread_restrictions.h index eec00fbb7969..07b78aa9641e 100644 --- a/security/sandbox/chromium/base/threading/thread_restrictions.h +++ b/security/sandbox/chromium/base/threading/thread_restrictions.h @@ -6,20 +6,17 @@ #define BASE_THREADING_THREAD_RESTRICTIONS_H_ #include "base/base_export.h" +#include "base/logging.h" #include "base/macros.h" -// See comment at top of thread_checker.h -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define ENABLE_THREAD_RESTRICTIONS 1 -#else -#define ENABLE_THREAD_RESTRICTIONS 0 -#endif - class BrowserProcessImpl; class HistogramSynchronizer; class NativeBackendKWallet; class ScopedAllowWaitForLegacyWebViewApi; +namespace blimp { +class BlimpBrowserTest; +} namespace cc { class CompletionEvent; class SingleThreadTaskGraphRunner; @@ -37,14 +34,14 @@ namespace content { class BrowserGpuChannelHostFactory; class BrowserGpuMemoryBufferManager; class BrowserShutdownProfileDumper; +class BrowserSurfaceViewManager; class BrowserTestBase; -class GpuChannelHost; class NestedMessagePumpAndroid; class ScopedAllowWaitForAndroidLayoutTests; class ScopedAllowWaitForDebugURL; class SoftwareOutputDeviceMus; class TextInputClientMac; -class RasterWorkerPool; +class CategorizedWorkerPool; } // namespace content namespace dbus { class Bus; @@ -53,15 +50,14 @@ namespace disk_cache { class BackendImpl; class InFlightIO; } -namespace gles2 { -class CommandBufferClientImpl; +namespace gpu { +class GpuChannelHost; } namespace mojo { -namespace common { -class MessagePumpMojo; +class SyncCallRestrictions; } -} -namespace mus { +namespace ui { +class CommandBufferClientImpl; class CommandBufferLocal; class GpuState; } @@ -81,7 +77,7 @@ class WindowResizeHelperMac; } namespace views { -class WindowManagerConnection; +class ScreenMus; } namespace base { @@ -90,6 +86,10 @@ namespace android { class JavaHandlerThread; } +namespace internal { +class TaskTracker; +} + class SequencedWorkerPool; class SimpleThread; class Thread; @@ -149,7 +149,7 @@ class BASE_EXPORT ThreadRestrictions { DISALLOW_COPY_AND_ASSIGN(ScopedAllowSingleton); }; -#if ENABLE_THREAD_RESTRICTIONS +#if DCHECK_IS_ON() // Set whether the current thread to make IO calls. // Threads start out in the *allowed* state. // Returns the previous value. @@ -188,16 +188,19 @@ class BASE_EXPORT ThreadRestrictions { private: // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first. // BEGIN ALLOWED USAGE. + friend class blimp::BlimpBrowserTest; friend class content::BrowserShutdownProfileDumper; + friend class content::BrowserSurfaceViewManager; friend class content::BrowserTestBase; friend class content::NestedMessagePumpAndroid; friend class content::ScopedAllowWaitForAndroidLayoutTests; friend class content::ScopedAllowWaitForDebugURL; friend class ::HistogramSynchronizer; + friend class internal::TaskTracker; friend class ::ScopedAllowWaitForLegacyWebViewApi; friend class cc::CompletionEvent; friend class cc::SingleThreadTaskGraphRunner; - friend class content::RasterWorkerPool; + friend class content::CategorizedWorkerPool; friend class remoting::AutoThread; friend class ui::WindowResizeHelperMac; friend class MessagePumpDefault; @@ -207,10 +210,10 @@ class BASE_EXPORT ThreadRestrictions { friend class ThreadTestHelper; friend class PlatformThread; friend class android::JavaHandlerThread; - friend class gles2::CommandBufferClientImpl; - friend class mojo::common::MessagePumpMojo; - friend class mus::CommandBufferLocal; - friend class mus::GpuState; + friend class mojo::SyncCallRestrictions; + friend class ui::CommandBufferClientImpl; + friend class ui::CommandBufferLocal; + friend class ui::GpuState; // END ALLOWED USAGE. // BEGIN USAGE THAT NEEDS TO BE FIXED. @@ -221,11 +224,11 @@ class BASE_EXPORT ThreadRestrictions { content::BrowserGpuChannelHostFactory; // http://crbug.com/125248 friend class content::BrowserGpuMemoryBufferManager; // http://crbug.com/420368 - friend class content::GpuChannelHost; // http://crbug.com/125264 friend class content::TextInputClientMac; // http://crbug.com/121917 friend class dbus::Bus; // http://crbug.com/125222 friend class disk_cache::BackendImpl; // http://crbug.com/74623 friend class disk_cache::InFlightIO; // http://crbug.com/74623 + friend class gpu::GpuChannelHost; // http://crbug.com/125264 friend class net::internal::AddressTrackerLinux; // http://crbug.com/125097 friend class net::NetworkChangeNotifierMac; // http://crbug.com/125097 friend class ::BrowserProcessImpl; // http://crbug.com/125207 @@ -233,10 +236,10 @@ class BASE_EXPORT ThreadRestrictions { #if !defined(OFFICIAL_BUILD) friend class content::SoftwareOutputDeviceMus; // Interim non-production code #endif - friend class views::WindowManagerConnection; + friend class views::ScreenMus; // END USAGE THAT NEEDS TO BE FIXED. -#if ENABLE_THREAD_RESTRICTIONS +#if DCHECK_IS_ON() static bool SetWaitAllowed(bool allowed); #else static bool SetWaitAllowed(bool allowed) { return true; } diff --git a/security/sandbox/chromium/base/time/time.cc b/security/sandbox/chromium/base/time/time.cc index 9188887e27bc..0183e0d82119 100644 --- a/security/sandbox/chromium/base/time/time.cc +++ b/security/sandbox/chromium/base/time/time.cc @@ -104,27 +104,23 @@ namespace time_internal { int64_t SaturatedAdd(TimeDelta delta, int64_t value) { CheckedNumeric rv(delta.delta_); rv += value; - return FromCheckedNumeric(rv); + if (rv.IsValid()) + return rv.ValueOrDie(); + // Positive RHS overflows. Negative RHS underflows. + if (value < 0) + return -std::numeric_limits::max(); + return std::numeric_limits::max(); } int64_t SaturatedSub(TimeDelta delta, int64_t value) { CheckedNumeric rv(delta.delta_); rv -= value; - return FromCheckedNumeric(rv); -} - -int64_t FromCheckedNumeric(const CheckedNumeric value) { - if (value.IsValid()) - return value.ValueUnsafe(); - - // We could return max/min but we don't really expose what the maximum delta - // is. Instead, return max/(-max), which is something that clients can reason - // about. - // TODO(rvargas) crbug.com/332611: don't use internal values. - int64_t limit = std::numeric_limits::max(); - if (value.validity() == internal::RANGE_UNDERFLOW) - limit = -limit; - return value.ValueOrDefault(limit); + if (rv.IsValid()) + return rv.ValueOrDie(); + // Negative RHS overflows. Positive RHS underflows. + if (value < 0) + return std::numeric_limits::max(); + return -std::numeric_limits::max(); } } // namespace time_internal @@ -135,11 +131,6 @@ std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { // Time ----------------------------------------------------------------------- -// static -Time Time::Max() { - return Time(std::numeric_limits::max()); -} - // static Time Time::FromTimeT(time_t tt) { if (tt == 0) @@ -265,6 +256,14 @@ bool Time::FromStringInternal(const char* time_string, } #endif +// static +bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) { + return lhs.year == rhs.year && lhs.month == rhs.month && + lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour && + lhs.minute == rhs.minute && lhs.second == rhs.second && + lhs.millisecond == rhs.millisecond; +} + std::ostream& operator<<(std::ostream& os, Time time) { Time::Exploded exploded; time.UTCExplode(&exploded); diff --git a/security/sandbox/chromium/base/time/time.h b/security/sandbox/chromium/base/time/time.h index ea19d7ed9d4d..1084e9517942 100644 --- a/security/sandbox/chromium/base/time/time.h +++ b/security/sandbox/chromium/base/time/time.h @@ -21,9 +21,11 @@ // ThreadTicks will "stand still" whenever the thread has been de-scheduled by // the operating system. // -// All time classes are copyable, assignable, and occupy 64-bits per -// instance. Thus, they can be efficiently passed by-value (as opposed to -// by-reference). +// All time classes are copyable, assignable, and occupy 64-bits per instance. +// As a result, prefer passing them by value: +// void MyFunction(TimeDelta arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const TimeDelta& arg); // Not preferred. // // Definitions of operator<< are provided to make these types work with // DCHECK_EQ() and other log macros. For human-readable formatting, see @@ -56,6 +58,7 @@ #include #include "base/base_export.h" +#include "base/compiler_specific.h" #include "base/numerics/safe_math.h" #include "build/build_config.h" @@ -74,12 +77,12 @@ // For FILETIME in FromFileTime, until it moves to a new converter class. // See TODO(iyengar) below. #include - #include "base/gtest_prod_util.h" #endif namespace base { +class PlatformThreadHandle; class TimeDelta; // The functions in the time_internal namespace are meant to be used only by the @@ -92,10 +95,6 @@ namespace time_internal { BASE_EXPORT int64_t SaturatedAdd(TimeDelta delta, int64_t value); BASE_EXPORT int64_t SaturatedSub(TimeDelta delta, int64_t value); -// Clamp |value| on overflow and underflow conditions. The int64_t argument and -// return value are in terms of a microsecond timebase. -BASE_EXPORT int64_t FromCheckedNumeric(const CheckedNumeric value); - } // namespace time_internal // TimeDelta ------------------------------------------------------------------ @@ -106,14 +105,17 @@ class BASE_EXPORT TimeDelta { } // Converts units of time to TimeDeltas. - static TimeDelta FromDays(int days); - static TimeDelta FromHours(int hours); - static TimeDelta FromMinutes(int minutes); - static TimeDelta FromSeconds(int64_t secs); - static TimeDelta FromMilliseconds(int64_t ms); - static TimeDelta FromSecondsD(double secs); - static TimeDelta FromMillisecondsD(double ms); - static TimeDelta FromMicroseconds(int64_t us); + static constexpr TimeDelta FromDays(int days); + static constexpr TimeDelta FromHours(int hours); + static constexpr TimeDelta FromMinutes(int minutes); + static constexpr TimeDelta FromSeconds(int64_t secs); + static constexpr TimeDelta FromMilliseconds(int64_t ms); + static constexpr TimeDelta FromSecondsD(double secs); + static constexpr TimeDelta FromMillisecondsD(double ms); + static constexpr TimeDelta FromMicroseconds(int64_t us); +#if defined(OS_POSIX) + static TimeDelta FromTimeSpec(const timespec& ts); +#endif #if defined(OS_WIN) static TimeDelta FromQPCValue(LONGLONG qpc_value); #endif @@ -199,13 +201,24 @@ class BASE_EXPORT TimeDelta { TimeDelta operator*(T a) const { CheckedNumeric rv(delta_); rv *= a; - return TimeDelta(time_internal::FromCheckedNumeric(rv)); + if (rv.IsValid()) + return TimeDelta(rv.ValueOrDie()); + // Matched sign overflows. Mismatched sign underflows. + if ((delta_ < 0) ^ (a < 0)) + return TimeDelta(-std::numeric_limits::max()); + return TimeDelta(std::numeric_limits::max()); } template TimeDelta operator/(T a) const { CheckedNumeric rv(delta_); rv /= a; - return TimeDelta(time_internal::FromCheckedNumeric(rv)); + if (rv.IsValid()) + return TimeDelta(rv.ValueOrDie()); + // Matched sign overflows. Mismatched sign underflows. + // Special case to catch divide by zero. + if ((delta_ < 0) ^ (a <= 0)) + return TimeDelta(-std::numeric_limits::max()); + return TimeDelta(std::numeric_limits::max()); } template TimeDelta& operator*=(T a) { @@ -222,25 +235,30 @@ class BASE_EXPORT TimeDelta { } // Comparison operators. - bool operator==(TimeDelta other) const { + constexpr bool operator==(TimeDelta other) const { return delta_ == other.delta_; } - bool operator!=(TimeDelta other) const { + constexpr bool operator!=(TimeDelta other) const { return delta_ != other.delta_; } - bool operator<(TimeDelta other) const { + constexpr bool operator<(TimeDelta other) const { return delta_ < other.delta_; } - bool operator<=(TimeDelta other) const { + constexpr bool operator<=(TimeDelta other) const { return delta_ <= other.delta_; } - bool operator>(TimeDelta other) const { + constexpr bool operator>(TimeDelta other) const { return delta_ > other.delta_; } - bool operator>=(TimeDelta other) const { + constexpr bool operator>=(TimeDelta other) const { return delta_ >= other.delta_; } +#if defined(OS_WIN) + // This works around crbug.com/635974 + constexpr TimeDelta(const TimeDelta& other) : delta_(other.delta_) {} +#endif + private: friend int64_t time_internal::SaturatedAdd(TimeDelta delta, int64_t value); friend int64_t time_internal::SaturatedSub(TimeDelta delta, int64_t value); @@ -248,10 +266,14 @@ class BASE_EXPORT TimeDelta { // Constructs a delta given the duration in microseconds. This is private // to avoid confusion by callers with an integer constructor. Use // FromSeconds, FromMilliseconds, etc. instead. - explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} + constexpr explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} // Private method to build a delta from a double. - static TimeDelta FromDouble(double value); + static constexpr TimeDelta FromDouble(double value); + + // Private method to build a delta from the product of a user-provided value + // and a known-positive value. + static constexpr TimeDelta FromProduct(int64_t value, int64_t positive_value); // Delta in microseconds. int64_t delta_; @@ -307,6 +329,12 @@ class TimeBase { // Returns true if this object represents the maximum time. bool is_max() const { return us_ == std::numeric_limits::max(); } + // Returns the maximum time, which should be greater than any reasonable time + // with which we might compare it. + static TimeClass Max() { + return TimeClass(std::numeric_limits::max()); + } + // For serializing only. Use FromInternalValue() to reconstitute. Please don't // use this and do arithmetic on it, as it is more error prone than using the // provided operators. @@ -434,10 +462,6 @@ class BASE_EXPORT Time : public time_internal::TimeBase