From 44ad00bb914edc3036703be288b4b25e54851f88 Mon Sep 17 00:00:00 2001 From: DOrian JAMINAIS Date: Wed, 26 Jun 2013 15:05:52 +0300 Subject: [PATCH 01/20] Bug 861478 - Search field should pre-fill with selected text. r=vporof --- browser/devtools/debugger/debugger-toolbar.js | 2 +- .../debugger/test/browser_dbg_scripts-searching-01.js | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/browser/devtools/debugger/debugger-toolbar.js b/browser/devtools/debugger/debugger-toolbar.js index fdc19b101165..35294afcc193 100644 --- a/browser/devtools/debugger/debugger-toolbar.js +++ b/browser/devtools/debugger/debugger-toolbar.js @@ -1189,7 +1189,7 @@ FilterView.prototype = { _doSearch: function(aOperator = "") { this._searchbox.focus(); this._searchbox.value = ""; // Need to clear value beforehand. Bug 779738. - this._searchbox.value = aOperator; + this._searchbox.value = aOperator + DebuggerView.getEditorSelectionText(); }, /** diff --git a/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js b/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js index a057c5aa452e..cb5c2108e729 100644 --- a/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js +++ b/browser/devtools/debugger/test/browser_dbg_scripts-searching-01.js @@ -16,7 +16,7 @@ var gSearchBox = null; function test() { - requestLongerTimeout(2); + requestLongerTimeout(3); debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) { gTab = aTab; @@ -269,6 +269,12 @@ function testScriptSearching() { isnot(gSources.widget.getAttribute("label"), noMatchingSources, "The scripts container should not display a notice that matches are found."); + + gEditor.setSelection(1, 5); + EventUtils.synthesizeKey("F", { accelKey:true }); + is(gSearchBox.value, "#" + gEditor.getSelectedText(), + "The search field has the right initial value."); + closeDebuggerAndFinish(); }}, 0); } From d9353abd9c855949037977de460f55d0a26c58d9 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Wed, 26 Jun 2013 07:16:54 -0500 Subject: [PATCH 02/20] Bug 880739 - disable image download test temporarily due to high random orange percentage. r=fryn --- .../base/tests/mochitest/browser_context_menu_tests.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/browser/metro/base/tests/mochitest/browser_context_menu_tests.js b/browser/metro/base/tests/mochitest/browser_context_menu_tests.js index 00f226e8854f..e9e783c5d0e0 100644 --- a/browser/metro/base/tests/mochitest/browser_context_menu_tests.js +++ b/browser/metro/base/tests/mochitest/browser_context_menu_tests.js @@ -409,7 +409,9 @@ gTests.push({ //////////////////////////////////////////////////////////// // Context menu options - + /* + XXX disabled temporarily due to bug 880739 + // image01 - 1x1x100x100 let promise = waitForEvent(document, "popupshown"); sendContextMenuClickToWindow(win, 10, 10); @@ -456,7 +458,7 @@ gTests.push({ purgeEventQueue(); ok(saveLocationPath.exists(), "image saved"); - + */ //////////////////////////////////////////////////////////// // Copy image @@ -465,10 +467,10 @@ gTests.push({ yield promise; ok(ContextMenuUI._menuPopup._visible, "is visible"); - menuItem = document.getElementById("context-copy-image"); + let menuItem = document.getElementById("context-copy-image"); ok(menuItem, "menu item exists"); ok(!menuItem.hidden, "menu item visible"); - popupPromise = waitForEvent(document, "popuphidden"); + let popupPromise = waitForEvent(document, "popuphidden"); EventUtils.synthesizeMouse(menuItem, 10, 10, {}, win); yield popupPromise; From 6df1314056cbf079b012ccd08446cb94a602660b Mon Sep 17 00:00:00 2001 From: Paolo Amadini Date: Wed, 26 Jun 2013 14:20:42 +0200 Subject: [PATCH 03/20] Bug 886375 - Add the becauseAccessDenied property to OS.File.Error. r=yoric --- toolkit/components/osfile/osfile_unix_allthreads.jsm | 9 +++++++++ toolkit/components/osfile/osfile_win_allthreads.jsm | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/toolkit/components/osfile/osfile_unix_allthreads.jsm b/toolkit/components/osfile/osfile_unix_allthreads.jsm index 89b2e6bf7dcf..bb2f28ec02f9 100644 --- a/toolkit/components/osfile/osfile_unix_allthreads.jsm +++ b/toolkit/components/osfile/osfile_unix_allthreads.jsm @@ -138,6 +138,15 @@ if (typeof Components != "undefined") { return this.unixErrno == OS.Constants.libc.EBADF; } }); + /** + * |true| if the error was raised because permission is denied to + * access a file or directory, |false| otherwise. + */ + Object.defineProperty(OSError.prototype, "becauseAccessDenied", { + get: function becauseAccessDenied() { + return this.unixErrno == OS.Constants.libc.EACCES; + } + }); /** * Serialize an instance of OSError to something that can be diff --git a/toolkit/components/osfile/osfile_win_allthreads.jsm b/toolkit/components/osfile/osfile_win_allthreads.jsm index 25c9cbf1486a..f809741a300a 100644 --- a/toolkit/components/osfile/osfile_win_allthreads.jsm +++ b/toolkit/components/osfile/osfile_win_allthreads.jsm @@ -151,6 +151,15 @@ if (typeof Components != "undefined") { return this.winLastError == exports.OS.Constants.Win.ERROR_INVALID_HANDLE; } }); + /** + * |true| if the error was raised because permission is denied to + * access a file or directory, |false| otherwise. + */ + Object.defineProperty(OSError.prototype, "becauseAccessDenied", { + get: function becauseAccessDenied() { + return this.winLastError == exports.OS.Constants.Win.ERROR_ACCESS_DENIED; + } + }); /** * Serialize an instance of OSError to something that can be From 5a4cfb038bfa6fd43349e98d2d0941c45fae17cd Mon Sep 17 00:00:00 2001 From: Paolo Amadini Date: Wed, 26 Jun 2013 14:21:06 +0200 Subject: [PATCH 04/20] Bug 835885 - Add serialization and deserialization. r=enn --- .../jsdownloads/src/DownloadCore.jsm | 45 ++++ .../jsdownloads/src/DownloadIntegration.jsm | 48 +++- .../jsdownloads/src/DownloadStore.jsm | 132 ++++++++++- .../components/jsdownloads/src/Downloads.jsm | 25 +- .../components/jsdownloads/test/unit/head.js | 31 +++ .../test/unit/test_DownloadList.js | 29 --- .../test/unit/test_DownloadStore.js | 219 ++++++++++++++++++ .../jsdownloads/test/unit/xpcshell.ini | 4 +- 8 files changed, 491 insertions(+), 42 deletions(-) create mode 100644 toolkit/components/jsdownloads/test/unit/test_DownloadStore.js diff --git a/toolkit/components/jsdownloads/src/DownloadCore.jsm b/toolkit/components/jsdownloads/src/DownloadCore.jsm index c98e91846036..2fb0cd8e074f 100644 --- a/toolkit/components/jsdownloads/src/DownloadCore.jsm +++ b/toolkit/components/jsdownloads/src/DownloadCore.jsm @@ -440,6 +440,23 @@ DownloadSource.prototype = { * should be sent or the download source is not HTTP. */ referrer: null, + + /** + * Returns a static representation of the current object state. + * + * @return A JavaScript object that can be serialized to JSON. + */ + serialize: function DS_serialize() + { + let serialized = { uri: this.uri.spec }; + if (this.isPrivate) { + serialized.isPrivate = true; + } + if (this.referrer) { + serialized.referrer = this.referrer.spec; + } + return serialized; + }, }; //////////////////////////////////////////////////////////////////////////////// @@ -456,6 +473,16 @@ DownloadTarget.prototype = { * The nsIFile for the download target. */ file: null, + + /** + * Returns a static representation of the current object state. + * + * @return A JavaScript object that can be serialized to JSON. + */ + serialize: function DT_serialize() + { + return { file: this.file.path }; + }, }; //////////////////////////////////////////////////////////////////////////////// @@ -555,6 +582,16 @@ DownloadSaver.prototype = { { throw new Error("Not implemented."); }, + + /** + * Returns a static representation of the current object state. + * + * @return A JavaScript object that can be serialized to JSON. + */ + serialize: function DS_serialize() + { + throw new Error("Not implemented."); + }, }; //////////////////////////////////////////////////////////////////////////////// @@ -686,6 +723,14 @@ DownloadCopySaver.prototype = { this._backgroundFileSaver = null; } }, + + /** + * Implements "DownloadSaver.serialize". + */ + serialize: function DCS_serialize() + { + return { type: "copy" }; + }, }; //////////////////////////////////////////////////////////////////////////////// diff --git a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm index a9cc7135299b..afafe5dc1fed 100644 --- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm +++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm @@ -25,14 +25,16 @@ const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore", + "resource://gre/modules/DownloadStore.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", + "resource://gre/modules/FileUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "OS", + "resource://gre/modules/osfile.jsm") XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "env", "@mozilla.org/process/environment;1", "nsIEnvironment"); @@ -51,6 +53,44 @@ XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() { this.DownloadIntegration = { // For testing only testMode: false, + dontLoad: false, + + /** + * Main DownloadStore object for loading and saving the list of persistent + * downloads, or null if the download list was never requested and thus it + * doesn't need to be persisted. + */ + _store: null, + + /** + * Performs initialization of the list of persistent downloads, before its + * first use by the host application. This function may be called only once + * during the entire lifetime of the application. + * + * @param aList + * DownloadList object to be populated with the download objects + * serialized from the previous session. This list will be persisted + * to disk during the session lifetime or when the session terminates. + * + * @return {Promise} + * @resolves When the list has been populated. + * @rejects JavaScript exception. + */ + loadPersistent: function DI_loadPersistent(aList) + { + if (this.dontLoad) { + return Promise.resolve(); + } + + if (this._store) { + throw new Error("loadPersistent may be called only once."); + } + + this._store = new DownloadStore(aList, OS.Path.join( + OS.Constants.Path.profileDir, + "downloads.json")); + return this._store.load(); + }, /** * Returns the system downloads directory asynchronously. diff --git a/toolkit/components/jsdownloads/src/DownloadStore.jsm b/toolkit/components/jsdownloads/src/DownloadStore.jsm index 8fd263d64281..cd956c4a0a11 100644 --- a/toolkit/components/jsdownloads/src/DownloadStore.jsm +++ b/toolkit/components/jsdownloads/src/DownloadStore.jsm @@ -25,14 +25,144 @@ const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Downloads", + "resource://gre/modules/Downloads.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", + "resource://gre/modules/NetUtil.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "OS", + "resource://gre/modules/osfile.jsm") +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + +const LocalFile = Components.Constructor("@mozilla.org/file/local;1", + "nsIFile", "initWithPath"); + +XPCOMUtils.defineLazyGetter(this, "gTextDecoder", function () { + return new TextDecoder(); +}); + +XPCOMUtils.defineLazyGetter(this, "gTextEncoder", function () { + return new TextEncoder(); +}); + //////////////////////////////////////////////////////////////////////////////// //// DownloadStore /** * Handles serialization of Download objects and persistence into a file, so * that the state of downloads can be restored across sessions. + * + * @param aList + * DownloadList object to be populated or serialized. + * @param aPath + * String containing the file path where data should be saved. */ -function DownloadStore() { } +function DownloadStore(aList, aPath) +{ + this.list = aList; + this.path = aPath; +} DownloadStore.prototype = { + /** + * DownloadList object to be populated or serialized. + */ + list: null, + + /** + * String containing the file path where data should be saved. + */ + path: "", + + /** + * Loads persistent downloads from the file to the list. + * + * @return {Promise} + * @resolves When the operation finished successfully. + * @rejects JavaScript exception. + */ + load: function DS_load() + { + return Task.spawn(function task_DS_load() { + let bytes; + try { + bytes = yield OS.File.read(this.path); + } catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) { + // If the file does not exist, there are no downloads to load. + return; + } + + let storeData = JSON.parse(gTextDecoder.decode(bytes)); + + // Create live downloads based on the static snapshot. + for (let downloadData of storeData) { + try { + let source = { uri: NetUtil.newURI(downloadData.source.uri) }; + if ("referrer" in downloadData.source) { + source.referrer = NetUtil.newURI(downloadData.source.referrer); + } + let download = yield Downloads.createDownload({ + source: source, + target: { file: new LocalFile(downloadData.target.file) }, + saver: downloadData.saver, + }); + + this.list.add(download); + } catch (ex) { + // If an item is unrecognized, don't prevent others from being loaded. + Cu.reportError(ex); + } + } + }.bind(this)); + }, + + /** + * Saves persistent downloads from the list to the file. + * + * If an error occurs, the previous file is not deleted. + * + * @return {Promise} + * @resolves When the operation finished successfully. + * @rejects JavaScript exception. + */ + save: function DS_save() + { + return Task.spawn(function task_DS_save() { + let downloads = yield this.list.getAll(); + + // Take a static snapshot of the current state of all the downloads. + let storeData = []; + let atLeastOneDownload = false; + for (let download of downloads) { + try { + storeData.push({ + source: download.source.serialize(), + target: download.target.serialize(), + saver: download.saver.serialize(), + }); + atLeastOneDownload = true; + } catch (ex) { + // If an item cannot be serialized, don't prevent others from being + // saved. + Cu.reportError(ex); + } + } + + if (atLeastOneDownload) { + // Create or overwrite the file if there are downloads to save. + let bytes = gTextEncoder.encode(JSON.stringify(storeData)); + yield OS.File.writeAtomic(this.path, bytes, + { tmpPath: this.path + ".tmp" }); + } else { + // Remove the file if there are no downloads to save at all. + try { + yield OS.File.remove(this.path); + } catch (ex if ex instanceof OS.File.Error && + (ex.becauseNoSuchFile || ex.becauseAccessDenied)) { + // On Windows, we may get an access denied error instead of a no such + // file error if the file existed before, and was recently deleted. + } + } + }.bind(this)); + }, }; diff --git a/toolkit/components/jsdownloads/src/Downloads.jsm b/toolkit/components/jsdownloads/src/Downloads.jsm index ed7c176671a4..9a7e4be8efe1 100644 --- a/toolkit/components/jsdownloads/src/Downloads.jsm +++ b/toolkit/components/jsdownloads/src/Downloads.jsm @@ -29,8 +29,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration", "resource://gre/modules/DownloadIntegration.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DownloadList", "resource://gre/modules/DownloadList.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore", - "resource://gre/modules/DownloadStore.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DownloadUIHelper", "resource://gre/modules/DownloadUIHelper.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", @@ -173,12 +171,27 @@ this.Downloads = { */ getPublicDownloadList: function D_getPublicDownloadList() { - if (!this._publicDownloadList) { - this._publicDownloadList = new DownloadList(true); + if (!this._promisePublicDownloadList) { + this._promisePublicDownloadList = Task.spawn( + function task_D_getPublicDownloadList() { + let list = new DownloadList(true); + try { + yield DownloadIntegration.loadPersistent(list); + } catch (ex) { + Cu.reportError(ex); + } + throw new Task.Result(list); + }); } - return Promise.resolve(this._publicDownloadList); + return this._promisePublicDownloadList; }, - _publicDownloadList: null, + + /** + * This promise is resolved with a reference to a DownloadList object that + * represents persistent downloads. This property is null before the list of + * downloads is requested for the first time. + */ + _promisePublicDownloadList: null, /** * Retrieves the DownloadList object for downloads that were started from diff --git a/toolkit/components/jsdownloads/test/unit/head.js b/toolkit/components/jsdownloads/test/unit/head.js index b5304e81912c..77ae49243be8 100644 --- a/toolkit/components/jsdownloads/test/unit/head.js +++ b/toolkit/components/jsdownloads/test/unit/head.js @@ -75,6 +75,8 @@ const TEST_INTERRUPTIBLE_GZIP_URI = NetUtil.newURI(HTTP_BASE + TEST_INTERRUPTIBLE_GZIP_PATH); const TEST_TARGET_FILE_NAME = "test-download.txt"; +const TEST_STORE_FILE_NAME = "test-downloads.json"; + const TEST_DATA_SHORT = "This test string is downloaded."; // Generate using gzipCompressString in TelemetryPing.js. const TEST_DATA_SHORT_GZIP_ENCODED_FIRST = [ @@ -184,6 +186,32 @@ function promiseSimpleDownload(aSourceURI) { }); } +/** + * Returns a new public DownloadList object. + * + * @return {Promise} + * @resolves The newly created DownloadList object. + * @rejects JavaScript exception. + */ +function promiseNewDownloadList() { + // Force the creation of a new public download list. + Downloads._promisePublicDownloadList = null; + return Downloads.getPublicDownloadList(); +} + +/** + * Returns a new private DownloadList object. + * + * @return {Promise} + * @resolves The newly created DownloadList object. + * @rejects JavaScript exception. + */ +function promiseNewPrivateDownloadList() { + // Force the creation of a new public download list. + Downloads._privateDownloadList = null; + return Downloads.getPrivateDownloadList(); +} + /** * Ensures that the given file contents are equal to the given string. * @@ -420,4 +448,7 @@ add_task(function test_common_initialize() bos.writeByteArray(TEST_DATA_SHORT_GZIP_ENCODED_SECOND, TEST_DATA_SHORT_GZIP_ENCODED_SECOND.length); }); + + // Disable integration with the host application requiring profile access. + DownloadIntegration.dontLoad = true; }); diff --git a/toolkit/components/jsdownloads/test/unit/test_DownloadList.js b/toolkit/components/jsdownloads/test/unit/test_DownloadList.js index 0b8eb8355b95..4828f6113302 100644 --- a/toolkit/components/jsdownloads/test/unit/test_DownloadList.js +++ b/toolkit/components/jsdownloads/test/unit/test_DownloadList.js @@ -9,35 +9,6 @@ "use strict"; -//////////////////////////////////////////////////////////////////////////////// -//// Globals - -/** - * Returns a new DownloadList object. - * - * @return {Promise} - * @resolves The newly created DownloadList object. - * @rejects JavaScript exception. - */ -function promiseNewDownloadList() { - // Force the creation of a new public download list. - Downloads._publicDownloadList = null; - return Downloads.getPublicDownloadList(); -} - -/** - * Returns a new private DownloadList object. - * - * @return {Promise} - * @resolves The newly created DownloadList object. - * @rejects JavaScript exception. - */ -function promiseNewPrivateDownloadList() { - // Force the creation of a new public download list. - Downloads._privateDownloadList = null; - return Downloads.getPrivateDownloadList(); -} - //////////////////////////////////////////////////////////////////////////////// //// Tests diff --git a/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js b/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js new file mode 100644 index 000000000000..b9fc857b212c --- /dev/null +++ b/toolkit/components/jsdownloads/test/unit/test_DownloadStore.js @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests the DownloadStore object. + */ + +"use strict"; + +//////////////////////////////////////////////////////////////////////////////// +//// Globals + +XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore", + "resource://gre/modules/DownloadStore.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "OS", + "resource://gre/modules/osfile.jsm") + +/** + * Returns a new DownloadList object with an associated DownloadStore. + * + * @param aStorePath + * String pointing to the file to be associated with the DownloadStore, + * or undefined to use a non-existing temporary file. In this case, the + * temporary file is deleted when the test file execution finishes. + * + * @return {Promise} + * @resolves Array [ Newly created DownloadList , associated DownloadStore ]. + * @rejects JavaScript exception. + */ +function promiseNewListAndStore(aStorePath) { + return promiseNewDownloadList().then(function (aList) { + let path = aStorePath || getTempFile(TEST_STORE_FILE_NAME).path; + let store = new DownloadStore(aList, path); + return [aList, store]; + }); +} + +//////////////////////////////////////////////////////////////////////////////// +//// Tests + +/** + * Saves downloads to a file, then reloads them. + */ +add_task(function test_save_reload() +{ + let [listForSave, storeForSave] = yield promiseNewListAndStore(); + let [listForLoad, storeForLoad] = yield promiseNewListAndStore( + storeForSave.path); + + listForSave.add(yield promiseSimpleDownload(TEST_SOURCE_URI)); + listForSave.add(yield Downloads.createDownload({ + source: { uri: TEST_EMPTY_URI, + referrer: TEST_REFERRER_URI }, + target: { file: getTempFile(TEST_TARGET_FILE_NAME) }, + saver: { type: "copy" }, + })); + + yield storeForSave.save(); + yield storeForLoad.load(); + + let itemsForSave = yield listForSave.getAll(); + let itemsForLoad = yield listForLoad.getAll(); + + do_check_eq(itemsForSave.length, itemsForLoad.length); + + // Downloads should be reloaded in the same order. + for (let i = 0; i < itemsForSave.length; i++) { + // The reloaded downloads are different objects. + do_check_neq(itemsForSave[i], itemsForLoad[i]); + + // The reloaded downloads have the same properties. + do_check_true(itemsForSave[i].source.uri.equals( + itemsForLoad[i].source.uri)); + if (itemsForSave[i].source.referrer) { + do_check_true(itemsForSave[i].source.referrer.equals( + itemsForLoad[i].source.referrer)); + } else { + do_check_true(itemsForLoad[i].source.referrer === null); + } + do_check_true(itemsForSave[i].target.file.equals( + itemsForLoad[i].target.file)); + do_check_eq(itemsForSave[i].saver.type, + itemsForLoad[i].saver.type); + } +}); + +/** + * Checks that saving an empty list deletes any existing file. + */ +add_task(function test_save_empty() +{ + let [list, store] = yield promiseNewListAndStore(); + + let createdFile = yield OS.File.open(store.path, { create: true }); + yield createdFile.close(); + + yield store.save(); + + do_check_false(yield OS.File.exists(store.path)); + + // If the file does not exist, saving should not generate exceptions. + yield store.save(); +}); + +/** + * Checks that loading from a missing file results in an empty list. + */ +add_task(function test_load_empty() +{ + let [list, store] = yield promiseNewListAndStore(); + + do_check_false(yield OS.File.exists(store.path)); + + yield store.load(); + + let items = yield list.getAll(); + do_check_eq(items.length, 0); +}); + +/** + * Loads downloads from a string in a predefined format. The purpose of this + * test is to verify that the JSON format used in previous versions can be + * loaded, assuming the file is reloaded on the same platform. + */ +add_task(function test_load_string_predefined() +{ + let [list, store] = yield promiseNewListAndStore(); + + // The platform-dependent file name should be generated dynamically. + let targetFile = getTempFile(TEST_TARGET_FILE_NAME); + let filePathLiteral = JSON.stringify(targetFile.path); + let sourceUriLiteral = JSON.stringify(TEST_SOURCE_URI.spec); + let emptyUriLiteral = JSON.stringify(TEST_EMPTY_URI.spec); + let referrerUriLiteral = JSON.stringify(TEST_REFERRER_URI.spec); + + let string = "[{\"source\":{\"uri\":" + sourceUriLiteral + "}," + + "\"target\":{\"file\":" + filePathLiteral + "}," + + "\"saver\":{\"type\":\"copy\"}}," + + "{\"source\":{\"uri\":" + emptyUriLiteral + "," + + "\"referrer\":" + referrerUriLiteral + "}," + + "\"target\":{\"file\":" + filePathLiteral + "}," + + "\"saver\":{\"type\":\"copy\"}}]"; + + yield OS.File.writeAtomic(store.path, + new TextEncoder().encode(string), + { tmpPath: store.path + ".tmp" }); + + yield store.load(); + + let items = yield list.getAll(); + + do_check_eq(items.length, 2); + + do_check_true(items[0].source.uri.equals(TEST_SOURCE_URI)); + do_check_true(items[0].target.file.equals(targetFile)); + + do_check_true(items[1].source.uri.equals(TEST_EMPTY_URI)); + do_check_true(items[1].source.referrer.equals(TEST_REFERRER_URI)); + do_check_true(items[1].target.file.equals(targetFile)); +}); + +/** + * Loads downloads from a well-formed JSON string containing unrecognized data. + */ +add_task(function test_load_string_unrecognized() +{ + let [list, store] = yield promiseNewListAndStore(); + + // The platform-dependent file name should be generated dynamically. + let targetFile = getTempFile(TEST_TARGET_FILE_NAME); + let filePathLiteral = JSON.stringify(targetFile.path); + let sourceUriLiteral = JSON.stringify(TEST_SOURCE_URI.spec); + + let string = "[{\"source\":null," + + "\"target\":null}," + + "{\"source\":{\"uri\":" + sourceUriLiteral + "}," + + "\"target\":{\"file\":" + filePathLiteral + "}," + + "\"saver\":{\"type\":\"copy\"}}]"; + + yield OS.File.writeAtomic(store.path, + new TextEncoder().encode(string), + { tmpPath: store.path + ".tmp" }); + + yield store.load(); + + let items = yield list.getAll(); + + do_check_eq(items.length, 1); + + do_check_true(items[0].source.uri.equals(TEST_SOURCE_URI)); + do_check_true(items[0].target.file.equals(targetFile)); +}); + +/** + * Loads downloads from a malformed JSON string. + */ +add_task(function test_load_string_malformed() +{ + let [list, store] = yield promiseNewListAndStore(); + + let string = "[{\"source\":null,\"target\":null}," + + "{\"source\":{\"uri\":\"about:blank\"}}"; + + yield OS.File.writeAtomic(store.path, new TextEncoder().encode(string), + { tmpPath: store.path + ".tmp" }); + + try { + yield store.load(); + do_throw("Exception expected when JSON data is malformed."); + } catch (ex if ex.name == "SyntaxError") { + do_print("The expected SyntaxError exception was thrown."); + } + + let items = yield list.getAll(); + + do_check_eq(items.length, 0); +}); diff --git a/toolkit/components/jsdownloads/test/unit/xpcshell.ini b/toolkit/components/jsdownloads/test/unit/xpcshell.ini index 45e2879bbf83..604ee7904b42 100644 --- a/toolkit/components/jsdownloads/test/unit/xpcshell.ini +++ b/toolkit/components/jsdownloads/test/unit/xpcshell.ini @@ -3,8 +3,8 @@ head = head.js tail = tail.js [test_DownloadCore.js] +[test_DownloadIntegration.js] [test_DownloadLegacy.js] [test_DownloadList.js] [test_Downloads.js] -[test_DownloadIntegration.js] - +[test_DownloadStore.js] From 35db2a3e66dc4ac61eaccd0925f611b2eade6f0f Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Wed, 26 Jun 2013 13:31:06 +0100 Subject: [PATCH 05/20] Bug 829085 - Fix hit testing when vector-effect=non-scaling-stroke is used. r=dholbert --- content/svg/content/test/Makefile.in | 1 + .../content/test/test_non-scaling-stroke.html | 53 +++++++++++++++++++ layout/svg/nsSVGPathGeometryFrame.cpp | 5 ++ 3 files changed, 59 insertions(+) create mode 100644 content/svg/content/test/test_non-scaling-stroke.html diff --git a/content/svg/content/test/Makefile.in b/content/svg/content/test/Makefile.in index 786c3057c86c..bfca9572ef65 100644 --- a/content/svg/content/test/Makefile.in +++ b/content/svg/content/test/Makefile.in @@ -45,6 +45,7 @@ MOCHITEST_FILES = \ test_hasFeature.xhtml \ $(filter disabled-for-intermittent-failures--bug-701060, test_lang.xhtml) \ test_nonAnimStrings.xhtml \ + test_non-scaling-stroke.html \ test_pathAnimInterpolation.xhtml \ test_pathSeg.xhtml \ test_pointAtLength.xhtml \ diff --git a/content/svg/content/test/test_non-scaling-stroke.html b/content/svg/content/test/test_non-scaling-stroke.html new file mode 100644 index 000000000000..06099bd9bfc2 --- /dev/null +++ b/content/svg/content/test/test_non-scaling-stroke.html @@ -0,0 +1,53 @@ + + + + + Test for Bug 829085 - non-scaling-stroke hit testing + + + + + + + Mozilla Bug 829085 - non-scaling-stroke hit testing +

+
+ + + + + + + + + +
+
+
+
+ + diff --git a/layout/svg/nsSVGPathGeometryFrame.cpp b/layout/svg/nsSVGPathGeometryFrame.cpp index f9792ae6bf13..33610b66e981 100644 --- a/layout/svg/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/nsSVGPathGeometryFrame.cpp @@ -244,6 +244,11 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) isHit = tmpCtx->PointInFill(userSpacePoint); if (!isHit && (hitTestFlags & SVG_HIT_TEST_STROKE)) { nsSVGUtils::SetupCairoStrokeGeometry(this, tmpCtx); + // tmpCtx's matrix may have transformed by SetupCairoStrokeGeometry + // if there is a non-scaling stroke. We need to transform userSpacePoint + // so that everything is using the same co-ordinate system. + userSpacePoint = + nsSVGUtils::GetStrokeTransform(this).Invert().Transform(userSpacePoint); isHit = tmpCtx->PointInStroke(userSpacePoint); } From 1120465f18672cef6d4edb305f8a4ace7fa30bc5 Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Sun, 16 Jun 2013 22:03:12 -0400 Subject: [PATCH 06/20] Bug 884057 - Fix a memory leak in GLContextProviderGLX: was not destroying pixmaps used for offscreen contexts - r=jgilbert --- gfx/gl/GLContextProviderGLX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp index ec36fee990d5..a36a3669168f 100644 --- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -1387,7 +1387,7 @@ DONE_CREATING_PIXMAP: display, glxpixmap, cfgs[chosenIndex], - false, + true, libToUse, xsurface); } From ebb91fd901fba6674608109314c50b9d79972fe4 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 25 Jun 2013 08:22:00 +0200 Subject: [PATCH 07/20] Bug 881504 - Fix crash in mozilla::a11y::DocManager::RemoveListeners, r=surkov --- accessible/src/base/DocManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/accessible/src/base/DocManager.cpp b/accessible/src/base/DocManager.cpp index bd689a2e0a40..39861563bdd4 100644 --- a/accessible/src/base/DocManager.cpp +++ b/accessible/src/base/DocManager.cpp @@ -355,6 +355,9 @@ DocManager::RemoveListeners(nsIDocument* aDocument) return; EventTarget* target = window->GetChromeEventHandler(); + if (!target) + return; + nsEventListenerManager* elm = target->GetListenerManager(true); elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"), dom::TrustedEventsAtCapture()); From f09265969f986014fed71f48c62ea3f2174a0830 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Wed, 26 Jun 2013 15:16:42 +0200 Subject: [PATCH 08/20] Bug 882416 - Fix Function constructor to override the noScriptRval flag. r=luke --- js/src/jit-test/tests/basic/bug882416.js | 6 ++++++ js/src/jsfun.cpp | 1 + 2 files changed, 7 insertions(+) create mode 100644 js/src/jit-test/tests/basic/bug882416.js diff --git a/js/src/jit-test/tests/basic/bug882416.js b/js/src/jit-test/tests/basic/bug882416.js new file mode 100644 index 000000000000..bc4c46abb6e6 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug882416.js @@ -0,0 +1,6 @@ +// |jit-test| error: can't convert +Error.prototype.toString = Function; +evaluate("n f", { + noScriptRval: true, + saveFrameChain: true +}); diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 3022ca1f3a78..83a015bd4544 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1351,6 +1351,7 @@ js::Function(JSContext *cx, unsigned argc, Value *vp) options.setPrincipals(principals) .setOriginPrincipals(originPrincipals) .setFileAndLine(filename, lineno) + .setNoScriptRval(false) .setCompileAndGo(true); unsigned n = args.length() ? args.length() - 1 : 0; From 9c80385e74d0023726a23d5ccca1e28c95b8eb9b Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Wed, 26 Jun 2013 15:16:48 +0200 Subject: [PATCH 09/20] Bug 885648 - Add barriers for generator stack value. r=terrence --- js/src/jit-test/tests/basic/bug885648.js | 9 +++++++++ js/src/jsiter.cpp | 10 ++++------ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 js/src/jit-test/tests/basic/bug885648.js diff --git a/js/src/jit-test/tests/basic/bug885648.js b/js/src/jit-test/tests/basic/bug885648.js new file mode 100644 index 000000000000..60816962cae4 --- /dev/null +++ b/js/src/jit-test/tests/basic/bug885648.js @@ -0,0 +1,9 @@ +gczeal(4,1); +var iterable = {persistedProp: 17}; +iterable.__iterator__ = function() { + yield ["foo", 2]; + yield ["bar", 3]; +}; +var it = Iterator(iterable); +assertEq(it.next().toString(), "foo,2"); +assertEq(it.next().toString(), "bar,3"); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index b2101a2c8309..18f088c43d1d 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1418,11 +1418,6 @@ GeneratorState::pushInterpreterFrame(JSContext *cx, FrameGuard *) * or else some kind of epoch scheme would have to be used. */ GeneratorWriteBarrierPre(cx, gen_); - - /* - * Don't change the state until after the frame is successfully pushed - * or else we might fail to scan some generator values. - */ gen_->state = futureState_; gen_->fp->clearSuspended(); @@ -1561,9 +1556,12 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj, if (gen->state == JSGEN_OPEN) { /* * Store the argument to send as the result of the yield - * expression. + * expression. The generator stack is not barriered, so we need + * write barriers here. */ + HeapValue::writeBarrierPre(gen->regs.sp[-1]); gen->regs.sp[-1] = arg; + HeapValue::writeBarrierPost(cx->runtime(), gen->regs.sp[-1], &gen->regs.sp[-1]); } futureState = JSGEN_RUNNING; break; From 7f4d63c6b843f719769064eb469b2d46fe92baa4 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 26 Jun 2013 12:34:47 +0200 Subject: [PATCH 10/20] Bug 648949 - Remove HAS_JS_GENERATORS #define. r=Waldo, r=jorendorff --- js/src/frontend/BytecodeEmitter.cpp | 8 -------- js/src/frontend/Parser.cpp | 18 ------------------ js/src/jsapi.cpp | 2 -- js/src/jsatom.cpp | 6 ++---- js/src/jsatom.h | 6 ++---- js/src/jsfun.cpp | 4 ---- js/src/jsiter.cpp | 13 +------------ js/src/jsiter.h | 3 --- js/src/jsreflect.cpp | 7 +------ js/src/vm/Interpreter.cpp | 8 -------- js/src/vm/Keywords.h | 12 +++--------- 11 files changed, 9 insertions(+), 78 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 213ffc45d7ca..b68423d14181 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -5476,7 +5476,6 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) * JSOP_SETELEM/JSOP_SETPROP would do. */ -#if JS_HAS_GENERATORS if (pn->isKind(PNK_ARRAYCOMP)) { if (!EmitNewInit(cx, bce, JSProto_Array, pn)) return false; @@ -5496,7 +5495,6 @@ EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) /* Emit the usual op needed for decompilation. */ return Emit1(cx, bce, JSOP_ENDINIT) >= 0; } -#endif /* JS_HAS_GENERATORS */ if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head && bce->checkSingletonContext()) return EmitSingletonInitialiser(cx, bce, pn); @@ -5782,7 +5780,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) ok = EmitReturn(cx, bce, pn); break; -#if JS_HAS_GENERATORS case PNK_YIELD: JS_ASSERT(bce->sc->isFunctionBox()); if (pn->pn_kid) { @@ -5797,7 +5794,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) if (Emit1(cx, bce, JSOP_YIELD) < 0) return false; break; -#endif case PNK_STATEMENTLIST: ok = EmitStatementList(cx, bce, pn, top); @@ -5943,7 +5939,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) : EmitVariables(cx, bce, pn, InitializeVars); break; #endif /* JS_HAS_BLOCK_SCOPE */ -#if JS_HAS_GENERATORS case PNK_ARRAYPUSH: { int slot; @@ -5962,12 +5957,9 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn) return false; break; } -#endif case PNK_ARRAY: -#if JS_HAS_GENERATORS case PNK_ARRAYCOMP: -#endif ok = EmitArray(cx, bce, pn); break; diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 92b87b19c859..7d676d07da78 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -4394,7 +4394,6 @@ Parser::returnStatementOrYieldExpression() } if (isYield) { - JS_ASSERT(JS_HAS_GENERATORS); if (!abortIfSyntaxParser()) return null(); @@ -4883,13 +4882,11 @@ Parser::expr() pn2->initList(pn); pn = pn2; do { -#if JS_HAS_GENERATORS pn2 = pn->last(); if (pn2->isKind(PNK_YIELD) && !pn2->isInParens()) { report(ParseError, false, pn2, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str); return null(); } -#endif pn2 = assignExpr(); if (!pn2) return null(); @@ -5158,12 +5155,10 @@ Parser::assignExpr() { JS_CHECK_RECURSION(context, return null()); -#if JS_HAS_GENERATORS if (tokenStream.matchToken(TOK_YIELD, TSF_OPERAND)) return returnStatementOrYieldExpression(); if (tokenStream.hadError()) return null(); -#endif // Save the tokenizer state in case we find an arrow function and have to // rewind. @@ -5369,8 +5364,6 @@ Parser::unaryExpr() return pn; } -#if JS_HAS_GENERATORS - /* * A dedicated helper for transplanting the comprehension expression E in * @@ -6104,22 +6097,17 @@ Parser::generatorExpr(Node kid) static const char js_generator_str[] = "generator"; #endif /* JS_HAS_GENERATOR_EXPRS */ -#endif /* JS_HAS_GENERATORS */ template typename ParseHandler::Node Parser::assignExprWithoutYield(unsigned msg) { -#ifdef JS_HAS_GENERATORS GenexpGuard yieldGuard(this); -#endif Node res = assignExpr(); yieldGuard.endBody(); if (res) { -#ifdef JS_HAS_GENERATORS if (!yieldGuard.checkValidBody(res, msg)) return null(); -#endif } return res; } @@ -6141,13 +6129,11 @@ Parser::argumentList(Node listNode) if (arg0) guard.endBody(); -#if JS_HAS_GENERATORS if (handler.isOperationWithoutParens(argNode, PNK_YIELD) && tokenStream.peekToken() == TOK_COMMA) { report(ParseError, false, argNode, JSMSG_BAD_GENERATOR_SYNTAX, js_yield_str); return false; } -#endif #if JS_HAS_GENERATOR_EXPRS if (tokenStream.matchToken(TOK_FOR)) { if (!guard.checkValidBody(argNode)) @@ -6375,9 +6361,7 @@ Parser::primaryExpr(TokenKind tt) pn = handler.newList(PNK_ARRAY, null(), JSOP_NEWINIT); if (!pn) return null(); -#if JS_HAS_GENERATORS handler.setBlockId(pn, pc->blockidGen); -#endif if (tokenStream.matchToken(TOK_RB, TSF_OPERAND)) { /* @@ -6437,7 +6421,6 @@ Parser::primaryExpr(TokenKind tt) } } -#if JS_HAS_GENERATORS /* * At this point, (index == 0 && missingTrailingComma) implies one * element initialiser was parsed. @@ -6483,7 +6466,6 @@ Parser::primaryExpr(TokenKind tt) if (!arrayInitializerComprehensionTail(pn)) return null(); } -#endif /* JS_HAS_GENERATORS */ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST); } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index bcb2a84cfac1..6833e6ab0331 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1813,9 +1813,7 @@ static const JSStdName standard_class_atoms[] = { {js_InitStringClass, EAGER_ATOM_AND_OCLASP(String)}, {js_InitExceptionClasses, EAGER_ATOM_AND_OCLASP(Error)}, {js_InitRegExpClass, EAGER_ATOM_AND_OCLASP(RegExp)}, -#if JS_HAS_GENERATORS {js_InitIteratorClasses, EAGER_ATOM_AND_OCLASP(StopIteration)}, -#endif {js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBufferObject::protoClass}, {js_InitWeakMapClass, EAGER_ATOM_AND_OCLASP(WeakMap)}, diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 182d5606ba69..4e82f2af4502 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -65,6 +65,7 @@ const char js_break_str[] = "break"; const char js_case_str[] = "case"; const char js_catch_str[] = "catch"; const char js_class_str[] = "class"; +const char js_close_str[] = "close"; const char js_const_str[] = "const"; const char js_continue_str[] = "continue"; const char js_debugger_str[] = "debugger"; @@ -89,6 +90,7 @@ const char js_package_str[] = "package"; const char js_private_str[] = "private"; const char js_protected_str[] = "protected"; const char js_public_str[] = "public"; +const char js_send_str[] = "send"; const char js_setter_str[] = "setter"; const char js_static_str[] = "static"; const char js_super_str[] = "super"; @@ -100,10 +102,6 @@ const char js_void_str[] = "void"; const char js_while_str[] = "while"; const char js_with_str[] = "with"; const char js_yield_str[] = "yield"; -#if JS_HAS_GENERATORS -const char js_close_str[] = "close"; -const char js_send_str[] = "send"; -#endif /* * For a browser build from 2007-08-09 after the browser starts up there are diff --git a/js/src/jsatom.h b/js/src/jsatom.h index 255de20cc366..7d92e6bcf0f9 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -135,6 +135,7 @@ extern const char js_break_str[]; extern const char js_case_str[]; extern const char js_catch_str[]; extern const char js_class_str[]; +extern const char js_close_str[]; extern const char js_const_str[]; extern const char js_continue_str[]; extern const char js_debugger_str[]; @@ -159,6 +160,7 @@ extern const char js_package_str[]; extern const char js_private_str[]; extern const char js_protected_str[]; extern const char js_public_str[]; +extern const char js_send_str[]; extern const char js_setter_str[]; extern const char js_static_str[]; extern const char js_super_str[]; @@ -170,10 +172,6 @@ extern const char js_void_str[]; extern const char js_while_str[]; extern const char js_with_str[]; extern const char js_yield_str[]; -#if JS_HAS_GENERATORS -extern const char js_close_str[]; -extern const char js_send_str[]; -#endif namespace js { diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 83a015bd4544..3d91be31818d 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -1206,7 +1206,6 @@ js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp) return true; } -#if JS_HAS_GENERATORS static JSBool fun_isGenerator(JSContext *cx, unsigned argc, Value *vp) { @@ -1226,7 +1225,6 @@ fun_isGenerator(JSContext *cx, unsigned argc, Value *vp) JS_SET_RVAL(cx, vp, BooleanValue(result)); return true; } -#endif /* ES5 15.3.4.5. */ static JSBool @@ -1317,9 +1315,7 @@ const JSFunctionSpec js::function_methods[] = { JS_FN(js_apply_str, js_fun_apply, 2,0), JS_FN(js_call_str, js_fun_call, 1,0), JS_FN("bind", fun_bind, 1,0), -#if JS_HAS_GENERATORS JS_FN("isGenerator", fun_isGenerator,0,0), -#endif JS_FS_END }; diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 18f088c43d1d..ed3466c05949 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -959,10 +959,8 @@ const JSFunctionSpec ElementIteratorObject::methods[] = { JS_FS_END }; -#if JS_HAS_GENERATORS static JSBool CloseGenerator(JSContext *cx, HandleObject genobj); -#endif bool js::ValueToIterator(JSContext *cx, unsigned flags, MutableHandleValue vp) @@ -1024,12 +1022,9 @@ js::CloseIterator(JSContext *cx, HandleObject obj) */ ni->props_cursor = ni->props_array; } - } -#if JS_HAS_GENERATORS - else if (obj->is()) { + } else if (obj->is()) { return CloseGenerator(cx, obj); } -#endif return true; } @@ -1320,8 +1315,6 @@ Class StopIterationObject::class_ = { /*** Generators **********************************************************************************/ -#if JS_HAS_GENERATORS - static void generator_finalize(FreeOp *fop, JSObject *obj) { @@ -1775,8 +1768,6 @@ static const JSFunctionSpec generator_methods[] = { JS_FS_END }; -#endif /* JS_HAS_GENERATORS */ - /* static */ bool GlobalObject::initIteratorClasses(JSContext *cx, Handle global) { @@ -1818,14 +1809,12 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle global) global->setReservedSlot(ELEMENT_ITERATOR_PROTO, ObjectValue(*proto)); } -#if JS_HAS_GENERATORS if (global->getSlot(GENERATOR_PROTO).isUndefined()) { proto = global->createBlankPrototype(cx, &GeneratorObject::class_); if (!proto || !DefinePropertiesAndBrand(cx, proto, NULL, generator_methods)) return false; global->setReservedSlot(GENERATOR_PROTO, ObjectValue(*proto)); } -#endif if (global->getPrototype(JSProto_StopIteration).isUndefined()) { proto = global->createBlankPrototype(cx, &StopIterationObject::class_); diff --git a/js/src/jsiter.h b/js/src/jsiter.h index d95765a6d01f..7f127e06c8fe 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -324,8 +324,6 @@ class ForOfIterator } /* namespace js */ -#if JS_HAS_GENERATORS - /* * Generator state codes. */ @@ -357,7 +355,6 @@ bool GeneratorHasMarkableFrame(JSGenerator *gen); } /* namespace js */ -#endif extern JSObject * js_InitIteratorClasses(JSContext *cx, js::HandleObject obj); diff --git a/js/src/jsreflect.cpp b/js/src/jsreflect.cpp index 59f6b89d7670..9a47bd36f6ca 100644 --- a/js/src/jsreflect.cpp +++ b/js/src/jsreflect.cpp @@ -2786,12 +2786,7 @@ ASTSerializer::function(ParseNode *pn, ASTType type, MutableHandleValue dst) { RootedFunction func(cx, pn->pn_funbox->function()); - bool isGenerator = -#if JS_HAS_GENERATORS - pn->pn_funbox->isGenerator(); -#else - false; -#endif + bool isGenerator = pn->pn_funbox->isGenerator(); bool isExpression = #if JS_HAS_EXPR_CLOSURES diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index d3748bc6d88e..2beefa453fb0 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1195,7 +1195,6 @@ Interpret(JSContext *cx, RunState &state) RootedScript rootScript0(cx); DebugOnly blockDepth; -#if JS_HAS_GENERATORS if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) { JS_ASSERT(size_t(regs.pc - script->code) <= script->length); JS_ASSERT(regs.stackDepth() <= script->nslots); @@ -1209,7 +1208,6 @@ Interpret(JSContext *cx, RunState &state) goto error; } } -#endif /* State communicated between non-local jumps: */ bool interpReturnOK; @@ -3050,7 +3048,6 @@ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR) } END_CASE(JSOP_LEAVEBLOCK) -#if JS_HAS_GENERATORS BEGIN_CASE(JSOP_GENERATOR) { JS_ASSERT(!cx->isExceptionPending()); @@ -3094,7 +3091,6 @@ BEGIN_CASE(JSOP_ARRAYPUSH) regs.sp--; } END_CASE(JSOP_ARRAYPUSH) -#endif /* JS_HAS_GENERATORS */ default: { @@ -3149,11 +3145,9 @@ END_CASE(JSOP_ARRAYPUSH) case JSTRY_CATCH: JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK); -#if JS_HAS_GENERATORS /* Catch cannot intercept the closing of a generator. */ if (JS_UNLIKELY(cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) break; -#endif /* * Don't clear exceptions to save cx->exception from GC @@ -3196,14 +3190,12 @@ END_CASE(JSOP_ARRAYPUSH) * is an asynchronous return from a generator. */ interpReturnOK = false; -#if JS_HAS_GENERATORS if (JS_UNLIKELY(cx->isExceptionPending() && cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) { cx->clearPendingException(); interpReturnOK = true; regs.fp()->clearReturnValue(); } -#endif } else { UnwindForUncatchableException(cx, regs); interpReturnOK = false; diff --git a/js/src/vm/Keywords.h b/js/src/vm/Keywords.h index 1fb416fbff2a..624ebfe594ca 100644 --- a/js/src/vm/Keywords.h +++ b/js/src/vm/Keywords.h @@ -25,13 +25,6 @@ # define FOR_LET_KEYWORD(macro) \ macro(let, let, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_1_7) #endif -#if JS_HAS_GENERATORS -# define FOR_YIELD_KEYWORD(macro) \ - macro(yield, yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7) -#else -# define FOR_YIELD_KEYWORD(macro) \ - macro(yield, yield, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_1_7) -#endif #define FOR_EACH_JAVASCRIPT_KEYWORD(macro) \ macro(false, false_, TOK_FALSE, JSOP_FALSE, JSVERSION_DEFAULT) \ @@ -79,9 +72,10 @@ macro(protected, protected_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \ macro(public, public_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \ macro(static, static_, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT) \ + /* ES5 future reserved keyword in strict mode, keyword in JS1.7 even when not strict. */ \ + macro(yield, yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7) \ /* Various conditional keywords. */ \ FOR_CONST_KEYWORD(macro) \ - FOR_LET_KEYWORD(macro) \ - FOR_YIELD_KEYWORD(macro) + FOR_LET_KEYWORD(macro) #endif /* vm_Keywords_h */ From 12938be54be16d0f7044d0cb46c631c43a5c630e Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Wed, 26 Jun 2013 09:44:21 -0400 Subject: [PATCH 11/20] Bug 883683 - Leak with DOM promises. r=bz --- dom/future/Future.cpp | 14 ++++++++++ dom/future/FutureCallback.cpp | 34 +++++++++++++---------- dom/future/tests/Makefile.in | 1 + dom/future/tests/test_bug883683.html | 41 ++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 dom/future/tests/test_bug883683.html diff --git a/dom/future/Future.cpp b/dom/future/Future.cpp index ab161e6e56a8..1bb40df0b389 100644 --- a/dom/future/Future.cpp +++ b/dom/future/Future.cpp @@ -108,6 +108,17 @@ Future::PrefEnabled() return Preferences::GetBool("dom.future.enabled", false); } +static void +EnterCompartment(Maybe& aAc, JSContext* aCx, + const Optional >& aValue) +{ + // FIXME Bug 878849 + if (aValue.WasPassed() && aValue.Value().isObject()) { + JS::Rooted rooted(aCx, &aValue.Value().toObject()); + aAc.construct(aCx, rooted); + } +} + /* static */ already_AddRefed Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx, FutureInit& aInit, ErrorResult& aRv) @@ -129,6 +140,9 @@ Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx, if (aRv.IsJSException()) { Optional > value(aCx); aRv.StealJSException(aCx, &value.Value()); + + Maybe ac; + EnterCompartment(ac, aCx, value); future->mResolver->Reject(aCx, value); } diff --git a/dom/future/FutureCallback.cpp b/dom/future/FutureCallback.cpp index f923228aa188..2fd81f5efb56 100644 --- a/dom/future/FutureCallback.cpp +++ b/dom/future/FutureCallback.cpp @@ -34,6 +34,17 @@ FutureCallback::~FutureCallback() MOZ_COUNT_DTOR(FutureCallback); } +static void +EnterCompartment(Maybe& aAc, JSContext* aCx, + const Optional >& aValue) +{ + // FIXME Bug 878849 + if (aValue.WasPassed() && aValue.Value().isObject()) { + JS::Rooted rooted(aCx, &aValue.Value().toObject()); + aAc.construct(aCx, rooted); + } +} + // ResolveFutureCallback NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolveFutureCallback, @@ -63,12 +74,8 @@ ResolveFutureCallback::Call(const Optional >& aValue) { // Run resolver's algorithm with value and the synchronous flag set. AutoJSContext cx; - // FIXME Bug 878849 Maybe ac; - if (aValue.WasPassed() && aValue.Value().isObject()) { - JS::Rooted rooted(cx, &aValue.Value().toObject()); - ac.construct(cx, rooted); - } + EnterCompartment(ac, cx, aValue); mResolver->ResolveInternal(cx, aValue, FutureResolver::SyncTask); } @@ -102,12 +109,8 @@ RejectFutureCallback::Call(const Optional >& aValue) { // Run resolver's algorithm with value and the synchronous flag set. AutoJSContext cx; - // FIXME Bug 878849 Maybe ac; - if (aValue.WasPassed() && aValue.Value().isObject()) { - JS::Rooted rooted(cx, &aValue.Value().toObject()); - ac.construct(cx, rooted); - } + EnterCompartment(ac, cx, aValue); mResolver->RejectInternal(cx, aValue, FutureResolver::SyncTask); } @@ -142,12 +145,8 @@ void WrapperFutureCallback::Call(const Optional >& aValue) { AutoJSContext cx; - // FIXME Bug 878849 Maybe ac; - if (aValue.WasPassed() && aValue.Value().isObject()) { - JS::Rooted rooted(cx, &aValue.Value().toObject()); - ac.construct(cx, rooted); - } + EnterCompartment(ac, cx, aValue); ErrorResult rv; @@ -162,12 +161,17 @@ WrapperFutureCallback::Call(const Optional >& aValue) if (rv.Failed() && rv.IsJSException()) { Optional > value(cx); rv.StealJSException(cx, &value.Value()); + + Maybe ac2; + EnterCompartment(ac2, cx, value); mNextResolver->RejectInternal(cx, value, FutureResolver::SyncTask); return; } // Otherwise, run resolver's resolve with value and the synchronous flag // set. + Maybe ac2; + EnterCompartment(ac2, cx, value); mNextResolver->ResolveInternal(cx, value, FutureResolver::SyncTask); } diff --git a/dom/future/tests/Makefile.in b/dom/future/tests/Makefile.in index c5de7223396c..0c1e3479dee8 100644 --- a/dom/future/tests/Makefile.in +++ b/dom/future/tests/Makefile.in @@ -14,6 +14,7 @@ include $(DEPTH)/config/autoconf.mk MOCHITEST_FILES = \ test_future.html \ test_resolve.html \ + test_bug883683.html \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/future/tests/test_bug883683.html b/dom/future/tests/test_bug883683.html new file mode 100644 index 000000000000..3404e7c1ff4e --- /dev/null +++ b/dom/future/tests/test_bug883683.html @@ -0,0 +1,41 @@ + + + + Future - bug 883683 + + + + +

+ +
+
+
+ + From 8b810c4a1a93b70a7ac364d2beea73bcdfb2367c Mon Sep 17 00:00:00 2001 From: Brian O'Keefe Date: Sat, 22 Jun 2013 10:33:31 -0400 Subject: [PATCH 12/20] Bug 885019 - Move GTEST_CPPSRCS, GTEST_CMMSRCS, and GTEST_CSRCS to moz.build as GTEST_CPP_SOURCES, GTEST_CMM_SOURCES, and GTEST_C_SOURCES. r=gps --- config/rules.mk | 3 +++ gfx/tests/gtest/Makefile.in | 17 --------------- gfx/tests/gtest/moz.build | 15 +++++++++++++ js/src/config/rules.mk | 3 +++ python/mozbuild/mozbuild/frontend/emitter.py | 3 +++ .../mozbuild/frontend/sandbox_symbols.py | 21 +++++++++++++++++++ .../backend/data/variable_passthru/moz.build | 4 ++++ .../test/backend/test_recursivemake.py | 12 +++++++++++ .../frontend/data/variable-passthru/moz.build | 4 ++++ .../mozbuild/test/frontend/test_emitter.py | 3 +++ testing/gtest/Makefile.in | 4 ---- testing/gtest/moz.build | 4 ++++ 12 files changed, 72 insertions(+), 21 deletions(-) diff --git a/config/rules.mk b/config/rules.mk index 98c20795633f..9774c2f45e44 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -17,6 +17,9 @@ endif _MOZBUILD_EXTERNAL_VARIABLES := \ DIRS \ EXTRA_PP_COMPONENTS \ + GTEST_CMMSRCS \ + GTEST_CPPSRCS \ + GTEST_CSRCS \ HOST_CSRCS \ HOST_LIBRARY_NAME \ MODULE \ diff --git a/gfx/tests/gtest/Makefile.in b/gfx/tests/gtest/Makefile.in index 7066a33c8c59..430cba997587 100644 --- a/gfx/tests/gtest/Makefile.in +++ b/gfx/tests/gtest/Makefile.in @@ -23,23 +23,6 @@ LOCAL_INCLUDES = \ -I$(topsrcdir)/gfx/2d/unittest \ $(NULL) -GTEST_CPPSRCS = \ - TestLayers.cpp \ - TestTiledLayerBuffer.cpp \ - TestAsyncPanZoomController.cpp \ - $(NULL) - -# Because of gkmedia on windows we wont find these -# symbols in xul.dll. -ifneq ($(MOZ_WIDGET_TOOLKIT),windows) -GTEST_CPPSRCS += \ - TestMoz2D.cpp \ - TestBase.cpp \ - TestPoint.cpp \ - TestScaling.cpp \ - $(NULL) -endif - include $(topsrcdir)/config/rules.mk include $(topsrcdir)/ipc/chromium/chromium-config.mk diff --git a/gfx/tests/gtest/moz.build b/gfx/tests/gtest/moz.build index 7b1af0cb9289..fcb5bee94f4d 100644 --- a/gfx/tests/gtest/moz.build +++ b/gfx/tests/gtest/moz.build @@ -8,3 +8,18 @@ MODULE = 'gfxtest' LIBRARY_NAME = 'gfxtest' +GTEST_CPP_SOURCES += [ + 'TestAsyncPanZoomController.cpp', + 'TestLayers.cpp', + 'TestTiledLayerBuffer.cpp', +] + +# Because of gkmedia on windows we wont find these +# symbols in xul.dll. +if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows': + GTEST_CPP_SOURCES += [ + 'TestBase.cpp' + 'TestMoz2D.cpp' + 'TestPoint.cpp' + 'TestScaling.cpp' + ] diff --git a/js/src/config/rules.mk b/js/src/config/rules.mk index 98c20795633f..9774c2f45e44 100644 --- a/js/src/config/rules.mk +++ b/js/src/config/rules.mk @@ -17,6 +17,9 @@ endif _MOZBUILD_EXTERNAL_VARIABLES := \ DIRS \ EXTRA_PP_COMPONENTS \ + GTEST_CMMSRCS \ + GTEST_CPPSRCS \ + GTEST_CSRCS \ HOST_CSRCS \ HOST_LIBRARY_NAME \ MODULE \ diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index aa973add5356..97af83373ff3 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -87,6 +87,9 @@ class TreeMetadataEmitter(object): EXTRA_COMPONENTS='EXTRA_COMPONENTS', EXTRA_JS_MODULES='EXTRA_JS_MODULES', EXTRA_PP_COMPONENTS='EXTRA_PP_COMPONENTS', + GTEST_CMMSRCS='GTEST_CMM_SOURCES', + GTEST_CPPSRCS='GTEST_CPP_SOURCES', + GTEST_CSRCS='GTEST_C_SOURCES', HOST_CSRCS='HOST_CSRCS', HOST_LIBRARY_NAME='HOST_LIBRARY_NAME', JS_MODULES_PATH='JS_MODULES_PATH', diff --git a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py index 844d8fa4b224..6740f5d3cdb3 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -118,6 +118,27 @@ VARIABLES = { files will be installed in the /components directory of the distribution. """), + 'GTEST_C_SOURCES': (StrictOrderingOnAppendList, list, [], + """C code source files for GTest unit tests. + + This variable contains a list of C GTEST unit test source files to + compile. + """), + + 'GTEST_CMM_SOURCES': (StrictOrderingOnAppendList, list, [], + """Sources for GTest unit tests to compile with the Objective C/C++ compiler. + + This variable contains a list of objective-C++ GTest unit test sources + to compile. + """), + + 'GTEST_CPP_SOURCES': (list, list, [], + """C++ source files for GTest unit tests. + + This is a list of C++ GTest unit test sources. Entries must be files + that exist. These generally have .cpp, .cc, or .cxx extensions. + """), + 'HOST_CSRCS': (StrictOrderingOnAppendList, list, [], """C source files to compile with the host compiler. diff --git a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build index de50eeaa4652..a1312c68b5e0 100644 --- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build @@ -13,6 +13,10 @@ DEFINES = ['-Dbar', '-Dfoo'] EXTRA_COMPONENTS = ['bar.js', 'foo.js'] EXTRA_PP_COMPONENTS = ['bar.pp.js', 'foo.pp.js'] +GTEST_C_SOURCES = ['test1.c', 'test2.c'] +GTEST_CMM_SOURCES = ['test1.mm', 'test2.mm'] +GTEST_CPP_SOURCES = ['test1.cpp', 'test2.cpp'] + HOST_CSRCS = ['bar.c', 'foo.c'] HOST_LIBRARY_NAME = 'host_bar' diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index 48ebabbbe94e..d4fe128cbe6f 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -162,6 +162,18 @@ class TestRecursiveMakeBackend(BackendTester): 'EXTRA_PP_COMPONENTS += bar.pp.js', 'EXTRA_PP_COMPONENTS += foo.pp.js', ], + 'GTEST_CMMSRCS': [ + 'GTEST_CMMSRCS += test1.mm', + 'GTEST_CMMSRCS += test2.mm', + ], + 'GTEST_CPPSRCS': [ + 'GTEST_CPPSRCS += test1.cpp', + 'GTEST_CPPSRCS += test2.cpp', + ], + 'GTEST_CSRCS': [ + 'GTEST_CSRCS += test1.c', + 'GTEST_CSRCS += test2.c', + ], 'HOST_CSRCS': [ 'HOST_CSRCS += bar.c', 'HOST_CSRCS += foo.c', diff --git a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build index e1f691f83a75..f70559fd5161 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build @@ -13,6 +13,10 @@ DEFINES=['-Dfans', '-Dtans'] EXTRA_COMPONENTS=['fans.js', 'tans.js'] EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'] +GTEST_C_SOURCES = ['test1.c', 'test2.c'] +GTEST_CMM_SOURCES = ['test1.mm', 'test2.mm'] +GTEST_CPP_SOURCES = ['test1.cpp', 'test2.cpp'] + HOST_CSRCS += ['fans.c', 'tans.c'] HOST_LIBRARY_NAME = 'host_fans' diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py index 29af433aa739..8cce4acffe41 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -131,6 +131,9 @@ class TestEmitterBasic(unittest.TestCase): DEFINES=['-Dfans', '-Dtans'], EXTRA_COMPONENTS=['fans.js', 'tans.js'], EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js'], + GTEST_CSRCS=['test1.c', 'test2.c'], + GTEST_CMMSRCS=['test1.mm', 'test2.mm'], + GTEST_CPPSRCS=['test1.cpp', 'test2.cpp'], HOST_CSRCS=['fans.c', 'tans.c'], HOST_LIBRARY_NAME='host_fans', LIBRARY_NAME='lib_name', diff --git a/testing/gtest/Makefile.in b/testing/gtest/Makefile.in index c5447316e60d..599a891e6885 100644 --- a/testing/gtest/Makefile.in +++ b/testing/gtest/Makefile.in @@ -22,10 +22,6 @@ EXPORT_LIBRARY = 1 LIBXUL_LIBRARY = 1 IS_COMPONENT = 1 -GTEST_CPPSRCS = \ - SanityTest.cpp \ - $(NULL) - LOCAL_INCLUDES += \ -I$(srcdir)/gtest \ -I$(srcdir)/gtest/include \ diff --git a/testing/gtest/moz.build b/testing/gtest/moz.build index be42de61dd37..0ea567b175d6 100644 --- a/testing/gtest/moz.build +++ b/testing/gtest/moz.build @@ -61,3 +61,7 @@ CPP_SOURCES += [ LIBRARY_NAME = 'gtest' +GTEST_CPP_SOURCES += [ + 'SanityTest.cpp', +] + From 46f2a6044624adc64eee3d3ba7f2de5d77b7a7e2 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Wed, 26 Jun 2013 11:47:50 +0200 Subject: [PATCH 13/20] Bug 885281 - Factor out TokenMatcher::matchContextualKeyword. r=Waldo --- js/src/frontend/Parser.cpp | 27 ++++++++------------------- js/src/frontend/TokenStream.h | 7 +++++++ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 7d676d07da78..eaa1e1396e76 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3692,12 +3692,9 @@ Parser::matchInOrOf(bool *isForOfp) *isForOfp = false; return true; } - if (tokenStream.matchToken(TOK_NAME)) { - if (tokenStream.currentToken().name() == context->names().of) { - *isForOfp = true; - return true; - } - tokenStream.ungetToken(); + if (tokenStream.matchContextualKeyword(context->names().of)) { + *isForOfp = true; + return true; } return false; } @@ -3764,13 +3761,9 @@ Parser::forStatement() bool isForEach = false; unsigned iflags = 0; - if (allowsForEachIn() && tokenStream.matchToken(TOK_NAME)) { - if (tokenStream.currentToken().name() == context->names().each) { - iflags = JSITER_FOREACH; - isForEach = true; - } else { - tokenStream.ungetToken(); - } + if (allowsForEachIn() && tokenStream.matchContextualKeyword(context->names().each)) { + iflags = JSITER_FOREACH; + isForEach = true; } MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR); @@ -5800,12 +5793,8 @@ Parser::comprehensionTail(ParseNode *kid, unsigned blockid, bo pn2->setOp(JSOP_ITER); pn2->pn_iflags = JSITER_ENUMERATE; - if (allowsForEachIn() && tokenStream.matchToken(TOK_NAME)) { - if (tokenStream.currentToken().name() == context->names().each) - pn2->pn_iflags |= JSITER_FOREACH; - else - tokenStream.ungetToken(); - } + if (allowsForEachIn() && tokenStream.matchContextualKeyword(context->names().each)) + pn2->pn_iflags |= JSITER_FOREACH; MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR); GenexpGuard guard(this); diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h index 0a8908bc9281..0bcbbd122a16 100644 --- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -631,6 +631,13 @@ class MOZ_STACK_CLASS TokenStream JS_ALWAYS_TRUE(matchToken(tt)); } + bool matchContextualKeyword(PropertyName* keyword) { + if (getToken() == TOK_NAME && currentToken().name() == keyword) + return true; + ungetToken(); + return false; + } + class MOZ_STACK_CLASS Position { public: /* From 6c5d882abe6f190de096efd57335e84629da6b59 Mon Sep 17 00:00:00 2001 From: Chris Kitching Date: Wed, 26 Jun 2013 09:46:14 -0400 Subject: [PATCH 14/20] Bug 885941 - Homogenize privacy links in Fennec. r=mleibovic --- mobile/android/app/mobile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index a769cc63d52d..603c583f450e 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -456,7 +456,7 @@ pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/"); pref("app.support.baseURL", "http://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/"); // Used to submit data to input from about:feedback pref("app.feedback.postURL", "https://input.mozilla.org/%LOCALE%/feedback"); -pref("app.privacyURL", "http://www.mozilla.org/%LOCALE%/privacy/"); +pref("app.privacyURL", "https://www.mozilla.org/legal/privacy/firefox.html"); pref("app.creditsURL", "http://www.mozilla.org/credits/"); pref("app.channelURL", "http://www.mozilla.org/%LOCALE%/firefox/channel/"); #if MOZ_UPDATE_CHANNEL == aurora From 75b7aa0a24a90e7541194778a75e14fe850caa79 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 26 Jun 2013 09:53:51 -0400 Subject: [PATCH 15/20] Bug 885030 - Move CalculateIntrinsicScale to FrameMetrics. r=kentuckyfriedtakahe --- dom/ipc/TabChild.cpp | 3 +-- gfx/layers/FrameMetrics.h | 9 +++++++++ gfx/layers/ipc/AsyncPanZoomController.cpp | 15 ++++----------- gfx/layers/ipc/AsyncPanZoomController.h | 6 ------ 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index c2b155616385..6db65474f66a 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -602,8 +602,7 @@ TabChild::HandlePossibleViewportChange() nsresult rv = utils->GetIsFirstPaint(&isFirstPaint); MOZ_ASSERT(NS_SUCCEEDED(rv)); if (NS_FAILED(rv) || isFirstPaint) { - CSSToScreenScale intrinsicScale = - AsyncPanZoomController::CalculateIntrinsicScale(metrics); + CSSToScreenScale intrinsicScale = metrics.CalculateIntrinsicScale(); // FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of // 0.0 to mean "did not calculate a zoom". In that case, we default // it to the intrinsic scale. diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 2d392f27a3af..b7b895c0dff9 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -94,6 +94,15 @@ public: return mScrollOffset * LayersPixelsPerCSSPixel(); } + /** + * Return the scale factor needed to fit the viewport + * into its composition bounds. + */ + CSSToScreenScale CalculateIntrinsicScale() const + { + return CSSToScreenScale(float(mCompositionBounds.width) / float(mViewport.width)); + } + // --------------------------------------------------------------------------- // The following metrics are all in widget space/device pixels. // diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 76367caa788c..dc315c9adf80 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -579,8 +579,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { // either axis such that we don't overscroll the boundaries when zooming. gfx::Point neededDisplacement; - float maxZoom = mMaxZoom / CalculateIntrinsicScale(mFrameMetrics).scale; - float minZoom = mMinZoom / CalculateIntrinsicScale(mFrameMetrics).scale; + float maxZoom = mMaxZoom / mFrameMetrics.CalculateIntrinsicScale().scale; + float minZoom = mMinZoom / mFrameMetrics.CalculateIntrinsicScale().scale; bool doScale = (spanRatio > 1.0 && userZoom < maxZoom) || (spanRatio < 1.0 && userZoom > minZoom); @@ -970,17 +970,10 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort( return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset; } -/*static*/ CSSToScreenScale -AsyncPanZoomController::CalculateIntrinsicScale(const FrameMetrics& aMetrics) -{ - return CSSToScreenScale(gfxFloat(aMetrics.mCompositionBounds.width) / - gfxFloat(aMetrics.mViewport.width)); -} - /*static*/ CSSToScreenScale AsyncPanZoomController::CalculateResolution(const FrameMetrics& aMetrics) { - return CalculateIntrinsicScale(aMetrics) * aMetrics.mZoom; + return aMetrics.CalculateIntrinsicScale() * aMetrics.mZoom; } /*static*/ CSSRect @@ -1310,7 +1303,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { CSSPoint scrollOffset = mFrameMetrics.mScrollOffset; float currentZoom = mFrameMetrics.mZoom.scale; float targetZoom; - float intrinsicScale = CalculateIntrinsicScale(mFrameMetrics).scale; + float intrinsicScale = mFrameMetrics.CalculateIntrinsicScale().scale; // The minimum zoom to prevent over-zoom-out. // If the zoom factor is lower than this (i.e. we are zoomed more into the page), diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index e44f2b600160..b637ec98660c 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -223,12 +223,6 @@ public: const gfx::Point& aAcceleration, double aEstimatedPaintDuration); - /** - * Return the scale factor needed to fit the viewport in |aMetrics| - * into its composition bounds. - */ - static CSSToScreenScale CalculateIntrinsicScale(const FrameMetrics& aMetrics); - /** * Return the resolution that content should be rendered at given * the configuration in aFrameMetrics: viewport dimensions, zoom From 3445b064079ae135d4cf32d512c0d0dab2919e01 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 26 Jun 2013 09:54:14 -0400 Subject: [PATCH 16/20] Bug 885030 - Move CalculateResolution from APZC to FrameMetrics. r=kentuckyfriedtakahe --- dom/ipc/TabChild.cpp | 8 ++---- gfx/layers/FrameMetrics.h | 11 ++++++++ gfx/layers/ipc/AsyncPanZoomController.cpp | 34 ++++++++++------------- gfx/layers/ipc/AsyncPanZoomController.h | 8 ------ widget/android/AndroidBridge.cpp | 4 +-- 5 files changed, 29 insertions(+), 36 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 6db65474f66a..bb346eb12aca 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -350,8 +350,7 @@ TabChild::Observe(nsISupports *aSubject, mLastMetrics.mZoom = ScreenToScreenScale(1.0); mLastMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize); mLastMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize); - CSSToScreenScale resolution = - AsyncPanZoomController::CalculateResolution(mLastMetrics); + CSSToScreenScale resolution = mLastMetrics.CalculateResolution(); // We use ScreenToLayerScale(1) below in order to ask gecko to render // what's currently visible on the screen. This is effectively turning // the async zoom amount into the gecko zoom amount. @@ -623,7 +622,7 @@ TabChild::HandlePossibleViewportChange() // new CSS viewport, so we know that there's no velocity, acceleration, and // we have no idea how long painting will take. metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0); - CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution(metrics); + CSSToScreenScale resolution = metrics.CalculateResolution(); metrics.mResolution = resolution / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale); @@ -1533,8 +1532,7 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics) utils->SetScrollPositionClampingScrollPortSize( cssCompositedRect.width, cssCompositedRect.height); ScrollWindowTo(window, aFrameMetrics.mScrollOffset); - CSSToScreenScale resolution = AsyncPanZoomController::CalculateResolution( - aFrameMetrics); + CSSToScreenScale resolution = aFrameMetrics.CalculateResolution(); utils->SetResolution(resolution.scale, resolution.scale); nsCOMPtr domDoc; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index b7b895c0dff9..37941f4f6402 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -103,6 +103,17 @@ public: return CSSToScreenScale(float(mCompositionBounds.width) / float(mViewport.width)); } + /** + * Return the resolution that content should be rendered at given + * the configuration in this metrics object: viewport dimensions, + * zoom factor, etc. (The mResolution member of this metrics is + * ignored.) + */ + CSSToScreenScale CalculateResolution() const + { + return CalculateIntrinsicScale() * mZoom; + } + // --------------------------------------------------------------------------- // The following metrics are all in widget space/device pixels. // diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index dc315c9adf80..a4691cb92d13 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -245,7 +245,7 @@ AsyncPanZoomController::ReceiveInputEvent(const nsInputEvent& aEvent, CSSToScreenScale currentResolution; { MonitorAutoLock monitor(mMonitor); - currentResolution = CalculateResolution(mFrameMetrics); + currentResolution = mFrameMetrics.CalculateResolution(); } nsEventStatus status; @@ -559,7 +559,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { { MonitorAutoLock monitor(mMonitor); - CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); gfxFloat userZoom = mFrameMetrics.mZoom.scale; ScreenPoint focusPoint = aEvent.mFocusPoint; @@ -660,7 +660,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) if (mGeckoContentController) { MonitorAutoLock monitor(mMonitor); - CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); CSSPoint point = WidgetSpaceToCompensatedViewportSpace( ScreenPoint::FromUnknownPoint(gfx::Point( aEvent.mPoint.x, aEvent.mPoint.y)), @@ -679,7 +679,7 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput if (mGeckoContentController) { MonitorAutoLock monitor(mMonitor); - CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); CSSPoint point = WidgetSpaceToCompensatedViewportSpace( ScreenPoint::FromUnknownPoint(gfx::Point( aEvent.mPoint.x, aEvent.mPoint.y)), @@ -695,7 +695,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) MonitorAutoLock monitor(mMonitor); if (mAllowZoom) { - CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); CSSPoint point = WidgetSpaceToCompensatedViewportSpace( ScreenPoint::FromUnknownPoint(gfx::Point( aEvent.mPoint.x, aEvent.mPoint.y)), @@ -765,7 +765,7 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) { // We want to inversely scale it because when you're zoomed further in, a // larger swipe should move you a shorter distance. - ScreenToCSSScale inverseResolution = CalculateResolution(mFrameMetrics).Inverse(); + ScreenToCSSScale inverseResolution = mFrameMetrics.CalculateResolution().Inverse(); gfx::Point displacement(mX.GetDisplacementForDuration(inverseResolution.scale, timeDelta), @@ -809,7 +809,7 @@ bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) { // We want to inversely scale it because when you're zoomed further in, a // larger swipe should move you a shorter distance. - ScreenToCSSScale inverseResolution = CalculateResolution(mFrameMetrics).Inverse(); + ScreenToCSSScale inverseResolution = mFrameMetrics.CalculateResolution().Inverse(); ScrollBy(CSSPoint::FromUnknownPoint(gfx::Point( mX.GetDisplacementForDuration(inverseResolution.scale, aDelta), @@ -838,7 +838,7 @@ void AsyncPanZoomController::ScrollBy(const CSSPoint& aOffset) { void AsyncPanZoomController::ScaleWithFocus(float aZoom, const ScreenPoint& aFocus) { float zoomFactor = aZoom / mFrameMetrics.mZoom.scale; - CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); SetZoomAndResolution(ScreenToScreenScale(aZoom)); @@ -900,7 +900,7 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort( double estimatedPaintDuration = aEstimatedPaintDuration > EPSILON ? aEstimatedPaintDuration : 1.0; - CSSToScreenScale resolution = CalculateResolution(aFrameMetrics); + CSSToScreenScale resolution = aFrameMetrics.CalculateResolution(); CSSIntRect compositionBounds = gfx::RoundedIn(aFrameMetrics.mCompositionBounds / resolution); CSSRect scrollableRect = aFrameMetrics.mScrollableRect; @@ -970,16 +970,10 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort( return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset; } -/*static*/ CSSToScreenScale -AsyncPanZoomController::CalculateResolution(const FrameMetrics& aMetrics) -{ - return aMetrics.CalculateIntrinsicScale() * aMetrics.mZoom; -} - /*static*/ CSSRect AsyncPanZoomController::CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics) { - CSSToScreenScale resolution = CalculateResolution(aMetrics); + CSSToScreenScale resolution = aMetrics.CalculateResolution(); CSSIntRect rect = gfx::RoundedIn(aMetrics.mCompositionBounds / resolution); return CSSRect(rect); } @@ -1139,7 +1133,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa // what PZC has transformed due to touches like panning or // pinching. Eventually, the root layer transform will become this // during runtime, but we must wait for Gecko to repaint. - localScale = CalculateResolution(mFrameMetrics); + localScale = mFrameMetrics.CalculateResolution(); if (frame.IsScrollable()) { metricsScrollOffset = frame.GetScrollOffsetInLayerPixels(); @@ -1231,9 +1225,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr aViewportFrame.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) { // Remote content has sync'd up to the composition geometry // change, so we can accept the viewport it's calculated. - CSSToScreenScale previousResolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale previousResolution = mFrameMetrics.CalculateResolution(); mFrameMetrics.mViewport = aViewportFrame.mViewport; - CSSToScreenScale newResolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale newResolution = mFrameMetrics.CalculateResolution(); needContentRepaint |= (previousResolution != newResolution); } @@ -1435,7 +1429,7 @@ void AsyncPanZoomController::TimeoutTouchListeners() { void AsyncPanZoomController::SetZoomAndResolution(const ScreenToScreenScale& aZoom) { mMonitor.AssertCurrentThreadOwns(); mFrameMetrics.mZoom = aZoom; - CSSToScreenScale resolution = CalculateResolution(mFrameMetrics); + CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); // We use ScreenToLayerScale(1) below in order to ask gecko to render // what's currently visible on the screen. This is effectively turning // the async zoom amount into the gecko zoom amount. diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index b637ec98660c..06ce217ec7d7 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -223,14 +223,6 @@ public: const gfx::Point& aAcceleration, double aEstimatedPaintDuration); - /** - * Return the resolution that content should be rendered at given - * the configuration in aFrameMetrics: viewport dimensions, zoom - * factor, etc. (The mResolution member of aFrameMetrics is - * ignored.) - */ - static CSSToScreenScale CalculateResolution(const FrameMetrics& aMetrics); - static CSSRect CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics); /** diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 5ee78d95015b..5095e21fda89 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -6,7 +6,6 @@ #include "mozilla/Util.h" #include "mozilla/layers/CompositorChild.h" #include "mozilla/layers/CompositorParent.h" -#include "mozilla/layers/AsyncPanZoomController.h" #include #include @@ -2784,8 +2783,7 @@ AndroidBridge::RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrame return; } - CSSToScreenScale resolution = - mozilla::layers::AsyncPanZoomController::CalculateResolution(aFrameMetrics); + CSSToScreenScale resolution = aFrameMetrics.CalculateResolution(); ScreenRect dp = (aFrameMetrics.mDisplayPort + aFrameMetrics.mScrollOffset) * resolution; AutoLocalJNIFrame jniFrame(env, 0); From e00fd765ebd4d45764ffbb98816ba548840e2304 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Wed, 26 Jun 2013 09:54:49 -0400 Subject: [PATCH 17/20] Bug 885030 - Move CalculateCompositedRectInCssPixels from APZC to FrameMetrics. r=kentuckyfriedtakahe --- dom/ipc/TabChild.cpp | 3 +-- gfx/layers/FrameMetrics.h | 5 +++++ gfx/layers/ipc/AsyncPanZoomController.cpp | 15 +++------------ gfx/layers/ipc/AsyncPanZoomController.h | 2 -- gfx/layers/ipc/Axis.cpp | 3 +-- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index bb346eb12aca..3a16de87017c 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1489,8 +1489,7 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics) return true; } - CSSRect cssCompositedRect = - AsyncPanZoomController::CalculateCompositedRectInCssPixels(aFrameMetrics); + CSSRect cssCompositedRect = aFrameMetrics.CalculateCompositedRectInCssPixels(); // The BrowserElementScrolling helper must know about these updated metrics // for other functions it performs, such as double tap handling. nsCString data; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 37941f4f6402..a9f4b67af02e 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -114,6 +114,11 @@ public: return CalculateIntrinsicScale() * mZoom; } + CSSRect CalculateCompositedRectInCssPixels() const + { + return CSSRect(gfx::RoundedIn(mCompositionBounds / CalculateResolution())); + } + // --------------------------------------------------------------------------- // The following metrics are all in widget space/device pixels. // diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index a4691cb92d13..4d848cd23e17 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -970,14 +970,6 @@ const CSSRect AsyncPanZoomController::CalculatePendingDisplayPort( return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset; } -/*static*/ CSSRect -AsyncPanZoomController::CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics) -{ - CSSToScreenScale resolution = aMetrics.CalculateResolution(); - CSSIntRect rect = gfx::RoundedIn(aMetrics.mCompositionBounds / resolution); - return CSSRect(rect); -} - void AsyncPanZoomController::SetDPI(int aDPI) { mDPI = aDPI; } @@ -1325,7 +1317,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { if (zoomToRect.IsEmpty() || (currentZoom == localMaxZoom && targetZoom >= localMaxZoom) || (currentZoom == localMinZoom && targetZoom <= localMinZoom)) { - CSSRect compositedRect = CalculateCompositedRectInCssPixels(mFrameMetrics); + CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels(); float y = scrollOffset.y; float newHeight = cssPageRect.width * (compositedRect.height / compositedRect.width); @@ -1348,8 +1340,7 @@ void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) { // Adjust the zoomToRect to a sensible position to prevent overscrolling. FrameMetrics metricsAfterZoom = mFrameMetrics; metricsAfterZoom.mZoom = mEndZoomToMetrics.mZoom; - CSSRect rectAfterZoom - = CalculateCompositedRectInCssPixels(metricsAfterZoom); + CSSRect rectAfterZoom = metricsAfterZoom.CalculateCompositedRectInCssPixels(); // If either of these conditions are met, the page will be // overscrolled after zoomed @@ -1461,7 +1452,7 @@ void AsyncPanZoomController::SendAsyncScrollEvent() { CSSSize scrollableSize; { scrollableSize = mFrameMetrics.mScrollableRect.Size(); - contentRect = AsyncPanZoomController::CalculateCompositedRectInCssPixels(mFrameMetrics); + contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels(); contentRect.MoveTo(mCurrentAsyncScrollOffset); } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 06ce217ec7d7..9be52bd3bbf8 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -223,8 +223,6 @@ public: const gfx::Point& aAcceleration, double aEstimatedPaintDuration); - static CSSRect CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics); - /** * Send an mozbrowserasyncscroll event. * *** The monitor must be held while calling this. diff --git a/gfx/layers/ipc/Axis.cpp b/gfx/layers/ipc/Axis.cpp index 0e77215b3129..5c4c07590918 100644 --- a/gfx/layers/ipc/Axis.cpp +++ b/gfx/layers/ipc/Axis.cpp @@ -298,8 +298,7 @@ float Axis::GetOrigin() { float Axis::GetCompositionLength() { const FrameMetrics& metrics = mAsyncPanZoomController->GetFrameMetrics(); - CSSRect cssCompositedRect = - AsyncPanZoomController::CalculateCompositedRectInCssPixels(metrics); + CSSRect cssCompositedRect = metrics.CalculateCompositedRectInCssPixels(); return GetRectLength(cssCompositedRect); } From 01309a4ba68b677b2e0b89fd1aed91ec2eff515a Mon Sep 17 00:00:00 2001 From: Mark Banner Date: Wed, 26 Jun 2013 14:56:11 +0100 Subject: [PATCH 18/20] Bug 886263 - Make places be enabled by default in all xpcshell-tests to avoid having to set it in lots of places (so that tests work with apps where places is disabled by default). r=mak --- docshell/test/unit/test_nsIDownloadHistory.js | 2 -- testing/xpcshell/head.js | 11 +++++++++++ .../downloads/test/unit/test_history_expiration.js | 3 --- toolkit/components/places/tests/head_common.js | 3 --- toolkit/components/social/test/xpcshell/head.js | 3 --- .../test/unit/test_removeDataFromDomain.js | 2 -- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/docshell/test/unit/test_nsIDownloadHistory.js b/docshell/test/unit/test_nsIDownloadHistory.js index 63db845086e2..2030f0702cef 100644 --- a/docshell/test/unit/test_nsIDownloadHistory.js +++ b/docshell/test/unit/test_nsIDownloadHistory.js @@ -61,8 +61,6 @@ function run_test() // Needed to properly setup and shutdown the profile. do_get_profile(); - Services.prefs.setBoolPref("places.history.enabled", true); - for (var i = 0; i < tests.length; i++) tests[i](); diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index 6f99d4ea4390..c4b7d895af14 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -45,6 +45,17 @@ try { } catch (e) { } +// Only if building of places is enabled. +if (runningInParent && + "mozIAsyncHistory" in Components.interfaces) { + // Ensure places history is enabled for xpcshell-tests as some non-FF + // apps disable it. + let (prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch)) { + prefs.setBoolPref("places.history.enabled", true); + }; +} + try { if (runningInParent) { let prefs = Components.classes["@mozilla.org/preferences-service;1"] diff --git a/toolkit/components/downloads/test/unit/test_history_expiration.js b/toolkit/components/downloads/test/unit/test_history_expiration.js index bd71f391ed3d..d7bc2407aa62 100644 --- a/toolkit/components/downloads/test/unit/test_history_expiration.js +++ b/toolkit/components/downloads/test/unit/test_history_expiration.js @@ -36,9 +36,6 @@ add_task(function test_execute() if (!("@mozilla.org/browser/nav-history-service;1" in Cc)) return; - // Ensure places is enabled. - Services.prefs.setBoolPref("places.history.enabled", true); - let dm = Cc["@mozilla.org/download-manager;1"]. getService(Ci.nsIDownloadManager); let db = dm.DBConnection; diff --git a/toolkit/components/places/tests/head_common.js b/toolkit/components/places/tests/head_common.js index 8f1956b221d6..e19429a08d9e 100644 --- a/toolkit/components/places/tests/head_common.js +++ b/toolkit/components/places/tests/head_common.js @@ -55,9 +55,6 @@ function LOG(aMsg) { let gTestDir = do_get_cwd(); -// Ensure history is enabled. -Services.prefs.setBoolPref("places.history.enabled", true); - // Initialize profile. let gProfD = do_get_profile(); diff --git a/toolkit/components/social/test/xpcshell/head.js b/toolkit/components/social/test/xpcshell/head.js index e1c7d57f000b..1bf261d668f7 100644 --- a/toolkit/components/social/test/xpcshell/head.js +++ b/toolkit/components/social/test/xpcshell/head.js @@ -6,9 +6,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -// Ensure history is enabled. -Services.prefs.setBoolPref("places.history.enabled", true); - XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/commonjs/sdk/core/promise.js"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", diff --git a/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js b/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js index ab10e8a598e2..26c2234e444f 100644 --- a/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js +++ b/toolkit/forgetaboutsite/test/unit/test_removeDataFromDomain.js @@ -733,8 +733,6 @@ let tests = [ function run_test() { - Services.prefs.setBoolPref("places.history.enabled", true); - for (let i = 0; i < tests.length; i++) add_task(tests[i]); From 939c924c2088d23dec94341eb100aac4624f1f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A3o=20Gottwald?= Date: Wed, 26 Jun 2013 15:56:12 +0200 Subject: [PATCH 19/20] Bug 887165 - Remove the unused primary-button class. r=bsmedberg --HG-- extra : rebase_source : cf476ec6c232f9f754201356ea8dab413752730f --- browser/base/content/urlbarBindings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index a83416a00428..41a26da3a576 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -1522,7 +1522,7 @@ class="click-to-play-plugins-notification-button-container" pack="center" align="center"> Date: Wed, 26 Jun 2013 15:56:29 +0200 Subject: [PATCH 20/20] Bug 887167 - Undo global-scope pollution from browser-plugins.js. r=jaws --HG-- extra : rebase_source : 45aa63c4fa5ae7ed65211ad294882f33cad449d5 --- browser/base/content/browser-plugins.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/browser/base/content/browser-plugins.js b/browser/base/content/browser-plugins.js index 8414a90aa3c4..44933eca9f5c 100644 --- a/browser/base/content/browser-plugins.js +++ b/browser/base/content/browser-plugins.js @@ -3,15 +3,15 @@ # 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/. -const kPrefNotifyMissingFlash = "plugins.notifyMissingFlash"; -const kPrefSessionPersistMinutes = "plugin.sessionPermissionNow.intervalInMinutes"; -const kPrefPersistentDays = "plugin.persistentPermissionAlways.intervalInDays"; - var gPluginHandler = { PLUGIN_SCRIPTED_STATE_NONE: 0, PLUGIN_SCRIPTED_STATE_FIRED: 1, PLUGIN_SCRIPTED_STATE_DONE: 2, + PREF_NOTIFY_MISSING_FLASH: "plugins.notifyMissingFlash", + PREF_SESSION_PERSIST_MINUTES: "plugin.sessionPermissionNow.intervalInMinutes", + PREF_PERSISTENT_DAYS: "plugin.persistentPermissionAlways.intervalInDays", + getPluginUI: function (plugin, className) { return plugin.ownerDocument. getAnonymousElementByAttribute(plugin, "class", className); @@ -468,13 +468,14 @@ var gPluginHandler = { let secondaryActions = null; let options = { dismissed: true }; - let showForFlash = Services.prefs.getBoolPref(kPrefNotifyMissingFlash); + let showForFlash = Services.prefs.getBoolPref(this.PREF_NOTIFY_MISSING_FLASH); if (pluginIdentifier == "flash" && showForFlash) { + let prefNotifyMissingFlash = this.PREF_NOTIFY_MISSING_FLASH; secondaryActions = [{ label: gNavigatorBundle.getString("installPlugin.ignoreButton.label"), accessKey: gNavigatorBundle.getString("installPlugin.ignoreButton.accesskey"), callback: function () { - Services.prefs.setBoolPref(kPrefNotifyMissingFlash, false); + Services.prefs.setBoolPref(prefNotifyMissingFlash, false); } }]; options.dismissed = false; @@ -690,7 +691,7 @@ var gPluginHandler = { } permission = Ci.nsIPermissionManager.ALLOW_ACTION; expireType = Ci.nsIPermissionManager.EXPIRE_SESSION; - expireTime = Date.now() + Services.prefs.getIntPref(kPrefSessionPersistMinutes) * 60 * 1000; + expireTime = Date.now() + Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) * 60 * 1000; break; case "allowalways": @@ -700,7 +701,7 @@ var gPluginHandler = { permission = Ci.nsIPermissionManager.ALLOW_ACTION; expireType = Ci.nsIPermissionManager.EXPIRE_TIME; expireTime = Date.now() + - Services.prefs.getIntPref(kPrefPersistentDays) * 24 * 60 * 60 * 1000; + Services.prefs.getIntPref(this.PREF_PERSISTENT_DAYS) * 24 * 60 * 60 * 1000; break; case "block":