diff -Nru firefox-50.0.2+build1/addon-sdk/source/lib/sdk/event/chrome.js firefox-50.1.0+build2/addon-sdk/source/lib/sdk/event/chrome.js --- firefox-50.0.2+build1/addon-sdk/source/lib/sdk/event/chrome.js 2016-11-30 08:51:00.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/lib/sdk/event/chrome.js 2016-12-09 08:27:44.000000000 +0000 @@ -57,7 +57,7 @@ // We need to remove any observer added once the add-on is unloaded; // otherwise we'll get a "dead object" exception. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1001833 - unload(() => removeObserver(observerChannel, topic), { weak: true }); + unload(() => removeObserver(observerChannel, topic)); return observerChannel; } diff -Nru firefox-50.0.2+build1/addon-sdk/source/lib/sdk/ui/frame/view.html firefox-50.1.0+build2/addon-sdk/source/lib/sdk/ui/frame/view.html --- firefox-50.0.2+build1/addon-sdk/source/lib/sdk/ui/frame/view.html 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/lib/sdk/ui/frame/view.html 2016-12-09 08:27:44.000000000 +0000 @@ -1,18 +1,18 @@ - + + + + + + + diff -Nru firefox-50.0.2+build1/addon-sdk/source/lib/sdk/ui/frame/view.js firefox-50.1.0+build2/addon-sdk/source/lib/sdk/ui/frame/view.js --- firefox-50.0.2+build1/addon-sdk/source/lib/sdk/ui/frame/view.js 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/lib/sdk/ui/frame/view.js 2016-12-09 08:27:44.000000000 +0000 @@ -63,20 +63,8 @@ view.setAttribute("id", id); view.setAttribute("flex", 2); - let innerFrame = document.createElementNS(HTML_NS, "iframe"); - innerFrame.setAttribute("id", id); - innerFrame.setAttribute("src", url); - innerFrame.setAttribute("seamless", "seamless"); - innerFrame.setAttribute("sandbox", "allow-scripts"); - innerFrame.setAttribute("scrolling", "no"); - innerFrame.setAttribute("data-is-sdk-inner-frame", true); - innerFrame.setAttribute("style", [ "border:none", - "position:absolute", "width:100%", "top: 0", - "left: 0", "overflow: hidden"].join(";")); - let outerFrame = document.createElementNS(XUL_NS, "iframe"); - outerFrame.setAttribute("src", OUTER_FRAME_URI + "#" + - encode(innerFrame.outerHTML)); + outerFrame.setAttribute("src", OUTER_FRAME_URI); outerFrame.setAttribute("id", "outer-" + id); outerFrame.setAttribute("data-is-sdk-outer-frame", true); outerFrame.setAttribute("type", "content"); @@ -86,6 +74,24 @@ outerFrame.setAttribute("scrolling", "no"); outerFrame.setAttribute("disablehistory", true); outerFrame.setAttribute("seamless", "seamless"); + outerFrame.addEventListener("load", function onload() { + outerFrame.removeEventListener("load", onload, true); + + let doc = outerFrame.contentDocument; + + let innerFrame = doc.createElementNS(HTML_NS, "iframe"); + innerFrame.setAttribute("id", id); + innerFrame.setAttribute("src", url); + innerFrame.setAttribute("seamless", "seamless"); + innerFrame.setAttribute("sandbox", "allow-scripts"); + innerFrame.setAttribute("scrolling", "no"); + innerFrame.setAttribute("data-is-sdk-inner-frame", true); + innerFrame.setAttribute("style", [ "border:none", + "position:absolute", "width:100%", "top: 0", + "left: 0", "overflow: hidden"].join(";")); + + doc.body.appendChild(innerFrame); + }, true); view.appendChild(outerFrame); diff -Nru firefox-50.0.2+build1/addon-sdk/source/test/addons/jetpack-addon.ini firefox-50.1.0+build2/addon-sdk/source/test/addons/jetpack-addon.ini --- firefox-50.0.2+build1/addon-sdk/source/test/addons/jetpack-addon.ini 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/test/addons/jetpack-addon.ini 2016-12-09 08:27:44.000000000 +0000 @@ -28,6 +28,7 @@ [page-mod-debugger-post.xpi] [page-mod-debugger-pre.xpi] [page-worker.xpi] +skip-if = true # Bug 1288619 and Bug 1288708 [places.xpi] [predefined-id-with-at.xpi] [preferences-branch.xpi] diff -Nru firefox-50.0.2+build1/addon-sdk/source/test/leak/jetpack-package.ini firefox-50.1.0+build2/addon-sdk/source/test/leak/jetpack-package.ini --- firefox-50.0.2+build1/addon-sdk/source/test/leak/jetpack-package.ini 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/test/leak/jetpack-package.ini 2016-12-09 08:27:44.000000000 +0000 @@ -5,4 +5,3 @@ [test-leak-window-events.js] [test-leak-event-dom-closed-window.js] [test-leak-tab-events.js] -[test-leak-event-chrome.js] diff -Nru firefox-50.0.2+build1/addon-sdk/source/test/leak/leak-utils.js firefox-50.1.0+build2/addon-sdk/source/test/leak/leak-utils.js --- firefox-50.0.2+build1/addon-sdk/source/test/leak/leak-utils.js 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/test/leak/leak-utils.js 2016-12-09 08:27:44.000000000 +0000 @@ -31,7 +31,6 @@ Cu.schedulePreciseGC(genGCCallback()); }); } -exports.gc = gc; // Execute the given test function and verify that we did not leak windows // in the process. The test function must return a promise or be a generator. diff -Nru firefox-50.0.2+build1/addon-sdk/source/test/leak/test-leak-event-chrome.js firefox-50.1.0+build2/addon-sdk/source/test/leak/test-leak-event-chrome.js --- firefox-50.0.2+build1/addon-sdk/source/test/leak/test-leak-event-chrome.js 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/addon-sdk/source/test/leak/test-leak-event-chrome.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -'use strict'; - -const { gc } = require("./leak-utils"); -const { Loader } = require("sdk/test/loader"); -const { Cu } = require("chrome"); -const { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); - -exports["test sdk/event/chrome does not leak when not referenced"] = function*(assert) { - let loader = Loader(module); - let { observe } = loader.require("sdk/event/chrome"); - let { on } = loader.require("sdk/event/core"); - - let gotFooEvent = false; - on(observe("test-foo"), "data", function(evt) { - gotFooEvent = true; - }); - - let bar = observe("test-bar"); - let barPromise = new Promise(resolve => { - on(bar, "data", function(evt) { - assert.ok(!gotFooEvent, "should not have gotten test-foo event"); - resolve(); - }); - }); - - // This should clear the test-foo observer channel because we are not - // holding a reference to it above. - yield gc(); - - Services.obs.notifyObservers(null, "test-foo", null); - Services.obs.notifyObservers(null, "test-bar", null); - - yield barPromise; - - loader.unload(); -} - -require("sdk/test").run(exports); diff -Nru firefox-50.0.2+build1/browser/app/blocklist.xml firefox-50.1.0+build2/browser/app/blocklist.xml --- firefox-50.0.2+build1/browser/app/blocklist.xml 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/browser/app/blocklist.xml 2016-12-09 08:27:44.000000000 +0000 @@ -1,5 +1,5 @@ - + @@ -21,6 +21,13 @@ + + + browser.startup.homepage + browser.search.defaultenginename + + + @@ -29,13 +36,6 @@ - - - browser.startup.homepage - browser.search.defaultenginename - - - @@ -88,18 +88,18 @@ - + - + - + - + @@ -137,22 +137,14 @@ - - - - - + - - - - @@ -161,11 +153,15 @@ - + - + + + + + @@ -173,6 +169,10 @@ + + + + @@ -207,14 +207,14 @@ - - - - + + + + @@ -283,17 +283,17 @@ - + - + - + - + @@ -303,6 +303,10 @@ + + + + @@ -311,10 +315,6 @@ - - - - @@ -323,11 +323,15 @@ + + + + - + @@ -335,14 +339,18 @@ - - - - + + + + + + + + @@ -351,28 +359,20 @@ - + - - - - - - - - - + - + @@ -400,11 +400,11 @@ - + - + @@ -416,14 +416,14 @@ - - - - + + + + @@ -444,6 +444,10 @@ + + + + @@ -452,10 +456,6 @@ - - - - @@ -479,11 +479,11 @@ - + - + @@ -529,15 +529,15 @@ - + - + - + - + @@ -545,9 +545,9 @@ - + - + @@ -630,14 +630,14 @@ - - - - + + + + @@ -662,19 +662,23 @@ - + - + + + + + - + @@ -686,10 +690,6 @@ - - - - @@ -702,23 +702,23 @@ - - - - + + + + - + - + @@ -730,14 +730,14 @@ - - - - + + + + @@ -750,26 +750,26 @@ - - - - - + - + - + + + + + @@ -787,6 +787,10 @@ + + + + browser.startup.homepage @@ -794,10 +798,6 @@ - - - - @@ -814,6 +814,10 @@ + + + + @@ -822,10 +826,6 @@ - - - - @@ -844,6 +844,10 @@ + + + + browser.startup.homepage @@ -855,7 +859,16 @@ - + + + browser.startup.homepage + + + + + + + @@ -867,47 +880,34 @@ - - - browser.startup.homepage - - - - + - + - + + - - - - - + - + - + - + - - - - @@ -929,6 +929,10 @@ + + + + @@ -937,10 +941,14 @@ - + + + + + browser.startup.homepage @@ -948,37 +956,29 @@ - + - + + + + + - + - + - + - - + - - - - - - - - - - - @@ -987,6 +987,10 @@ + + + + browser.startup.homepage @@ -994,18 +998,14 @@ - + - + - - - - @@ -1037,15 +1037,15 @@ - + - + - + @@ -1069,16 +1069,19 @@ - + + - + + + + - @@ -1088,9 +1091,6 @@ - - - @@ -1138,7 +1138,18 @@ - + + + + + + + browser.startup.homepage + browser.search.defaultenginename + + + + @@ -1149,21 +1160,13 @@ - + browser.startup.homepage browser.search.defaultenginename - - - - - - - - @@ -1173,22 +1176,23 @@ - - - browser.startup.homepage - browser.search.defaultenginename - + + + + + + - + @@ -1200,10 +1204,6 @@ - - - - @@ -1212,14 +1212,6 @@ - - - - - - - - browser.startup.homepage @@ -1231,6 +1223,18 @@ + + + + + + + + + + + + @@ -1239,10 +1243,6 @@ - - - - @@ -1289,19 +1289,15 @@ - - - - - + - + - + @@ -1313,6 +1309,14 @@ + + + + + + + + browser.startup.homepage @@ -1320,10 +1324,6 @@ - - - - @@ -1364,6 +1364,14 @@ + + + + + + + + @@ -1372,18 +1380,10 @@ - - - - - - - - @@ -1392,11 +1392,11 @@ - + - + @@ -1423,12 +1423,12 @@ - + - - + + @@ -1450,6 +1450,10 @@ + + + + @@ -1458,10 +1462,6 @@ - - - - @@ -1536,14 +1536,14 @@ - - - - + + + + @@ -1572,14 +1572,14 @@ - - - - + + + + @@ -1592,17 +1592,17 @@ - + - + - + - + @@ -1616,11 +1616,11 @@ - + - + @@ -1643,10 +1643,6 @@ - - - - browser.startup.homepage @@ -1654,6 +1650,10 @@ + + + + @@ -1687,11 +1687,15 @@ + + + + - + @@ -1699,17 +1703,17 @@ - + - + - + - + @@ -1717,7 +1721,7 @@ - + @@ -1725,10 +1729,6 @@ - - - - @@ -1745,6 +1745,14 @@ + + + + + + + + @@ -1753,22 +1761,14 @@ - - - - - + - + - - - - @@ -1801,6 +1801,10 @@ + + + + @@ -1813,10 +1817,6 @@ - - - - @@ -1865,14 +1865,14 @@ - - - - + + + + @@ -1881,6 +1881,10 @@ + + + + @@ -1889,29 +1893,25 @@ - - - - - + - + + + + + - + - + - + - - - - - + @@ -1948,10 +1948,6 @@ - - - - @@ -1960,15 +1956,19 @@ + + + + - + - + @@ -2102,6 +2102,11 @@ https://get.adobe.com/flashplayer/ + + + https://get.adobe.com/flashplayer/ + + @@ -2151,6 +2156,11 @@ + + + https://get.adobe.com/flashplayer/ + + @@ -3417,9 +3427,6 @@ - - Os2rnHWYhryvdOXfgan06A== - d8AtKymQwkOPDBj+hjPzFg== @@ -3699,9 +3706,6 @@ Cfk9lw== - - U3t2Vk8pfxTcaUPpIq0seQ== - EqthLKdUgwI= @@ -3714,9 +3718,6 @@ M64Z5ufZzDRVTHkJR1uXzw== - - RurwlgVMxeP6Zepun0LGZA== - BAAAAAABGMGjftY= diff -Nru firefox-50.0.2+build1/browser/base/content/test/general/browser_web_channel.js firefox-50.1.0+build2/browser/base/content/test/general/browser_web_channel.js --- firefox-50.0.2+build1/browser/base/content/test/general/browser_web_channel.js 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/browser/base/content/test/general/browser_web_channel.js 2016-12-09 08:27:44.000000000 +0000 @@ -37,6 +37,26 @@ } }, { + desc: "WebChannel generic message in a private window.", + run: function* () { + let promiseTestDone = new Promise(function(resolve, reject) { + let channel = new WebChannel("generic", Services.io.newURI(HTTP_PATH, null, null)); + channel.listen(function(id, message, target) { + is(id, "generic"); + is(message.something.nested, "hello"); + channel.stopListening(); + resolve(); + }); + }); + + const url = HTTP_PATH + HTTP_ENDPOINT + "?generic"; + let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({private: true}); + yield BrowserTestUtils.openNewForegroundTab(privateWindow.gBrowser, url); + yield promiseTestDone; + yield BrowserTestUtils.closeWindow(privateWindow); + } + }, + { desc: "WebChannel two way communication", run: function* () { return new Promise(function(resolve, reject) { diff -Nru firefox-50.0.2+build1/browser/config/version_display.txt firefox-50.1.0+build2/browser/config/version_display.txt --- firefox-50.0.2+build1/browser/config/version_display.txt 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/browser/config/version_display.txt 2016-12-09 08:27:45.000000000 +0000 @@ -1 +1 @@ -50.0.2 +50.1.0 diff -Nru firefox-50.0.2+build1/browser/config/version.txt firefox-50.1.0+build2/browser/config/version.txt --- firefox-50.0.2+build1/browser/config/version.txt 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/browser/config/version.txt 2016-12-09 08:27:45.000000000 +0000 @@ -1 +1 @@ -50.0.2 +50.1.0 diff -Nru firefox-50.0.2+build1/browser/extensions/pocket/content/main.js firefox-50.1.0+build2/browser/extensions/pocket/content/main.js --- firefox-50.0.2+build1/browser/extensions/pocket/content/main.js 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/browser/extensions/pocket/content/main.js 2016-12-09 08:27:46.000000000 +0000 @@ -366,14 +366,19 @@ // send our own "show" event to the panel's script, so the // script can prepare the panel for display. var _showMessageId = "show"; - pktUIMessaging.addMessageListener(_showMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _showMessageId, function(panelId, data) { // Let panel know that it is ready pktUIMessaging.sendMessageToPanel(panelId, _showMessageId); }); // Open a new tab with a given url and activate if var _openTabWithUrlMessageId = "openTabWithUrl"; - pktUIMessaging.addMessageListener(_openTabWithUrlMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _openTabWithUrlMessageId, function(panelId, data, contentPrincipal) { + try { + urlSecurityCheck(data.url, contentPrincipal, Services.scriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL); + } catch (ex) { + return; + } // Check if the tab should become active after opening var activate = true; @@ -388,39 +393,39 @@ // Close the panel var _closeMessageId = "close"; - pktUIMessaging.addMessageListener(_closeMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _closeMessageId, function(panelId, data) { getPanel().hidePopup(); }); // Send the current url to the panel var _getCurrentURLMessageId = "getCurrentURL"; - pktUIMessaging.addMessageListener(_getCurrentURLMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _getCurrentURLMessageId, function(panelId, data) { pktUIMessaging.sendResponseMessageToPanel(panelId, _getCurrentURLMessageId, getCurrentUrl()); }); var _resizePanelMessageId = "resizePanel"; - pktUIMessaging.addMessageListener(_resizePanelMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _resizePanelMessageId, function(panelId, data) { resizePanel(data); }); // Callback post initialization to tell background script that panel is "ready" for communication. - pktUIMessaging.addMessageListener("listenerReady", function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, "listenerReady", function(panelId, data) { }); - pktUIMessaging.addMessageListener("collapseSavePanel", function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, "collapseSavePanel", function(panelId, data) { if (!pktApi.isPremiumUser() && !isInOverflowMenu()) resizePanel({width:savePanelWidth, height:savePanelHeights.collapsed}); }); - pktUIMessaging.addMessageListener("expandSavePanel", function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, "expandSavePanel", function(panelId, data) { if (!isInOverflowMenu()) resizePanel({width:savePanelWidth, height:savePanelHeights.expanded}); }); // Ask for recently accessed/used tags for auto complete var _getTagsMessageId = "getTags"; - pktUIMessaging.addMessageListener(_getTagsMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _getTagsMessageId, function(panelId, data) { pktApi.getTags(function(tags, usedTags) { pktUIMessaging.sendResponseMessageToPanel(panelId, _getTagsMessageId, { tags: tags, @@ -431,7 +436,7 @@ // Ask for suggested tags based on passed url var _getSuggestedTagsMessageId = "getSuggestedTags"; - pktUIMessaging.addMessageListener(_getSuggestedTagsMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _getSuggestedTagsMessageId, function(panelId, data) { pktApi.getSuggestedTagsForURL(data.url, { success: function(data, response) { var suggestedTags = data.suggested_tags; @@ -451,7 +456,7 @@ // Pass url and array list of tags, add to existing save item accordingly var _addTagsMessageId = "addTags"; - pktUIMessaging.addMessageListener(_addTagsMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _addTagsMessageId, function(panelId, data) { pktApi.addTagsToURL(data.url, data.tags, { success: function(data, response) { var successResponse = {status: "success"}; @@ -465,7 +470,7 @@ // Based on clicking "remove page" CTA, and passed unique item id, remove the item var _deleteItemMessageId = "deleteItem"; - pktUIMessaging.addMessageListener(_deleteItemMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _deleteItemMessageId, function(panelId, data) { pktApi.deleteItem(data.itemId, { success: function(data, response) { var successResponse = {status: "success"}; @@ -478,7 +483,7 @@ }); var _initL10NMessageId = "initL10N"; - pktUIMessaging.addMessageListener(_initL10NMessageId, function(panelId, data) { + pktUIMessaging.addMessageListener(iframe, _initL10NMessageId, function(panelId, data) { var strings = {}; var bundle = Services.strings.createBundle("chrome://pocket/locale/pocket.properties"); var e = bundle.getSimpleEnumeration(); @@ -627,10 +632,11 @@ /** * Register a listener and callback for a specific messageId */ - function addMessageListener(messageId, callback) { - document.addEventListener(prefixedMessageId(messageId), function(e) { + function addMessageListener(iframe, messageId, callback) { + iframe.addEventListener(prefixedMessageId(messageId), function(e) { + var nodePrincipal = e.target.nodePrincipal; // ignore to ensure we do not pick up other events in the browser - if (e.target.tagName !== 'PKTMESSAGEFROMPANELELEMENT') { + if (!nodePrincipal || !nodePrincipal.URI || !nodePrincipal.URI.spec.startsWith("about:pocket")) { return; } @@ -638,7 +644,7 @@ var payload = JSON.parse(e.target.getAttribute("payload"))[0]; var panelId = payload.panelId; var data = payload.data; - callback(panelId, data); + callback(panelId, data, nodePrincipal); // Cleanup the element e.target.parentNode.removeChild(e.target); @@ -647,14 +653,6 @@ } /** - * Remove a message listener - */ - function removeMessageListener(messageId, callback) { - document.removeEventListener(prefixedMessageId(messageId), callback); - } - - - /** * Send a message to the panel's iframe */ function sendMessageToPanel(panelId, messageId, payload) { @@ -751,7 +749,6 @@ */ return { addMessageListener: addMessageListener, - removeMessageListener: removeMessageListener, sendMessageToPanel: sendMessageToPanel, sendResponseMessageToPanel: sendResponseMessageToPanel, sendErrorMessageToPanel: sendErrorMessageToPanel, diff -Nru firefox-50.0.2+build1/browser/extensions/pocket/content/panels/js/saved.js firefox-50.1.0+build2/browser/extensions/pocket/content/panels/js/saved.js --- firefox-50.0.2+build1/browser/extensions/pocket/content/panels/js/saved.js 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/browser/extensions/pocket/content/panels/js/saved.js 2016-12-09 08:27:46.000000000 +0000 @@ -31,7 +31,9 @@ var newtagleft = 0; container.children().remove(); for (var i = 0; i < tags.length; i++) { - var newtag = $('
  • ' + tags[i] + '
  • '); + var newtag = $('
  • '); + newtag.find('a').text(tags[i]); + newtag.addClass(tagclass); container.append(newtag); var templeft = newtag.position().left; this.cxt_suggested_available++; diff -Nru firefox-50.0.2+build1/browser/extensions/pocket/content/panels/js/vendor/jquery.tokeninput.min.js firefox-50.1.0+build2/browser/extensions/pocket/content/panels/js/vendor/jquery.tokeninput.min.js --- firefox-50.0.2+build1/browser/extensions/pocket/content/panels/js/vendor/jquery.tokeninput.min.js 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/browser/extensions/pocket/content/panels/js/vendor/jquery.tokeninput.min.js 2016-12-09 08:27:46.000000000 +0000 @@ -49,8 +49,18 @@ idPrefix: "token-input-", // Formatters - resultsFormatter: function(item){ return "
  • " + item[this.propertyToSearch]+ "
  • " }, - tokenFormatter: function(item) { return "
  • " + item[this.propertyToSearch] + "

  • " }, + resultsFormatter: function(item) { + let listItem = document.createElement("li"); + listItem.textContent = item[this.propertyToSearch]; + return listItem.outerHTML; + }, + tokenFormatter: function(item) { + let listItem = document.createElement("li"); + let p = document.createElement("p"); + p.textContent = item[this.propertyToSearch]; + listItem.appendChild(p); + return listItem.outerHTML; + }, // Validations validateItem: null, diff -Nru firefox-50.0.2+build1/browser/installer/package-manifest.in firefox-50.1.0+build2/browser/installer/package-manifest.in --- firefox-50.0.2+build1/browser/installer/package-manifest.in 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/browser/installer/package-manifest.in 2016-12-09 08:27:46.000000000 +0000 @@ -409,6 +409,8 @@ @RESPATH@/components/NetworkGeolocationProvider.manifest @RESPATH@/components/NetworkGeolocationProvider.js @RESPATH@/components/extensions.manifest +@RESPATH@/components/EditorUtils.manifest +@RESPATH@/components/EditorUtils.js @RESPATH@/components/addonManager.js @RESPATH@/components/amContentHandler.js @RESPATH@/components/amInstallTrigger.js diff -Nru firefox-50.0.2+build1/config/milestone.txt firefox-50.1.0+build2/config/milestone.txt --- firefox-50.0.2+build1/config/milestone.txt 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/config/milestone.txt 2016-12-09 08:27:46.000000000 +0000 @@ -10,4 +10,4 @@ # hardcoded milestones in the tree from these two files. #-------------------------------------------------------- -50.0.2 +50.1.0 diff -Nru firefox-50.0.2+build1/debian/changelog firefox-50.1.0+build2/debian/changelog --- firefox-50.0.2+build1/debian/changelog 2016-11-30 09:25:16.000000000 +0000 +++ firefox-50.1.0+build2/debian/changelog 2016-12-09 09:20:10.000000000 +0000 @@ -1,3 +1,10 @@ +firefox (50.1.0+build2-0ubuntu0.12.04.1) precise-security; urgency=medium + + * New upstream stable release (50.1.0build2) + - see USN-3155-1 + + -- Chris Coulson Thu, 08 Dec 2016 20:50:24 +0000 + firefox (50.0.2+build1-0ubuntu0.12.04.1) precise-security; urgency=medium * New upstream stable release (50.0.2build1) diff -Nru firefox-50.0.2+build1/devtools/client/netmonitor/netmonitor.css firefox-50.1.0+build2/devtools/client/netmonitor/netmonitor.css --- firefox-50.0.2+build1/devtools/client/netmonitor/netmonitor.css 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/devtools/client/netmonitor/netmonitor.css 2016-12-09 08:27:47.000000000 +0000 @@ -44,6 +44,7 @@ @media (max-width: 700px) { #toolbar-spacer, #details-pane-toggle, + #details-pane.pane-collapsed, .requests-menu-waterfall, #requests-menu-network-summary-button > .toolbarbutton-text { display: none; diff -Nru firefox-50.0.2+build1/docshell/base/nsDocShell.cpp firefox-50.1.0+build2/docshell/base/nsDocShell.cpp --- firefox-50.0.2+build1/docshell/base/nsDocShell.cpp 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/docshell/base/nsDocShell.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -8938,6 +8938,8 @@ nsSubDocumentFrame* subDocFrame = do_QueryFrame(container->GetPrimaryFrame()); rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr; + } else { + rootViewParent = nullptr; } if (sibling && sibling->GetShell() && diff -Nru firefox-50.0.2+build1/dom/base/Navigator.cpp firefox-50.1.0+build2/dom/base/Navigator.cpp --- firefox-50.0.2+build1/dom/base/Navigator.cpp 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/dom/base/Navigator.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -2050,9 +2050,10 @@ return nullptr; } - // We pass ourself to RefreshVRDevices, so NotifyVRDevicesUpdated will + // We pass mWindow's id to RefreshVRDevices, so NotifyVRDevicesUpdated will // be called asynchronously, resolving the promises in mVRGetDevicesPromises. - if (!VRDevice::RefreshVRDevices(this)) { + nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow); + if (!VRDevice::RefreshVRDevices(win->WindowID())) { p->MaybeReject(NS_ERROR_FAILURE); return p.forget(); } diff -Nru firefox-50.0.2+build1/dom/base/nsDataDocumentContentPolicy.cpp firefox-50.1.0+build2/dom/base/nsDataDocumentContentPolicy.cpp --- firefox-50.0.2+build1/dom/base/nsDataDocumentContentPolicy.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/dom/base/nsDataDocumentContentPolicy.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -75,7 +75,12 @@ } } - if (doc->IsBeingUsedAsImage()) { + nsIDocument* docToCheckForImage = doc->GetDisplayDocument(); + if (!docToCheckForImage) { + docToCheckForImage = doc; + } + + if (docToCheckForImage->IsBeingUsedAsImage()) { // We only allow SVG images to load content from URIs that are local and // also satisfy one of the following conditions: // - URI inherits security context, e.g. data URIs diff -Nru firefox-50.0.2+build1/dom/base/nsDocument.cpp firefox-50.1.0+build2/dom/base/nsDocument.cpp --- firefox-50.0.2+build1/dom/base/nsDocument.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/dom/base/nsDocument.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -13016,6 +13016,24 @@ return mSandboxFlags & SANDBOXED_SCRIPTS; } +bool +nsIDocument::InlineScriptAllowedByCSP() +{ + nsCOMPtr csp; + nsresult rv = NodePrincipal()->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, true); + bool allowsInlineScript = true; + if (csp) { + nsresult rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT, + EmptyString(), // aNonce + EmptyString(), // FIXME get script sample (bug 1314567) + 0, // aLineNumber + &allowsInlineScript); + NS_ENSURE_SUCCESS(rv, true); + } + return allowsInlineScript; +} + static bool MightBeAboutOrChromeScheme(nsIURI* aURI) { diff -Nru firefox-50.0.2+build1/dom/base/nsIDocument.h firefox-50.1.0+build2/dom/base/nsIDocument.h --- firefox-50.0.2+build1/dom/base/nsIDocument.h 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/dom/base/nsIDocument.h 2016-12-09 08:27:48.000000000 +0000 @@ -2791,6 +2791,8 @@ bool HasScriptsBlockedBySandbox(); + bool InlineScriptAllowedByCSP(); + void ReportHasScrollLinkedEffect(); bool HasScrollLinkedEffect() const { diff -Nru firefox-50.0.2+build1/dom/base/nsNodeUtils.cpp firefox-50.1.0+build2/dom/base/nsNodeUtils.cpp --- firefox-50.0.2+build1/dom/base/nsNodeUtils.cpp 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/dom/base/nsNodeUtils.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -570,8 +570,13 @@ JSAutoCompartment ac(cx, wrapper); rv = ReparentWrapper(cx, wrapper); if (NS_FAILED(rv)) { + if (wasRegistered) { + aNode->OwnerDoc()->UnregisterActivityObserver(aNode->AsElement()); + } aNode->mNodeInfo.swap(newNodeInfo); - + if (wasRegistered) { + aNode->OwnerDoc()->RegisterActivityObserver(aNode->AsElement()); + } return rv; } } diff -Nru firefox-50.0.2+build1/dom/bindings/BindingUtils.h firefox-50.1.0+build2/dom/bindings/BindingUtils.h --- firefox-50.0.2+build1/dom/bindings/BindingUtils.h 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/dom/bindings/BindingUtils.h 2016-12-09 08:27:49.000000000 +0000 @@ -2314,6 +2314,22 @@ AtomizeAndPinJSString(cx, *(vector[vector.length() - 1]).address(), name); } +// We use one constructor JSNative to represent all DOM interface objects (so +// we can easily detect when we need to wrap them in an Xray wrapper). We store +// the real JSNative in the mNative member of a JSNativeHolder in the +// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a +// specific interface object. We also store the NativeProperties in the +// JSNativeHolder. +// Note that some interface objects are not yet a JSFunction but a normal +// JSObject with a DOMJSClass, those do not use these slots. + +enum { + CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0 +}; + +bool +Constructor(JSContext* cx, unsigned argc, JS::Value* vp); + // Implementation of the bits that XrayWrapper needs /** @@ -2387,6 +2403,9 @@ } else { protop.set(JS::GetRealmObjectPrototype(cx)); } + } else if (JS_ObjectIsFunction(cx, obj)) { + MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor)); + protop.set(JS::GetRealmFunctionPrototype(cx)); } else { const js::Class* clasp = js::GetObjectClass(obj); MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp)); @@ -2405,22 +2424,6 @@ extern const js::ObjectOps sInterfaceObjectClassObjectOps; -// We use one constructor JSNative to represent all DOM interface objects (so -// we can easily detect when we need to wrap them in an Xray wrapper). We store -// the real JSNative in the mNative member of a JSNativeHolder in the -// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a -// specific interface object. We also store the NativeProperties in the -// JSNativeHolder. -// Note that some interface objects are not yet a JSFunction but a normal -// JSObject with a DOMJSClass, those do not use these slots. - -enum { - CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0 -}; - -bool -Constructor(JSContext* cx, unsigned argc, JS::Value* vp); - inline bool UseDOMXray(JSObject* obj) { @@ -2437,7 +2440,7 @@ return JS_IsNativeFunction(obj, Constructor) || js::GetObjectClass(obj)->getConstruct(); } - #endif +#endif // Helpers for creating a const version of a type. template diff -Nru firefox-50.0.2+build1/dom/bindings/test/chrome.ini firefox-50.1.0+build2/dom/bindings/test/chrome.ini --- firefox-50.0.2+build1/dom/bindings/test/chrome.ini 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/dom/bindings/test/chrome.ini 2016-12-09 08:27:49.000000000 +0000 @@ -24,3 +24,4 @@ skip-if = e10s # prerendering doesn't work in e10s yet [test_bug1123516_maplikesetlikechrome.xul] skip-if = debug == false +[test_bug1287912.html] diff -Nru firefox-50.0.2+build1/dom/bindings/test/test_bug1287912.html firefox-50.1.0+build2/dom/bindings/test/test_bug1287912.html --- firefox-50.0.2+build1/dom/bindings/test/test_bug1287912.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/dom/bindings/test/test_bug1287912.html 2016-12-09 08:27:49.000000000 +0000 @@ -0,0 +1,37 @@ + + + + + + Test for Bug 1287912 + + + + +Mozilla Bug 1287912 +

    + +
    +
    +
    + + diff -Nru firefox-50.0.2+build1/dom/filesystem/tests/mochitest.ini firefox-50.1.0+build2/dom/filesystem/tests/mochitest.ini --- firefox-50.0.2+build1/dom/filesystem/tests/mochitest.ini 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/dom/filesystem/tests/mochitest.ini 2016-12-09 08:27:45.000000000 +0000 @@ -7,3 +7,4 @@ [test_basic.html] [test_webkitdirectory.html] [test_worker_basic.html] +[test_bug1319088.html] diff -Nru firefox-50.0.2+build1/dom/filesystem/tests/test_bug1319088.html firefox-50.1.0+build2/dom/filesystem/tests/test_bug1319088.html --- firefox-50.0.2+build1/dom/filesystem/tests/test_bug1319088.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/dom/filesystem/tests/test_bug1319088.html 2016-12-09 08:27:45.000000000 +0000 @@ -0,0 +1,66 @@ + + + + Test for bug 1319088 + + + + + + + + + + diff -Nru firefox-50.0.2+build1/dom/html/HTMLInputElement.cpp firefox-50.1.0+build2/dom/html/HTMLInputElement.cpp --- firefox-50.0.2+build1/dom/html/HTMLInputElement.cpp 2016-11-30 08:51:02.000000000 +0000 +++ firefox-50.1.0+build2/dom/html/HTMLInputElement.cpp 2016-12-09 08:27:45.000000000 +0000 @@ -347,18 +347,7 @@ if (aArray[i].IsFile()) { BlobImplOrDirectoryPath* data = mBlobImplsOrDirectoryPaths.AppendElement(); - RefPtr file = aArray[i].GetAsFile(); - - nsAutoString name; - file->GetName(name); - - nsAutoString path; - path.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL); - path.Append(name); - - file->SetPath(path); - - data->mBlobImpl = file->Impl(); + data->mBlobImpl = aArray[i].GetAsFile()->Impl(); data->mType = BlobImplOrDirectoryPath::eBlobImpl; } else { MOZ_ASSERT(aArray[i].IsDirectory()); diff -Nru firefox-50.0.2+build1/dom/media/MediaDecoderReader.cpp firefox-50.1.0+build2/dom/media/MediaDecoderReader.cpp --- firefox-50.0.2+build1/dom/media/MediaDecoderReader.cpp 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/MediaDecoderReader.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -237,9 +237,14 @@ } ReaderQueue::Instance().Add(this); +} +nsresult +MediaDecoderReader::Init() +{ // Dispatch initialization that needs to happen on that task queue. mTaskQueue->Dispatch(NewRunnableMethod(this, &MediaDecoderReader::InitializationTask)); + return InitInternal(); } void diff -Nru firefox-50.0.2+build1/dom/media/MediaDecoderReader.h firefox-50.1.0+build2/dom/media/MediaDecoderReader.h --- firefox-50.0.2+build1/dom/media/MediaDecoderReader.h 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/MediaDecoderReader.h 2016-12-09 08:27:46.000000000 +0000 @@ -100,7 +100,7 @@ // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE // on failure. - virtual nsresult Init() { return NS_OK; } + nsresult Init(); // Release media resources they should be released in dormant state // The reader can be made usable again by calling ReadMetadata(). @@ -411,6 +411,8 @@ MediaEventProducer mOnMediaNotSeekable; private: + virtual nsresult InitInternal() { return NS_OK; } + // Does any spinup that needs to happen on this task queue. This runs on a // different thread than Init, and there should not be ordering dependencies // between the two (even though in practice, Init will always run first right diff -Nru firefox-50.0.2+build1/dom/media/MediaFormatReader.cpp firefox-50.1.0+build2/dom/media/MediaFormatReader.cpp --- firefox-50.0.2+build1/dom/media/MediaFormatReader.cpp 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/MediaFormatReader.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -171,7 +171,7 @@ } nsresult -MediaFormatReader::Init() +MediaFormatReader::InitInternal() { MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread."); diff -Nru firefox-50.0.2+build1/dom/media/MediaFormatReader.h firefox-50.1.0+build2/dom/media/MediaFormatReader.h --- firefox-50.0.2+build1/dom/media/MediaFormatReader.h 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/MediaFormatReader.h 2016-12-09 08:27:46.000000000 +0000 @@ -34,8 +34,6 @@ virtual ~MediaFormatReader(); - nsresult Init() override; - size_t SizeOfVideoQueueInFrames() override; size_t SizeOfAudioQueueInFrames() override; @@ -103,6 +101,7 @@ void GetMozDebugReaderData(nsAString& aString); private: + nsresult InitInternal() override; bool HasVideo() const { return mVideo.mTrackDemuxer; } bool HasAudio() const { return mAudio.mTrackDemuxer; } diff -Nru firefox-50.0.2+build1/dom/media/MediaRecorder.cpp firefox-50.1.0+build2/dom/media/MediaRecorder.cpp --- firefox-50.0.2+build1/dom/media/MediaRecorder.cpp 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/MediaRecorder.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -111,8 +111,22 @@ }; NS_IMPL_ISUPPORTS(MediaRecorderReporter, nsIMemoryReporter); -NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRecorder, DOMEventTargetHelper, - mDOMStream, mAudioNode) +NS_IMPL_CYCLE_COLLECTION_CLASS(MediaRecorder) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaRecorder, + DOMEventTargetHelper) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStream) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioNode) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaRecorder, + DOMEventTargetHelper) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMStream) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioNode) + tmp->UnRegisterActivityObserver(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRecorder) NS_INTERFACE_MAP_ENTRY(nsIDocumentActivity) @@ -1011,9 +1025,9 @@ MediaRecorder::RegisterActivityObserver() { if (nsPIDOMWindowInner* window = GetOwner()) { - nsIDocument* doc = window->GetExtantDoc(); - if (doc) { - doc->RegisterActivityObserver( + mDocument = window->GetExtantDoc(); + if (mDocument) { + mDocument->RegisterActivityObserver( NS_ISUPPORTS_CAST(nsIDocumentActivity*, this)); } } @@ -1022,12 +1036,9 @@ void MediaRecorder::UnRegisterActivityObserver() { - if (nsPIDOMWindowInner* window = GetOwner()) { - nsIDocument* doc = window->GetExtantDoc(); - if (doc) { - doc->UnregisterActivityObserver( - NS_ISUPPORTS_CAST(nsIDocumentActivity*, this)); - } + if (mDocument) { + mDocument->UnregisterActivityObserver( + NS_ISUPPORTS_CAST(nsIDocumentActivity*, this)); } } diff -Nru firefox-50.0.2+build1/dom/media/MediaRecorder.h firefox-50.1.0+build2/dom/media/MediaRecorder.h --- firefox-50.0.2+build1/dom/media/MediaRecorder.h 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/MediaRecorder.h 2016-12-09 08:27:46.000000000 +0000 @@ -148,6 +148,9 @@ // Hold the sessions reference and clean it when the DestroyRunnable for a // session is running. nsTArray > mSessions; + + nsCOMPtr mDocument; + // It specifies the container format as well as the audio and video capture formats. nsString mMimeType; diff -Nru firefox-50.0.2+build1/dom/media/ogg/OggReader.cpp firefox-50.1.0+build2/dom/media/ogg/OggReader.cpp --- firefox-50.0.2+build1/dom/media/ogg/OggReader.cpp 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/ogg/OggReader.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -164,7 +164,7 @@ } } -nsresult OggReader::Init() { +nsresult OggReader::InitInternal() { int ret = ogg_sync_init(&mOggState); NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE); return NS_OK; diff -Nru firefox-50.0.2+build1/dom/media/ogg/OggReader.h firefox-50.1.0+build2/dom/media/ogg/OggReader.h --- firefox-50.0.2+build1/dom/media/ogg/OggReader.h 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/ogg/OggReader.h 2016-12-09 08:27:46.000000000 +0000 @@ -32,7 +32,6 @@ ~OggReader(); public: - nsresult Init() override; nsresult ResetDecode(TrackSet aTracks = TrackSet(TrackInfo::kAudioTrack, TrackInfo::kVideoTrack)) override; bool DecodeAudioData() override; @@ -47,6 +46,8 @@ media::TimeIntervals GetBuffered() override; private: + nsresult InitInternal() override; + bool HasAudio() { return (mVorbisState != 0 && mVorbisState->mActive) || (mOpusState != 0 && mOpusState->mActive); diff -Nru firefox-50.0.2+build1/dom/media/platforms/agnostic/VorbisDecoder.cpp firefox-50.1.0+build2/dom/media/platforms/agnostic/VorbisDecoder.cpp --- firefox-50.0.2+build1/dom/media/platforms/agnostic/VorbisDecoder.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/platforms/agnostic/VorbisDecoder.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -156,7 +156,7 @@ const unsigned char* aData = aSample->Data(); size_t aLength = aSample->Size(); int64_t aOffset = aSample->mOffset; - uint64_t aTstampUsecs = aSample->mTime; + int64_t aTstampUsecs = aSample->mTime; int64_t aTotalFrames = 0; MOZ_ASSERT(mPacketCount >= 3); diff -Nru firefox-50.0.2+build1/dom/media/webrtc/MediaEngineWebRTCAudio.cpp firefox-50.1.0+build2/dom/media/webrtc/MediaEngineWebRTCAudio.cpp --- firefox-50.0.2+build1/dom/media/webrtc/MediaEngineWebRTCAudio.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/dom/media/webrtc/MediaEngineWebRTCAudio.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -820,16 +820,10 @@ while (mRegisteredHandles.Length()) { MOZ_ASSERT(mState == kAllocated || mState == kStopped); - Deallocate(nullptr); // XXX Extend concurrent constraints code to mics. - } - - if (mState != kReleased) { - FreeChannel(); - MOZ_ASSERT(sChannelsOpen > 0); - if (--sChannelsOpen == 0) { - DeInitEngine(); - } + // on last Deallocate(), FreeChannel()s and DeInit()s if all channels are released + Deallocate(mRegisteredHandles[0].get()); } + MOZ_ASSERT(mState == kReleased); mAudioInput = nullptr; } diff -Nru firefox-50.0.2+build1/dom/plugins/base/nsJSNPRuntime.cpp firefox-50.1.0+build2/dom/plugins/base/nsJSNPRuntime.cpp --- firefox-50.0.2+build1/dom/plugins/base/nsJSNPRuntime.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/dom/plugins/base/nsJSNPRuntime.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -1185,6 +1185,8 @@ } return obj; } + + JSAutoCompartment ac(cx, obj); if (!::JS_GetPrototype(cx, obj, &obj)) { return nullptr; } diff -Nru firefox-50.0.2+build1/dom/security/test/csp/file_bug1312272.html firefox-50.1.0+build2/dom/security/test/csp/file_bug1312272.html --- firefox-50.0.2+build1/dom/security/test/csp/file_bug1312272.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/dom/security/test/csp/file_bug1312272.html 2016-12-09 08:27:47.000000000 +0000 @@ -0,0 +1,13 @@ + + + + + + marquee inline script tests for Bug 1312272 + + +bug 1312272 + + + diff -Nru firefox-50.0.2+build1/dom/security/test/csp/file_bug1312272.html^headers^ firefox-50.1.0+build2/dom/security/test/csp/file_bug1312272.html^headers^ --- firefox-50.0.2+build1/dom/security/test/csp/file_bug1312272.html^headers^ 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/dom/security/test/csp/file_bug1312272.html^headers^ 2016-12-09 08:27:47.000000000 +0000 @@ -0,0 +1 @@ +Content-Security-Policy: default-src *; script-src * 'unsafe-eval' diff -Nru firefox-50.0.2+build1/dom/security/test/csp/file_bug1312272.js firefox-50.1.0+build2/dom/security/test/csp/file_bug1312272.js --- firefox-50.0.2+build1/dom/security/test/csp/file_bug1312272.js 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/dom/security/test/csp/file_bug1312272.js 2016-12-09 08:27:47.000000000 +0000 @@ -0,0 +1,8 @@ +var m = document.getElementById("m"); +m.addEventListener("click", function() { + // this will trigger after onstart, obviously. + parent.postMessage('finish', '*'); +}); +console.log("finish-handler setup"); +m.click(); +console.log("clicked"); diff -Nru firefox-50.0.2+build1/dom/security/test/csp/mochitest.ini firefox-50.1.0+build2/dom/security/test/csp/mochitest.ini --- firefox-50.0.2+build1/dom/security/test/csp/mochitest.ini 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/dom/security/test/csp/mochitest.ini 2016-12-09 08:27:47.000000000 +0000 @@ -22,6 +22,9 @@ file_bug885433_blocks.html^headers^ file_bug888172.html file_bug888172.sjs + file_bug1312272.html + file_bug1312272.js + file_bug1312272.html^headers^ file_evalscript_main.js file_evalscript_main_allowed.js file_evalscript_main.html @@ -279,3 +282,5 @@ [test_require_sri_meta.html] [test_sendbeacon.html] [test_upgrade_insecure_docwrite_iframe.html] +[test_bug1312272.html] + diff -Nru firefox-50.0.2+build1/dom/security/test/csp/test_bug1312272.html firefox-50.1.0+build2/dom/security/test/csp/test_bug1312272.html --- firefox-50.0.2+build1/dom/security/test/csp/test_bug1312272.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/dom/security/test/csp/test_bug1312272.html 2016-12-09 08:27:47.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + + Test for bug 1312272 + + + + + + + + + + diff -Nru firefox-50.0.2+build1/dom/vr/VRDevice.cpp firefox-50.1.0+build2/dom/vr/VRDevice.cpp --- firefox-50.0.2+build1/dom/vr/VRDevice.cpp 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/dom/vr/VRDevice.cpp 2016-12-09 08:27:49.000000000 +0000 @@ -22,10 +22,10 @@ namespace dom { /*static*/ bool -VRDevice::RefreshVRDevices(dom::Navigator* aNavigator) +VRDevice::RefreshVRDevices(uint64_t aWindowId) { gfx::VRManagerChild* vm = gfx::VRManagerChild::Get(); - return vm && vm->RefreshVRDevicesWithCallback(aNavigator); + return vm && vm->RefreshVRDevicesWithCallback(aWindowId); } /*static*/ void diff -Nru firefox-50.0.2+build1/dom/vr/VRDevice.h firefox-50.1.0+build2/dom/vr/VRDevice.h --- firefox-50.0.2+build1/dom/vr/VRDevice.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/dom/vr/VRDevice.h 2016-12-09 08:27:49.000000000 +0000 @@ -201,7 +201,7 @@ VRDeviceType GetType() const { return mType; } - static bool RefreshVRDevices(dom::Navigator* aNavigator); + static bool RefreshVRDevices(uint64_t aWindowId); static void UpdateVRDevices(nsTArray >& aDevices, nsISupports* aParent); diff -Nru firefox-50.0.2+build1/dom/webidl/Document.webidl firefox-50.1.0+build2/dom/webidl/Document.webidl --- firefox-50.0.2+build1/dom/webidl/Document.webidl 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/dom/webidl/Document.webidl 2016-12-09 08:27:49.000000000 +0000 @@ -438,9 +438,11 @@ }; // Extension to give chrome and XBL JS the ability to determine whether -// the document is sandboxed without permission to run scripts. +// the document is sandboxed without permission to run scripts +// and whether inline scripts are blocked by the document's CSP. partial interface Document { [Func="IsChromeOrXBL"] readonly attribute boolean hasScriptsBlockedBySandbox; + [Func="IsChromeOrXBL"] readonly attribute boolean inlineScriptAllowedByCSP; }; Document implements XPathEvaluator; diff -Nru firefox-50.0.2+build1/editor/libeditor/HTMLEditor.cpp firefox-50.1.0+build2/editor/libeditor/HTMLEditor.cpp --- firefox-50.0.2+build1/editor/libeditor/HTMLEditor.cpp 2016-11-30 08:51:08.000000000 +0000 +++ firefox-50.1.0+build2/editor/libeditor/HTMLEditor.cpp 2016-12-09 08:27:50.000000000 +0000 @@ -3222,6 +3222,27 @@ eInserted); } +bool +HTMLEditor::IsInObservedSubtree(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild) +{ + if (!aChild) { + return false; + } + + Element* root = GetRoot(); + // To be super safe here, check both ChromeOnlyAccess and GetBindingParent. + // That catches (also unbound) native anonymous content, XBL and ShadowDOM. + if (root && + (root->ChromeOnlyAccess() != aChild->ChromeOnlyAccess() || + root->GetBindingParent() != aChild->GetBindingParent())) { + return false; + } + + return !aChild->ChromeOnlyAccess() && !aChild->GetBindingParent(); +} + void HTMLEditor::DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer, @@ -3229,7 +3250,7 @@ int32_t aIndexInContainer, InsertedOrAppended aInsertedOrAppended) { - if (!aChild) { + if (!IsInObservedSubtree(aDocument, aContainer, aChild)) { return; } @@ -3277,6 +3298,10 @@ int32_t aIndexInContainer, nsIContent* aPreviousSibling) { + if (!IsInObservedSubtree(aDocument, aContainer, aChild)) { + return; + } + nsCOMPtr kungFuDeathGrip(this); if (SameCOMIdentity(aChild, mRootElement)) { diff -Nru firefox-50.0.2+build1/editor/libeditor/HTMLEditor.h firefox-50.1.0+build2/editor/libeditor/HTMLEditor.h --- firefox-50.0.2+build1/editor/libeditor/HTMLEditor.h 2016-11-30 08:51:08.000000000 +0000 +++ firefox-50.1.0+build2/editor/libeditor/HTMLEditor.h 2016-12-09 08:27:50.000000000 +0000 @@ -939,6 +939,10 @@ int32_t& aMarginLeft, int32_t& aMarginTop); + bool IsInObservedSubtree(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild); + // resizing bool mIsObjectResizingEnabled; bool mIsResizing; diff -Nru firefox-50.0.2+build1/gfx/2d/DrawTargetRecording.cpp firefox-50.1.0+build2/gfx/2d/DrawTargetRecording.cpp --- firefox-50.0.2+build1/gfx/2d/DrawTargetRecording.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/2d/DrawTargetRecording.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -245,7 +245,8 @@ mPattern = new (mSurfPat) SurfacePattern(GetSourceSurface(surfPat->mSurface), surfPat->mExtendMode, surfPat->mMatrix, - surfPat->mSamplingFilter); + surfPat->mSamplingFilter, + surfPat->mSamplingRect); return mPattern; } case PatternType::LINEAR_GRADIENT: @@ -299,12 +300,13 @@ } DrawTargetRecording::DrawTargetRecording(const DrawTargetRecording *aDT, - const IntSize &aSize, - SurfaceFormat aFormat) + DrawTarget *aSimilarDT) : mRecorder(aDT->mRecorder) - , mFinalDT(aDT->mFinalDT->CreateSimilarDrawTarget(aSize, aFormat)) + , mFinalDT(aSimilarDT) { - mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(this, aSize, aFormat)); + mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(this, + mFinalDT->GetSize(), + mFinalDT->GetFormat())); mFormat = mFinalDT->GetFormat(); } @@ -649,7 +651,14 @@ already_AddRefed DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const { - return MakeAndAddRef(this, aSize, aFormat); + RefPtr similarDT = + mFinalDT->CreateSimilarDrawTarget(aSize, aFormat); + if (!similarDT) { + return nullptr; + } + + similarDT = new DrawTargetRecording(this, similarDT); + return similarDT.forget(); } already_AddRefed diff -Nru firefox-50.0.2+build1/gfx/2d/DrawTargetRecording.h firefox-50.1.0+build2/gfx/2d/DrawTargetRecording.h --- firefox-50.0.2+build1/gfx/2d/DrawTargetRecording.h 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/2d/DrawTargetRecording.h 2016-12-09 08:27:44.000000000 +0000 @@ -19,16 +19,6 @@ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetRecording, override) DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false); - /** - * Used for creating a DrawTargetRecording for a CreateSimilarDrawTarget call. - * - * @param aDT DrawTargetRecording on which CreateSimilarDrawTarget was called - * @param aSize size for the similar DrawTarget - * @param aFormat format for the similar DrawTarget - */ - DrawTargetRecording(const DrawTargetRecording *aDT, const IntSize &aSize, - SurfaceFormat aFormat); - ~DrawTargetRecording(); virtual DrawTargetType GetType() const override { return mFinalDT->GetType(); } @@ -322,6 +312,17 @@ } private: + /** + * Used for creating a DrawTargetRecording for a CreateSimilarDrawTarget call. + * We have to call CreateSimilarDrawTarget on mFinalDT up front and pass it in + * as it can fail. + * + * @param aDT DrawTargetRecording on which CreateSimilarDrawTarget was called + * @param aSimilarDT Similar DrawTarget created from aDT.mFinalDT. + */ + DrawTargetRecording(const DrawTargetRecording *aDT, + DrawTarget *aSimilarDT); + Path *GetPathForPathRecording(const Path *aPath) const; already_AddRefed EnsurePathStored(const Path *aPath); void EnsurePatternDependenciesStored(const Pattern &aPattern); diff -Nru firefox-50.0.2+build1/gfx/2d/Factory.cpp firefox-50.1.0+build2/gfx/2d/Factory.cpp --- firefox-50.0.2+build1/gfx/2d/Factory.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/gfx/2d/Factory.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -434,7 +434,7 @@ } if (!retVal) { - gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize << ", Data: " << hexa(aData) << ", Stride: " << aStride; + gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize << ", Data: " << hexa((void *)aData) << ", Stride: " << aStride; } return retVal.forget(); diff -Nru firefox-50.0.2+build1/gfx/2d/RecordedEvent.cpp firefox-50.1.0+build2/gfx/2d/RecordedEvent.cpp --- firefox-50.0.2+build1/gfx/2d/RecordedEvent.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/2d/RecordedEvent.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -282,6 +282,7 @@ store->mSamplingFilter = pat->mSamplingFilter; store->mMatrix = pat->mMatrix; store->mSurface = pat->mSurface; + store->mSamplingRect = pat->mSamplingRect; return; } } @@ -551,7 +552,8 @@ mPattern = new (mSurfPat) SurfacePattern(mTranslator->LookupSourceSurface(storage->mSurface), storage->mExtend, storage->mMatrix, - storage->mSamplingFilter); + storage->mSamplingFilter, + storage->mSamplingRect); return mPattern; } case PatternType::LINEAR_GRADIENT: diff -Nru firefox-50.0.2+build1/gfx/2d/RecordedEvent.h firefox-50.1.0+build2/gfx/2d/RecordedEvent.h --- firefox-50.0.2+build1/gfx/2d/RecordedEvent.h 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/2d/RecordedEvent.h 2016-12-09 08:27:44.000000000 +0000 @@ -24,10 +24,10 @@ // loss of backwards compatibility. Old streams will not work in a player // using a newer major revision. And new streams will not work in a player // using an older major revision. -const uint16_t kMajorRevision = 4; +const uint16_t kMajorRevision = 5; // A change in minor revision means additions of new events. New streams will // not play in older players. -const uint16_t kMinorRevision = 1; +const uint16_t kMinorRevision = 0; struct ReferencePtr { @@ -141,6 +141,7 @@ SamplingFilter mSamplingFilter; ReferencePtr mSurface; Matrix mMatrix; + IntRect mSamplingRect; }; struct PatternStorage diff -Nru firefox-50.0.2+build1/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp firefox-50.1.0+build2/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp --- firefox-50.0.2+build1/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/gfx/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -73,6 +73,10 @@ unsigned int maxVaryingVectors = static_cast(mRegisterMap.size()); + if (varyingRows > maxVaryingVectors) { + return false; + } + // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row. // Variables are then allocated to successive rows, aligning them to the 1st column." if (varyingColumns >= 2 && varyingColumns <= 4) diff -Nru firefox-50.0.2+build1/gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp firefox-50.1.0+build2/gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp --- firefox-50.0.2+build1/gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/skia/skia/src/effects/gradients/Sk4fGradientBase.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -127,7 +127,13 @@ const Sk4f c4f0 = SkPM4f::FromPMColor(c0).to4f() * componentScale; const Sk4f c4f1 = SkPM4f::FromPMColor(c1).to4f() * componentScale; - const Sk4f dc4f = (c4f1 - c4f0) / (p1 - p0); + + // Either p0 or p1 can be (-)inf for synthetic clamp edge intervals. + SkASSERT(SkScalarIsFinite(p0) || SkScalarIsFinite(p1)); + const auto dp = p1 - p0; + // Clamp edge intervals are always zero-ramp. + SkASSERT(SkScalarIsFinite(dp) || fZeroRamp); + const Sk4f dc4f = SkScalarIsFinite(dp) ? (c4f1 - c4f0) / dp : 0; c4f0.store(&fC0.fVec); dc4f.store(&fDc.fVec); @@ -218,7 +224,7 @@ // synthetic edge interval: -/+inf .. P0 const SkPMColor clamp_color = pack_color(shader.fOrigColors[first_index], fColorsArePremul); - const SkScalar clamp_pos = reverse ? SK_ScalarMax : SK_ScalarMin; + const SkScalar clamp_pos = reverse ? SK_ScalarInfinity : SK_ScalarNegativeInfinity; fIntervals.emplace_back(clamp_color, clamp_pos, clamp_color, first_pos, componentScale); @@ -245,7 +251,7 @@ // synthetic edge interval: Pn .. +/-inf const SkPMColor clamp_color = pack_color(shader.fOrigColors[last_index], fColorsArePremul); - const SkScalar clamp_pos = reverse ? SK_ScalarMin : SK_ScalarMax; + const SkScalar clamp_pos = reverse ? SK_ScalarNegativeInfinity : SK_ScalarInfinity; fIntervals.emplace_back(clamp_color, last_pos, clamp_color, clamp_pos, componentScale); diff -Nru firefox-50.0.2+build1/gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp firefox-50.1.0+build2/gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp --- firefox-50.0.2+build1/gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/skia/skia/src/effects/gradients/Sk4fLinearGradient.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -318,11 +318,16 @@ private: void compute_interval_props(SkScalar t) { - const Sk4f dC = DstTraits::load(fInterval->fDc); - fCc = DstTraits::load(fInterval->fC0); - fCc = fCc + dC * Sk4f(t); - fDcDx = dC * fDx; fZeroRamp = fIsVertical || fInterval->isZeroRamp(); + fCc = DstTraits::load(fInterval->fC0); + + if (fInterval->isZeroRamp()) { + fDcDx = 0; + } else { + const Sk4f dC = DstTraits::load(fInterval->fDc); + fCc = fCc + dC * Sk4f(t); + fDcDx = dC * fDx; + } } const Interval* next_interval(const Interval* i) const { diff -Nru firefox-50.0.2+build1/gfx/skia/skia/src/gpu/GrResourceProvider.cpp firefox-50.1.0+build2/gfx/skia/skia/src/gpu/GrResourceProvider.cpp --- firefox-50.0.2+build1/gfx/skia/skia/src/gpu/GrResourceProvider.cpp 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/gfx/skia/skia/src/gpu/GrResourceProvider.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -96,8 +96,11 @@ if (kDynamic_GrAccessPattern == accessPattern) { // bin by pow2 with a reasonable min - static const uint32_t MIN_SIZE = 1 << 12; - size = SkTMax(MIN_SIZE, GrNextPow2(SkToUInt(size))); + static const size_t MIN_SIZE = 1 << 12; + size_t allocSize = size > (1u << 31) + ? size_t(SkTMin(uint64_t(SIZE_MAX), uint64_t(GrNextPow2(uint32_t(uint64_t(size) >> 32))) << 32)) + : size_t(GrNextPow2(uint32_t(size))); + allocSize = SkTMax(allocSize, MIN_SIZE); GrScratchKey key; GrBuffer::ComputeScratchKeyForDynamicBuffer(size, intendedType, &key); diff -Nru firefox-50.0.2+build1/gfx/thebes/gfxUserFontSet.cpp firefox-50.1.0+build2/gfx/thebes/gfxUserFontSet.cpp --- firefox-50.0.2+build1/gfx/thebes/gfxUserFontSet.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/gfx/thebes/gfxUserFontSet.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -635,6 +635,16 @@ SanitizeOpenTypeData(aFontData, aLength, saneLen, fontType); if (!saneData) { mFontSet->LogMessage(this, "rejected by sanitizer"); + } else { + // Check whether saneData is a known OpenType format; it might be + // a TrueType Collection, which OTS would accept but we don't yet + // know how to handle. If so, discard. + if (gfxFontUtils::DetermineFontDataType(saneData, saneLen) != + GFX_USERFONT_OPENTYPE) { + mFontSet->LogMessage(this, "not a supported OpenType format"); + free((void*)saneData); + saneData = nullptr; + } } if (saneData) { if (saneLen) { diff -Nru firefox-50.0.2+build1/gfx/vr/ipc/VRManagerChild.cpp firefox-50.1.0+build2/gfx/vr/ipc/VRManagerChild.cpp --- firefox-50.0.2+build1/gfx/vr/ipc/VRManagerChild.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/gfx/vr/ipc/VRManagerChild.cpp 2016-12-09 08:27:46.000000000 +0000 @@ -9,6 +9,7 @@ #include "VRManagerParent.h" #include "VRDeviceProxy.h" #include "VRDeviceProxyOrientationFallBack.h" +#include "nsGlobalWindow.h" #include "mozilla/StaticPtr.h" #include "mozilla/layers/CompositorThread.h" // for CompositorThread #include "mozilla/dom/Navigator.h" @@ -149,7 +150,16 @@ mDevices = devices; - for (auto& nav: mNavigatorCallbacks) { + for (auto& windowId : mNavigatorCallbacks) { + nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(windowId); + if (!window) { + continue; + } + ErrorResult result; + dom::Navigator* nav = window->GetNavigator(result); + if (NS_WARN_IF(result.Failed())) { + continue; + } nav->NotifyVRDevicesUpdated(); } mNavigatorCallbacks.Clear(); @@ -183,11 +193,11 @@ } bool -VRManagerChild::RefreshVRDevicesWithCallback(dom::Navigator* aNavigator) +VRManagerChild::RefreshVRDevicesWithCallback(uint64_t aWindowId) { bool success = SendRefreshDevices(); if (success) { - mNavigatorCallbacks.AppendElement(aNavigator); + mNavigatorCallbacks.AppendElement(aWindowId); } return success; } diff -Nru firefox-50.0.2+build1/gfx/vr/ipc/VRManagerChild.h firefox-50.1.0+build2/gfx/vr/ipc/VRManagerChild.h --- firefox-50.0.2+build1/gfx/vr/ipc/VRManagerChild.h 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/gfx/vr/ipc/VRManagerChild.h 2016-12-09 08:27:46.000000000 +0000 @@ -27,7 +27,7 @@ int GetInputFrameID(); bool GetVRDevices(nsTArray >& aDevices); - bool RefreshVRDevicesWithCallback(dom::Navigator* aNavigator); + bool RefreshVRDevicesWithCallback(uint64_t aWindowId); static void InitSameProcess(); static void InitWithGPUProcess(Endpoint&& aEndpoint); @@ -52,7 +52,7 @@ private: nsTArray > mDevices; - nsTArray mNavigatorCallbacks; + nsTArray mNavigatorCallbacks; int32_t mInputFrameID; }; diff -Nru firefox-50.0.2+build1/gfx/vr/moz.build firefox-50.1.0+build2/gfx/vr/moz.build --- firefox-50.0.2+build1/gfx/vr/moz.build 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/gfx/vr/moz.build 2016-12-09 08:27:46.000000000 +0000 @@ -14,6 +14,7 @@ ] LOCAL_INCLUDES += [ + '/dom/base', '/gfx/thebes', ] diff -Nru firefox-50.0.2+build1/js/public/Id.h firefox-50.1.0+build2/js/public/Id.h --- firefox-50.0.2+build1/js/public/Id.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/js/public/Id.h 2016-12-09 08:27:49.000000000 +0000 @@ -182,18 +182,6 @@ namespace js { template <> -struct DefaultHasher -{ - typedef jsid Lookup; - static HashNumber hash(jsid id) { - return JSID_BITS(id); - } - static bool match(jsid id1, jsid id2) { - return id1 == id2; - } -}; - -template <> struct BarrierMethods { static void postBarrier(jsid* idp, jsid prev, jsid next) {} diff -Nru firefox-50.0.2+build1/js/src/builtin/MapObject.cpp firefox-50.1.0+build2/js/src/builtin/MapObject.cpp --- firefox-50.0.2+build1/js/src/builtin/MapObject.cpp 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/js/src/builtin/MapObject.cpp 2016-12-09 08:27:49.000000000 +0000 @@ -63,13 +63,21 @@ return true; } -HashNumber -HashableValue::hash() const +static HashNumber +HashValue(const Value& v) { // HashableValue::setValue normalizes values so that the SameValue relation // on HashableValues is the same as the == relationship on // value.data.asBits. - return value.asRawBits(); + if (v.isString()) + return v.toString()->asAtom().hash(); + return v.asRawBits(); +} + +HashNumber +HashableValue::hash() const +{ + return HashValue(value); } bool @@ -364,7 +372,7 @@ struct UnbarrieredHashPolicy { typedef Value Lookup; - static HashNumber hash(const Lookup& v) { return v.asRawBits(); } + static HashNumber hash(const Lookup& v) { return HashValue(v); } static bool match(const Value& k, const Lookup& l) { return k == l; } static bool isEmpty(const Value& v) { return v.isMagic(JS_HASH_KEY_EMPTY); } static void makeEmpty(Value* vp) { vp->setMagic(JS_HASH_KEY_EMPTY); } diff -Nru firefox-50.0.2+build1/js/src/builtin/RegExp.cpp firefox-50.1.0+build2/js/src/builtin/RegExp.cpp --- firefox-50.0.2+build1/js/src/builtin/RegExp.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/js/src/builtin/RegExp.cpp 2016-12-09 08:27:49.000000000 +0000 @@ -1613,18 +1613,14 @@ } bool -js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, uint8_t* result) +js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto, uint8_t* result) { JS::AutoCheckCannotGC nogc; - if (!rx->isNative()) { - *result = false; - return true; - } - NativeObject* nobj = static_cast(rx); + RegExpObject* rx = &obj->as(); Shape* shape = cx->compartment()->regExps.getOptimizableRegExpInstanceShape(); - if (shape == nobj->lastProperty()) { + if (shape == rx->lastProperty()) { *result = true; return true; } @@ -1639,12 +1635,12 @@ return true; } - if (!RegExpObject::isInitialShape(nobj)) { + if (!RegExpObject::isInitialShape(rx)) { *result = false; return true; } - cx->compartment()->regExps.setOptimizableRegExpInstanceShape(nobj->lastProperty()); + cx->compartment()->regExps.setOptimizableRegExpInstanceShape(rx->lastProperty()); *result = true; return true; } diff -Nru firefox-50.0.2+build1/js/src/builtin/RegExp.h firefox-50.1.0+build2/js/src/builtin/RegExp.h --- firefox-50.0.2+build1/js/src/builtin/RegExp.h 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/js/src/builtin/RegExp.h 2016-12-09 08:27:49.000000000 +0000 @@ -113,7 +113,7 @@ RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp); extern MOZ_MUST_USE bool -RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, uint8_t* result); +RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto, uint8_t* result); extern MOZ_MUST_USE bool RegExpGetSubstitution(JSContext* cx, HandleLinearString matched, HandleLinearString string, diff -Nru firefox-50.0.2+build1/js/src/builtin/RegExp.js firefox-50.1.0+build2/js/src/builtin/RegExp.js --- firefox-50.0.2+build1/js/src/builtin/RegExp.js 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/js/src/builtin/RegExp.js 2016-12-09 08:27:49.000000000 +0000 @@ -156,6 +156,9 @@ // * exec // * lastIndex function IsRegExpMethodOptimizable(rx) { + if (!IsRegExpObject(rx)) + return false; + var RegExpProto = GetBuiltinPrototype("RegExp"); // If RegExpPrototypeOptimizable and RegExpInstanceOptimizable succeed, // `RegExpProto.exec` is guaranteed to be data properties. diff -Nru firefox-50.0.2+build1/js/src/gc/Allocator.cpp firefox-50.1.0+build2/js/src/gc/Allocator.cpp --- firefox-50.0.2+build1/js/src/gc/Allocator.cpp 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/js/src/gc/Allocator.cpp 2016-12-09 08:27:49.000000000 +0000 @@ -191,11 +191,14 @@ } #if defined(JS_GC_ZEAL) || defined(DEBUG) - MOZ_ASSERT_IF(rt->isAtomsCompartment(cx->compartment()), - kind == AllocKind::STRING || - kind == AllocKind::FAT_INLINE_STRING || + MOZ_ASSERT_IF(cx->compartment()->isAtomsCompartment(), + kind == AllocKind::ATOM || + kind == AllocKind::FAT_INLINE_ATOM || kind == AllocKind::SYMBOL || kind == AllocKind::JITCODE); + MOZ_ASSERT_IF(!cx->compartment()->isAtomsCompartment(), + kind != AllocKind::ATOM && + kind != AllocKind::FAT_INLINE_ATOM); MOZ_ASSERT(!rt->isHeapBusy()); MOZ_ASSERT(isAllocAllowed()); #endif diff -Nru firefox-50.0.2+build1/js/src/gc/Heap.h firefox-50.1.0+build2/js/src/gc/Heap.h --- firefox-50.0.2+build1/js/src/gc/Heap.h 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/js/src/gc/Heap.h 2016-12-09 08:27:49.000000000 +0000 @@ -109,6 +109,8 @@ FAT_INLINE_STRING, STRING, EXTERNAL_STRING, + FAT_INLINE_ATOM, + ATOM, SYMBOL, JITCODE, LIMIT, @@ -145,6 +147,8 @@ D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString) \ D(STRING, String, JSString, JSString) \ D(EXTERNAL_STRING, String, JSExternalString, JSExternalString) \ + D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom) \ + D(ATOM, String, js::NormalAtom, js::NormalAtom) \ D(SYMBOL, Symbol, JS::Symbol, JS::Symbol) \ D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode) diff -Nru firefox-50.0.2+build1/js/src/jit/VMFunctions.cpp firefox-50.1.0+build2/js/src/jit/VMFunctions.cpp --- firefox-50.0.2+build1/js/src/jit/VMFunctions.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jit/VMFunctions.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -1182,14 +1182,18 @@ MOZ_ASSERT(str->length() <= JSString::MAX_LENGTH); gc::AllocKind kind = str->getAllocKind(); - if (str->isFatInline()) - MOZ_ASSERT(kind == gc::AllocKind::FAT_INLINE_STRING); - else if (str->isExternal()) + if (str->isFatInline()) { + MOZ_ASSERT(kind == gc::AllocKind::FAT_INLINE_STRING || + kind == gc::AllocKind::FAT_INLINE_ATOM); + } else if (str->isExternal()) { MOZ_ASSERT(kind == gc::AllocKind::EXTERNAL_STRING); - else if (str->isAtom() || str->isFlat()) + } else if (str->isAtom()) { + MOZ_ASSERT(kind == gc::AllocKind::ATOM); + } else if (str->isFlat()) { MOZ_ASSERT(kind == gc::AllocKind::STRING || kind == gc::AllocKind::FAT_INLINE_STRING); - else + } else { MOZ_ASSERT(kind == gc::AllocKind::STRING); + } #endif } diff -Nru firefox-50.0.2+build1/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js firefox-50.1.0+build2/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js --- firefox-50.0.2+build1/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js 2016-11-30 08:51:08.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js 2016-12-09 08:27:50.000000000 +0000 @@ -44,36 +44,38 @@ // JSExtensibleString - limited by available memory - X // JSUndependedString - same as JSExtensibleString - +// Note that atoms are 8 bytes larger than non-atoms, to store the atom's hash code. + // Latin-1 -assertEq(tByteSize(""), s(16, 24)); // T, T -assertEq(tByteSize("1"), s(16, 24)); // T, T -assertEq(tByteSize("1234567"), s(16, 24)); // T, T -assertEq(tByteSize("12345678"), s(32, 24)); // F, T -assertEq(tByteSize("123456789.12345"), s(32, 24)); // F, T -assertEq(tByteSize("123456789.123456"), s(32, 32)); // F, F -assertEq(tByteSize("123456789.123456789.123"), s(32, 32)); // F, F -assertEq(tByteSize("123456789.123456789.1234"), s(48, 56)); // X, X -assertEq(tByteSize("123456789.123456789.123456789.1"), s(48, 56)); // X, X -assertEq(tByteSize("123456789.123456789.123456789.12"), s(64, 72)); // X, X +assertEq(tByteSize(""), s(24, 32)); // T, T +assertEq(tByteSize("1"), s(24, 32)); // T, T +assertEq(tByteSize("1234567"), s(24, 32)); // T, T +assertEq(tByteSize("12345678"), s(40, 32)); // F, T +assertEq(tByteSize("123456789.12345"), s(40, 32)); // F, T +assertEq(tByteSize("123456789.123456"), s(40, 40)); // F, F +assertEq(tByteSize("123456789.123456789.123"), s(40, 40)); // F, F +assertEq(tByteSize("123456789.123456789.1234"), s(56, 64)); // X, X +assertEq(tByteSize("123456789.123456789.123456789.1"), s(56, 64)); // X, X +assertEq(tByteSize("123456789.123456789.123456789.12"), s(72, 80)); // X, X // Inline char16_t atoms. // "Impassionate gods have never seen the red that is the Tatsuta River." // - Ariwara no Narihira -assertEq(tByteSize("千"), s(16, 24)); // T, T -assertEq(tByteSize("千早"), s(16, 24)); // T, T -assertEq(tByteSize("千早ぶ"), s(16, 24)); // T, T -assertEq(tByteSize("千早ぶる"), s(32, 24)); // F, T -assertEq(tByteSize("千早ぶる神"), s(32, 24)); // F, T -assertEq(tByteSize("千早ぶる神代"), s(32, 24)); // F, T -assertEq(tByteSize("千早ぶる神代も"), s(32, 24)); // F, T -assertEq(tByteSize("千早ぶる神代もき"), s(32, 32)); // F, F -assertEq(tByteSize("千早ぶる神代もきかず龍"), s(32, 32)); // F, F -assertEq(tByteSize("千早ぶる神代もきかず龍田"), s(48, 56)); // X, X -assertEq(tByteSize("千早ぶる神代もきかず龍田川 か"), s(48, 56)); // X, X -assertEq(tByteSize("千早ぶる神代もきかず龍田川 から"), s(64, 72)); // X, X -assertEq(tByteSize("千早ぶる神代もきかず龍田川 からくれなゐに水く"), s(64, 72)); // X, X -assertEq(tByteSize("千早ぶる神代もきかず龍田川 からくれなゐに水くく"), s(80, 88)); // X, X -assertEq(tByteSize("千早ぶる神代もきかず龍田川 からくれなゐに水くくるとは"), s(80, 88)); // X, X +assertEq(tByteSize("千"), s(24, 32)); // T, T +assertEq(tByteSize("千早"), s(24, 32)); // T, T +assertEq(tByteSize("千早ぶ"), s(24, 32)); // T, T +assertEq(tByteSize("千早ぶる"), s(40, 32)); // F, T +assertEq(tByteSize("千早ぶる神"), s(40, 32)); // F, T +assertEq(tByteSize("千早ぶる神代"), s(40, 32)); // F, T +assertEq(tByteSize("千早ぶる神代も"), s(40, 32)); // F, T +assertEq(tByteSize("千早ぶる神代もき"), s(40, 40)); // F, F +assertEq(tByteSize("千早ぶる神代もきかず龍"), s(40, 40)); // F, F +assertEq(tByteSize("千早ぶる神代もきかず龍田"), s(56, 64)); // X, X +assertEq(tByteSize("千早ぶる神代もきかず龍田川 か"), s(56, 64)); // X, X +assertEq(tByteSize("千早ぶる神代もきかず龍田川 から"), s(72, 80)); // X, X +assertEq(tByteSize("千早ぶる神代もきかず龍田川 からくれなゐに水く"), s(72, 80)); // X, X +assertEq(tByteSize("千早ぶる神代もきかず龍田川 からくれなゐに水くく"), s(88, 96)); // X, X +assertEq(tByteSize("千早ぶる神代もきかず龍田川 からくれなゐに水くくるとは"), s(88, 96)); // X, X // A Latin-1 rope. This changes size when flattened. // "In a village of La Mancha, the name of which I have no desire to call to mind" diff -Nru firefox-50.0.2+build1/js/src/jsatom.cpp firefox-50.1.0+build2/js/src/jsatom.cpp --- firefox-50.0.2+build1/js/src/jsatom.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jsatom.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -346,7 +346,8 @@ return nullptr; } - JSAtom* atom = flat->morphAtomizedStringIntoAtom(); + JSAtom* atom = flat->morphAtomizedStringIntoAtom(lookup.hash); + MOZ_ASSERT(atom->hash() == lookup.hash); // We have held the lock since looking up p, and the operations we've done // since then can't GC; therefore the atoms table has not been modified and diff -Nru firefox-50.0.2+build1/js/src/jsatom.h firefox-50.1.0+build2/js/src/jsatom.h --- firefox-50.0.2+build1/js/src/jsatom.h 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jsatom.h 2016-12-09 08:27:44.000000000 +0000 @@ -23,14 +23,6 @@ namespace js { -JS_STATIC_ASSERT(sizeof(HashNumber) == 4); - -static MOZ_ALWAYS_INLINE js::HashNumber -HashId(jsid id) -{ - return mozilla::HashGeneric(JSID_BITS(id)); -} - /* * Return a printable, lossless char[] representation of a string-type atom. * The lifetime of the result matches the lifetime of bytes. diff -Nru firefox-50.0.2+build1/js/src/jsatominlines.h firefox-50.1.0+build2/js/src/jsatominlines.h --- firefox-50.0.2+build1/js/src/jsatominlines.h 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jsatominlines.h 2016-12-09 08:27:44.000000000 +0000 @@ -156,12 +156,13 @@ AtomHasher::Lookup::Lookup(const JSAtom* atom) : isLatin1(atom->hasLatin1Chars()), length(atom->length()), atom(atom) { + hash = atom->hash(); if (isLatin1) { latin1Chars = atom->latin1Chars(nogc); - hash = mozilla::HashString(latin1Chars, length); + MOZ_ASSERT(mozilla::HashString(latin1Chars, length) == hash); } else { twoByteChars = atom->twoByteChars(nogc); - hash = mozilla::HashString(twoByteChars, length); + MOZ_ASSERT(mozilla::HashString(twoByteChars, length) == hash); } } @@ -171,7 +172,7 @@ JSAtom* key = entry.asPtrUnbarriered(); if (lookup.atom) return lookup.atom == key; - if (key->length() != lookup.length) + if (key->length() != lookup.length || key->hash() != lookup.hash) return false; if (key->hasLatin1Chars()) { diff -Nru firefox-50.0.2+build1/js/src/jscompartment.cpp firefox-50.1.0+build2/js/src/jscompartment.cpp --- firefox-50.0.2+build1/js/src/jscompartment.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jscompartment.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -50,6 +50,7 @@ runtime_(zone->runtimeFromMainThread()), principals_(nullptr), isSystem_(false), + isAtomsCompartment_(false), isSelfHosting(false), marked(true), warnedAboutExprClosure(false), diff -Nru firefox-50.0.2+build1/js/src/jscompartment.h firefox-50.1.0+build2/js/src/jscompartment.h --- firefox-50.0.2+build1/js/src/jscompartment.h 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jscompartment.h 2016-12-09 08:27:44.000000000 +0000 @@ -324,6 +324,13 @@ isSystem_ = isSystem; } + bool isAtomsCompartment() const { + return isAtomsCompartment_; + } + void setIsAtomsCompartment() { + isAtomsCompartment_ = true; + } + // Used to approximate non-content code when reporting telemetry. inline bool isProbablySystemOrAddonCode() const { if (creationOptions_.addonIdOrNull()) @@ -334,6 +341,8 @@ private: JSPrincipals* principals_; bool isSystem_; + bool isAtomsCompartment_; + public: bool isSelfHosting; bool marked; diff -Nru firefox-50.0.2+build1/js/src/jsgc.cpp firefox-50.1.0+build2/js/src/jsgc.cpp --- firefox-50.0.2+build1/js/src/jsgc.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jsgc.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -358,6 +358,8 @@ gcstats::PHASE_SWEEP_STRING, { AllocKind::FAT_INLINE_STRING, AllocKind::STRING, + AllocKind::FAT_INLINE_ATOM, + AllocKind::ATOM, AllocKind::SYMBOL } }, @@ -1764,7 +1766,9 @@ AllocKind::BASE_SHAPE, AllocKind::FAT_INLINE_STRING, AllocKind::STRING, - AllocKind::EXTERNAL_STRING + AllocKind::EXTERNAL_STRING, + AllocKind::FAT_INLINE_ATOM, + AllocKind::ATOM }; Arena* diff -Nru firefox-50.0.2+build1/js/src/jsgc.h firefox-50.1.0+build2/js/src/jsgc.h --- firefox-50.0.2+build1/js/src/jsgc.h 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jsgc.h 2016-12-09 08:27:44.000000000 +0000 @@ -105,6 +105,8 @@ false, /* AllocKind::FAT_INLINE_STRING */ false, /* AllocKind::STRING */ false, /* AllocKind::EXTERNAL_STRING */ + false, /* AllocKind::FAT_INLINE_ATOM */ + false, /* AllocKind::ATOM */ false, /* AllocKind::SYMBOL */ false, /* AllocKind::JITCODE */ }; @@ -140,6 +142,8 @@ true, /* AllocKind::FAT_INLINE_STRING */ true, /* AllocKind::STRING */ false, /* AllocKind::EXTERNAL_STRING */ + true, /* AllocKind::FAT_INLINE_ATOM */ + true, /* AllocKind::ATOM */ true, /* AllocKind::SYMBOL */ false, /* AllocKind::JITCODE */ }; diff -Nru firefox-50.0.2+build1/js/src/jsiter.cpp firefox-50.1.0+build2/js/src/jsiter.cpp --- firefox-50.0.2+build1/js/src/jsiter.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/jsiter.cpp 2016-12-09 08:27:44.000000000 +0000 @@ -68,17 +68,7 @@ TraceManuallyBarrieredEdge(trc, &iterObj_, "iterObj"); } -struct IdHashPolicy { - typedef jsid Lookup; - static HashNumber hash(jsid id) { - return JSID_BITS(id); - } - static bool match(jsid id1, jsid id2) { - return id1 == id2; - } -}; - -typedef HashSet IdSet; +typedef HashSet> IdSet; static inline bool NewKeyValuePair(JSContext* cx, jsid id, const Value& val, MutableHandleValue rval) diff -Nru firefox-50.0.2+build1/js/src/proxy/Wrapper.cpp firefox-50.1.0+build2/js/src/proxy/Wrapper.cpp --- firefox-50.0.2+build1/js/src/proxy/Wrapper.cpp 2016-11-30 08:51:01.000000000 +0000 +++ firefox-50.1.0+build2/js/src/proxy/Wrapper.cpp 2016-12-09 08:27:45.000000000 +0000 @@ -329,7 +329,10 @@ Wrapper::wrappedObject(JSObject* wrapper) { MOZ_ASSERT(wrapper->is()); - return wrapper->as().target(); + JSObject* target = wrapper->as().target(); + if (target) + JS::ExposeObjectToActiveJS(target); + return target; } JS_FRIEND_API(JSObject*) diff -Nru firefox-50.0.2+build1/js/src/vm/ObjectGroup.cpp firefox-50.1.0+build2/js/src/vm/ObjectGroup.cpp --- firefox-50.0.2+build1/js/src/vm/ObjectGroup.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/ObjectGroup.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -553,39 +553,33 @@ return nullptr; } - if (proto.isObject()) { - RootedObject obj(cx, proto.toObject()); - - if (associated) { - if (associated->is()) { - if (!TypeNewScript::make(cx->asJSContext(), group, &associated->as())) - return nullptr; - } else { - group->setTypeDescr(&associated->as()); - } + if (associated) { + if (associated->is()) { + if (!TypeNewScript::make(cx->asJSContext(), group, &associated->as())) + return nullptr; + } else { + group->setTypeDescr(&associated->as()); } + } - /* - * Some builtin objects have slotful native properties baked in at - * creation via the Shape::{insert,get}initialShape mechanism. Since - * these properties are never explicitly defined on new objects, update - * the type information for them here. - */ - - const JSAtomState& names = cx->names(); - - if (obj->is()) - AddTypePropertyId(cx, group, nullptr, NameToId(names.lastIndex), TypeSet::Int32Type()); - - if (obj->is()) - AddTypePropertyId(cx, group, nullptr, NameToId(names.length), TypeSet::Int32Type()); - - if (obj->is()) { - AddTypePropertyId(cx, group, nullptr, NameToId(names.fileName), TypeSet::StringType()); - AddTypePropertyId(cx, group, nullptr, NameToId(names.lineNumber), TypeSet::Int32Type()); - AddTypePropertyId(cx, group, nullptr, NameToId(names.columnNumber), TypeSet::Int32Type()); - AddTypePropertyId(cx, group, nullptr, NameToId(names.stack), TypeSet::StringType()); - } + /* + * Some builtin objects have slotful native properties baked in at + * creation via the Shape::{insert,get}initialShape mechanism. Since + * these properties are never explicitly defined on new objects, update + * the type information for them here. + */ + + const JSAtomState& names = cx->names(); + + if (clasp == &RegExpObject::class_) { + AddTypePropertyId(cx, group, nullptr, NameToId(names.lastIndex), TypeSet::Int32Type()); + } else if (clasp == &StringObject::class_) { + AddTypePropertyId(cx, group, nullptr, NameToId(names.length), TypeSet::Int32Type()); + } else if (ErrorObject::isErrorClass((clasp))) { + AddTypePropertyId(cx, group, nullptr, NameToId(names.fileName), TypeSet::StringType()); + AddTypePropertyId(cx, group, nullptr, NameToId(names.lineNumber), TypeSet::Int32Type()); + AddTypePropertyId(cx, group, nullptr, NameToId(names.columnNumber), TypeSet::Int32Type()); + AddTypePropertyId(cx, group, nullptr, NameToId(names.stack), TypeSet::StringType()); } return group; @@ -1119,7 +1113,7 @@ }; static inline HashNumber hash(const Lookup& lookup) { - return (HashNumber) (JSID_BITS(lookup.properties[lookup.nproperties - 1].id) ^ + return (HashNumber) (HashId(lookup.properties[lookup.nproperties - 1].id) ^ lookup.nproperties); } diff -Nru firefox-50.0.2+build1/js/src/vm/RegExpObject.h firefox-50.1.0+build2/js/src/vm/RegExpObject.h --- firefox-50.0.2+build1/js/src/vm/RegExpObject.h 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/RegExpObject.h 2016-12-09 08:27:47.000000000 +0000 @@ -425,8 +425,8 @@ static unsigned lastIndexSlot() { return LAST_INDEX_SLOT; } - static bool isInitialShape(NativeObject* nobj) { - Shape* shape = nobj->lastProperty(); + static bool isInitialShape(RegExpObject* rx) { + Shape* shape = rx->lastProperty(); if (!shape->hasSlot()) return false; if (shape->maybeSlot() != LAST_INDEX_SLOT) diff -Nru firefox-50.0.2+build1/js/src/vm/Runtime.cpp firefox-50.1.0+build2/js/src/vm/Runtime.cpp --- firefox-50.0.2+build1/js/src/vm/Runtime.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/Runtime.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -312,6 +312,7 @@ return false; atomsCompartment->setIsSystem(true); + atomsCompartment->setIsAtomsCompartment(); atomsZone.forget(); this->atomsCompartment_ = atomsCompartment.forget(); diff -Nru firefox-50.0.2+build1/js/src/vm/Shape.h firefox-50.1.0+build2/js/src/vm/Shape.h --- firefox-50.0.2+build1/js/src/vm/Shape.h 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/Shape.h 2016-12-09 08:27:47.000000000 +0000 @@ -29,6 +29,7 @@ #include "js/RootingAPI.h" #include "js/UbiNode.h" #include "vm/ObjectGroup.h" +#include "vm/String.h" #ifdef _MSC_VER #pragma warning(push) @@ -1205,7 +1206,7 @@ /* Accumulate from least to most random so the low bits are most random. */ hash = mozilla::RotateLeft(hash, 4) ^ attrs; hash = mozilla::RotateLeft(hash, 4) ^ slot_; - hash = mozilla::RotateLeft(hash, 4) ^ JSID_BITS(propid); + hash = mozilla::RotateLeft(hash, 4) ^ HashId(propid); hash = mozilla::RotateLeft(hash, 4) ^ uintptr_t(rawGetter); hash = mozilla::RotateLeft(hash, 4) ^ uintptr_t(rawSetter); return hash; diff -Nru firefox-50.0.2+build1/js/src/vm/String.cpp firefox-50.1.0+build2/js/src/vm/String.cpp --- firefox-50.0.2+build1/js/src/vm/String.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/String.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -71,8 +71,12 @@ JS::ubi::Node::Size JS::ubi::Concrete::size(mozilla::MallocSizeOf mallocSizeOf) const { - JSString &str = get(); - size_t size = str.isFatInline() ? sizeof(JSFatInlineString) : sizeof(JSString); + JSString& str = get(); + size_t size; + if (str.isAtom()) + size = str.isFatInline() ? sizeof(js::FatInlineAtom) : sizeof(js::NormalAtom); + else + size = str.isFatInline() ? sizeof(JSFatInlineString) : sizeof(JSString); // We can't use mallocSizeof on things in the nursery. At the moment, // strings are never in the nursery, but that may change. @@ -802,7 +806,8 @@ JSFlatString* s = NewInlineString(cx, Latin1Range(buffer, 1)); if (!s) return false; - unitStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(); + HashNumber hash = mozilla::HashString(buffer, 1); + unitStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash); } for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) { @@ -810,7 +815,8 @@ JSFlatString* s = NewInlineString(cx, Latin1Range(buffer, 2)); if (!s) return false; - length2StaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(); + HashNumber hash = mozilla::HashString(buffer, 2); + length2StaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash); } for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++) { @@ -828,7 +834,8 @@ JSFlatString* s = NewInlineString(cx, Latin1Range(buffer, 3)); if (!s) return false; - intStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(); + HashNumber hash = mozilla::HashString(buffer, 3); + intStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash); } } diff -Nru firefox-50.0.2+build1/js/src/vm/String.h firefox-50.1.0+build2/js/src/vm/String.h --- firefox-50.0.2+build1/js/src/vm/String.h 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/String.h 2016-12-09 08:27:47.000000000 +0000 @@ -123,7 +123,11 @@ * | | * | +-- JSFatInlineString - / header is fat * | - * JSAtom - / string equality === pointer equality + * JSAtom (abstract) - / string equality === pointer equality + * | | + * | +-- js::NormalAtom - JSFlatString + atom hash code + * | | + * | +-- js::FatInlineAtom - JSFatInlineString + atom hash code * | * js::PropertyName - / chars don't contain an index (uint32_t) * @@ -135,10 +139,9 @@ * Atoms can additionally be permanent, i.e. unable to be collected, and can * be combined with other string types to create additional most-derived types * that satisfy the invariants of more than one of the abovementioned - * most-derived types: - * - InlineAtom = JSInlineString + JSAtom (atom with inline chars, abstract) - * - ThinInlineAtom = JSThinInlineString + JSAtom (atom with inline chars) - * - FatInlineAtom = JSFatInlineString + JSAtom (atom with (more) inline chars) + * most-derived types. Furthermore, each atom stores a hash number (based on its + * chars). This hash number is used as key in the atoms table and when the atom + * is used as key in a JS Map/Set. * * Derived string types can be queried from ancestor types via isX() and * retrieved with asX() debug-only-checked casts. @@ -769,14 +772,8 @@ * Once a JSFlatString sub-class has been added to the atom state, this * operation changes the string to the JSAtom type, in place. */ - MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoAtom() { - d.u1.flags |= ATOM_BIT; - return &asAtom(); - } - MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoPermanentAtom() { - d.u1.flags |= PERMANENT_ATOM_MASK; - return &asAtom(); - } + MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoAtom(js::HashNumber hash); + MOZ_ALWAYS_INLINE JSAtom* morphAtomizedStringIntoPermanentAtom(js::HashNumber hash); inline void finalize(js::FreeOp* fop); @@ -988,6 +985,9 @@ d.u1.flags |= PERMANENT_ATOM_MASK; } + inline js::HashNumber hash() const; + inline void initHash(js::HashNumber hash); + #ifdef DEBUG void dump(FILE* fp); void dump(); @@ -999,6 +999,83 @@ namespace js { +class NormalAtom : public JSAtom +{ + protected: // Silence Clang unused-field warning. + HashNumber hash_; + uint32_t padding_; // Ensure the size is a multiple of gc::CellSize. + + public: + HashNumber hash() const { + return hash_; + } + void initHash(HashNumber hash) { + hash_ = hash; + } +}; + +static_assert(sizeof(NormalAtom) == sizeof(JSString) + sizeof(uint64_t), + "NormalAtom must have size of a string + HashNumber, " + "aligned to gc::CellSize"); + +class FatInlineAtom : public JSAtom +{ + protected: // Silence Clang unused-field warning. + char inlineStorage_[sizeof(JSFatInlineString) - sizeof(JSString)]; + HashNumber hash_; + uint32_t padding_; // Ensure the size is a multiple of gc::CellSize. + + public: + HashNumber hash() const { + return hash_; + } + void initHash(HashNumber hash) { + hash_ = hash; + } +}; + +static_assert(sizeof(FatInlineAtom) == sizeof(JSFatInlineString) + sizeof(uint64_t), + "FatInlineAtom must have size of a fat inline string + HashNumber, " + "aligned to gc::CellSize"); + +} // namespace js + +inline js::HashNumber +JSAtom::hash() const +{ + if (isFatInline()) + return static_cast(this)->hash(); + return static_cast(this)->hash(); +} + +inline void +JSAtom::initHash(js::HashNumber hash) +{ + if (isFatInline()) + return static_cast(this)->initHash(hash); + return static_cast(this)->initHash(hash); +} + +MOZ_ALWAYS_INLINE JSAtom* +JSFlatString::morphAtomizedStringIntoAtom(js::HashNumber hash) +{ + d.u1.flags |= ATOM_BIT; + JSAtom* atom = &asAtom(); + atom->initHash(hash); + return atom; +} + +MOZ_ALWAYS_INLINE JSAtom* +JSFlatString::morphAtomizedStringIntoPermanentAtom(js::HashNumber hash) +{ + d.u1.flags |= PERMANENT_ATOM_MASK; + JSAtom* atom = &asAtom(); + atom->initHash(hash); + return atom; +} + +namespace js { + class StaticStrings { private: @@ -1206,6 +1283,28 @@ return NewStringCopyN(cx, s, strlen(s)); } +JS_STATIC_ASSERT(sizeof(HashNumber) == 4); + +static MOZ_ALWAYS_INLINE js::HashNumber +HashId(jsid id) +{ + if (MOZ_LIKELY(JSID_IS_ATOM(id))) + return JSID_TO_ATOM(id)->hash(); + return mozilla::HashGeneric(JSID_BITS(id)); +} + +template <> +struct DefaultHasher +{ + typedef jsid Lookup; + static HashNumber hash(jsid id) { + return HashId(id); + } + static bool match(jsid id1, jsid id2) { + return id1 == id2; + } +}; + } /* namespace js */ // Addon IDs are interned atoms which are never destroyed. This detail is diff -Nru firefox-50.0.2+build1/js/src/vm/String-inl.h firefox-50.1.0+build2/js/src/vm/String-inl.h --- firefox-50.0.2+build1/js/src/vm/String-inl.h 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/js/src/vm/String-inl.h 2016-12-09 08:27:47.000000000 +0000 @@ -13,6 +13,7 @@ #include "mozilla/Range.h" #include "jscntxt.h" +#include "jscompartment.h" #include "gc/Allocator.h" #include "gc/Marking.h" @@ -220,7 +221,11 @@ if (!validateLength(cx, length)) return nullptr; - JSFlatString* str = static_cast(js::Allocate(cx)); + JSFlatString* str; + if (cx->compartment()->isAtomsCompartment()) + str = js::Allocate(cx); + else + str = static_cast(js::Allocate(cx)); if (!str) return nullptr; @@ -247,6 +252,9 @@ MOZ_ALWAYS_INLINE JSThinInlineString* JSThinInlineString::new_(js::ExclusiveContext* cx) { + if (cx->compartment()->isAtomsCompartment()) + return (JSThinInlineString*)(js::Allocate(cx)); + return static_cast(js::Allocate(cx)); } @@ -254,6 +262,9 @@ MOZ_ALWAYS_INLINE JSFatInlineString* JSFatInlineString::new_(js::ExclusiveContext* cx) { + if (cx->compartment()->isAtomsCompartment()) + return (JSFatInlineString*)(js::Allocate(cx)); + return js::Allocate(cx); } @@ -351,6 +362,7 @@ { /* FatInline strings are in a different arena. */ MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_STRING); + MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_ATOM); if (isFlat()) asFlat().finalize(fop); @@ -362,6 +374,7 @@ JSFlatString::finalize(js::FreeOp* fop) { MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_STRING); + MOZ_ASSERT(getAllocKind() != js::gc::AllocKind::FAT_INLINE_ATOM); if (!isInline()) fop->free_(nonInlineCharsRaw()); @@ -381,6 +394,8 @@ { MOZ_ASSERT(JSString::isAtom()); MOZ_ASSERT(JSString::isFlat()); + MOZ_ASSERT(getAllocKind() == js::gc::AllocKind::ATOM || + getAllocKind() == js::gc::AllocKind::FAT_INLINE_ATOM); if (!isInline()) fop->free_(nonInlineCharsRaw()); diff -Nru firefox-50.0.2+build1/l10n/changesets firefox-50.1.0+build2/l10n/changesets --- firefox-50.0.2+build1/l10n/changesets 2016-11-30 09:03:54.000000000 +0000 +++ firefox-50.1.0+build2/l10n/changesets 2016-12-09 08:40:18.000000000 +0000 @@ -1,91 +1,91 @@ ach 730:72c548f97e82 af 966:676daf929ded -an 833:e5d825045ca1 -ar 2230:123fea67f4e0 -as 1068:463b595279e5 -ast 1745:dda44cadd427 -az 839:4d87e836c55b -be 2172:047c164b5b1d -bg 1651:e36f8bcfd846 -bn-BD 1459:1023c93a4fe2 -bn-IN 1311:2b2cbdb42980 -br 1826:f674fce50b82 +an 835:7406fc6fdc58 +ar 2233:c613be7b7494 +as 1070:b72dd4b7a305 +ast 1748:f0f66a7117f9 +az 841:d88d21acbdd4 +be 2175:b72707d30bf0 +bg 1652:da9a9f4ad94d +bn-BD 1460:b8df37338700 +bn-IN 1313:e127be82fc9b +br 1829:e1f1d6194976 bs 863:3425b8fcf1ab -ca 3006:0a69a761fcf2 -cak 553:256e9a302293 -cs 4731:eaebf7e6fa81 -cy 1631:9fe477174313 -da 2745:f7dd57cbdcbc -de 5496:d4f63990331c -dsb 851:b3b798a4e175 -el 1727:83ffe66a2828 -en-GB 2452:6041abb4c88b -en-ZA 873:5e2d46f1be42 -eo 1390:4bcae5df01a7 -es-AR 3103:e92ed9fb8a69 -es-CL 1663:c7254ea14d74 -es-ES 4799:02ae8e6640c2 -es-MX 1563:8ef82e2cf334 -et 2225:a4591b6c10f1 -eu 2098:1cd915cc6f46 -fa 1629:3e126d37ce2a -ff 900:b98f6b5b31ac -fi 2760:7bc66dc34cca -fr 7799:59c1fadd1e56 -fy-NL 3172:4fb65d3b8a0b -ga-IE 2327:f32ab42cfb46 -gd 2159:0df17a47a583 -gl 3482:33b4f4e2eb4e -gn 266:7c57fe8d4c2f -gu-IN 1549:76b4ed27c48f -he 1821:db95c8dd2878 -hi-IN 1448:51531d6591e2 -hr 2217:69f2784ebed7 -hsb 1018:abc7a15315e3 -hu 3064:ae10f12a46c6 -hy-AM 1723:29c8673c03ba -id 2179:697f81afbedf -is 1873:6d448e1f3c83 -it 7253:43c1bf577560 -ja 2913:5e2e217b5355 -ja-JP-mac 2388:4f0460057e33 -kk 1461:f0373dfa1d69 +ca 3009:7dd5009dc783 +cak 555:369033cfd5c6 +cs 4734:265a445f2bdf +cy 1634:64a6aec4a78d +da 2748:f9a32324dfdb +de 5499:65d00240c57c +dsb 854:eb533f5fcde9 +el 1730:2e0349ede0e9 +en-GB 2455:a8ece8304624 +en-ZA 875:dca05b316cae +eo 1392:2fb355572837 +es-AR 3106:e34ca800be77 +es-CL 1665:d3a7dc11410d +es-ES 4802:f56f25ea9035 +es-MX 1565:4386ddfaa4a8 +et 2228:ee2aa0dca879 +eu 2101:0f47e8a15f27 +fa 1631:352b57e48327 +ff 902:9f63ab726685 +fi 2763:1b61ddddb405 +fr 7802:d91d09e9589e +fy-NL 3175:fb5941206a9d +ga-IE 2330:34c71eccf78e +gd 2162:9c16f7543ad4 +gl 3485:7225cee37061 +gn 268:cb488dd12fe5 +gu-IN 1551:ab7edf4d5640 +he 1824:ad4f9154a6ec +hi-IN 1450:27dd37dc8e3c +hr 2220:f4f593c515e0 +hsb 1021:968d2b31c9af +hu 3067:a23a810de9f9 +hy-AM 1726:5df91ff23b17 +id 2182:f18d00685080 +is 1876:92556bd9fa24 +it 7256:57f4f63b62f9 +ja 2916:45a60d6b8655 +ja-JP-mac 2389:de83265732bc +kk 1463:fcea16e131c4 km 982:00277d0045d3 -kn 1449:02172da07e92 -ko 2472:aa41fd9e790e +kn 1451:65fc5ee91377 +ko 2475:a9981b90295c lij 992:6a94ea30eef6 -lt 3582:79fdc2902e5a -lv 1710:3fd9278458e6 -mai 1159:75cc0a2f33ad +lt 3585:6ccb2e579bfd +lv 1712:0fb141dfc6c8 +mai 1161:e2b5034a6d9e mk 847:0f98fd626df2 -ml 1328:21a44d0f6f7a -mr 1466:90a0c0fd7aaf -ms 945:c32ae2d06e30 -nb-NO 3220:828b32e0bde5 -nl 6109:5adbe6d0853b -nn-NO 1968:34443e0e449d -or 1153:9e20f3f9b4b1 -pa-IN 2263:b447eaf0b96b -pl 9287:8bb0e08b2f80 -pt-BR 2877:3595a49ce288 -pt-PT 5686:c5a7b7e87fe9 -rm 1787:389c3307725b -ro 2505:845033cc08f4 -ru 4701:d0213f5db4a0 -si 1545:8a2f079e0b3c -sk 4470:078ed9415ec9 -sl 2962:670c32f5a433 -son 1193:e7789d73ce32 -sq 2375:c7f92d999144 -sr 1613:614cbf875285 -sv-SE 5303:9b50a51b4e6c -ta 1230:4196ccbccc96 -te 1294:4932f72ac2dd -th 1751:510bb901e9e6 -tr 2793:a76bb110a253 -uk 3655:d91da766fb7f -uz 774:bf2d3a9b5401 -vi 1233:a0c5754da707 -xh 993:01776b460dd7 -zh-CN 2974:3d4aa11e66b6 -zh-TW 3123:16271b4e6b6e +ml 1330:e13287eda129 +mr 1468:25e4a93d07eb +ms 947:b74c5f0322fd +nb-NO 3223:5894b32e79a6 +nl 6112:bcdfd5b486fd +nn-NO 1971:8a0da41fb201 +or 1155:89a3846c0b3c +pa-IN 2266:4261e12dad64 +pl 9293:3cada1a3feb9 +pt-BR 2880:1a3e26127441 +pt-PT 5689:4be058ed887c +rm 1790:dfe70a5e304d +ro 2508:d18454fc4cae +ru 4704:323ab3a71098 +si 1546:9665fbaa4c69 +sk 4473:941f6eb9b286 +sl 2965:670d95eccc35 +son 1195:5207fd38961a +sq 2378:3165434dc77c +sr 1616:1ea28c2b6187 +sv-SE 5306:7eb57a836b89 +ta 1232:ff95ca25b765 +te 1296:21d675058c87 +th 1753:186494dd70cc +tr 2796:95f563ea206c +uk 3658:74507dd03f8c +uz 776:9c06a8d1b402 +vi 1234:7c712e2f9db2 +xh 995:41f521ddc69c +zh-CN 2977:c7d9bc361e9c +zh-TW 3126:00ad8b4d6425 diff -Nru firefox-50.0.2+build1/layout/base/nsCSSRendering.cpp firefox-50.1.0+build2/layout/base/nsCSSRendering.cpp --- firefox-50.0.2+build1/layout/base/nsCSSRendering.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/layout/base/nsCSSRendering.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -2744,16 +2744,21 @@ } // Fit the gradient line exactly into the source rect. + // aSrc is relative to aIntrinsincSize. + // srcRectDev will be relative to srcSize, so in the same coordinate space + // as lineStart / lineEnd. + gfxRect srcRectDev = nsLayoutUtils::RectToGfxRect( + CSSPixel::ToAppUnits(aSrc), appUnitsPerDevPixel); if (lineStart.x != lineEnd.x) { - rectLen = aPresContext->CSSPixelsToDevPixels(aSrc.width); - offset = ((double)aSrc.x - lineStart.x) / lineLength; - lineStart.x = aSrc.x; - lineEnd.x = aSrc.x + rectLen; + rectLen = srcRectDev.width; + offset = (srcRectDev.x - lineStart.x) / lineLength; + lineStart.x = srcRectDev.x; + lineEnd.x = srcRectDev.XMost(); } else { - rectLen = aPresContext->CSSPixelsToDevPixels(aSrc.height); - offset = ((double)aSrc.y - lineStart.y) / lineLength; - lineStart.y = aSrc.y; - lineEnd.y = aSrc.y + rectLen; + rectLen = srcRectDev.height; + offset = (srcRectDev.y - lineStart.y) / lineLength; + lineStart.y = srcRectDev.y; + lineEnd.y = srcRectDev.YMost(); } // Adjust gradient stop positions for the new gradient line. @@ -5759,8 +5764,7 @@ nsSize repeatSize; nsRect fillRect(aFill); nsRect tile = ComputeTile(fillRect, aHFill, aVFill, aUnitSize, repeatSize); - CSSIntSize imageSize(nsPresContext::AppUnitsToIntCSSPixels(srcRect.width), - nsPresContext::AppUnitsToIntCSSPixels(srcRect.height)); + CSSIntSize imageSize(srcRect.width, srcRect.height); return nsLayoutUtils::DrawBackgroundImage(*aRenderingContext.ThebesContext(), aPresContext, subImage, imageSize, samplingFilter, diff -Nru firefox-50.0.2+build1/layout/base/Units.h firefox-50.1.0+build2/layout/base/Units.h --- firefox-50.0.2+build1/layout/base/Units.h 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/layout/base/Units.h 2016-12-09 08:27:47.000000000 +0000 @@ -264,6 +264,13 @@ NSToCoordRoundWithClamp(aRect.width * float(AppUnitsPerCSSPixel())), NSToCoordRoundWithClamp(aRect.height * float(AppUnitsPerCSSPixel()))); } + + static nsRect ToAppUnits(const CSSIntRect& aRect) { + return nsRect(NSToCoordRoundWithClamp(float(aRect.x) * float(AppUnitsPerCSSPixel())), + NSToCoordRoundWithClamp(float(aRect.y) * float(AppUnitsPerCSSPixel())), + NSToCoordRoundWithClamp(float(aRect.width) * float(AppUnitsPerCSSPixel())), + NSToCoordRoundWithClamp(float(aRect.height) * float(AppUnitsPerCSSPixel()))); + } }; /* diff -Nru firefox-50.0.2+build1/layout/reftests/bugs/1315113-1.html firefox-50.1.0+build2/layout/reftests/bugs/1315113-1.html --- firefox-50.0.2+build1/layout/reftests/bugs/1315113-1.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/layout/reftests/bugs/1315113-1.html 2016-12-09 08:27:48.000000000 +0000 @@ -0,0 +1,23 @@ + + + +Test for bug 1315113: Gradient in border image + + +
    diff -Nru firefox-50.0.2+build1/layout/reftests/bugs/1315113-1-ref.html firefox-50.1.0+build2/layout/reftests/bugs/1315113-1-ref.html --- firefox-50.0.2+build1/layout/reftests/bugs/1315113-1-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/layout/reftests/bugs/1315113-1-ref.html 2016-12-09 08:27:48.000000000 +0000 @@ -0,0 +1,21 @@ + + + +Reference for test for bug 1315113: Gradient in border image + + +
    diff -Nru firefox-50.0.2+build1/layout/reftests/bugs/1315113-2.html firefox-50.1.0+build2/layout/reftests/bugs/1315113-2.html --- firefox-50.0.2+build1/layout/reftests/bugs/1315113-2.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/layout/reftests/bugs/1315113-2.html 2016-12-09 08:27:48.000000000 +0000 @@ -0,0 +1,23 @@ + + + +Test for bug 1315113: Gradient in border image + + +
    diff -Nru firefox-50.0.2+build1/layout/reftests/bugs/1315113-2-ref.html firefox-50.1.0+build2/layout/reftests/bugs/1315113-2-ref.html --- firefox-50.0.2+build1/layout/reftests/bugs/1315113-2-ref.html 1970-01-01 00:00:00.000000000 +0000 +++ firefox-50.1.0+build2/layout/reftests/bugs/1315113-2-ref.html 2016-12-09 08:27:48.000000000 +0000 @@ -0,0 +1,21 @@ + + + +Reference for test for bug 1315113: Gradient in border image + + +
    diff -Nru firefox-50.0.2+build1/layout/reftests/bugs/reftest.list firefox-50.1.0+build2/layout/reftests/bugs/reftest.list --- firefox-50.0.2+build1/layout/reftests/bugs/reftest.list 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/layout/reftests/bugs/reftest.list 2016-12-09 08:27:49.000000000 +0000 @@ -1968,3 +1968,6 @@ # should be same. |fuzzy()| here allows the difference in border, but not # background color. fuzzy(255,1000) skip-if(!cocoaWidget) == 1294102-1.html 1294102-1-ref.html +fuzzy(2,320000) == 1315113-1.html 1315113-1-ref.html +fuzzy(2,20000) == 1315113-2.html 1315113-2-ref.html + diff -Nru firefox-50.0.2+build1/layout/style/nsRuleNode.cpp firefox-50.1.0+build2/layout/style/nsRuleNode.cpp --- firefox-50.0.2+build1/layout/style/nsRuleNode.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/layout/style/nsRuleNode.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -393,6 +393,11 @@ return viewportSize; } +// If |aStyleFont| is nullptr, aStyleContext->StyleFont() is used. +// +// In case that |aValue| is rem unit, if |aStyleContext| is null, callers must +// specify a valid |aStyleFont| and |aUseProvidedRootEmSize| must be true so +// that we can get the length from |aStyleFont|. static nscoord CalcLengthWith(const nsCSSValue& aValue, nscoord aFontSize, const nsStyleFont* aStyleFont, @@ -409,8 +414,8 @@ "not a length or calc unit"); NS_ASSERTION(aStyleFont || aStyleContext, "Must have style data"); - NS_ASSERTION(!aStyleFont || !aStyleContext, - "Duplicate sources of data"); + NS_ASSERTION(aStyleContext || aUseProvidedRootEmSize, + "Must have style context or specify aUseProvidedRootEmSize"); NS_ASSERTION(aPresContext, "Must have prescontext"); if (aValue.IsFixedLengthUnit()) { @@ -505,21 +510,13 @@ } else { // This is not the root element or we are calculating something other // than font size, so rem is relative to the root element's font size. - RefPtr rootStyle; - const nsStyleFont *rootStyleFont = styleFont; - Element* docElement = aPresContext->Document()->GetRootElement(); - - if (docElement) { - nsIFrame* rootFrame = docElement->GetPrimaryFrame(); - if (rootFrame) { - rootStyle = rootFrame->StyleContext(); - } else { - rootStyle = aPresContext->StyleSet()->ResolveStyleFor(docElement, - nullptr); - } - rootStyleFont = rootStyle->StyleFont(); + // Find the root style context by walking up the style context tree. + nsStyleContext* rootStyle = aStyleContext; + while (rootStyle->GetParent()) { + rootStyle = rootStyle->GetParent(); } + const nsStyleFont *rootStyleFont = rootStyle->StyleFont(); rootFontSize = rootStyleFont->mFont.size; } @@ -3199,15 +3196,19 @@ const nscoord mParentSize; const nsStyleFont* const mParentFont; nsPresContext* const mPresContext; + nsStyleContext* const mStyleContext; const bool mAtRoot; RuleNodeCacheConditions& mConditions; SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont, - nsPresContext* aPresContext, bool aAtRoot, + nsPresContext* aPresContext, + nsStyleContext* aStyleContext, + bool aAtRoot, RuleNodeCacheConditions& aConditions) : mParentSize(aParentSize), mParentFont(aParentFont), mPresContext(aPresContext), + mStyleContext(aStyleContext), mAtRoot(aAtRoot), mConditions(aConditions) { @@ -3222,7 +3223,7 @@ // between us and the parent is simply ignored. size = CalcLengthWith(aValue, mParentSize, mParentFont, - nullptr, mPresContext, mAtRoot, + mStyleContext, mPresContext, mAtRoot, true, mConditions); if (!aValue.IsRelativeLengthUnit() && mParentFont->mAllowZoom) { size = nsStyleFont::ZoomText(mPresContext, size); @@ -3246,6 +3247,7 @@ /* static */ void nsRuleNode::SetFontSize(nsPresContext* aPresContext, + nsStyleContext* aContext, const nsRuleData* aRuleData, const nsStyleFont* aFont, const nsStyleFont* aParentFont, @@ -3312,7 +3314,8 @@ sizeValue->GetUnit() == eCSSUnit_Percent || sizeValue->IsCalcUnit()) { SetFontSizeCalcOps ops(aParentSize, aParentFont, - aPresContext, aAtRoot, + aPresContext, aContext, + aAtRoot, aConditions); *aSize = css::ComputeCalc(*sizeValue, ops); if (*aSize < 0) { @@ -3658,7 +3661,7 @@ aFont->mScriptMinSize = CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize, aParentFont, - nullptr, aPresContext, atRoot, true, + aContext, aPresContext, atRoot, true /* aUseUserFontSet */, aConditions); } @@ -3900,7 +3903,8 @@ scriptLevelAdjustedParentSize != scriptLevelAdjustedUnconstrainedParentSize; - SetFontSize(aPresContext, aRuleData, aFont, aParentFont, + SetFontSize(aPresContext, aContext, + aRuleData, aFont, aParentFont, &aFont->mSize, systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize, aUsedStartStruct, atRoot, aConditions); @@ -3930,7 +3934,8 @@ // already called SetUncacheable. RuleNodeCacheConditions unconstrainedConditions; - SetFontSize(aPresContext, aRuleData, aFont, aParentFont, + SetFontSize(aPresContext, aContext, + aRuleData, aFont, aParentFont, &aFont->mScriptUnconstrainedSize, systemFont, aParentFont->mScriptUnconstrainedSize, scriptLevelAdjustedUnconstrainedParentSize, diff -Nru firefox-50.0.2+build1/layout/style/nsRuleNode.h firefox-50.1.0+build2/layout/style/nsRuleNode.h --- firefox-50.0.2+build1/layout/style/nsRuleNode.h 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/layout/style/nsRuleNode.h 2016-12-09 08:27:47.000000000 +0000 @@ -755,6 +755,7 @@ // helpers for |ComputeFontData| that need access to |mNoneBits|: static void SetFontSize(nsPresContext* aPresContext, + nsStyleContext* aContext, const nsRuleData* aRuleData, const nsStyleFont* aFont, const nsStyleFont* aParentFont, diff -Nru firefox-50.0.2+build1/layout/style/xbl-marquee/xbl-marquee.xml firefox-50.1.0+build2/layout/style/xbl-marquee/xbl-marquee.xml --- firefox-50.0.2+build1/layout/style/xbl-marquee/xbl-marquee.xml 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/layout/style/xbl-marquee/xbl-marquee.xml 2016-12-09 08:27:47.000000000 +0000 @@ -285,6 +285,12 @@ return true; } + // attribute event handlers should only be added if the + // document's CSP allows it. + if (!document.inlineScriptAllowedByCSP) { + return true; + } + if (this._ignoreNextCall) { return this._ignoreNextCall = false; } diff -Nru firefox-50.0.2+build1/mobile/android/installer/package-manifest.in firefox-50.1.0+build2/mobile/android/installer/package-manifest.in --- firefox-50.0.2+build1/mobile/android/installer/package-manifest.in 2016-11-30 08:51:03.000000000 +0000 +++ firefox-50.1.0+build2/mobile/android/installer/package-manifest.in 2016-12-09 08:27:46.000000000 +0000 @@ -304,6 +304,8 @@ @BINPATH@/components/TooltipTextProvider.manifest @BINPATH@/components/NetworkGeolocationProvider.manifest @BINPATH@/components/NetworkGeolocationProvider.js +@BINPATH@/components/EditorUtils.manifest +@BINPATH@/components/EditorUtils.js @BINPATH@/components/extensions.manifest @BINPATH@/components/utils.manifest @BINPATH@/components/simpleServices.js diff -Nru firefox-50.0.2+build1/netwerk/base/ArrayBufferInputStream.cpp firefox-50.1.0+build2/netwerk/base/ArrayBufferInputStream.cpp --- firefox-50.0.2+build1/netwerk/base/ArrayBufferInputStream.cpp 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/base/ArrayBufferInputStream.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -13,7 +13,6 @@ ArrayBufferInputStream::ArrayBufferInputStream() : mBufferLength(0) -, mOffset(0) , mPos(0) , mClosed(false) { @@ -33,11 +32,16 @@ return NS_ERROR_FAILURE; } - mArrayBuffer.emplace(aCx, arrayBuffer); - uint32_t buflen = JS_GetArrayBufferByteLength(arrayBuffer); - mOffset = std::min(buflen, aByteOffset); - mBufferLength = std::min(buflen - mOffset, aLength); + uint32_t offset = std::min(buflen, aByteOffset); + mBufferLength = std::min(buflen - offset, aLength); + + mArrayBuffer = mozilla::MakeUnique(mBufferLength); + + JS::AutoCheckCannotGC nogc; + bool isShared; + char* src = (char*) JS_GetArrayBufferData(arrayBuffer, &isShared, nogc) + offset; + memcpy(&mArrayBuffer[0], src, mBufferLength); return NS_OK; } @@ -55,8 +59,7 @@ return NS_BASE_STREAM_CLOSED; } if (mArrayBuffer) { - uint32_t buflen = JS_GetArrayBufferByteLength(mArrayBuffer->get()); - *aCount = buflen ? buflen - mPos : 0; + *aCount = mBufferLength ? mBufferLength - mPos : 0; } else { *aCount = 0; } @@ -86,34 +89,14 @@ while (mPos < mBufferLength) { uint32_t remaining = mBufferLength - mPos; MOZ_ASSERT(mArrayBuffer); - uint32_t byteLength = JS_GetArrayBufferByteLength(mArrayBuffer->get()); - if (byteLength == 0) { - mClosed = true; - return NS_BASE_STREAM_CLOSED; - } - // If you change the size of this buffer, please also remember to - // update test_arraybufferinputstream.html. - char buffer[8192]; - uint32_t count = std::min(std::min(aCount, remaining), uint32_t(mozilla::ArrayLength(buffer))); + uint32_t count = std::min(aCount, remaining); if (count == 0) { break; } - // It is just barely possible that writer() will detach the ArrayBuffer's - // data, setting its length to zero. Or move the data to a different memory - // area. (This would only happen in a subclass that passed something other - // than NS_CopySegmentToBuffer as 'writer'). So copy the data out into a - // holding area before passing it to writer(). - { - JS::AutoCheckCannotGC nogc; - bool isShared; - char* src = (char*) JS_GetArrayBufferData(mArrayBuffer->get(), &isShared, nogc) + mOffset + mPos; - MOZ_ASSERT(!isShared); // Because ArrayBuffer - memcpy(buffer, src, count); - } uint32_t written; - nsresult rv = writer(this, closure, buffer, *result, count, &written); + nsresult rv = writer(this, closure, &mArrayBuffer[0] + mPos, *result, count, &written); if (NS_FAILED(rv)) { // InputStreams do not propagate errors to caller. return NS_OK; diff -Nru firefox-50.0.2+build1/netwerk/base/ArrayBufferInputStream.h firefox-50.1.0+build2/netwerk/base/ArrayBufferInputStream.h --- firefox-50.0.2+build1/netwerk/base/ArrayBufferInputStream.h 2016-11-30 08:51:04.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/base/ArrayBufferInputStream.h 2016-12-09 08:27:47.000000000 +0000 @@ -9,6 +9,7 @@ #include "nsIArrayBufferInputStream.h" #include "js/Value.h" #include "mozilla/Maybe.h" +#include "mozilla/UniquePtr.h" #define NS_ARRAYBUFFERINPUTSTREAM_CONTRACTID "@mozilla.org/io/arraybuffer-input-stream;1" #define NS_ARRAYBUFFERINPUTSTREAM_CID \ @@ -28,10 +29,9 @@ private: virtual ~ArrayBufferInputStream() {} - mozilla::Maybe > mArrayBuffer; - uint32_t mBufferLength; // length of slice - uint32_t mOffset; // permanent offset from start of actual buffer - uint32_t mPos; // offset from start of slice + mozilla::UniquePtr mArrayBuffer; + uint32_t mBufferLength; + uint32_t mPos; bool mClosed; }; diff -Nru firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelChild.cpp firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelChild.cpp --- firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelChild.cpp 2016-11-30 08:51:05.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelChild.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -204,10 +204,10 @@ // to, so we fall through. if (mKeptAlive && mRefCnt == 1 && mIPCOpen) { mKeptAlive = false; - // Send_delete calls NeckoChild::DeallocPHttpChannel, which will release - // again to refcount==0 - PHttpChannelChild::Send__delete__(this); - return 0; + // We send a message to the parent, which calls SendDelete, and then the + // child calling Send__delete__() to finally drop the refcount to 0. + SendDeletingChannel(); + return 1; } if (mRefCnt == 0) { @@ -920,9 +920,9 @@ mKeptAlive = true; SendDocumentChannelCleanup(); } else { - // This calls NeckoChild::DeallocPHttpChannelChild(), which deletes |this| if IPDL - // holds the last reference. Don't rely on |this| existing after here. - PHttpChannelChild::Send__delete__(this); + // The parent process will respond by sending a DeleteSelf message and + // making sure not to send any more messages after that. + SendDeletingChannel(); } } @@ -1108,12 +1108,8 @@ HandleAsyncAbort(); if (mIPCOpen) { - PHttpChannelChild::Send__delete__(this); + SendDeletingChannel(); } - // WARNING: DO NOT RELY ON |THIS| EXISTING ANY MORE! - // - // NeckoChild::DeallocPHttpChannelChild() may have been called, which deletes - // |this| if IPDL holds the last reference. } void @@ -1144,12 +1140,96 @@ return true; } +bool +HttpChannelChild::RecvFinishInterceptedRedirect() +{ + // Hold a ref to this to keep it from being deleted by Send__delete__() + RefPtr self(this); + Send__delete__(this); + + // The IPDL connection was torn down by a interception logic in + // CompleteRedirectSetup, and we need to call FinishInterceptedRedirect. + NS_DispatchToMainThread(NewRunnableMethod(this, &HttpChannelChild::FinishInterceptedRedirect)); + + return true; +} + void HttpChannelChild::DeleteSelf() { + // Hold a ref to this to keep it from being deleted by Send__delete__() + RefPtr self(this); Send__delete__(this); } +class OverrideRunnable : public Runnable { +public: + RefPtr mChannel; + RefPtr mNewChannel; + RefPtr mListener; + nsCOMPtr mInput; + nsAutoPtr mHead; + + OverrideRunnable(HttpChannelChild* aChannel, + HttpChannelChild* aNewChannel, + InterceptStreamListener* aListener, + nsIInputStream* aInput, + nsAutoPtr& aHead) + : mChannel(aChannel) + , mNewChannel(aNewChannel) + , mListener(aListener) + , mInput(aInput) + , mHead(aHead) + { + } + + NS_IMETHOD Run() override { + bool ret = mChannel->Redirect3Complete(this); + + // If the method returns false, it means the IPDL connection is being + // asyncly torn down and reopened, and OverrideWithSynthesizedResponse + // will be called later from FinishInterceptedRedirect. This object will + // be assigned to HttpChannelChild::mOverrideRunnable in order to do so. + // If it is true, we can call the method right now. + if (ret) { + OverrideWithSynthesizedResponse(); + } + + return NS_OK; + } + + void OverrideWithSynthesizedResponse() { + if (mNewChannel) { + mNewChannel->OverrideWithSynthesizedResponse(mHead, mInput, mListener); + } + } +}; + +void HttpChannelChild::FinishInterceptedRedirect() +{ + nsresult rv; + if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) { + MOZ_ASSERT(!mInterceptedRedirectContext, "the context should be null!"); + rv = AsyncOpen2(mInterceptedRedirectListener); + } else { + rv = AsyncOpen(mInterceptedRedirectListener, mInterceptedRedirectContext); + } + mInterceptedRedirectListener = nullptr; + mInterceptedRedirectContext = nullptr; + + if (mInterceptingChannel) { + mInterceptingChannel->CleanupRedirectingChannel(rv); + mInterceptingChannel = nullptr; + } + + if (mOverrideRunnable) { + RefPtr override = + static_cast(mOverrideRunnable.get()); + override->OverrideWithSynthesizedResponse(); + mOverrideRunnable = nullptr; + } +} + bool HttpChannelChild::RecvReportSecurityMessage(const nsString& messageTag, const nsString& messageCategory) @@ -1351,7 +1431,7 @@ { public: explicit Redirect3Event(HttpChannelChild* child) : mChild(child) {} - void Run() { mChild->Redirect3Complete(); } + void Run() { mChild->Redirect3Complete(nullptr); } private: HttpChannelChild* mChild; }; @@ -1427,17 +1507,45 @@ return true; } -void -HttpChannelChild::Redirect3Complete() +// Returns true if has actually completed the redirect and cleaned up the +// channel, or false the interception logic kicked in and we need to asyncly +// call FinishInterceptedRedirect and CleanupRedirectingChannel. +// The argument is an optional OverrideRunnable that we pass to the redirected +// channel. +bool +HttpChannelChild::Redirect3Complete(OverrideRunnable* aRunnable) { LOG(("HttpChannelChild::Redirect3Complete [this=%p]\n", this)); nsresult rv = NS_OK; + nsCOMPtr chan = do_QueryInterface(mRedirectChannelChild); + RefPtr httpChannelChild = static_cast(chan.get()); // Chrome channel has been AsyncOpen'd. Reflect this in child. - if (mRedirectChannelChild) + if (mRedirectChannelChild) { + if (httpChannelChild) { + httpChannelChild->mOverrideRunnable = aRunnable; + httpChannelChild->mInterceptingChannel = this; + } rv = mRedirectChannelChild->CompleteRedirectSetup(mListener, mListenerContext); + } + + if (!httpChannelChild || !httpChannelChild->mShouldParentIntercept) { + // The redirect channel either isn't a HttpChannelChild, or the interception + // logic wasn't triggered, so we can clean it up right here. + CleanupRedirectingChannel(rv); + if (httpChannelChild) { + httpChannelChild->mOverrideRunnable = nullptr; + httpChannelChild->mInterceptingChannel = nullptr; + } + return true; + } + return false; +} +void +HttpChannelChild::CleanupRedirectingChannel(nsresult rv) +{ // Redirecting to new channel: shut this down and init new channel if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, NS_BINDING_ABORTED); @@ -1515,12 +1623,26 @@ // AsyncOpen but was intercepted and suspended. We must tear it down and start // fresh - we will intercept the child channel this time, before creating a new // parent channel unnecessarily. - PHttpChannelChild::Send__delete__(this); - if (mLoadInfo && mLoadInfo->GetEnforceSecurity()) { - MOZ_ASSERT(!aContext, "aContext should be null!"); - return AsyncOpen2(listener); - } - return AsyncOpen(listener, aContext); + + // Since this method is called from RecvRedirect3Complete which itself is + // called from either OnRedirectVerifyCallback via OverrideRunnable, or from + // RecvRedirect3Complete. The order of events must always be: + // 1. Teardown the IPDL connection + // 2. AsyncOpen the connection again + // 3. Cleanup the redirecting channel (the one calling Redirect3Complete) + // 4. [optional] Call OverrideWithSynthesizedResponse on the redirected + // channel if the call came from OverrideRunnable. + mInterceptedRedirectListener = listener; + mInterceptedRedirectContext = aContext; + + // This will send a message to the parent notifying it that we are closing + // down. After closing the IPC channel, we will proceed to execute + // FinishInterceptedRedirect() which AsyncOpen's the channel again. + SendFinishInterceptedRedirect(); + + // XXX valentin: The interception logic should be rewritten to avoid + // calling AsyncOpen on the channel _after_ we call Send__delete__() + return NS_OK; } /* @@ -1549,34 +1671,6 @@ // HttpChannelChild::nsIAsyncVerifyRedirectCallback //----------------------------------------------------------------------------- -class OverrideRunnable : public Runnable { - RefPtr mChannel; - RefPtr mNewChannel; - RefPtr mListener; - nsCOMPtr mInput; - nsAutoPtr mHead; - -public: - OverrideRunnable(HttpChannelChild* aChannel, - HttpChannelChild* aNewChannel, - InterceptStreamListener* aListener, - nsIInputStream* aInput, - nsAutoPtr& aHead) - : mChannel(aChannel) - , mNewChannel(aNewChannel) - , mListener(aListener) - , mInput(aInput) - , mHead(aHead) - { - } - - NS_IMETHOD Run() { - mChannel->Redirect3Complete(); - mNewChannel->OverrideWithSynthesizedResponse(mHead, mInput, mListener); - return NS_OK; - } -}; - NS_IMETHODIMP HttpChannelChild::OnRedirectVerifyCallback(nsresult result) { @@ -1603,9 +1697,10 @@ if (mRedirectingForSubsequentSynthesizedResponse) { nsCOMPtr httpChannelChild = do_QueryInterface(mRedirectChannelChild); - MOZ_ASSERT(httpChannelChild); RefPtr redirectedChannel = static_cast(httpChannelChild.get()); + // redirectChannel will be NULL if mRedirectChannelChild isn't a + // nsIHttpChannelChild (it could be a DataChannelChild). RefPtr streamListener = new InterceptStreamListener(redirectedChannel, mListenerContext); diff -Nru firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelChild.h firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelChild.h --- firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelChild.h 2016-11-30 08:51:05.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelChild.h 2016-12-09 08:27:48.000000000 +0000 @@ -145,6 +145,7 @@ bool RecvFlushedForDiversion() override; bool RecvDivertMessages() override; bool RecvDeleteSelf() override; + bool RecvFinishInterceptedRedirect() override; bool RecvReportSecurityMessage(const nsString& messageTag, const nsString& messageCategory) override; @@ -245,6 +246,17 @@ // is synthesized. bool mSuspendParentAfterSynthesizeResponse; + // Needed to call AsyncOpen in FinishInterceptedRedirect + nsCOMPtr mInterceptedRedirectListener; + nsCOMPtr mInterceptedRedirectContext; + // Needed to call CleanupRedirectingChannel in FinishInterceptedRedirect + RefPtr mInterceptingChannel; + // Used to call OverrideWithSynthesizedResponse in FinishInterceptedRedirect + RefPtr mOverrideRunnable; + + void FinishInterceptedRedirect(); + void CleanupRedirectingChannel(nsresult rv); + // true after successful AsyncOpen until OnStopRequest completes. bool RemoteChannelExists() { return mIPCOpen && !mKeptAlive; } @@ -284,7 +296,7 @@ const nsHttpResponseHead& responseHead, const nsACString& securityInfoSerialization, const nsACString& channelId); - void Redirect3Complete(); + bool Redirect3Complete(OverrideRunnable* aRunnable); void DeleteSelf(); // Create a a new channel to be used in a redirection, based on the provided diff -Nru firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelParent.cpp firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelParent.cpp --- firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelParent.cpp 2016-11-30 08:51:05.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelParent.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -1296,11 +1296,14 @@ } nsHttpResponseHead *responseHead = mChannel->GetResponseHead(); - bool result = SendRedirect1Begin(registrarId, uriParams, redirectFlags, - responseHead ? *responseHead - : nsHttpResponseHead(), - secInfoSerialization, - channelId); + bool result = false; + if (!mIPCClosed) { + result = SendRedirect1Begin(registrarId, uriParams, redirectFlags, + responseHead ? *responseHead + : nsHttpResponseHead(), + secInfoSerialization, + channelId); + } if (!result) { // Bug 621446 investigation mSentRedirect1BeginFailed = true; @@ -1653,6 +1656,24 @@ return rv; } +bool +HttpChannelParent::RecvDeletingChannel() +{ + // We need to ensure that the parent channel will not be sending any more IPC + // messages after this, as the child is going away. DoSendDeleteSelf will + // set mIPCClosed = true; + return DoSendDeleteSelf(); +} + +bool +HttpChannelParent::RecvFinishInterceptedRedirect() +{ + // We make sure not to send any more messages until the IPC channel is torn + // down by the child. + mIPCClosed = true; + return SendFinishInterceptedRedirect(); +} + //----------------------------------------------------------------------------- // HttpChannelSecurityWarningReporter //----------------------------------------------------------------------------- diff -Nru firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelParent.h firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelParent.h --- firefox-50.0.2+build1/netwerk/protocol/http/HttpChannelParent.h 2016-11-30 08:51:05.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/protocol/http/HttpChannelParent.h 2016-12-09 08:27:48.000000000 +0000 @@ -185,6 +185,9 @@ // Calls SendDeleteSelf and sets mIPCClosed to true because we should not // send any more messages after that. Bug 1274886 bool DoSendDeleteSelf(); + // Called to notify the parent channel to not send any more IPC messages. + virtual bool RecvDeletingChannel() override; + virtual bool RecvFinishInterceptedRedirect() override; private: void UpdateAndSerializeSecurityInfo(nsACString& aSerializedSecurityInfoOut); diff -Nru firefox-50.0.2+build1/netwerk/protocol/http/nsHttpChunkedDecoder.cpp firefox-50.1.0+build2/netwerk/protocol/http/nsHttpChunkedDecoder.cpp --- firefox-50.0.2+build1/netwerk/protocol/http/nsHttpChunkedDecoder.cpp 2016-11-30 08:51:05.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/protocol/http/nsHttpChunkedDecoder.cpp 2016-12-09 08:27:48.000000000 +0000 @@ -96,14 +96,18 @@ char *p = static_cast(memchr(buf, '\n', count)); if (p) { *p = 0; - if ((p > buf) && (*(p-1) == '\r')) // eliminate a preceding CR + count = p - buf; // new length + *bytesConsumed = count + 1; // length + newline + if ((p > buf) && (*(p-1) == '\r')) { // eliminate a preceding CR *(p-1) = 0; - *bytesConsumed = p - buf + 1; + count--; + } // make buf point to the full line buffer to parse if (!mLineBuf.IsEmpty()) { - mLineBuf.Append(buf); + mLineBuf.Append(buf, count); buf = (char *) mLineBuf.get(); + count = mLineBuf.Length(); } if (mWaitEOF) { diff -Nru firefox-50.0.2+build1/netwerk/protocol/http/PHttpChannel.ipdl firefox-50.1.0+build2/netwerk/protocol/http/PHttpChannel.ipdl --- firefox-50.0.2+build1/netwerk/protocol/http/PHttpChannel.ipdl 2016-11-30 08:51:05.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/protocol/http/PHttpChannel.ipdl 2016-12-09 08:27:48.000000000 +0000 @@ -85,6 +85,10 @@ async RemoveCorsPreflightCacheEntry(URIParams uri, PrincipalInfo requestingPrincipal); + // After receiving this message, the parent calls SendDeleteSelf, and makes + // sure not to send any more messages after that. + async DeletingChannel(); + async __delete__(); child: @@ -158,6 +162,13 @@ // Tell the child to issue a deprecation warning. async IssueDeprecationWarning(uint32_t warning, bool asError); + +both: + // After receiving this message, the parent calls SendDeleteSelf, and makes + // sure not to send any more messages after that. When receiving this message, + // the child will call Send__delete__() and complete the steps required to + // finish the redirect. + async FinishInterceptedRedirect(); }; diff -Nru firefox-50.0.2+build1/netwerk/test/mochitests/test_arraybufferinputstream.html firefox-50.1.0+build2/netwerk/test/mochitests/test_arraybufferinputstream.html --- firefox-50.0.2+build1/netwerk/test/mochitests/test_arraybufferinputstream.html 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/netwerk/test/mochitests/test_arraybufferinputstream.html 2016-12-09 08:27:48.000000000 +0000 @@ -19,6 +19,7 @@ var ab = new ArrayBuffer(4000); var ta = new Uint8Array(ab); ta[0] = 'a'.charCodeAt(0); + ta[1] = 'b'.charCodeAt(0); const Cc = SpecialPowers.Cc, Ci = SpecialPowers.Ci, Cr = SpecialPowers.Cr; var abis = Cc["@mozilla.org/io/arraybuffer-input-stream;1"] @@ -41,13 +42,11 @@ try { - sis.read(1); - ok(false, "reading from stream shouldn't have worked"); + is(sis.read(1), "b", "should read 'b' after detaching buffer"); } catch (e) { - ok(e.result === Cr.NS_BASE_STREAM_CLOSED, - "detaching underneath an input stream should close it"); + ok(false, "reading from stream should have worked"); } // A regression test for bug 1265076. Previously, overflowing diff -Nru firefox-50.0.2+build1/parser/html/jArray.h firefox-50.1.0+build2/parser/html/jArray.h --- firefox-50.0.2+build1/parser/html/jArray.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/parser/html/jArray.h 2016-12-09 08:27:48.000000000 +0000 @@ -50,12 +50,12 @@ L length; static jArray newJArray(L const len) { MOZ_ASSERT(len >= 0, "Negative length."); - jArray newArray = { new T[len], len }; + jArray newArray = { new T[size_t(len)], len }; return newArray; } static jArray newFallibleJArray(L const len) { MOZ_ASSERT(len >= 0, "Negative length."); - T* a = new (mozilla::fallible) T[len]; + T* a = new (mozilla::fallible) T[size_t(len)]; jArray newArray = { a, a ? len : 0 }; return newArray; } diff -Nru firefox-50.0.2+build1/parser/html/nsHtml5ArrayCopy.h firefox-50.1.0+build2/parser/html/nsHtml5ArrayCopy.h --- firefox-50.0.2+build1/parser/html/nsHtml5ArrayCopy.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/parser/html/nsHtml5ArrayCopy.h 2016-12-09 08:27:48.000000000 +0000 @@ -36,43 +36,43 @@ static inline void arraycopy(char16_t* source, int32_t sourceOffset, char16_t* target, int32_t targetOffset, int32_t length) { - memcpy(&(target[targetOffset]), &(source[sourceOffset]), length * sizeof(char16_t)); + memcpy(&(target[targetOffset]), &(source[sourceOffset]), size_t(length) * sizeof(char16_t)); } static inline void arraycopy(char16_t* source, char16_t* target, int32_t length) { - memcpy(target, source, length * sizeof(char16_t)); + memcpy(target, source, size_t(length) * sizeof(char16_t)); } static inline void arraycopy(int32_t* source, int32_t* target, int32_t length) { - memcpy(target, source, length * sizeof(int32_t)); + memcpy(target, source, size_t(length) * sizeof(int32_t)); } static inline void arraycopy(nsString** source, nsString** target, int32_t length) { - memcpy(target, source, length * sizeof(nsString*)); + memcpy(target, source, size_t(length) * sizeof(nsString*)); } static inline void arraycopy(nsHtml5AttributeName** source, nsHtml5AttributeName** target, int32_t length) { - memcpy(target, source, length * sizeof(nsHtml5AttributeName*)); + memcpy(target, source, size_t(length) * sizeof(nsHtml5AttributeName*)); } static inline void arraycopy(nsHtml5StackNode** source, nsHtml5StackNode** target, int32_t length) { - memcpy(target, source, length * sizeof(nsHtml5StackNode*)); + memcpy(target, source, size_t(length) * sizeof(nsHtml5StackNode*)); } static inline void arraycopy(nsHtml5StackNode** arr, int32_t sourceOffset, int32_t targetOffset, int32_t length) { - memmove(&(arr[targetOffset]), &(arr[sourceOffset]), length * sizeof(nsHtml5StackNode*)); + memmove(&(arr[targetOffset]), &(arr[sourceOffset]), size_t(length) * sizeof(nsHtml5StackNode*)); } }; #endif // nsHtml5ArrayCopy_h diff -Nru firefox-50.0.2+build1/parser/html/nsHtml5TokenizerCppSupplement.h firefox-50.1.0+build2/parser/html/nsHtml5TokenizerCppSupplement.h --- firefox-50.0.2+build1/parser/html/nsHtml5TokenizerCppSupplement.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/parser/html/nsHtml5TokenizerCppSupplement.h 2016-12-09 08:27:48.000000000 +0000 @@ -4,39 +4,56 @@ #include "mozilla/Likely.h" +// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits +// is 2^30. Note that this is counting char16_t units. The underlying +// bytes will be twice that, but they fit even in 32-bit size_t even +// if a contiguous chunk of memory of that size is pretty unlikely to +// be available on a 32-bit system. +#define MAX_POWER_OF_TWO_IN_INT32 0x40000000 + bool nsHtml5Tokenizer::EnsureBufferSpace(int32_t aLength) { - MOZ_ASSERT(aLength >= 0, "Negative length."); + MOZ_RELEASE_ASSERT(aLength >= 0, "Negative length."); + if (aLength > MAX_POWER_OF_TWO_IN_INT32) { + // Can't happen when loading from network. + return false; + } + CheckedInt worstCase(strBufLen); + worstCase += aLength; + worstCase += charRefBufLen; // Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB. // Adding to the general worst case instead of only the // TreeBuilder-exposed worst case to avoid re-introducing a bug when // unifying the tokenizer and tree builder buffers in the future. - size_t worstCase = size_t(strBufLen) + - size_t(aLength) + - size_t(charRefBufLen) + - size_t(2); - if (worstCase > INT32_MAX) { - // Since we index into the buffer using int32_t due to the Java heritage - // of the code, let's treat this as OOM. + worstCase += 2; + if (!worstCase.isValid()) { + return false; + } + if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) { return false; } // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer // so that the call below becomes unnecessary. - tokenHandler->EnsureBufferSpace(worstCase); + if (!tokenHandler->EnsureBufferSpace(worstCase.value())) { + return false; + } if (!strBuf) { - // Add one to round to the next power of two to avoid immediate - // reallocation once there are a few characters in the buffer. - strBuf = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase + 1)); + if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) { + // Add one to round to the next power of two to avoid immediate + // reallocation once there are a few characters in the buffer. + worstCase += 1; + } + strBuf = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value())); if (!strBuf) { return false; } - } else if (worstCase > size_t(strBuf.length)) { - jArray newBuf = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase)); + } else if (worstCase.value() > strBuf.length) { + jArray newBuf = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value())); if (!newBuf) { return false; } - memcpy(newBuf,strBuf, sizeof(char16_t) * strBufLen); + memcpy(newBuf, strBuf, sizeof(char16_t) * size_t(strBufLen)); strBuf = newBuf; } return true; diff -Nru firefox-50.0.2+build1/parser/html/nsHtml5TreeBuilderCppSupplement.h firefox-50.1.0+build2/parser/html/nsHtml5TreeBuilderCppSupplement.h --- firefox-50.0.2+build1/parser/html/nsHtml5TreeBuilderCppSupplement.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/parser/html/nsHtml5TreeBuilderCppSupplement.h 2016-12-09 08:27:48.000000000 +0000 @@ -961,30 +961,42 @@ charBufferLen += aLength; } +// INT32_MAX is (2^31)-1. Therefore, the highest power-of-two that fits +// is 2^30. Note that this is counting char16_t units. The underlying +// bytes will be twice that, but they fit even in 32-bit size_t even +// if a contiguous chunk of memory of that size is pretty unlikely to +// be available on a 32-bit system. +#define MAX_POWER_OF_TWO_IN_INT32 0x40000000 + bool -nsHtml5TreeBuilder::EnsureBufferSpace(size_t aLength) +nsHtml5TreeBuilder::EnsureBufferSpace(int32_t aLength) { // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer // so that this method becomes unnecessary. - size_t worstCase = size_t(charBufferLen) + aLength; - if (worstCase > INT32_MAX) { - // Since we index into the buffer using int32_t due to the Java heritage - // of the code, let's treat this as OOM. + CheckedInt worstCase(charBufferLen); + worstCase += aLength; + if (!worstCase.isValid()) { + return false; + } + if (worstCase.value() > MAX_POWER_OF_TWO_IN_INT32) { return false; } if (!charBuffer) { - // Add one to round to the next power of two to avoid immediate - // reallocation once there are a few characters in the buffer. - charBuffer = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase + 1)); + if (worstCase.value() < MAX_POWER_OF_TWO_IN_INT32) { + // Add one to round to the next power of two to avoid immediate + // reallocation once there are a few characters in the buffer. + worstCase += 1; + } + charBuffer = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value())); if (!charBuffer) { return false; } - } else if (worstCase > size_t(charBuffer.length)) { - jArray newBuf = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase)); + } else if (worstCase.value() > charBuffer.length) { + jArray newBuf = jArray::newFallibleJArray(mozilla::RoundUpPow2(worstCase.value())); if (!newBuf) { return false; } - memcpy(newBuf, charBuffer, sizeof(char16_t) * charBufferLen); + memcpy(newBuf, charBuffer, sizeof(char16_t) * size_t(charBufferLen)); charBuffer = newBuf; } return true; diff -Nru firefox-50.0.2+build1/parser/html/nsHtml5TreeBuilderHSupplement.h firefox-50.1.0+build2/parser/html/nsHtml5TreeBuilderHSupplement.h --- firefox-50.0.2+build1/parser/html/nsHtml5TreeBuilderHSupplement.h 2016-11-30 08:51:06.000000000 +0000 +++ firefox-50.1.0+build2/parser/html/nsHtml5TreeBuilderHSupplement.h 2016-12-09 08:27:48.000000000 +0000 @@ -138,7 +138,7 @@ * next call to this method. * @return true if successful; false if out of memory */ - bool EnsureBufferSpace(size_t aLength); + bool EnsureBufferSpace(int32_t aLength); void EnableViewSource(nsHtml5Highlighter* aHighlighter); diff -Nru firefox-50.0.2+build1/SOURCE_CHANGESET firefox-50.1.0+build2/SOURCE_CHANGESET --- firefox-50.0.2+build1/SOURCE_CHANGESET 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/SOURCE_CHANGESET 2016-12-09 08:27:51.000000000 +0000 @@ -1 +1 @@ -cc272f7d48d3544ffaf242b51430ffcf3a932a29 \ No newline at end of file +8612c3320053b796678921f8f23358e3e9df997e \ No newline at end of file diff -Nru firefox-50.0.2+build1/testing/docker/recipes/run-task firefox-50.1.0+build2/testing/docker/recipes/run-task --- firefox-50.0.2+build1/testing/docker/recipes/run-task 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/docker/recipes/run-task 2016-12-09 08:27:45.000000000 +0000 @@ -23,6 +23,7 @@ import os import pwd import re +import socket import stat import subprocess import sys @@ -109,7 +110,7 @@ except ValueError: print_line(b'vcs', 'invalid JSON in hg fingerprint secret') sys.exit(1) - except urllib2.URLError: + except (urllib2.URLError, socket.timeout): print_line(b'vcs', 'Unable to retrieve current hg.mozilla.org fingerprint' 'using the secret service, using fallback instead.') # XXX This fingerprint will not be accurate if running on an old diff -Nru firefox-50.0.2+build1/testing/firefox-ui/tests/puppeteer/test_windows.py firefox-50.1.0+build2/testing/firefox-ui/tests/puppeteer/test_windows.py --- firefox-50.0.2+build1/testing/firefox-ui/tests/puppeteer/test_windows.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/firefox-ui/tests/puppeteer/test_windows.py 2016-12-09 08:27:45.000000000 +0000 @@ -38,7 +38,7 @@ finally: BaseWindowTestCase.tearDown(self) - def test_windows(self): + def test_switch_to(self): url = self.marionette.absolute_url('layout/mozilla.html') # Open two more windows @@ -81,6 +81,18 @@ self.assertEqual(len(self.windows.all), 1) + def test_switch_to_unknown_window_type(self): + def open_by_js(_): + with self.marionette.using_context('chrome'): + self.marionette.execute_script(""" + window.open('chrome://browser/content/safeMode.xul', '_blank', + 'chrome,centerscreen,resizable=no'); + """) + + win = self.browser.open_window(callback=open_by_js, expected_window_class=BaseWindow) + win.close() + self.browser.switch_to() + class TestBaseWindow(BaseWindowTestCase): diff -Nru firefox-50.0.2+build1/testing/mozharness/configs/releases/postrelease_firefox_release.py firefox-50.1.0+build2/testing/mozharness/configs/releases/postrelease_firefox_release.py --- firefox-50.0.2+build1/testing/mozharness/configs/releases/postrelease_firefox_release.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/mozharness/configs/releases/postrelease_firefox_release.py 2016-12-09 08:27:45.000000000 +0000 @@ -7,7 +7,7 @@ ], "repo": { "repo": "https://hg.mozilla.org/releases/mozilla-release", - "branch": "FIREFOX_50_0_2_RELBRANCH", + "branch": "default", "dest": "mozilla-release", "vcs": "hg", }, diff -Nru firefox-50.0.2+build1/testing/mozharness/configs/releases/updates_firefox_release.py firefox-50.1.0+build2/testing/mozharness/configs/releases/updates_firefox_release.py --- firefox-50.0.2+build1/testing/mozharness/configs/releases/updates_firefox_release.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/mozharness/configs/releases/updates_firefox_release.py 2016-12-09 08:27:45.000000000 +0000 @@ -3,7 +3,7 @@ "log_name": "updates_release", "repo": { "repo": "https://hg.mozilla.org/build/tools", - "branch": "FIREFOX_50_0_2", + "branch": "default", "dest": "tools", "vcs": "hg", }, diff -Nru firefox-50.0.2+build1/testing/mozharness/scripts/release/generate-checksums.py firefox-50.1.0+build2/testing/mozharness/scripts/release/generate-checksums.py --- firefox-50.0.2+build1/testing/mozharness/scripts/release/generate-checksums.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/mozharness/scripts/release/generate-checksums.py 2016-12-09 08:27:46.000000000 +0000 @@ -130,6 +130,7 @@ r"^.*\.mar$", r"^.*Setup.*\.exe$", r"^.*\.xpi$", + r"^.*fennec.*\.apk$", ] def _get_bucket_name(self): diff -Nru firefox-50.0.2+build1/testing/mozharness/scripts/release/push-candidate-to-releases.py firefox-50.1.0+build2/testing/mozharness/scripts/release/push-candidate-to-releases.py --- firefox-50.0.2+build1/testing/mozharness/scripts/release/push-candidate-to-releases.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/mozharness/scripts/release/push-candidate-to-releases.py 2016-12-09 08:27:46.000000000 +0000 @@ -49,6 +49,7 @@ r"^.*/host.*$", r"^.*/mar-tools/.*$", r"^.*robocop.apk$", + r"^.*bouncer.apk$", r"^.*contrib.*", r"^.*/beetmover-checksums/.*$", ], diff -Nru firefox-50.0.2+build1/testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py firefox-50.1.0+build2/testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py --- firefox-50.0.2+build1/testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py 2016-12-09 08:27:46.000000000 +0000 @@ -106,12 +106,7 @@ # Retrieve window type to determine the type of chrome window if handle != self.marionette.current_chrome_window_handle: self.switch_to(handle) - - window_type = Wait(self.marionette).until( - lambda mn: mn.get_window_type(), - message='Cannot get window type for chrome window handle "%s"' % handle - ) - + window_type = self.marionette.get_window_type() finally: # Ensure to switch back to the original window if handle != current_handle: @@ -120,8 +115,7 @@ if window_type in self.windows_map: window = self.windows_map[window_type](lambda: self.marionette, handle) else: - raise errors.UnknownWindowError('Unknown window type "%s" for handle: "%s"' % - (window_type, handle)) + window = BaseWindow(lambda: self.marionette, handle) if expected_class is not None and type(window) is not expected_class: raise errors.UnexpectedWindowTypeError('Expected window "%s" but got "%s"' % diff -Nru firefox-50.0.2+build1/testing/web-platform/harness/wptrunner/browsers/firefox.py firefox-50.1.0+build2/testing/web-platform/harness/wptrunner/browsers/firefox.py --- firefox-50.0.2+build1/testing/web-platform/harness/wptrunner/browsers/firefox.py 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/testing/web-platform/harness/wptrunner/browsers/firefox.py 2016-12-09 08:27:46.000000000 +0000 @@ -63,7 +63,7 @@ **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, **kwargs) - executor_kwargs["close_after_done"] = True + executor_kwargs["close_after_done"] = test_type != "reftest" if kwargs["timeout_multiplier"] is None: if test_type == "reftest": if run_info_data["debug"] or run_info_data.get("asan"): diff -Nru firefox-50.0.2+build1/toolkit/components/places/nsNavHistory.cpp firefox-50.1.0+build2/toolkit/components/places/nsNavHistory.cpp --- firefox-50.0.2+build1/toolkit/components/places/nsNavHistory.cpp 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/toolkit/components/places/nsNavHistory.cpp 2016-12-09 08:27:47.000000000 +0000 @@ -3363,7 +3363,8 @@ // URI if (NS_SUCCEEDED(aQuery->GetHasUri(&hasIt)) && hasIt) { - clause.Condition("h.url =").Param(":uri"); + clause.Condition("h.url_hash = hash(").Param(":uri").Str(")") + .Condition("h.url =").Param(":uri"); } // annotation diff -Nru firefox-50.0.2+build1/toolkit/modules/WebChannel.jsm firefox-50.1.0+build2/toolkit/modules/WebChannel.jsm --- firefox-50.0.2+build1/toolkit/modules/WebChannel.jsm 2016-11-30 08:51:10.000000000 +0000 +++ firefox-50.1.0+build2/toolkit/modules/WebChannel.jsm 2016-12-09 08:27:48.000000000 +0000 @@ -171,7 +171,7 @@ // The permission manager operates on domain names rather than true // origins (bug 1066517). To mitigate that, we explicitly check that // the scheme is https://. - let uri = Services.io.newURI(requestPrincipal.origin, null, null); + let uri = Services.io.newURI(requestPrincipal.originNoSuffix, null, null); if (uri.scheme != "https") { return false; } @@ -183,7 +183,7 @@ } else { // a simple URI, so just check for an exact match. this._originCheckCallback = requestPrincipal => { - return originOrPermission.prePath === requestPrincipal.origin; + return originOrPermission.prePath === requestPrincipal.originNoSuffix; } } this._originOrPermission = originOrPermission; diff -Nru firefox-50.0.2+build1/widget/cocoa/TextInputHandler.h firefox-50.1.0+build2/widget/cocoa/TextInputHandler.h --- firefox-50.0.2+build1/widget/cocoa/TextInputHandler.h 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/widget/cocoa/TextInputHandler.h 2016-12-09 08:27:49.000000000 +0000 @@ -521,6 +521,10 @@ bool mKeyPressHandled; // Whether the key event causes other key events via IME or something. bool mCausedOtherKeyEvents; + // Whether the key event causes composition change or committing + // composition. So, even if InsertText() is called, this may be false + // if it dispatches keypress event. + bool mCompositionDispatched; KeyEventState() : mKeyEvent(nullptr) { @@ -559,11 +563,13 @@ mKeyPressDispatched = false; mKeyPressHandled = false; mCausedOtherKeyEvents = false; + mCompositionDispatched = false; } bool IsDefaultPrevented() const { - return mKeyDownHandled || mKeyPressHandled || mCausedOtherKeyEvents; + return mKeyDownHandled || mKeyPressHandled || mCausedOtherKeyEvents || + mCompositionDispatched; } bool CanDispatchKeyPressEvent() const diff -Nru firefox-50.0.2+build1/widget/cocoa/TextInputHandler.mm firefox-50.1.0+build2/widget/cocoa/TextInputHandler.mm --- firefox-50.0.2+build1/widget/cocoa/TextInputHandler.mm 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/widget/cocoa/TextInputHandler.mm 2016-12-09 08:27:49.000000000 +0000 @@ -1682,10 +1682,12 @@ MOZ_LOG(gLog, LogLevel::Info, ("%p TextInputHandler::HandleKeyDownEvent, " - "keydown handled=%s, keypress handled=%s, causedOtherKeyEvents=%s", + "keydown handled=%s, keypress handled=%s, causedOtherKeyEvents=%s, " + "compositionDispatched=%s", this, TrueOrFalse(currentKeyEvent->mKeyDownHandled), TrueOrFalse(currentKeyEvent->mKeyPressHandled), - TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents))); + TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents), + TrueOrFalse(currentKeyEvent->mCompositionDispatched))); return currentKeyEvent->IsDefaultPrevented(); NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); @@ -2119,7 +2121,7 @@ "aReplacementRange=%p { location=%llu, length=%llu }, " "IsIMEComposing()=%s, IgnoreIMEComposition()=%s, " "keyevent=%p, keydownHandled=%s, keypressDispatched=%s, " - "causedOtherKeyEvents=%s", + "causedOtherKeyEvents=%s, compositionDispatched=%s", this, GetCharacters([aAttrString string]), aReplacementRange, aReplacementRange ? aReplacementRange->location : 0, aReplacementRange ? aReplacementRange->length : 0, @@ -2130,7 +2132,9 @@ currentKeyEvent ? TrueOrFalse(currentKeyEvent->mKeyPressDispatched) : "N/A", currentKeyEvent ? - TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A")); + TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A", + currentKeyEvent ? + TrueOrFalse(currentKeyEvent->mCompositionDispatched) : "N/A")); if (IgnoreIMEComposition()) { return; @@ -2188,15 +2192,15 @@ return; } - if (str.Length() != 1 || IsIMEComposing()) { + if (str.Length() != 1 || IsIMEComposing() || + (currentKeyEvent && currentKeyEvent->mCompositionDispatched)) { InsertTextAsCommittingComposition(aAttrString, aReplacementRange); // For now, consume keypress events when we dispatch the string with a // composition for preventing to dispatch keypress events later. // TODO: When there is a currentKeyEvent, we should dispatch keypress // events even if the length of the string is over 1. if (currentKeyEvent) { - currentKeyEvent->mKeyPressHandled = true; - currentKeyEvent->mKeyPressDispatched = true; + currentKeyEvent->mCompositionDispatched = true; } return; } diff -Nru firefox-50.0.2+build1/widget/ContentCache.cpp firefox-50.1.0+build2/widget/ContentCache.cpp --- firefox-50.0.2+build1/widget/ContentCache.cpp 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/widget/ContentCache.cpp 2016-12-09 08:27:49.000000000 +0000 @@ -829,7 +829,7 @@ return false; } - if ((aRoundToExistingOffset && mTextRectArray.IsValid()) || + if ((aRoundToExistingOffset && mTextRectArray.HasRects()) || mTextRectArray.IsOverlappingWith(aOffset, aLength)) { aUnionTextRect = mTextRectArray.GetUnionRectAsFarAsPossible(aOffset, aLength, @@ -1173,7 +1173,8 @@ bool aRoundToExistingOffset) const { LayoutDeviceIntRect rect; - if (!aRoundToExistingOffset && !IsOverlappingWith(aOffset, aLength)) { + if (!HasRects() || + (!aRoundToExistingOffset && !IsOverlappingWith(aOffset, aLength))) { return rect; } uint32_t startOffset = std::max(aOffset, mStart); @@ -1184,6 +1185,9 @@ if (aRoundToExistingOffset && endOffset < mStart + 1) { endOffset = mStart + 1; } + if (NS_WARN_IF(endOffset < startOffset)) { + return rect; + } for (uint32_t i = 0; i < endOffset - startOffset; i++) { rect = rect.Union(mRects[startOffset - mStart + i]); } diff -Nru firefox-50.0.2+build1/widget/ContentCache.h firefox-50.1.0+build2/widget/ContentCache.h --- firefox-50.0.2+build1/widget/ContentCache.h 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/widget/ContentCache.h 2016-12-09 08:27:49.000000000 +0000 @@ -182,6 +182,10 @@ CheckedInt(mStart) + mRects.Length(); return endOffset.isValid(); } + bool HasRects() const + { + return IsValid() && !mRects.IsEmpty(); + } uint32_t StartOffset() const { NS_ASSERTION(IsValid(), @@ -213,7 +217,7 @@ } bool IsOverlappingWith(uint32_t aOffset, uint32_t aLength) const { - if (!IsValid() || aOffset == UINT32_MAX) { + if (!HasRects() || aOffset == UINT32_MAX || !aLength) { return false; } CheckedInt endOffset = @@ -221,7 +225,7 @@ if (NS_WARN_IF(!endOffset.isValid())) { return false; } - return aOffset <= EndOffset() && endOffset.value() >= mStart; + return aOffset < EndOffset() && endOffset.value() > mStart; } LayoutDeviceIntRect GetRect(uint32_t aOffset) const; LayoutDeviceIntRect GetUnionRect(uint32_t aOffset, uint32_t aLength) const; diff -Nru firefox-50.0.2+build1/widget/gtk/mozgtk/mozgtk.c firefox-50.1.0+build2/widget/gtk/mozgtk/mozgtk.c --- firefox-50.0.2+build1/widget/gtk/mozgtk/mozgtk.c 2016-11-30 08:51:07.000000000 +0000 +++ firefox-50.1.0+build2/widget/gtk/mozgtk/mozgtk.c 2016-12-09 08:27:49.000000000 +0000 @@ -609,3 +609,22 @@ STUB(gdkx_visual_get) STUB(gtk_object_get_type) #endif + +#ifndef GTK3_SYMBOLS +// Only define the following workaround when using GTK3, which we detect +// by checking if GTK3 stubs are not provided. +#include +// Bug 1271100 +// We need to trick system Cairo into not using the XShm extension due to +// a race condition in it that results in frequent BadAccess errors. Cairo +// relies upon XShmQueryExtension to initially detect if XShm is available. +// So we define our own stub that always indicates XShm not being present. +// mozgtk loads before libXext/libcairo and so this stub will take priority. +// Our tree usage goes through xcb and remains unaffected by this. +MOZ_EXPORT Bool +XShmQueryExtension(Display* aDisplay) +{ + return False; +} +#endif +