Merge m-c to b2g-inbound.

This commit is contained in:
Ryan VanderMeulen 2014-04-25 16:32:31 -04:00
commit 1e5d88f939
322 changed files with 7191 additions and 1659 deletions

View File

@ -1211,7 +1211,7 @@ exports.testShowToOpenXToClose = function(assert, done) {
onShow: function() {
assert.ok(isChecked(menuitem), 'menuitem is checked');
let closeButton = window.document.querySelector('#sidebar-header > toolbarbutton.tabs-closebutton');
let closeButton = window.document.querySelector('#sidebar-header > toolbarbutton.close-icon');
simulateCommand(closeButton);
},
onHide: function() {

View File

@ -14,7 +14,7 @@
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml",
"{objdir}/dist/b2g-update/b2g-gecko-update.mar"
"{objdir}/dist/b2g-update/*.mar"
],
"zip_files": [
["{workdir}/out/target/product/flame/*.img", "out/target/product/flame/"],

View File

@ -457,13 +457,6 @@ pref("browser.tabs.drawInTitlebar", false);
pref("browser.tabs.drawInTitlebar", true);
#endif
// Where to show tab close buttons:
// 0 on active tab only
// 1 on all tabs until tabClipWidth is reached, then active tab only
// 2 no close buttons at all
// 3 at the end of the tabstrip
pref("browser.tabs.closeButtons", 1);
// When tabs opened by links in other tabs via a combination of
// browser.link.open_newwindow being set to 3 and target="_blank" etc are
// closed:
@ -1163,7 +1156,6 @@ pref("services.sync.prefs.sync.browser.search.update", true);
pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
pref("services.sync.prefs.sync.browser.startup.homepage", true);
pref("services.sync.prefs.sync.browser.startup.page", true);
pref("services.sync.prefs.sync.browser.tabs.closeButtons", true);
pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);
pref("services.sync.prefs.sync.browser.tabs.warnOnClose", true);
pref("services.sync.prefs.sync.browser.tabs.warnOnOpen", true);

View File

@ -489,10 +489,6 @@ menuitem.spell-suggestion {
font-weight: bold;
}
#sidebar-header > .tabs-closebutton {
-moz-user-focus: normal;
}
/* apply Fitts' law to the notification bar's close button */
window[sizemode="maximized"] #content .notification-inner {
border-right: 0px !important;

View File

@ -549,7 +549,7 @@
iconsize="small"
aria-label="&tabsToolbar.label;"
context="toolbar-context-menu"
defaultset="tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton"
defaultset="tabbrowser-tabs,new-tab-button,alltabs-button"
collapsed="true">
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
@ -600,13 +600,6 @@
</menupopup>
</toolbarbutton>
<toolbarbutton id="tabs-closebutton"
class="close-button tabs-closebutton close-icon"
command="cmd_close"
label="&closeTab.label;"
cui-areatype="toolbar"
tooltiptext="&closeTab.label;"/>
#if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
<hbox class="private-browsing-indicator" skipintoolbarset="true"/>
#endif
@ -1054,7 +1047,7 @@
<sidebarheader id="sidebar-header" align="center">
<label id="sidebar-title" persist="value" flex="1" crop="end" control="sidebar"/>
<image id="sidebar-throbber"/>
<toolbarbutton class="tabs-closebutton close-icon" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="toggleSidebar();"/>
<toolbarbutton class="close-icon tabbable" tooltiptext="&sidebarCloseButton.tooltip;" oncommand="toggleSidebar();"/>
</sidebarheader>
<browser id="sidebar" flex="1" autoscroll="false" disablehistory="true"
style="min-width: 14em; width: 18em; max-width: 36em;"/>

View File

@ -12,12 +12,11 @@
.tab-close-button {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-close-tab-button");
display: none;
}
.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([pinned])[selected="true"],
.tabbrowser-tabs[closebuttons="alltabs"] > * > * > * > .tab-close-button:not([pinned]) {
display: -moz-box;
.tab-close-button[pinned],
.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([selected="true"]) {
display: none;
}
.tab-label[pinned] {

View File

@ -1913,7 +1913,7 @@
if (this.tabs.length - this._removingTabs.length == 1) {
closeWindow = aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab :
!window.toolbar.visible ||
this.tabContainer._closeWindowWithLastTab;
Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
// Closing the tab and replacing it with a blank one is notably slower
// than closing the window right away. If the caller opts in, take
@ -3372,16 +3372,12 @@
<constructor>
<![CDATA[
this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
this.mCloseButtons = Services.prefs.getIntPref("browser.tabs.closeButtons");
this._closeWindowWithLastTab = Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
var tab = this.firstChild;
tab.label = this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle");
tab.setAttribute("crop", "end");
tab.setAttribute("onerror", "this.removeAttribute('image');");
this.adjustTabstrip();
Services.prefs.addObserver("browser.tabs.", this._prefObserver, false);
window.addEventListener("resize", this, false);
window.addEventListener("load", this, false);
@ -3394,12 +3390,6 @@
]]>
</constructor>
<destructor>
<![CDATA[
Services.prefs.removeObserver("browser.tabs.", this._prefObserver);
]]>
</destructor>
<field name="tabbrowser" readonly="true">
document.getElementById(this.getAttribute("tabbrowser"));
</field>
@ -3471,22 +3461,6 @@
]]></body>
</method>
<field name="_prefObserver"><![CDATA[({
tabContainer: this,
observe: function (subject, topic, data) {
switch (data) {
case "browser.tabs.closeButtons":
this.tabContainer.mCloseButtons = Services.prefs.getIntPref(data);
this.tabContainer.adjustTabstrip();
break;
case "browser.tabs.closeWindowWithLastTab":
this.tabContainer._closeWindowWithLastTab = Services.prefs.getBoolPref(data);
this.tabContainer.adjustTabstrip();
break;
}
}
});]]></field>
<field name="_blockDblClick">false</field>
<field name="_tabDropIndicator">
@ -3563,42 +3537,23 @@
<body><![CDATA[
let numTabs = this.childNodes.length -
this.tabbrowser._removingTabs.length;
// modes for tabstrip
// 0 - button on active tab only
// 1 - close buttons on all tabs
// 2 - no close buttons at all
// 3 - close button at the end of the tabstrip
switch (this.mCloseButtons) {
case 0:
this.setAttribute("closebuttons", "activetab");
break;
case 1:
if (numTabs <= 2) {
// This is an optimization to avoid layout flushes by calling
// getBoundingClientRect() when we just opened a second tab. In
// this case it's highly unlikely that the tab width is smaller
// than mTabClipWidth and the tab close button obscures too much
// of the tab's label. In the edge case of the window being too
// narrow (or if tabClipWidth has been set to a way higher value),
// we'll correct the 'closebuttons' attribute after the tabopen
// animation has finished.
this.setAttribute("closebuttons", "alltabs");
} else {
let tab = this.tabbrowser.visibleTabs[this.tabbrowser._numPinnedTabs];
if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth)
this.setAttribute("closebuttons", "alltabs");
else
this.setAttribute("closebuttons", "activetab");
if (numTabs > 2) {
// This is an optimization to avoid layout flushes by calling
// getBoundingClientRect() when we just opened a second tab. In
// this case it's highly unlikely that the tab width is smaller
// than mTabClipWidth and the tab close button obscures too much
// of the tab's label. In the edge case of the window being too
// narrow (or if tabClipWidth has been set to a way higher value),
// we'll correct the 'closebuttons' attribute after the tabopen
// animation has finished.
let tab = this.tabbrowser.visibleTabs[this.tabbrowser._numPinnedTabs];
if (tab && tab.getBoundingClientRect().width <= this.mTabClipWidth) {
this.setAttribute("closebuttons", "activetab");
return;
}
break;
case 2:
case 3:
this.setAttribute("closebuttons", "never");
break;
}
var tabstripClosebutton = document.getElementById("tabs-closebutton");
if (tabstripClosebutton && tabstripClosebutton.parentNode == this._container)
tabstripClosebutton.collapsed = this.mCloseButtons != 3;
this.removeAttribute("closebuttons");
]]></body>
</method>
@ -4272,8 +4227,7 @@
return;
if (event.target.localName == "tab") {
if (this.childNodes.length > 1 || !this._closeWindowWithLastTab)
this.tabbrowser.removeTab(event.target, {animate: true, byMouse: true});
this.tabbrowser.removeTab(event.target, {animate: true, byMouse: true});
} else if (event.originalTarget.localName == "box") {
BrowserOpenTab();
} else {

View File

@ -224,7 +224,6 @@ let CustomizableUIInternal = {
"tabbrowser-tabs",
"new-tab-button",
"alltabs-button",
"tabs-closebutton",
],
defaultCollapsed: null,
}, true);

View File

@ -179,10 +179,10 @@ CustomizeMode.prototype = {
// customization mode when pressing ESC.
document.addEventListener("keypress", this);
// Same goes for the menu button - if we're customizing, a mousedown to the
// Same goes for the menu button - if we're customizing, a click on the
// menu button means a quick exit from customization mode.
window.PanelUI.hide();
window.PanelUI.menuButton.addEventListener("mousedown", this);
window.PanelUI.menuButton.addEventListener("command", this);
window.PanelUI.menuButton.open = true;
window.PanelUI.beginBatchUpdate();
@ -331,7 +331,7 @@ CustomizeMode.prototype = {
CustomizableUI.removeListener(this);
this.document.removeEventListener("keypress", this);
this.window.PanelUI.menuButton.removeEventListener("mousedown", this);
this.window.PanelUI.menuButton.removeEventListener("command", this);
this.window.PanelUI.menuButton.open = false;
this.window.PanelUI.beginBatchUpdate();
@ -1181,13 +1181,13 @@ CustomizeMode.prototype = {
case "dragend":
this._onDragEnd(aEvent);
break;
case "mousedown":
if (aEvent.button == 0 &&
(aEvent.originalTarget == this.window.PanelUI.menuButton)) {
case "command":
if (aEvent.originalTarget == this.window.PanelUI.menuButton) {
this.exit();
aEvent.preventDefault();
return;
}
break;
case "mousedown":
this._onMouseDown(aEvent);
break;
case "mouseup":

View File

@ -65,6 +65,19 @@ skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s f
[browser_943683_migration_test.js]
[browser_944887_destroyWidget_should_destroy_in_palette.js]
[browser_945739_showInPrivateBrowsing_customize_mode.js]
[browser_947914_button_addons.js]
[browser_947914_button_copy.js]
[browser_947914_button_cut.js]
[browser_947914_button_find.js]
[browser_947914_button_history.js]
[browser_947914_button_newPrivateWindow.js]
[browser_947914_button_newWindow.js]
[browser_947914_button_paste.js]
[browser_947914_button_print.js]
[browser_947914_button_savePage.js]
[browser_947914_button_zoomIn.js]
[browser_947914_button_zoomOut.js]
[browser_947914_button_zoomReset.js]
[browser_947987_removable_default.js]
[browser_948985_non_removable_defaultArea.js]
[browser_952963_areaType_getter_no_area.js]

View File

@ -0,0 +1,34 @@
/* 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";
add_task(function() {
info("Check addons button existence and functionality");
let initialLocation = gBrowser.currentURI.spec;
yield PanelUI.show();
let addonsButton = document.getElementById("add-ons-button");
ok(addonsButton, "Add-ons button exists in Panel Menu");
addonsButton.click();
yield waitForCondition(function() gBrowser.currentURI &&
gBrowser.currentURI.spec == "about:addons");
let addonsPage = gBrowser.selectedBrowser.contentWindow.document.
getElementById("addons-page");
ok(addonsPage, "Add-ons page was opened");
// close the add-ons tab
if(gBrowser.tabs.length > 1) {
gBrowser.removeTab(gBrowser.selectedTab);
}
else {
var tabToRemove = gBrowser.selectedTab;
gBrowser.addTab(initialLocation);
gBrowser.removeTab(tabToRemove);
}
});

View File

@ -0,0 +1,51 @@
/* 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";
add_task(function() {
info("Check copy button existence and functionality");
var testText = "copy text test";
let initialLocation = gBrowser.currentURI.spec;
yield PanelUI.show();
let copyButton = document.getElementById("copy-button");
ok(copyButton, "Copy button exists in Panel Menu");
is(copyButton.getAttribute("disabled"), "true", "Copy button is initially disabled");
// copy text from URL bar
gURLBar.value = testText;
gURLBar.focus();
gURLBar.select();
yield PanelUI.show();
ok(!copyButton.hasAttribute("disabled"), "Copy button gets enabled");
copyButton.click();
is(gURLBar.value, testText, "Selected text is unaltered when clicking copy");
// check that the text was added to the clipboard
let clipboard = Services.clipboard;
let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
const globalClipboard = clipboard.kGlobalClipboard;
transferable.init(null);
transferable.addDataFlavor("text/unicode");
clipboard.getData(transferable, globalClipboard);
let str = {}, strLength = {};
transferable.getTransferData("text/unicode", str, strLength);
let clipboardValue = "";
if (str.value) {
str.value.QueryInterface(Ci.nsISupportsString);
clipboardValue = str.value.data;
}
is(clipboardValue, testText, "Data was copied to the clipboard.");
// restore the tab location and clear the clipboard
Services.clipboard.emptyClipboard(globalClipboard);
gURLBar.value = initialLocation;
});

View File

@ -0,0 +1,50 @@
/* 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";
add_task(function() {
info("Check cut button existence and functionality");
var testText = "cut text test";
let initialLocation = gBrowser.currentURI.spec;
yield PanelUI.show();
let cutButton = document.getElementById("cut-button");
ok(cutButton, "Cut button exists in Panel Menu");
ok(cutButton.getAttribute("disabled"), "Cut button is disabled");
// cut text from URL bar
gURLBar.value = testText;
gURLBar.focus();
gURLBar.select();
yield PanelUI.show();
ok(!cutButton.hasAttribute("disabled"), "Cut button gets enabled");
cutButton.click();
is(gURLBar.value, "", "Selected text is removed from source when clicking on cut");
// check that the text was added to the clipboard
let clipboard = Services.clipboard;
let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
const globalClipboard = clipboard.kGlobalClipboard;
transferable.init(null);
transferable.addDataFlavor("text/unicode");
clipboard.getData(transferable, globalClipboard);
let str = {}, strLength = {};
transferable.getTransferData("text/unicode", str, strLength);
let clipboardValue = "";
if (str.value) {
str.value.QueryInterface(Ci.nsISupportsString);
clipboardValue = str.value.data;
}
is(clipboardValue, testText, "Data was copied to the clipboard.");
// restore the tab location and clear the clipboard
gBrowser.value = initialLocation;
Services.clipboard.emptyClipboard(globalClipboard);
});

View File

@ -0,0 +1,20 @@
/* 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";
add_task(function() {
info("Check find button existence and functionality");
yield PanelUI.show();
let findButton = document.getElementById("find-button");
ok(findButton, "Find button exists in Panel Menu");
findButton.click();
ok(!gFindBar.hasAttribute("hidden"), "Findbar opened successfully");
// close find bar
gFindBar.close();
});

View File

@ -0,0 +1,22 @@
/* 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";
add_task(function() {
info("Check history button existence and functionality");
yield PanelUI.show();
let historyButton = document.getElementById("history-panelmenu");
ok(historyButton, "History button appears in Panel Menu");
historyButton.click();
let historyPanel = document.getElementById("PanelUI-history");
ok(historyPanel.getAttribute("current"), "History Panel is in view");
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise
});

View File

@ -0,0 +1,45 @@
/* 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";
add_task(function() {
info("Check private browsing button existence and functionality");
yield PanelUI.show();
var windowWasHandled = false;
let privateWindow = null;
let observerWindowOpened = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
privateWindow = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
privateWindow.addEventListener("load", function newWindowHandler() {
privateWindow.removeEventListener("load", newWindowHandler, false);
is(privateWindow.location.href, "chrome://browser/content/browser.xul",
"A new browser window was opened");
ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "Window is private");
windowWasHandled = true;
}, false);
}
}
}
Services.ww.registerNotification(observerWindowOpened);
let privateBrowsingButton = document.getElementById("privatebrowsing-button");
ok(privateBrowsingButton, "Private browsing button exists in Panel Menu");
privateBrowsingButton.click();
try{
yield waitForCondition(() => windowWasHandled);
yield promiseWindowClosed(privateWindow);
}
catch(e) {
ok(false, "The new private browser window was not properly handled");
}
finally {
Services.ww.unregisterNotification(observerWindowOpened);
}
});

View File

@ -0,0 +1,45 @@
/* 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";
add_task(function() {
info("Check new window button existence and functionality");
yield PanelUI.show();
var windowWasHandled = false;
var newWindow = null;
let observerWindowOpened = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
newWindow = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
newWindow.addEventListener("load", function newWindowHandler() {
newWindow.removeEventListener("load", newWindowHandler, false);
is(newWindow.location.href, "chrome://browser/content/browser.xul",
"A new browser window was opened");
ok(!PrivateBrowsingUtils.isWindowPrivate(newWindow), "Window is not private");
windowWasHandled = true;
}, false);
}
}
}
Services.ww.registerNotification(observerWindowOpened);
let newWindowButton = document.getElementById("new-window-button");
ok(newWindowButton, "New Window button exists in Panel Menu");
newWindowButton.click();
try{
yield waitForCondition(() => windowWasHandled);
yield promiseWindowClosed(newWindow);
}
catch(e) {
ok(false, "The new browser window was not properly handled");
}
finally {
Services.ww.unregisterNotification(observerWindowOpened);
}
});

View File

@ -0,0 +1,35 @@
/* 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";
add_task(function() {
info("Check paste button existence and functionality");
let initialLocation = gBrowser.currentURI.spec;
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
const globalClipboard = Services.clipboard.kGlobalClipboard;
yield PanelUI.show();
let pasteButton = document.getElementById("paste-button");
ok(pasteButton, "Paste button exists in Panel Menu");
// add text to clipboard
var text = "Sample text for testing";
clipboard.copyString(text);
// test paste button by pasting text to URL bar
gURLBar.focus();
yield PanelUI.show();
ok(!pasteButton.hasAttribute("disabled"), "Paste button is enabled");
pasteButton.click();
is(gURLBar.value, text, "Text pasted successfully");
// clear the clipboard and restore the tab location as it was at the begining of the test
Services.clipboard.emptyClipboard(globalClipboard);
gURLBar.value = initialLocation;
});

View File

@ -0,0 +1,32 @@
/* 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 isOSX = (Services.appinfo.OS === "Darwin");
add_task(function() {
info("Check print button existence and functionality");
yield PanelUI.show();
let printButton = document.getElementById("print-button");
ok(printButton, "Print button exists in Panel Menu");
if(isOSX) {
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
}
else {
printButton.click();
yield waitForCondition(() => window.gInPrintPreviewMode);
ok(window.gInPrintPreviewMode, "Entered print preview mode");
// close print preview
PrintUtils.exitPrintPreview();
yield waitForCondition(() => !window.gInPrintPreviewMode);
}
});

View File

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check save page button existence");
yield PanelUI.show();
let savePageButton = document.getElementById("save-page-button");
ok(savePageButton, "Save Page button exists in Panel Menu");
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
});

View File

@ -0,0 +1,31 @@
/* 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";
add_task(function() {
info("Check zoom in button existence and functionality");
let initialPageZoom = ZoomManager.zoom;
is(initialPageZoom, 1, "Initial zoom factor should be 1");
yield PanelUI.show();
let zoomInButton = document.getElementById("zoom-in-button");
ok(zoomInButton, "Zoom in button exists in Panel Menu");
zoomInButton.click();
let pageZoomLevel = parseInt(ZoomManager.zoom * 100);
let zoomResetButton = document.getElementById("zoom-reset-button");
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
ok(pageZoomLevel > 100 && pageZoomLevel == expectedZoomLevel, "Page zoomed in correctly");
// close the Panel
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
// reset zoom level
ZoomManager.zoom = initialPageZoom;
});

View File

@ -0,0 +1,32 @@
/* 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";
add_task(function() {
info("Check zoom out button existence and functionality");
let initialPageZoom = ZoomManager.zoom;
is(initialPageZoom, 1, "Initial zoom factor should be 1");
yield PanelUI.show();
let zoomOutButton = document.getElementById("zoom-out-button");
ok(zoomOutButton, "Zoom out button exists in Panel Menu");
zoomOutButton.click();
let pageZoomLevel = Math.round(ZoomManager.zoom*100);
let zoomResetButton = document.getElementById("zoom-reset-button");
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
ok(pageZoomLevel < 100 && pageZoomLevel == expectedZoomLevel, "Page zoomed out correctly");
// close the panel
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
// reset zoom level
ZoomManager.zoom = initialPageZoom;
});

View File

@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check zoom reset button existence and functionality");
let initialPageZoom = ZoomManager.zoom;
is(initialPageZoom, 1, "Initial zoom factor should be 1");
ZoomManager.zoom = 0.5;
yield PanelUI.show();
let zoomResetButton = document.getElementById("zoom-reset-button");
ok(zoomResetButton, "Zoom reset button exists in Panel Menu");
zoomResetButton.click();
let pageZoomLevel = parseInt(ZoomManager.zoom * 100);
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
ok(pageZoomLevel == expectedZoomLevel && pageZoomLevel == 100, "Page zoom reset correctly");
// close the panel
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
//reset the zoom level
ZoomManager.zoom = initialPageZoom;
});

View File

@ -103,6 +103,11 @@ function test() {
value: "MOZLBR",
purpose:"keyword",
},
{
name: "form",
value: "MOZTSB",
purpose: "newtab",
},
],
mozparams: {},
},

View File

@ -67,7 +67,7 @@ function test() {
},
{
name: "new tab search",
searchURL: base,
searchURL: base + "&form=MOZTSB",
run: function () {
function doSearch(doc) {
// Re-add the listener, and perform a search

View File

@ -20,7 +20,7 @@ function test() {
TabView.moveTabTo(newTabs[newTabs.length - 1], null);
ok(gBrowser.visibleTabs[0].getBoundingClientRect().width > gBrowser.tabContainer.mTabClipWidth,
"Tab width is bigger than tab clip width");
is(gBrowser.tabContainer.getAttribute("closebuttons"), "alltabs", "Show button on all tabs.")
is(gBrowser.tabContainer.getAttribute("closebuttons"), "", "Show button on all tabs.")
// clean up and finish
newTabs.forEach(function(tab) {

View File

@ -447,7 +447,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY bookmarkThisFrameCmd.accesskey "m">
<!ENTITY emailPageCmd.label "Email Link…">
<!ENTITY emailPageCmd.accesskey "E">
<!ENTITY switchToMetroCmd.label "Relaunch in Windows 8 style &brandShortName;">
<!ENTITY savePageCmd.label "Save Page As…">
<!ENTITY savePageCmd.accesskey "A">
<!-- alternate for content area context menu -->
@ -739,47 +738,7 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY uiTour.infoPanel.close "Close">
<!-- LOCALIZATION NOTE: the following strings are unused in Australis, they're
kept here to avoid warnings from l10n tools like compare-locales on
l10n-central. They will be definitely removed when Australis is ready
for mozilla-aurora. -->
<!ENTITY navbarCmd.accesskey "N">
<!ENTITY addonBarCmd.label "Add-on Bar">
<!ENTITY addonBarCmd.accesskey "A">
<!ENTITY throbberItem.title "Activity Indicator">
<!ENTITY appMenuButton.label "Menu">
<!ENTITY appMenuButton.tooltip "Open &brandShortName; menu">
<!ENTITY feedButton.label "Subscribe">
<!ENTITY feedButton.tooltip "Subscribe to this page…">
<!ENTITY bookmarksButton.tooltip "Display your bookmarks">
<!ENTITY historyButton.tooltip "Display pages you've viewed recently">
<!ENTITY viewTabsOnTop.label "Tabs on Top">
<!ENTITY viewTabsOnTop.accesskey "T">
<!ENTITY appMenuEdit.label "Edit">
<!ENTITY appMenuToolbarLayout.label "Toolbar Layout…">
<!ENTITY appMenuSidebars.label "Sidebars">
<!ENTITY appMenuFind.label "Find…">
<!ENTITY appMenuUnsorted.label "Unsorted Bookmarks">
<!ENTITY appMenuWebDeveloper.label "Web Developer">
<!ENTITY appMenuGettingStarted.label "Getting Started">
<!ENTITY appMenuSafeMode.label "Restart with Add-ons Disabled…">
<!ENTITY appMenuSafeMode.accesskey "R">
<!ENTITY cutButton.tooltip "Cut">
<!ENTITY copyButton.tooltip "Copy">
<!ENTITY pasteButton.tooltip "Paste">
<!ENTITY zoomOutButton.tooltip "Zoom out">
<!ENTITY zoomInButton.tooltip "Zoom in">
<!ENTITY zoomControls.label "Zoom Controls">
<!ENTITY addonBarCloseButton.tooltip "Close Add-on Bar">
<!ENTITY toggleAddonBarCmd.key "/">
<!ENTITY backForwardItem.title "Back/Forward">
<!ENTITY viewBookmarksSidebar.label "Show in Sidebar">
<!ENTITY bookmarksItem.title "Bookmarks">
<!ENTITY openLocationCmd.label "Open Location…">
<!ENTITY openLocationCmd.accesskey "L">
<!ENTITY bookmarksMenuButton.tooltip "Display your bookmarks">
<!ENTITY switchToMetroCmd2.label "Relaunch in &brandShortName; for Windows 8 Touch">
<!ENTITY tabGroupsButton.tooltip "Group your tabs">
<!-- end of strings to be removed post-Australis -->
<!ENTITY switchToMetroCmd2.label "Relaunch in &brandShortName; for Windows 8 Touch">

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -62,7 +62,6 @@ XPCOMUtils.defineLazyGetter(this, "DEFAULT_AREA_PLACEMENTS", function() {
"tabbrowser-tabs",
"new-tab-button",
"alltabs-button",
"tabs-closebutton",
],
"PersonalToolbar": [
"personal-bookmarks",

View File

@ -1772,32 +1772,15 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
z-index: 3;
}
/* In-tab close button */
.tab-close-button > .toolbarbutton-icon {
/* XXX Buttons have padding in widget/ that we don't want here but can't override with good CSS, so we must
use evil CSS to give the impression of smaller content */
margin: -4px;
}
/* Tabstrip close button */
.tabs-closebutton,
.tab-close-button {
-moz-appearance: none;
height: 16px;
width: 16px;
}
.tabs-closebutton:not([selected]):not(:hover),
/* Tab close button */
.tab-close-button:not([selected]):not(:hover) {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 64, 16, 48);
}
.tabs-closebutton:not([selected]):not(:hover):-moz-lwtheme-brighttext,
.tab-close-button:not([selected]):not(:hover):-moz-lwtheme-brighttext {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
}
.tabs-closebutton:not([selected]):not(:hover):-moz-lwtheme-darktext,
.tab-close-button:not([selected]):not(:hover):-moz-lwtheme-darktext {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 96, 16, 80);
}
@ -1810,23 +1793,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
-moz-image-region: auto;
}
.customization-tipPanel-closeBox > .close-icon {
-moz-appearance: none;
width: 16px;
height: 16px;
}
/* The :hover:active style from toolkit doesn't seem to work in this panel so just use :active. */
.customization-tipPanel-closeBox > .close-icon:active {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 48, 16, 32);
}
.tabs-closebutton > .toolbarbutton-icon {
/* XXX Buttons have padding in widget/ that we don't want here but can't override with good CSS, so we must
use evil CSS to give the impression of smaller content */
margin: -2px;
}
/* Tabbrowser arrowscrollbox arrows */
.tabbrowser-arrowscrollbox > .scrollbutton-up,
.tabbrowser-arrowscrollbox > .scrollbutton-down {
@ -1903,11 +1869,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
/* Sidebar */
#sidebar-header > .tabs-closebutton {
margin-bottom: 0px !important;
padding: 0px 2px 0px 2px !important;
}
#sidebar-throbber[loading="true"] {
list-style-image: url("chrome://global/skin/icons/loading_16.png");
-moz-margin-end: 4px;
@ -2235,6 +2196,11 @@ chatbox {
border-left: 3px solid transparent;
}
/* The :hover:active style from toolkit doesn't seem to work in this panel so just use :active. */
.customization-tipPanel-closeBox > .close-icon:active {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 48, 16, 32);
}
/* End customization mode */

View File

@ -9,7 +9,7 @@
}
.requests-menu-status-and-method {
width: 7em;
width: 9em;
}
.requests-menu-domain {

View File

@ -228,7 +228,6 @@ browser.jar:
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
skin/classic/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
skin/classic/browser/devtools/magnifying-glass-light@2x.png (../shared/devtools/images/magnifying-glass-light@2x.png)
skin/classic/browser/devtools/option-icon.png (../shared/devtools/images/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (../shared/devtools/images/itemToggle.png)
skin/classic/browser/devtools/itemToggle-light.png (../shared/devtools/images/itemToggle-light.png)
skin/classic/browser/devtools/itemArrow-dark-rtl.png (../shared/devtools/images/itemArrow-dark-rtl.png)

View File

@ -2623,10 +2623,6 @@ sidebarheader {
list-style-image: url("chrome://global/skin/icons/loading_16.png");
}
sidebarheader > .tabs-closebutton > .toolbarbutton-text {
display: none;
}
/* ----- CONTENT ----- */
.browserContainer > findbar {
@ -3179,18 +3175,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
box-shadow: inset -5px 0 ThreeDShadow;
}
/* Tabstrip close button */
.tabs-closebutton {
-moz-padding-end: 4px;
border: none;
}
@media (min-resolution: 2dppx) {
.tabs-closebutton > .toolbarbutton-icon {
width: 16px;
}
}
/* Bookmarks toolbar */
#PlacesToolbarDropIndicator {
list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png);

View File

@ -349,7 +349,6 @@ browser.jar:
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
skin/classic/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
skin/classic/browser/devtools/magnifying-glass-light@2x.png (../shared/devtools/images/magnifying-glass-light@2x.png)
skin/classic/browser/devtools/option-icon.png (../shared/devtools/images/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (../shared/devtools/images/itemToggle.png)
skin/classic/browser/devtools/itemToggle-light.png (../shared/devtools/images/itemToggle-light.png)
skin/classic/browser/devtools/itemArrow-dark-rtl.png (../shared/devtools/images/itemArrow-dark-rtl.png)

View File

@ -728,7 +728,7 @@ menuitem.subviewbutton@menuStateHover@,
border-color: hsla(210,4%,10%,.11);
}
panelview .toolbarbutton-1@buttonStateActive@,
panelview .toolbarbutton-1:-moz-any(@buttonStateActive@,[checked=true]),
toolbarbutton.subviewbutton@buttonStateActive@,
menu.subviewbutton@menuStateActive@,
menuitem.subviewbutton@menuStateActive@,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 B

View File

@ -119,14 +119,14 @@
.devtools-option-toolbarbutton {
-moz-appearance: none;
list-style-image: url("chrome://browser/skin/devtools/option-icon.png");
-moz-image-region: rect(0px 16px 16px 0px);
list-style-image: url("chrome://browser/skin/devtools/tool-options.svg");
background: none;
opacity: .8;
border: none;
}
.devtools-option-toolbarbutton[open=true] {
-moz-image-region: rect(0px 32px 16px 16px);
opacity: 1;
}
.devtools-menulist > .menulist-label-box {
@ -792,7 +792,6 @@
.theme-light .command-button-invertable[checked=true]:not(:active) > image,
.theme-light .devtools-tab[icon-invertable][selected] > image,
.theme-light .devtools-tab[icon-invertable][highlighted] > image,
.theme-light .devtools-option-toolbarbutton[open] > image,
.theme-light #resume[checked] > image {
filter: none !important;
}

View File

@ -1766,6 +1766,13 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
-moz-padding-start: 0px;
}
#sidebar-header > .close-icon {
-moz-appearance: none;
padding: 4px 2px;
margin: 0;
border: none;
}
.browserContainer > findbar {
background-color: -moz-dialog;
color: -moz-DialogText;
@ -1997,20 +2004,6 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
box-shadow: inset -5px 0 ThreeDShadow;
}
/* Tabstrip close button */
.tabs-closebutton {
-moz-appearance: none;
padding: 4px 2px;
margin: 0px;
border: none;
}
.tabs-closebutton > .toolbarbutton-icon {
-moz-margin-end: 0px !important;
-moz-padding-end: 2px !important;
-moz-padding-start: 2px !important;
}
toolbarbutton.chevron {
list-style-image: url("chrome://global/skin/toolbar/chevron.gif") !important;
}

View File

@ -265,7 +265,6 @@ browser.jar:
skin/classic/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
skin/classic/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
skin/classic/browser/devtools/magnifying-glass-light@2x.png (../shared/devtools/images/magnifying-glass-light@2x.png)
skin/classic/browser/devtools/option-icon.png (../shared/devtools/images/option-icon.png)
skin/classic/browser/devtools/itemToggle.png (../shared/devtools/images/itemToggle.png)
skin/classic/browser/devtools/itemToggle-light.png (../shared/devtools/images/itemToggle-light.png)
skin/classic/browser/devtools/itemArrow-dark-rtl.png (../shared/devtools/images/itemArrow-dark-rtl.png)
@ -628,7 +627,6 @@ browser.jar:
skin/classic/aero/browser/devtools/magnifying-glass@2x.png (../shared/devtools/images/magnifying-glass@2x.png)
skin/classic/aero/browser/devtools/magnifying-glass-light.png (../shared/devtools/images/magnifying-glass-light.png)
skin/classic/aero/browser/devtools/magnifying-glass-light@2x.png (../shared/devtools/images/magnifying-glass-light@2x.png)
skin/classic/aero/browser/devtools/option-icon.png (../shared/devtools/images/option-icon.png)
skin/classic/aero/browser/devtools/itemToggle.png (../shared/devtools/images/itemToggle.png)
skin/classic/aero/browser/devtools/itemToggle-light.png (../shared/devtools/images/itemToggle-light.png)
skin/classic/aero/browser/devtools/itemArrow-dark-rtl.png (../shared/devtools/images/itemArrow-dark-rtl.png)

View File

@ -15,7 +15,6 @@ DEPRECATED_OPERATION(SetAttributeNodeNS)
DEPRECATED_OPERATION(RemoveAttributeNode)
DEPRECATED_OPERATION(CreateAttribute)
DEPRECATED_OPERATION(CreateAttributeNS)
DEPRECATED_OPERATION(Specified)
DEPRECATED_OPERATION(OwnerElement)
DEPRECATED_OPERATION(NodeValue)
DEPRECATED_OPERATION(TextContent)

View File

@ -226,7 +226,6 @@ Attr::SetValue(const nsAString& aValue)
bool
Attr::Specified() const
{
OwnerDoc()->WarnOnceAbout(nsIDocument::eSpecified);
return true;
}

View File

@ -1493,6 +1493,8 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
nsCOMPtr<nsIInputStream> input;
channel->Open(getter_AddRefs(input));
nsString dataString;
jschar* dataStringBuf = nullptr;
size_t dataStringLength = 0;
uint64_t avail64 = 0;
if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) {
if (avail64 > UINT32_MAX) {
@ -1504,10 +1506,14 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
return;
}
nsScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
EmptyString(), nullptr, dataString);
EmptyString(), nullptr,
dataStringBuf, dataStringLength);
}
if (!dataString.IsEmpty()) {
JS::SourceBufferHolder srcBuf(dataStringBuf, dataStringLength,
JS::SourceBufferHolder::GiveOwnership);
if (dataStringBuf && dataStringLength > 0) {
AutoSafeJSContext cx;
JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
if (global) {
@ -1518,14 +1524,12 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
JS::Rooted<JSObject*> funobj(cx);
if (aRunInGlobalScope) {
options.setNoScriptRval(true);
script = JS::Compile(cx, JS::NullPtr(), options, dataString.get(),
dataString.Length());
script = JS::Compile(cx, JS::NullPtr(), options, srcBuf);
} else {
JS::Rooted<JSFunction *> fun(cx);
fun = JS::CompileFunction(cx, JS::NullPtr(), options,
nullptr, 0, nullptr, /* name, nargs, args */
dataString.get(),
dataString.Length());
srcBuf);
if (!fun) {
return;
}

View File

@ -1286,7 +1286,8 @@ nsINode::UnoptimizableCCNode() const
const uintptr_t problematicFlags = (NODE_IS_ANONYMOUS_ROOT |
NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
NODE_IS_NATIVE_ANONYMOUS_ROOT |
NODE_MAY_BE_IN_BINDING_MNGR);
NODE_MAY_BE_IN_BINDING_MNGR |
NODE_IS_IN_SHADOW_TREE);
return HasFlag(problematicFlags) ||
NodeType() == nsIDOMNode::ATTRIBUTE_NODE ||
// For strange cases like xbl:content/xbl:children

View File

@ -76,12 +76,21 @@ public:
mLoading(true),
mIsInline(true),
mHasSourceMapURL(false),
mScriptTextBuf(nullptr),
mScriptTextLength(0),
mJSVersion(aVersion),
mLineNo(1),
mCORSMode(aCORSMode)
{
}
~nsScriptLoadRequest()
{
if (mScriptTextBuf) {
js_free(mScriptTextBuf);
}
}
NS_DECL_THREADSAFE_ISUPPORTS
void FireScriptAvailable(nsresult aResult)
@ -103,7 +112,8 @@ public:
bool mIsInline; // Is the script inline or loaded?
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
nsString mSourceMapURL; // Holds source map url for loaded scripts
nsString mScriptText; // Holds script for text loaded scripts
jschar* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
uint32_t mJSVersion;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
@ -851,7 +861,7 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
JS::CompileOptions options(cx);
FillCompileOptionsForRequest(aRequest, global, &options);
if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptText.Length())) {
if (!JS::CanCompileOffThread(cx, options, aRequest->mScriptTextLength)) {
return NS_ERROR_FAILURE;
}
@ -859,7 +869,7 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
new NotifyOffThreadScriptLoadCompletedRunnable(aRequest, this);
if (!JS::CompileOffThread(cx, options,
aRequest->mScriptText.get(), aRequest->mScriptText.Length(),
aRequest->mScriptTextBuf, aRequest->mScriptTextLength,
OffThreadScriptLoaderCallback,
static_cast<void*>(runnable))) {
return NS_ERROR_OUT_OF_MEMORY;
@ -884,8 +894,11 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
}
NS_ENSURE_ARG(aRequest);
nsAFlatString* script;
nsAutoString textData;
const jschar* scriptBuf = nullptr;
size_t scriptLength = 0;
JS::SourceBufferHolder::Ownership giveScriptOwnership =
JS::SourceBufferHolder::NoOwnership;
nsCOMPtr<nsIDocument> doc;
@ -897,14 +910,23 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
// copies.
aRequest->mElement->GetScriptText(textData);
script = &textData;
scriptBuf = textData.get();
scriptLength = textData.Length();
giveScriptOwnership = JS::SourceBufferHolder::NoOwnership;
}
else {
script = &aRequest->mScriptText;
scriptBuf = aRequest->mScriptTextBuf;
scriptLength = aRequest->mScriptTextLength;
giveScriptOwnership = JS::SourceBufferHolder::GiveOwnership;
aRequest->mScriptTextBuf = nullptr;
aRequest->mScriptTextLength = 0;
doc = scriptElem->OwnerDoc();
}
JS::SourceBufferHolder srcBuf(scriptBuf, scriptLength, giveScriptOwnership);
nsCOMPtr<nsIScriptElement> oldParserInsertedScript;
uint32_t parserCreated = aRequest->mElement->GetParserCreated();
if (parserCreated) {
@ -937,7 +959,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
doc->BeginEvaluatingExternalScript();
}
aRequest->mElement->BeginEvaluating();
rv = EvaluateScript(aRequest, *script, aOffThreadToken);
rv = EvaluateScript(aRequest, srcBuf, aOffThreadToken);
aRequest->mElement->EndEvaluating();
if (doc) {
doc->EndEvaluatingExternalScript();
@ -1044,7 +1066,7 @@ nsScriptLoader::FillCompileOptionsForRequest(nsScriptLoadRequest *aRequest,
nsresult
nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript,
JS::SourceBufferHolder& aSrcBuf,
void** aOffThreadToken)
{
// We need a document to evaluate scripts.
@ -1095,7 +1117,7 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
JS::CompileOptions options(entryScript.cx());
FillCompileOptionsForRequest(aRequest, global, &options);
nsresult rv = nsJSUtils::EvaluateString(entryScript.cx(), aScript, global, options,
nsresult rv = nsJSUtils::EvaluateString(entryScript.cx(), aSrcBuf, global, options,
aOffThreadToken);
// Put the old script back in case it wants to do anything else.
@ -1246,10 +1268,12 @@ DetectByteOrderMark(const unsigned char* aBytes, int32_t aLen, nsCString& oChars
/* static */ nsresult
nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength, const nsAString& aHintCharset,
nsIDocument* aDocument, nsString& aString)
nsIDocument* aDocument,
jschar*& aBufOut, size_t& aLengthOut)
{
if (!aLength) {
aString.Truncate();
aBufOut = nullptr;
aLengthOut = 0;
return NS_OK;
}
@ -1302,17 +1326,23 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
aLength, &unicodeLength);
NS_ENSURE_SUCCESS(rv, rv);
if (!aString.SetLength(unicodeLength, fallible_t())) {
aBufOut = static_cast<jschar*>(js_malloc(unicodeLength * sizeof(jschar)));
if (!aBufOut) {
aLengthOut = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
char16_t *ustr = aString.BeginWriting();
aLengthOut = unicodeLength;
rv = unicodeDecoder->Convert(reinterpret_cast<const char*>(aData),
(int32_t *) &aLength, ustr,
(int32_t *) &aLength, aBufOut,
&unicodeLength);
MOZ_ASSERT(NS_SUCCEEDED(rv));
aString.SetLength(unicodeLength);
aLengthOut = unicodeLength;
if (NS_FAILED(rv)) {
js_free(aBufOut);
aBufOut = nullptr;
aLengthOut = 0;
}
return rv;
}
@ -1426,7 +1456,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
hintCharset = mPreloads[i].mCharset;
}
rv = ConvertToUTF16(channel, aString, aStringLen, hintCharset, mDocument,
aRequest->mScriptText);
aRequest->mScriptTextBuf, aRequest->mScriptTextLength);
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -21,6 +21,10 @@
class nsScriptLoadRequest;
class nsIURI;
namespace JS {
class SourceBufferHolder;
}
//////////////////////////////////////////////////////////////
// Script loader implementation
//////////////////////////////////////////////////////////////
@ -140,12 +144,17 @@ public:
* attribute). May be the empty string.
* @param aDocument Document which the data is loaded for. Must not be
* null.
* @param aString [out] Data as converted to unicode
* @param aBufOut [out] jschar array allocated by ConvertToUTF16 and
* containing data converted to unicode. Caller must
* js_free() this data when no longer needed.
* @param aLengthOut [out] Length of array returned in aBufOut in number
* of jschars.
*/
static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength,
const nsAString& aHintCharset,
nsIDocument* aDocument, nsString& aString);
nsIDocument* aDocument,
jschar*& aBufOut, size_t& aLengthOut);
/**
* Processes any pending requests that are ready for processing.
@ -277,7 +286,7 @@ private:
void FireScriptEvaluated(nsresult aResult,
nsScriptLoadRequest* aRequest);
nsresult EvaluateScript(nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript,
JS::SourceBufferHolder& aSrcBuf,
void **aOffThreadToken);
already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();

View File

@ -479,7 +479,7 @@ skip-if = os == "win" || (buildapp=='b2g'&&debug) || (toolkit == 'gonk' && !debu
[test_media_selection.html]
skip-if = os == "win" || (toolkit == 'gonk' && !debug) # See bug 897843, b2g(timed out)
[test_seek.html]
skip-if = toolkit == 'android' || os == "win" || (toolkit == 'gonk' && !debug) # See bug 832678, 795271, and 857424 # android(bug 845162) androidx86(bug 845162)
skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) # See bug 832678, 795271, and 857424 # android(bug 845162) androidx86(bug 845162)
# The tests below contain backend-specific tests. Write backend independent
# tests rather than adding to this list.

View File

@ -23,6 +23,7 @@
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.requestLongerTimeout(3);
var manager = new MediaTestManager;
// https://bugzilla.mozilla.org/show_bug.cgi?id=634747
@ -73,9 +74,8 @@ function startTest(test, token) {
ok(a, name + ": " + msg);
}}(name);
var localFinish = function(v, manager) { return function() {
if (v.parentNode) {
v.parentNode.removeChild(v);
}
v.onerror = null;
removeNodeAndSource(v);
dump("SEEK-TEST: Finished " + name + "\n");
manager.finished(v.token);
}}(v, manager);

View File

@ -22,6 +22,8 @@
#include "nsISupportsUtils.h"
#endif
#include "YuvStamper.h"
#define VIDEO_RATE USECS_PER_S
#define AUDIO_RATE 16000
#define AUDIO_FRAME_LENGTH ((AUDIO_RATE * MediaEngine::DEFAULT_AUDIO_TIMER_MS) / 1000)
@ -239,6 +241,13 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
static_cast<layers::PlanarYCbCrImage*>(image.get());
layers::PlanarYCbCrData data;
AllocateSolidColorFrame(data, mOpts.mWidth, mOpts.mHeight, 0x80, mCb, mCr);
uint64_t timestamp = PR_Now();
YuvStamper::Encode(mOpts.mWidth, mOpts.mHeight, mOpts.mWidth,
data.mYChannel,
reinterpret_cast<unsigned char*>(&timestamp), sizeof(timestamp),
0, 0);
ycbcr_image->SetData(data);
// SetData copies data, so we can free the frame
ReleaseFrame(data);

View File

@ -142,6 +142,7 @@ AudioOutputObserver::InsertFarEnd(const AudioDataValue *aBuffer, uint32_t aSampl
#endif
aSamples -= to_copy;
mSamplesSaved += to_copy;
aBuffer += to_copy * aChannels;
if (mSamplesSaved >= mChunkSize) {
int free_slots = mPlayoutFifo->capacity() - mPlayoutFifo->size();

View File

@ -2619,8 +2619,7 @@ OffThreadScriptReceiverCallback(void *aToken, void *aCallbackData)
}
nsresult
nsXULPrototypeScript::Compile(const char16_t* aText,
int32_t aTextLength,
nsXULPrototypeScript::Compile(JS::SourceBufferHolder& aSrcBuf,
nsIURI* aURI,
uint32_t aLineNo,
nsIDocument* aDocument,
@ -2651,9 +2650,9 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
JS::ExposeObjectToActiveJS(scope);
}
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aSrcBuf.length())) {
if (!JS::CompileOffThread(cx, options,
static_cast<const jschar*>(aText), aTextLength,
aSrcBuf.get(), aSrcBuf.length(),
OffThreadScriptReceiverCallback,
static_cast<void*>(aOffThreadReceiver))) {
return NS_ERROR_OUT_OF_MEMORY;
@ -2661,8 +2660,7 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
// This reference will be consumed by the NotifyOffThreadScriptCompletedRunnable.
NS_ADDREF(aOffThreadReceiver);
} else {
JSScript* script = JS::Compile(cx, scope, options,
static_cast<const jschar*>(aText), aTextLength);
JSScript* script = JS::Compile(cx, scope, options, aSrcBuf);
if (!script)
return NS_ERROR_OUT_OF_MEMORY;
Set(script);
@ -2670,6 +2668,20 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
return NS_OK;
}
nsresult
nsXULPrototypeScript::Compile(const char16_t* aText,
int32_t aTextLength,
nsIURI* aURI,
uint32_t aLineNo,
nsIDocument* aDocument,
nsXULPrototypeDocument* aProtoDoc,
nsIOffThreadScriptReceiver *aOffThreadReceiver /* = nullptr */)
{
JS::SourceBufferHolder srcBuf(aText, aTextLength,
JS::SourceBufferHolder::NoOwnership);
return Compile(srcBuf, aURI, aLineNo, aDocument, aProtoDoc, aOffThreadReceiver);
}
void
nsXULPrototypeScript::UnlinkJSObjects()
{

View File

@ -56,6 +56,10 @@ class StyleRule;
}
}
namespace JS {
class SourceBufferHolder;
}
////////////////////////////////////////////////////////////////////////
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
@ -231,6 +235,12 @@ public:
nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput,
nsXULPrototypeDocument* aProtoDoc);
nsresult Compile(JS::SourceBufferHolder& aSrcBuf,
nsIURI* aURI, uint32_t aLineNo,
nsIDocument* aDocument,
nsXULPrototypeDocument* aProtoDoc,
nsIOffThreadScriptReceiver *aOffThreadReceiver = nullptr);
nsresult Compile(const char16_t* aText, int32_t aTextLength,
nsIURI* aURI, uint32_t aLineNo,
nsIDocument* aDocument,

View File

@ -245,6 +245,10 @@ XULDocument::~XULDocument()
NS_IF_RELEASE(kNC_attribute);
NS_IF_RELEASE(kNC_value);
}
if (mOffThreadCompileStringBuf) {
js_free(mOffThreadCompileStringBuf);
}
}
} // namespace dom
@ -3526,14 +3530,26 @@ XULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
// XXX should also check nsIHttpChannel::requestSucceeded
MOZ_ASSERT(!mOffThreadCompiling && mOffThreadCompileString.Length() == 0,
MOZ_ASSERT(!mOffThreadCompiling && (mOffThreadCompileStringLength == 0 &&
!mOffThreadCompileStringBuf),
"XULDocument can't load multiple scripts at once");
rv = nsScriptLoader::ConvertToUTF16(channel, string, stringLen,
EmptyString(), this, mOffThreadCompileString);
EmptyString(), this,
mOffThreadCompileStringBuf,
mOffThreadCompileStringLength);
if (NS_SUCCEEDED(rv)) {
rv = mCurrentScriptProto->Compile(mOffThreadCompileString.get(),
mOffThreadCompileString.Length(),
// Attempt to give ownership of the buffer to the JS engine. If
// we hit offthread compilation, however, we will have to take it
// back below in order to keep the memory alive until compilation
// completes.
JS::SourceBufferHolder srcBuf(mOffThreadCompileStringBuf,
mOffThreadCompileStringLength,
JS::SourceBufferHolder::GiveOwnership);
mOffThreadCompileStringBuf = nullptr;
mOffThreadCompileStringLength = 0;
rv = mCurrentScriptProto->Compile(srcBuf,
uri, 1, this,
mCurrentPrototype,
this);
@ -3542,10 +3558,15 @@ XULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
// compile finishes. Keep the contents of the compiled script
// alive until the compilation finishes.
mOffThreadCompiling = true;
// If the JS engine did not take the source buffer, then take
// it back here to ensure it remains alive.
mOffThreadCompileStringBuf = srcBuf.take();
if (mOffThreadCompileStringBuf) {
mOffThreadCompileStringLength = srcBuf.length();
}
BlockOnload();
return NS_OK;
}
mOffThreadCompileString.Truncate();
}
}
@ -3567,7 +3588,11 @@ XULDocument::OnScriptCompileComplete(JSScript* aScript, nsresult aStatus)
}
// After compilation finishes the script's characters are no longer needed.
mOffThreadCompileString.Truncate();
if (mOffThreadCompileStringBuf) {
js_free(mOffThreadCompileStringBuf);
mOffThreadCompileStringBuf = nullptr;
mOffThreadCompileStringLength = 0;
}
// Clear mCurrentScriptProto now, but save it first for use below in
// the execute code, and in the while loop that resumes walks of other

View File

@ -460,7 +460,8 @@ protected:
* If the current transcluded script is being compiled off thread, the
* source for that script.
*/
nsString mOffThreadCompileString;
jschar* mOffThreadCompileStringBuf;
size_t mOffThreadCompileStringLength;
/**
* Check if a XUL template builder has already been hooked up.

View File

@ -179,6 +179,22 @@ nsJSUtils::EvaluateString(JSContext* aCx,
const EvaluateOptions& aEvaluateOptions,
JS::MutableHandle<JS::Value> aRetValue,
void **aOffThreadToken)
{
const nsPromiseFlatString& flatScript = PromiseFlatString(aScript);
JS::SourceBufferHolder srcBuf(flatScript.get(), aScript.Length(),
JS::SourceBufferHolder::NoOwnership);
return EvaluateString(aCx, srcBuf, aScopeObject, aCompileOptions,
aEvaluateOptions, aRetValue, aOffThreadToken);
}
nsresult
nsJSUtils::EvaluateString(JSContext* aCx,
JS::SourceBufferHolder& aSrcBuf,
JS::Handle<JSObject*> aScopeObject,
JS::CompileOptions& aCompileOptions,
const EvaluateOptions& aEvaluateOptions,
JS::MutableHandle<JS::Value> aRetValue,
void **aOffThreadToken)
{
PROFILER_LABEL("JS", "EvaluateString");
MOZ_ASSERT_IF(aCompileOptions.versionSet,
@ -186,6 +202,7 @@ nsJSUtils::EvaluateString(JSContext* aCx,
MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aEvaluateOptions.needResult);
MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aEvaluateOptions.needResult);
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
MOZ_ASSERT(aSrcBuf.get());
// Unfortunately, the JS engine actually compiles scripts with a return value
// in a different, less efficient way. Furthermore, it can't JIT them in many
@ -232,12 +249,10 @@ nsJSUtils::EvaluateString(JSContext* aCx,
} else {
if (aEvaluateOptions.needResult) {
ok = JS::Evaluate(aCx, rootedScope, aCompileOptions,
PromiseFlatString(aScript).get(),
aScript.Length(), aRetValue);
aSrcBuf, aRetValue);
} else {
ok = JS::Evaluate(aCx, rootedScope, aCompileOptions,
PromiseFlatString(aScript).get(),
aScript.Length());
aSrcBuf);
}
}
@ -292,6 +307,20 @@ nsJSUtils::EvaluateString(JSContext* aCx,
options, &unused, aOffThreadToken);
}
nsresult
nsJSUtils::EvaluateString(JSContext* aCx,
JS::SourceBufferHolder& aSrcBuf,
JS::Handle<JSObject*> aScopeObject,
JS::CompileOptions& aCompileOptions,
void **aOffThreadToken)
{
EvaluateOptions options;
options.setNeedResult(false);
JS::RootedValue unused(aCx);
return EvaluateString(aCx, aSrcBuf, aScopeObject, aCompileOptions,
options, &unused, aOffThreadToken);
}
//
// nsDOMJSUtils.h
//

View File

@ -95,6 +95,14 @@ public:
JS::MutableHandle<JS::Value> aRetValue,
void **aOffThreadToken = nullptr);
static nsresult EvaluateString(JSContext* aCx,
JS::SourceBufferHolder& aSrcBuf,
JS::Handle<JSObject*> aScopeObject,
JS::CompileOptions &aCompileOptions,
const EvaluateOptions& aEvaluateOptions,
JS::MutableHandle<JS::Value> aRetValue,
void **aOffThreadToken = nullptr);
static nsresult EvaluateString(JSContext* aCx,
const nsAString& aScript,
@ -102,6 +110,12 @@ public:
JS::CompileOptions &aCompileOptions,
void **aOffThreadToken = nullptr);
static nsresult EvaluateString(JSContext* aCx,
JS::SourceBufferHolder& aSrcBuf,
JS::Handle<JSObject*> aScopeObject,
JS::CompileOptions &aCompileOptions,
void **aOffThreadToken = nullptr);
};
class MOZ_STACK_CLASS AutoDontReportUncaught {

View File

@ -49,7 +49,6 @@ SetAttributeNodeNSWarning=Use of setAttributeNodeNS() is deprecated. Use setAttr
RemoveAttributeNodeWarning=Use of removeAttributeNode() is deprecated. Use removeAttribute() instead.
CreateAttributeWarning=Use of document.createAttribute() is deprecated. Use element.setAttribute() instead.
CreateAttributeNSWarning=Use of document.createAttributeNS() is deprecated. Use element.setAttributeNS() instead.
SpecifiedWarning=Use of attributes' specified attribute is deprecated. It always returns true.
OwnerElementWarning=Use of attributes' ownerElement attribute is deprecated.
NodeValueWarning=Use of attributes' nodeValue attribute is deprecated. Use value instead.
TextContentWarning=Use of attributes' textContent attribute is deprecated. Use value instead.

View File

@ -8,7 +8,8 @@ function test() {
let fm = Components.classes["@mozilla.org/focus-manager;1"]
.getService(Components.interfaces.nsIFocusManager);
let tabs = [ gBrowser.selectedTab, gBrowser.addTab() ];
let tabs = [ gBrowser.addTab(), gBrowser.addTab() ];
gBrowser.selectedTab = tabs[0];
let testingList = [
{ uri: "data:text/html,<body onload=\"setTimeout(function () { document.getElementById('target').focus(); }, 10);\"><input id='target'></body>",
@ -61,7 +62,6 @@ function test() {
function runNextTest() {
if (++testingIndex >= testingList.length) {
// cleaning-up...
gBrowser.addTab();
for (let i = 0; i < tabs.length; i++) {
gBrowser.removeTab(tabs[i]);
}

View File

@ -13,7 +13,8 @@ function test() {
"<button id=\"eventTarget\" onmousedown=\"onMouseDown(event);\">click here</button>" +
"<input id=\"willBeFocused\"></body>";
let tab = gBrowser.selectedTab;
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
// Set the focus to the contents.
tab.linkedBrowser.focus();
@ -52,7 +53,6 @@ function test() {
button);
}
gBrowser.addTab();
gBrowser.removeTab(tab);
finish();
}

View File

@ -18,14 +18,13 @@ interface Attr : Node {
readonly attribute DOMString name;
readonly attribute DOMString? namespaceURI;
readonly attribute DOMString? prefix;
readonly attribute boolean specified;
};
// Mozilla extensions
partial interface Attr {
readonly attribute boolean specified;
[GetterThrows]
readonly attribute Element? ownerElement;
};

View File

@ -135,10 +135,19 @@ ChannelFromScriptURL(nsIPrincipal* principal,
struct ScriptLoadInfo
{
ScriptLoadInfo()
: mLoadResult(NS_ERROR_NOT_INITIALIZED), mExecutionScheduled(false),
mExecutionResult(false)
: mScriptTextBuf(nullptr)
, mScriptTextLength(0)
, mLoadResult(NS_ERROR_NOT_INITIALIZED), mExecutionScheduled(false)
, mExecutionResult(false)
{ }
~ScriptLoadInfo()
{
if (mScriptTextBuf) {
js_free(mScriptTextBuf);
}
}
bool
ReadyToExecute()
{
@ -147,7 +156,8 @@ struct ScriptLoadInfo
nsString mURL;
nsCOMPtr<nsIChannel> mChannel;
nsString mScriptText;
jschar* mScriptTextBuf;
size_t mScriptTextLength;
nsresult mLoadResult;
bool mExecutionScheduled;
@ -448,12 +458,13 @@ private:
// per spec. So we explicitly pass in the charset hint.
rv = nsScriptLoader::ConvertToUTF16(aLoadInfo.mChannel, aString, aStringLen,
NS_LITERAL_STRING("UTF-8"), parentDoc,
aLoadInfo.mScriptText);
aLoadInfo.mScriptTextBuf,
aLoadInfo.mScriptTextLength);
if (NS_FAILED(rv)) {
return rv;
}
if (aLoadInfo.mScriptText.IsEmpty()) {
if (!aLoadInfo.mScriptTextBuf || !aLoadInfo.mScriptTextLength) {
return NS_ERROR_FAILURE;
}
@ -730,8 +741,14 @@ ScriptExecutorRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
JS::CompileOptions options(aCx);
options.setFileAndLine(filename.get(), 1);
if (!JS::Evaluate(aCx, global, options, loadInfo.mScriptText.get(),
loadInfo.mScriptText.Length())) {
JS::SourceBufferHolder srcBuf(loadInfo.mScriptTextBuf,
loadInfo.mScriptTextLength,
JS::SourceBufferHolder::GiveOwnership);
loadInfo.mScriptTextBuf = nullptr;
loadInfo.mScriptTextLength = 0;
if (!JS::Evaluate(aCx, global, options, srcBuf)) {
return true;
}

View File

@ -107,18 +107,33 @@ Compositor::DrawDiagnostics(DiagnosticFlags aFlags,
gfx::Rect
Compositor::ClipRectInLayersCoordinates(gfx::Rect aClip) const {
gfx::Rect result;
aClip = aClip + GetCurrentRenderTarget()->GetOrigin();
gfx::IntSize destSize = GetWidgetSize();
switch (mScreenRotation) {
case ROTATION_90:
case ROTATION_270:
result = gfx::Rect(aClip.y, aClip.x, aClip.height, aClip.width);
break;
case ROTATION_0:
case ROTATION_180:
default:
result = aClip;
break;
case ROTATION_90:
result = gfx::Rect(aClip.y,
destSize.width - aClip.x - aClip.width,
aClip.height, aClip.width);
break;
case ROTATION_270:
result = gfx::Rect(destSize.height - aClip.y - aClip.height,
aClip.x,
aClip.height, aClip.width);
break;
case ROTATION_180:
result = gfx::Rect(destSize.width - aClip.x - aClip.width,
destSize.height - aClip.y - aClip.height,
aClip.width, aClip.height);
break;
// ScreenRotation has a sentinel value, need to catch it in the switch
// statement otherwise the build fails (-WError)
default: {}
}
return result + GetCurrentRenderTarget()->GetOrigin();
return result;
}
void

View File

@ -500,6 +500,7 @@ public:
// In addition, the clip rect needs to be offset by the rendering origin.
// This becomes important if intermediate surfaces are used.
gfx::Rect ClipRectInLayersCoordinates(gfx::Rect aClip) const;
protected:
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
const gfx::Rect& aVisibleRect,
@ -528,6 +529,8 @@ protected:
ScreenRotation mScreenRotation;
virtual gfx::IntSize GetWidgetSize() const = 0;
private:
static LayersBackend sBackend;

View File

@ -378,6 +378,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
{
nsIntRect intRect;
mWidget->GetClientBounds(intRect);
mWidgetSize = gfx::ToIntSize(intRect.Size());
// The result of GetClientBounds is shifted over by the size of the window
// manager styling. We want to ignore that.

View File

@ -125,9 +125,12 @@ public:
gfx::DrawTarget *GetDrawTarget() { return mDrawTarget; }
private:
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE { return mWidgetSize; }
// Widget associated with this compositor
nsIWidget *mWidget;
nsIntSize mWidgetSize;
gfx::IntSize mWidgetSize;
// The final destination surface
RefPtr<gfx::DrawTarget> mDrawTarget;

View File

@ -485,7 +485,14 @@ TileClient::DiscardBackBuffer()
{
if (mBackBuffer) {
MOZ_ASSERT(mBackLock);
mManager->GetTexturePool(mBackBuffer->GetFormat())->ReturnTextureClient(mBackBuffer);
if (!mBackBuffer->ImplementsLocking() && mBackLock->GetReadCount() > 1) {
// Our current back-buffer is still locked by the compositor. This can occur
// when the client is producing faster than the compositor can consume. In
// this case we just want to drop it and not return it to the pool.
mManager->GetTexturePool(mBackBuffer->GetFormat())->ReportClientLost();
} else {
mManager->GetTexturePool(mBackBuffer->GetFormat())->ReturnTextureClient(mBackBuffer);
}
mBackLock->ReadUnlock();
mBackBuffer = nullptr;
mBackLock = nullptr;

View File

@ -22,8 +22,49 @@ namespace layers {
class Compositor;
/**
* IPDL actor used by CompositableHost to match with its corresponding
* CompositableClient on the content side.
*
* CompositableParent is owned by the IPDL system. It's deletion is triggered
* by either the CompositableChild's deletion, or by the IPDL communication
* goind down.
*/
class CompositableParent : public PCompositableParent
{
public:
CompositableParent(CompositableParentManager* aMgr,
const TextureInfo& aTextureInfo,
uint64_t aID = 0)
{
MOZ_COUNT_CTOR(CompositableParent);
mHost = CompositableHost::Create(aTextureInfo);
mHost->SetAsyncID(aID);
if (aID) {
CompositableMap::Set(aID, this);
}
}
~CompositableParent()
{
MOZ_COUNT_DTOR(CompositableParent);
CompositableMap::Erase(mHost->GetAsyncID());
}
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{
if (mHost) {
mHost->Detach(nullptr, CompositableHost::FORCE_DETACH);
}
}
RefPtr<CompositableHost> mHost;
};
CompositableHost::CompositableHost(const TextureInfo& aTextureInfo)
: mTextureInfo(aTextureInfo)
, mAsyncID(0)
, mCompositorID(0)
, mCompositor(nullptr)
, mLayer(nullptr)
, mFlashCounter(0)
@ -41,6 +82,28 @@ CompositableHost::~CompositableHost()
}
}
PCompositableParent*
CompositableHost::CreateIPDLActor(CompositableParentManager* aMgr,
const TextureInfo& aTextureInfo,
uint64_t aID)
{
return new CompositableParent(aMgr, aTextureInfo, aID);
}
bool
CompositableHost::DestroyIPDLActor(PCompositableParent* aActor)
{
delete aActor;
return true;
}
CompositableHost*
CompositableHost::FromIPDLActor(PCompositableParent* aActor)
{
MOZ_ASSERT(aActor);
return static_cast<CompositableParent*>(aActor)->mHost;
}
void
CompositableHost::UseTextureHost(TextureHost* aTexture)
{
@ -171,43 +234,14 @@ CompositableHost::DumpTextureHost(FILE* aFile, TextureHost* aTexture)
}
#endif
void
CompositableParent::ActorDestroy(ActorDestroyReason why)
{
if (mHost) {
mHost->Detach(nullptr, CompositableHost::FORCE_DETACH);
}
}
CompositableParent::CompositableParent(CompositableParentManager* aMgr,
const TextureInfo& aTextureInfo,
uint64_t aID)
: mManager(aMgr)
, mType(aTextureInfo.mCompositableType)
, mID(aID)
, mCompositorID(0)
{
MOZ_COUNT_CTOR(CompositableParent);
mHost = CompositableHost::Create(aTextureInfo);
if (aID) {
CompositableMap::Set(aID, this);
}
}
CompositableParent::~CompositableParent()
{
MOZ_COUNT_DTOR(CompositableParent);
CompositableMap::Erase(mID);
}
namespace CompositableMap {
typedef std::map<uint64_t, CompositableParent*> CompositableMap_t;
typedef std::map<uint64_t, PCompositableParent*> CompositableMap_t;
static CompositableMap_t* sCompositableMap = nullptr;
bool IsCreated() {
return sCompositableMap != nullptr;
}
CompositableParent* Get(uint64_t aID)
PCompositableParent* Get(uint64_t aID)
{
if (!IsCreated() || aID == 0) {
return nullptr;
@ -218,7 +252,7 @@ CompositableParent* Get(uint64_t aID)
}
return it->second;
}
void Set(uint64_t aID, CompositableParent* aParent)
void Set(uint64_t aID, PCompositableParent* aParent)
{
if (!IsCreated() || aID == 0) {
return;

View File

@ -51,6 +51,7 @@ class Compositor;
class ISurfaceAllocator;
class ThebesBufferData;
class TiledLayerComposer;
class CompositableParentManager;
struct EffectChain;
/**
@ -307,8 +308,28 @@ public:
mFlashCounter = mFlashCounter >= DIAGNOSTIC_FLASH_COUNTER_MAX
? DIAGNOSTIC_FLASH_COUNTER_MAX : mFlashCounter + 1;
}
static PCompositableParent*
CreateIPDLActor(CompositableParentManager* mgr,
const TextureInfo& textureInfo,
uint64_t asyncID);
static bool DestroyIPDLActor(PCompositableParent* actor);
static CompositableHost* FromIPDLActor(PCompositableParent* actor);
uint64_t GetCompositorID() const { return mCompositorID; }
uint64_t GetAsyncID() const { return mAsyncID; }
void SetCompositorID(uint64_t aID) { mCompositorID = aID; }
void SetAsyncID(uint64_t aID) { mAsyncID = aID; }
protected:
TextureInfo mTextureInfo;
uint64_t mAsyncID;
uint64_t mCompositorID;
Compositor* mCompositor;
Layer* mLayer;
RefPtr<CompositableBackendSpecificData> mBackendData;
@ -317,65 +338,6 @@ protected:
bool mKeepAttached;
};
class CompositableParentManager;
/**
* IPDL actor used by CompositableHost to match with its corresponding
* CompositableClient on the content side.
*
* CompositableParent is owned by the IPDL system. It's deletion is triggered
* by either the CompositableChild's deletion, or by the IPDL communication
* goind down.
*/
class CompositableParent : public PCompositableParent
{
public:
CompositableParent(CompositableParentManager* aMgr,
const TextureInfo& aTextureInfo,
uint64_t aID = 0);
~CompositableParent();
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
CompositableHost* GetCompositableHost() const
{
return mHost;
}
void SetCompositableHost(CompositableHost* aHost)
{
mHost = aHost;
}
CompositableType GetType() const
{
return mType;
}
CompositableParentManager* GetCompositableManager() const
{
return mManager;
}
void SetCompositorID(uint64_t aCompositorID)
{
mCompositorID = aCompositorID;
}
uint64_t GetCompositorID() const
{
return mCompositorID;
}
private:
RefPtr<CompositableHost> mHost;
CompositableParentManager* mManager;
CompositableType mType;
uint64_t mID;
uint64_t mCompositorID;
};
/**
* Global CompositableMap, to use in the compositor thread only.
*
@ -406,8 +368,8 @@ private:
namespace CompositableMap {
void Create();
void Destroy();
CompositableParent* Get(uint64_t aID);
void Set(uint64_t aID, CompositableParent* aParent);
PCompositableParent* Get(uint64_t aID);
void Set(uint64_t aID, PCompositableParent* aParent);
void Erase(uint64_t aID);
void Clear();
} // CompositableMap

View File

@ -7,6 +7,7 @@
#define MOZILLA_GFX_COMPOSITORD3D11_H
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
#include "mozilla/layers/Compositor.h"
#include "TextureD3D11.h"
#include <d3d11.h>
@ -157,6 +158,8 @@ private:
void SetPSForEffect(Effect *aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat);
void PaintToTarget();
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE { return gfx::ToIntSize(mSize); }
RefPtr<ID3D11DeviceContext> mContext;
RefPtr<ID3D11Device> mDevice;
RefPtr<IDXGISwapChain> mSwapChain;

View File

@ -7,6 +7,7 @@
#define MOZILLA_GFX_COMPOSITORD3D9_H
#include "mozilla/gfx/2D.h"
#include "gfx2DGlue.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/TextureD3D9.h"
#include "DeviceManagerD3D9.h"
@ -153,6 +154,11 @@ private:
void ReportFailure(const nsACString &aMsg, HRESULT aCode);
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE
{
return gfx::ToIntSize(mSize);
}
/* Device manager instance for this compositor */
nsRefPtr<DeviceManagerD3D9> mDeviceManager;

View File

@ -32,10 +32,10 @@ namespace layers {
class ClientTiledLayerBuffer;
class Compositor;
template<typename T>
CompositableHost* AsCompositable(const T& op)
template<typename Op>
CompositableHost* AsCompositable(const Op& op)
{
return static_cast<CompositableParent*>(op.compositableParent())->GetCompositableHost();
return CompositableHost::FromIPDLActor(op.compositableParent());
}
// This function can in some cases fail and return false without it being a bug.
@ -52,12 +52,12 @@ CompositableHost* AsCompositable(const T& op)
template<typename T>
bool ScheduleComposition(const T& op)
{
CompositableParent* comp = static_cast<CompositableParent*>(op.compositableParent());
if (!comp || !comp->GetCompositorID()) {
CompositableHost* comp = AsCompositable(op);
uint64_t id = comp->GetCompositorID();
if (!comp || !id) {
return false;
}
CompositorParent* cp
= CompositorParent::GetCompositor(comp->GetCompositorID());
CompositorParent* cp = CompositorParent::GetCompositor(id);
if (!cp) {
return false;
}
@ -73,13 +73,10 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
case CompositableOperation::TOpCreatedIncrementalTexture: {
MOZ_LAYERS_LOG(("[ParentSide] Created texture"));
const OpCreatedIncrementalTexture& op = aEdit.get_OpCreatedIncrementalTexture();
CompositableParent* compositableParent =
static_cast<CompositableParent*>(op.compositableParent());
CompositableHost* compositable = compositableParent->GetCompositableHost();
CompositableHost* compositable = AsCompositable(op);
bool success =
compositable->CreatedIncrementalTexture(compositableParent->GetCompositableManager(),
compositable->CreatedIncrementalTexture(this,
op.textureInfo(),
op.bufferRect());
if (!success) {
@ -91,9 +88,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer"));
const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion();
CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
CompositableHost* compositable =
compositableParent->GetCompositableHost();
CompositableHost* compositable = AsCompositable(op);
Layer* layer = compositable->GetLayer();
if (!layer || layer->GetType() != Layer::TYPE_THEBES) {
return false;
@ -113,7 +108,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
return false;
}
replyv.push_back(
OpContentBufferSwap(compositableParent, nullptr, frontUpdatedRegion));
OpContentBufferSwap(op.compositableParent(), nullptr, frontUpdatedRegion));
RenderTraceInvalidateEnd(thebes, "FF00FF");
// return texure data to client if necessary
@ -125,9 +120,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
const OpPaintTextureIncremental& op = aEdit.get_OpPaintTextureIncremental();
CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
CompositableHost* compositable =
compositableParent->GetCompositableHost();
CompositableHost* compositable = AsCompositable(op);
SurfaceDescriptor desc = op.image();
@ -140,8 +133,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
}
case CompositableOperation::TOpUpdatePictureRect: {
const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect();
CompositableHost* compositable
= static_cast<CompositableParent*>(op.compositableParent())->GetCompositableHost();
CompositableHost* compositable = AsCompositable(op);
MOZ_ASSERT(compositable);
compositable->SetPictureRect(op.picture());
break;
@ -149,9 +141,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
case CompositableOperation::TOpUseTiledLayerBuffer: {
MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer();
CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
CompositableHost* compositable =
compositableParent->GetCompositableHost();
CompositableHost* compositable = AsCompositable(op);
TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer();
NS_ASSERTION(tileComposer, "compositable is not a tile composer");

View File

@ -193,13 +193,12 @@ ImageBridgeParent::AllocPCompositableParent(const TextureInfo& aInfo,
{
uint64_t id = GenImageContainerID();
*aID = id;
return new CompositableParent(this, aInfo, id);
return CompositableHost::CreateIPDLActor(this, aInfo, id);
}
bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor)
{
delete aActor;
return true;
return CompositableHost::DestroyIPDLActor(aActor);
}
PTextureParent*

View File

@ -60,13 +60,6 @@ cast(const PLayerParent* in)
static_cast<const ShadowLayerParent*>(in));
}
static CompositableParent*
cast(const PCompositableParent* in)
{
return const_cast<CompositableParent*>(
static_cast<const CompositableParent*>(in));
}
template<class OpCreateT>
static ShadowLayerParent*
AsLayerComposite(const OpCreateT& op)
@ -508,24 +501,26 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
}
case Edit::TOpAttachCompositable: {
const OpAttachCompositable& op = edit.get_OpAttachCompositable();
if (!Attach(cast(op.layerParent()), cast(op.compositableParent()), false)) {
CompositableHost* host = CompositableHost::FromIPDLActor(op.compositableParent());
if (!Attach(cast(op.layerParent()), host, false)) {
return false;
}
cast(op.compositableParent())->SetCompositorID(
mLayerManager->GetCompositor()->GetCompositorID());
host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
break;
}
case Edit::TOpAttachAsyncCompositable: {
const OpAttachAsyncCompositable& op = edit.get_OpAttachAsyncCompositable();
CompositableParent* compositableParent = CompositableMap::Get(op.containerID());
PCompositableParent* compositableParent = CompositableMap::Get(op.containerID());
if (!compositableParent) {
NS_ERROR("CompositableParent not found in the map");
return false;
}
if (!Attach(cast(op.layerParent()), compositableParent, true)) {
CompositableHost* host = CompositableHost::FromIPDLActor(compositableParent);
if (!Attach(cast(op.layerParent()), host, true)) {
return false;
}
compositableParent->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
break;
}
default:
@ -694,9 +689,13 @@ LayerTransactionParent::RecvSetAsyncScrollOffset(PLayerParent* aLayer,
bool
LayerTransactionParent::Attach(ShadowLayerParent* aLayerParent,
CompositableParent* aCompositable,
bool aIsAsyncVideo)
CompositableHost* aCompositable,
bool aIsAsync)
{
if (!aCompositable) {
return false;
}
Layer* baselayer = aLayerParent->AsLayer();
if (!baselayer) {
return false;
@ -709,21 +708,16 @@ LayerTransactionParent::Attach(ShadowLayerParent* aLayerParent,
Compositor* compositor
= static_cast<LayerManagerComposite*>(aLayerParent->AsLayer()->Manager())->GetCompositor();
CompositableHost* compositable = aCompositable->GetCompositableHost();
if (!compositable) {
return false;
}
if (!layer->SetCompositableHost(compositable)) {
if (!layer->SetCompositableHost(aCompositable)) {
// not all layer types accept a compositable, see bug 967824
return false;
}
compositable->Attach(aLayerParent->AsLayer(),
compositor,
aIsAsyncVideo
? CompositableHost::ALLOW_REATTACH
| CompositableHost::KEEP_ATTACHED
: CompositableHost::NO_FLAGS);
aCompositable->Attach(aLayerParent->AsLayer(),
compositor,
aIsAsync
? CompositableHost::ALLOW_REATTACH
| CompositableHost::KEEP_ATTACHED
: CompositableHost::NO_FLAGS);
return true;
}
@ -789,14 +783,13 @@ LayerTransactionParent::DeallocPLayerParent(PLayerParent* actor)
PCompositableParent*
LayerTransactionParent::AllocPCompositableParent(const TextureInfo& aInfo)
{
return new CompositableParent(this, aInfo);
return CompositableHost::CreateIPDLActor(this, aInfo, 0);
}
bool
LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* actor)
LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* aActor)
{
delete actor;
return true;
return CompositableHost::DestroyIPDLActor(aActor);
}
PTextureParent*

View File

@ -121,7 +121,7 @@ protected:
virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
bool Attach(ShadowLayerParent* aLayerParent,
CompositableParent* aCompositable,
CompositableHost* aCompositable,
bool aIsAsyncVideo);
void AddIPDLReference() {

View File

@ -6,6 +6,7 @@
#ifndef MOZILLA_GFX_COMPOSITOROGL_H
#define MOZILLA_GFX_COMPOSITOROGL_H
#include "gfx2DGlue.h"
#include "GLContextTypes.h" // for GLContext, etc
#include "GLDefs.h" // for GLuint, LOCAL_GL_TEXTURE_2D, etc
#include "OGLShaderProgram.h" // for ShaderProgramOGL, etc
@ -285,6 +286,11 @@ private:
const gfx::Matrix4x4 &aTransformi,
GLuint aDrawMode);
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE
{
return gfx::ToIntSize(mWidgetSize);
}
/**
* Context target, nullptr when drawing directly to our swap chain.
*/

View File

@ -1,208 +0,0 @@
var detectList = [
"chardet.universal_charset_detector",
"chardet.ja_parallel_state_machine",
"chardet.ko_parallel_state_machine",
"chardet.zhtw_parallel_state_machine",
"chardet.zhcn_parallel_state_machine",
"chardet.zh_parallel_state_machine",
"chardet.cjk_parallel_state_machine",
"chardet.off",
"chardet.ruprob",
"chardet.ukprob",
];
var encoderList = [
"ISO-8859-1",
"windows-1252",
"macintosh",
"UTF-8",
"us-ascii",
"ISO-8859-2",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
"ISO-8859-6",
"ISO-8859-6-I",
"ISO-8859-6-E",
"ISO-8859-7",
"ISO-8859-8",
"ISO-8859-8-I",
"ISO-8859-8-E",
"ISO-8859-9",
"ISO-8859-10",
"ISO-8859-13",
"ISO-8859-14",
"ISO-8859-15",
"ISO-8859-16",
"ISO-IR-111",
"windows-1250",
"windows-1251",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"TIS-620",
"windows-874",
"ISO-8859-11",
"KOI8-R",
"KOI8-U",
"x-mac-ce",
"x-mac-greek",
"x-mac-turkish",
"x-mac-croatian",
"x-mac-romanian",
"x-mac-cyrillic",
"x-mac-icelandic",
"armscii-8",
"x-viet-tcvn5712",
"VISCII",
"x-viet-vps",
"UTF-16",
"UTF-16BE",
"UTF-16LE",
"T.61-8bit",
"x-user-defined",
"x-mac-arabic",
"x-mac-devanagari",
"x-mac-farsi",
"x-mac-gurmukhi",
"x-mac-gujarati",
"x-mac-hebrew",
"IBM850",
"IBM852",
"IBM855",
"IBM857",
"IBM862",
"IBM864",
"IBM866",
"Shift_JIS",
"ISO-2022-JP",
"EUC-JP",
"jis_0201",
"x-euc-tw",
"Big5",
"Big5-HKSCS",
"hkscs-1",
"EUC-KR",
"x-johab",
"GB2312",
"gbk",
"HZ-GB-2312",
"gb18030",
"replacement",
];
var decoderList = [
"ISO-8859-1",
"windows-1252",
"macintosh",
"UTF-8",
"us-ascii",
"ISO-8859-2",
"ISO-8859-3",
"ISO-8859-4",
"ISO-8859-5",
"ISO-8859-6",
"ISO-8859-6-I",
"ISO-8859-6-E",
"ISO-8859-7",
"ISO-8859-8",
"ISO-8859-8-I",
"ISO-8859-8-E",
"ISO-8859-9",
"ISO-8859-10",
"ISO-8859-13",
"ISO-8859-14",
"ISO-8859-15",
"ISO-8859-16",
"ISO-IR-111",
"windows-1250",
"windows-1251",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"TIS-620",
"windows-874",
"ISO-8859-11",
"KOI8-R",
"KOI8-U",
"x-mac-ce",
"x-mac-greek",
"x-mac-turkish",
"x-mac-croatian",
"x-mac-romanian",
"x-mac-cyrillic",
"x-mac-icelandic",
"armscii-8",
"x-viet-tcvn5712",
"VISCII",
"x-viet-vps",
"UTF-16",
"UTF-16BE",
"UTF-16LE",
"T.61-8bit",
"x-user-defined",
"x-mac-arabic",
"x-mac-devanagari",
"x-mac-farsi",
"x-mac-gurmukhi",
"x-mac-gujarati",
"x-mac-hebrew",
"IBM850",
"IBM852",
"IBM855",
"IBM857",
"IBM862",
"IBM864",
"IBM866",
"Shift_JIS",
"ISO-2022-JP",
"EUC-JP",
"x-euc-tw",
"Big5",
"Big5-HKSCS",
"EUC-KR",
"x-johab",
"GB2312",
"gbk",
"HZ-GB-2312",
"gb18030",
"ISO-2022-KR",
"ISO-2022-CN",
"replacement",
];
function verifyList(aEnumerator, aList)
{
var count = 0;
while (aEnumerator.hasMore()) {
var result = aEnumerator.getNext();
for (var i = 0; i < aList.length; i++) {
if (result == aList[i]) {
count++;
break;
}
}
if (i == aList.length) {
do_throw("Unknown chardet: " + result);
}
}
do_check_eq(count, aList.length);
}
function run_test()
{
var cm = Components.classes["@mozilla.org/charset-converter-manager;1"]
.getService(Components.interfaces.nsICharsetConverterManager);
verifyList(cm.GetCharsetDetectorList(), detectList);
verifyList(cm.getEncoderList(), encoderList);
verifyList(cm.getDecoderList(), decoderList);
}

View File

@ -39,7 +39,6 @@ support-files =
[test_bug715319.euc_jp.js]
[test_bug715319.gb2312.js]
[test_bug715319.dbcs.js]
[test_bug718500.js]
[test_charset_conversion.js]
[test_decode_8859-1.js]
[test_decode_8859-10.js]

View File

@ -37,6 +37,8 @@ template <typename T> class AutoVectorRooter;
template<typename K, typename V> class AutoHashMapRooter;
template<typename T> class AutoHashSetRooter;
class SourceBufferHolder;
class HandleValueArray;
}
@ -87,6 +89,7 @@ using JS::IsAcceptableThis;
using JS::NativeImpl;
using JS::OwningCompileOptions;
using JS::ReadOnlyCompileOptions;
using JS::SourceBufferHolder;
using JS::Rooted;
using JS::RootedFunction;

View File

@ -320,9 +320,10 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
.setNoScriptRval(false)
.setOriginPrincipals(originPrincipals)
.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
SourceBufferHolder srcBuf(chars.get(), length, SourceBufferHolder::NoOwnership);
JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
scopeobj, callerScript, options,
chars.get(), length, flatStr, staticLevel);
srcBuf, flatStr, staticLevel);
if (!compiled)
return false;
@ -388,9 +389,10 @@ js::DirectEvalStringFromIon(JSContext *cx,
.setNoScriptRval(false)
.setOriginPrincipals(originPrincipals)
.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
SourceBufferHolder srcBuf(chars.get(), length, SourceBufferHolder::NoOwnership);
JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
scopeobj, callerScript, options,
chars.get(), length, flatStr, staticLevel);
srcBuf, flatStr, staticLevel);
if (!compiled)
return false;

View File

@ -27,12 +27,12 @@ using namespace js::frontend;
using mozilla::Maybe;
static bool
CheckLength(ExclusiveContext *cx, size_t length)
CheckLength(ExclusiveContext *cx, SourceBufferHolder &srcBuf)
{
// Note this limit is simply so we can store sourceStart and sourceEnd in
// JSScript as 32-bits. It could be lifted fairly easily, since the compiler
// is using size_t internally already.
if (length > UINT32_MAX) {
if (srcBuf.length() > UINT32_MAX) {
if (cx->isJSContext())
JS_ReportErrorNumber(cx->asJSContext(), js_GetErrorMessage, nullptr,
JSMSG_SOURCE_TOO_LONG);
@ -154,14 +154,14 @@ CanLazilyParse(ExclusiveContext *cx, const ReadOnlyCompileOptions &options)
void
frontend::MaybeCallSourceHandler(JSContext *cx, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length)
SourceBufferHolder &srcBuf)
{
JSSourceHandler listener = cx->runtime()->debugHooks.sourceHandler;
void *listenerData = cx->runtime()->debugHooks.sourceHandlerData;
if (listener) {
void *listenerTSData;
listener(options.filename(), options.lineno, chars, length,
listener(options.filename(), options.lineno, srcBuf.get(), srcBuf.length(),
&listenerTSData, listenerData);
}
}
@ -184,11 +184,13 @@ JSScript *
frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject scopeChain,
HandleScript evalCaller,
const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length,
SourceBufferHolder &srcBuf,
JSString *source_ /* = nullptr */,
unsigned staticLevel /* = 0 */,
SourceCompressionTask *extraSct /* = nullptr */)
{
JS_ASSERT(srcBuf.get());
RootedString source(cx, source_);
js::TraceLogger *logger = nullptr;
@ -201,7 +203,7 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
js::AutoTraceLog typeLogger(logger, TraceLogger::ParserCompileScript);
if (cx->isJSContext())
MaybeCallSourceHandler(cx->asJSContext(), options, chars, length);
MaybeCallSourceHandler(cx->asJSContext(), options, srcBuf);
/*
* The scripted callerFrame can only be given for compile-and-go scripts
@ -211,7 +213,7 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
JS_ASSERT_IF(evalCaller, options.forEval);
JS_ASSERT_IF(staticLevel != 0, evalCaller);
if (!CheckLength(cx, length))
if (!CheckLength(cx, srcBuf))
return nullptr;
JS_ASSERT_IF(staticLevel != 0, !options.sourceIsLazy);
@ -227,7 +229,7 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
if (!cx->compartment()->options().discardSource()) {
if (options.sourceIsLazy)
ss->setSourceRetrievable();
else if (!ss->setSourceCopy(cx, chars, length, false, sct))
else if (!ss->setSourceCopy(cx, srcBuf, false, sct))
return nullptr;
}
@ -235,12 +237,14 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (canLazilyParse) {
syntaxParser.construct(cx, alloc, options, chars, length, /* foldConstants = */ false,
syntaxParser.construct(cx, alloc, options, srcBuf.get(), srcBuf.length(),
/* foldConstants = */ false,
(Parser<SyntaxParseHandler> *) nullptr,
(LazyScript *) nullptr);
}
Parser<FullParseHandler> parser(cx, alloc, options, chars, length, /* foldConstants = */ true,
Parser<FullParseHandler> parser(cx, alloc, options, srcBuf.get(), srcBuf.length(),
/* foldConstants = */ true,
canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
parser.sct = sct;
parser.ss = ss;
@ -251,7 +255,8 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
bool savedCallerFun = options.compileAndGo &&
evalCaller && evalCaller->functionOrCallerFunction();
Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun,
options, staticLevel, sourceObject, 0, length));
options, staticLevel, sourceObject, 0,
srcBuf.length()));
if (!script)
return nullptr;
@ -491,7 +496,7 @@ frontend::CompileLazyFunction(JSContext *cx, Handle<LazyScript*> lazy, const jsc
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
static bool
CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyCompileOptions &options,
const AutoNameVector &formals, const jschar *chars, size_t length,
const AutoNameVector &formals, SourceBufferHolder &srcBuf,
GeneratorKind generatorKind)
{
js::TraceLogger *logger = js::TraceLoggerForMainThread(cx->runtime());
@ -502,9 +507,9 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
// FIXME: make Function pass in two strings and parse them as arguments and
// ProgramElements respectively.
MaybeCallSourceHandler(cx, options, chars, length);
MaybeCallSourceHandler(cx, options, srcBuf);
if (!CheckLength(cx, length))
if (!CheckLength(cx, srcBuf))
return false;
RootedScriptSource sourceObject(cx, CreateScriptSourceObject(cx, options));
@ -515,7 +520,7 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
SourceCompressionTask sct(cx);
JS_ASSERT(!options.sourceIsLazy);
if (!cx->compartment()->options().discardSource()) {
if (!ss->setSourceCopy(cx, chars, length, true, &sct))
if (!ss->setSourceCopy(cx, srcBuf, true, &sct))
return false;
}
@ -524,7 +529,8 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
Maybe<Parser<SyntaxParseHandler> > syntaxParser;
if (canLazilyParse) {
syntaxParser.construct(cx, &cx->tempLifoAlloc(),
options, chars, length, /* foldConstants = */ false,
options, srcBuf.get(), srcBuf.length(),
/* foldConstants = */ false,
(Parser<SyntaxParseHandler> *) nullptr,
(LazyScript *) nullptr);
}
@ -532,7 +538,8 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
JS_ASSERT(!options.forEval);
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
options, chars, length, /* foldConstants = */ true,
options, srcBuf.get(), srcBuf.length(),
/* foldConstants = */ true,
canLazilyParse ? &syntaxParser.ref() : nullptr, nullptr);
parser.sct = &sct;
parser.ss = ss;
@ -584,7 +591,7 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
Rooted<JSScript*> script(cx, JSScript::Create(cx, js::NullPtr(), false, options,
/* staticLevel = */ 0, sourceObject,
/* sourceStart = */ 0, length));
/* sourceStart = */ 0, srcBuf.length()));
if (!script)
return false;
@ -626,15 +633,15 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
bool
frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions &options,
const AutoNameVector &formals, const jschar *chars, size_t length)
const AutoNameVector &formals, JS::SourceBufferHolder &srcBuf)
{
return CompileFunctionBody(cx, fun, options, formals, chars, length, NotGenerator);
return CompileFunctionBody(cx, fun, options, formals, srcBuf, NotGenerator);
}
bool
frontend::CompileStarGeneratorBody(JSContext *cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions &options, const AutoNameVector &formals,
const jschar *chars, size_t length)
JS::SourceBufferHolder &srcBuf)
{
return CompileFunctionBody(cx, fun, options, formals, chars, length, StarGenerator);
return CompileFunctionBody(cx, fun, options, formals, srcBuf, StarGenerator);
}

View File

@ -23,7 +23,7 @@ namespace frontend {
JSScript *
CompileScript(ExclusiveContext *cx, LifoAlloc *alloc,
HandleObject scopeChain, HandleScript evalCaller,
const ReadOnlyCompileOptions &options, const jschar *chars, size_t length,
const ReadOnlyCompileOptions &options, SourceBufferHolder &srcBuf,
JSString *source_ = nullptr, unsigned staticLevel = 0,
SourceCompressionTask *extraSct = nullptr);
@ -33,11 +33,11 @@ CompileLazyFunction(JSContext *cx, Handle<LazyScript*> lazy, const jschar *chars
bool
CompileFunctionBody(JSContext *cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions &options,
const AutoNameVector &formals, const jschar *chars, size_t length);
const AutoNameVector &formals, JS::SourceBufferHolder &srcBuf);
bool
CompileStarGeneratorBody(JSContext *cx, MutableHandleFunction fun,
const ReadOnlyCompileOptions &options,
const AutoNameVector &formals, const jschar *chars, size_t length);
const AutoNameVector &formals, JS::SourceBufferHolder &srcBuf);
ScriptSourceObject *
CreateScriptSourceObject(ExclusiveContext *cx, const ReadOnlyCompileOptions &options);
@ -48,7 +48,7 @@ CreateScriptSourceObject(ExclusiveContext *cx, const ReadOnlyCompileOptions &opt
*/
void
MaybeCallSourceHandler(JSContext *cx, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length);
JS::SourceBufferHolder &srcBuf);
/*
* True if str consists of an IdentifierStart character, followed by one or

View File

@ -567,7 +567,7 @@ js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind
tenuredSize += moveElementsToTenured(dst, src, dstKind);
if (src->is<TypedArrayObject>())
dst->setPrivate(dst->fixedData(TypedArrayObject::FIXED_DATA_START));
forwardTypedArrayPointers(dst, src);
/* The shape's list head may point into the old object. */
if (&src->shape_ == dst->shape_->listp)
@ -576,6 +576,35 @@ js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind
return tenuredSize;
}
void
js::Nursery::forwardTypedArrayPointers(JSObject *dst, JSObject *src)
{
/*
* Typed array data may be stored inline inside the object's fixed slots. If
* so, we need update the private pointer and leave a forwarding pointer at
* the start of the data.
*/
TypedArrayObject &typedArray = src->as<TypedArrayObject>();
JS_ASSERT_IF(typedArray.buffer(), !isInside(src->getPrivate()));
if (typedArray.buffer())
return;
void *srcData = src->fixedData(TypedArrayObject::FIXED_DATA_START);
void *dstData = dst->fixedData(TypedArrayObject::FIXED_DATA_START);
JS_ASSERT(src->getPrivate() == srcData);
dst->setPrivate(dstData);
/*
* We don't know the number of slots here, but
* TypedArrayObject::AllocKindForLazyBuffer ensures that it's always at
* least one.
*/
size_t nslots = 1;
setSlotsForwardingPointer(reinterpret_cast<HeapSlot*>(srcData),
reinterpret_cast<HeapSlot*>(dstData),
nslots);
}
size_t
js::Nursery::moveSlotsToTenured(JSObject *dst, JSObject *src, AllocKind dstKind)
{

View File

@ -271,6 +271,7 @@ class Nursery
size_t moveObjectToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
size_t moveElementsToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
size_t moveSlotsToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
void forwardTypedArrayPointers(JSObject *dst, JSObject *src);
/* Handle relocation of slots/elements pointers stored in Ion frames. */
void setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots);

View File

@ -0,0 +1,13 @@
var SECTION = "";
gcPreserveCode()
gczeal(9, 1000);
function test() {
var f32 = new Float32Array(10);
f32[0] = 5;
var i = 0;
for (var j = 0; j < 10000; ++j) {
f32[i + 1] = f32[i] - 1;
SECTION += 1;
}
}
test();

View File

@ -578,7 +578,8 @@ HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, Hand
.setCompileAndGo(false)
.setNoScriptRval(false);
if (!frontend::CompileFunctionBody(cx, &fun, options, formals, src->chars(), end - begin))
SourceBufferHolder srcBuf(src->chars(), end - begin, SourceBufferHolder::NoOwnership);
if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf))
return false;
// Call the function we just recompiled.

View File

@ -4525,7 +4525,7 @@ JS::CompileOptions::wrap(JSContext *cx, JSCompartment *compartment)
JSScript *
JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length)
SourceBufferHolder &srcBuf)
{
JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
@ -4533,7 +4533,15 @@ JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optio
assertSameCompartment(cx, obj);
AutoLastFrameCheck lfc(cx);
return frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, chars, length);
return frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf);
}
JSScript *
JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return Compile(cx, obj, options, srcBuf);
}
JSScript *
@ -4689,7 +4697,7 @@ JS_GetGlobalFromScript(JSScript *script)
JS_PUBLIC_API(JSFunction *)
JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
const jschar *chars, size_t length)
SourceBufferHolder &srcBuf)
{
JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
AssertHeapIsIdle(cx);
@ -4716,7 +4724,7 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOption
if (!fun)
return nullptr;
if (!frontend::CompileFunctionBody(cx, &fun, options, formals, chars, length))
if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf))
return nullptr;
if (obj && funAtom && options.defineOnScope) {
@ -4729,6 +4737,15 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOption
return fun;
}
JS_PUBLIC_API(JSFunction *)
JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
const jschar *chars, size_t length)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf);
}
JS_PUBLIC_API(JSFunction *)
JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
@ -4858,7 +4875,7 @@ static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
static bool
Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
const jschar *chars, size_t length, JS::Value *rval)
SourceBufferHolder &srcBuf, JS::Value *rval)
{
CompileOptions options(cx, optionsArg);
JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
@ -4873,7 +4890,7 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsA
SourceCompressionTask sct(cx);
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
obj, NullPtr(), options,
chars, length, nullptr, 0, &sct));
srcBuf, nullptr, 0, &sct));
if (!script)
return false;
@ -4897,6 +4914,14 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsA
return result;
}
static bool
Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
const jschar *chars, size_t length, JS::Value *rval)
{
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
return ::Evaluate(cx, obj, optionsArg, srcBuf, rval);
}
static bool
Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
const char *bytes, size_t length, JS::Value *rval)
@ -4909,8 +4934,8 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
if (!chars)
return false;
bool ok = ::Evaluate(cx, obj, options, chars, length, rval);
js_free(chars);
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
bool ok = ::Evaluate(cx, obj, options, srcBuf, rval);
return ok;
}
@ -4930,6 +4955,13 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsA
return Evaluate(cx, obj, options, buffer.begin(), buffer.length(), rval);
}
extern JS_PUBLIC_API(bool)
JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
SourceBufferHolder &srcBuf, MutableHandleValue rval)
{
return ::Evaluate(cx, obj, optionsArg, srcBuf, rval.address());
}
extern JS_PUBLIC_API(bool)
JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
const jschar *chars, size_t length, MutableHandleValue rval)
@ -4951,6 +4983,13 @@ JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &opti
return ::Evaluate(cx, obj, optionsArg, filename, rval.address());
}
extern JS_PUBLIC_API(bool)
JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
SourceBufferHolder &srcBuf)
{
return ::Evaluate(cx, obj, optionsArg, srcBuf, nullptr);
}
extern JS_PUBLIC_API(bool)
JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
const jschar *chars, size_t length)
@ -4982,6 +5021,16 @@ JS_EvaluateUCScript(JSContext *cx, HandleObject obj, const jschar *chars, unsign
return ::Evaluate(cx, obj, options, chars, length, rval.address());
}
JS_PUBLIC_API(bool)
JS_EvaluateUCScript(JSContext *cx, HandleObject obj, SourceBufferHolder &srcBuf,
const char *filename, unsigned lineno, MutableHandleValue rval)
{
CompileOptions options(cx);
options.setFileAndLine(filename, lineno);
return ::Evaluate(cx, obj, options, srcBuf, rval.address());
}
JS_PUBLIC_API(bool)
JS_EvaluateScript(JSContext *cx, HandleObject obj, const char *bytes, unsigned nbytes,
const char *filename, unsigned lineno, MutableHandleValue rval)

View File

@ -877,6 +877,91 @@ class AutoIdRooter : private AutoGCRooter
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
// Container class for passing in script source buffers to the JS engine. This
// not only groups the buffer and length values, it also provides a way to
// optionally pass ownership of the buffer to the JS engine without copying.
// Rules for use:
//
// 1) The data array must be allocated with js_malloc() or js_realloc() if
// ownership is being granted to the SourceBufferHolder.
// 2) If ownership is not given to the SourceBufferHolder, then the memory
// must be kept alive until the JS compilation is complete.
// 3) Any code calling SourceBufferHolder::take() must guarantee to keep the
// memory alive until JS compilation completes. Normally only the JS
// engine should be calling take().
//
// Example use:
//
// size_t length = 512;
// jschar* chars = static_cast<jschar*>(js_malloc(sizeof(jschar) * length));
// JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
// JS::Compile(cx, obj, options, srcBuf);
//
class MOZ_STACK_CLASS SourceBufferHolder MOZ_FINAL
{
public:
enum Ownership {
NoOwnership,
GiveOwnership
};
SourceBufferHolder(const jschar *data, size_t dataLength, Ownership ownership)
: data_(data),
length_(dataLength),
ownsChars_(ownership == GiveOwnership)
{
// Ensure that null buffers properly return an unowned, empty,
// null-terminated string.
static const jschar NullChar_ = 0;
if (!get()) {
data_ = &NullChar_;
length_ = 0;
ownsChars_ = false;
}
}
~SourceBufferHolder() {
if (ownsChars_)
js_free(const_cast<jschar *>(data_));
}
// Access the underlying source buffer without affecting ownership.
const jschar *get() const { return data_; }
// Length of the source buffer in jschars (not bytes)
size_t length() const { return length_; }
// Returns true if the SourceBufferHolder owns the buffer and will free
// it upon destruction. If true, it is legal to call take().
bool ownsChars() const { return ownsChars_; }
// Retrieve and take ownership of the underlying data buffer. The caller
// is now responsible for calling js_free() on the returned value, *but only
// after JS script compilation has completed*.
//
// After the buffer has been taken the SourceBufferHolder functions as if
// it had been constructed on an unowned buffer; get() and length() still
// work. In order for this to be safe the taken buffer must be kept alive
// until after JS script compilation completes as noted above.
//
// Note, it's the caller's responsibility to check ownsChars() before taking
// the buffer. Taking and then free'ing an unowned buffer will have dire
// consequences.
jschar *take() {
JS_ASSERT(ownsChars_);
ownsChars_ = false;
return const_cast<jschar *>(data_);
}
private:
SourceBufferHolder(SourceBufferHolder &) MOZ_DELETE;
SourceBufferHolder &operator=(SourceBufferHolder &) MOZ_DELETE;
const jschar *data_;
size_t length_;
bool ownsChars_;
};
} /* namespace JS */
/************************************************************************/
@ -3648,6 +3733,10 @@ extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length);
extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
SourceBufferHolder &srcBuf);
extern JS_PUBLIC_API(JSScript *)
Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file);
@ -3691,6 +3780,11 @@ CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOption
const char *name, unsigned nargs, const char *const *argnames,
const jschar *chars, size_t length);
extern JS_PUBLIC_API(JSFunction *)
CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const char *name, unsigned nargs, const char *const *argnames,
SourceBufferHolder &srcBuf);
} /* namespace JS */
extern JS_PUBLIC_API(JSString *)
@ -3785,6 +3879,10 @@ JS_EvaluateUCScript(JSContext *cx, JS::Handle<JSObject*> obj,
namespace JS {
extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
SourceBufferHolder &srcBuf, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length, JS::MutableHandleValue rval);
@ -3797,6 +3895,10 @@ extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const char *filename, JS::MutableHandleValue rval);
extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
SourceBufferHolder &srcBuf);
extern JS_PUBLIC_API(bool)
Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
const jschar *chars, size_t length);

View File

@ -1617,10 +1617,11 @@ FunctionConstructor(JSContext *cx, unsigned argc, Value *vp, GeneratorKind gener
fun->setHasRest();
bool ok;
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
if (isStarGenerator)
ok = frontend::CompileStarGeneratorBody(cx, &fun, options, formals, chars, length);
ok = frontend::CompileStarGeneratorBody(cx, &fun, options, formals, srcBuf);
else
ok = frontend::CompileFunctionBody(cx, &fun, options, formals, chars, length);
ok = frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf);
args.rval().setObject(*fun);
return ok;
}

View File

@ -3853,7 +3853,7 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction *
if (fun) {
if (fun->hasScript())
fun = fun->nonLazyScript()->functionNonDelazifying();
else if (fun->isInterpretedLazy())
else if (fun->isInterpretedLazy() && !fun->isSelfHostedBuiltin())
fun = fun->lazyScript()->functionNonDelazifying();
else
fun = nullptr;

View File

@ -1567,11 +1567,11 @@ ScriptSource::substring(JSContext *cx, uint32_t start, uint32_t stop)
}
bool
ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t length,
ScriptSource::setSourceCopy(ExclusiveContext *cx, SourceBufferHolder &srcBuf,
bool argumentsNotIncluded, SourceCompressionTask *task)
{
JS_ASSERT(!hasSourceData());
length_ = length;
length_ = srcBuf.length();
argumentsNotIncluded_ = argumentsNotIncluded;
// There are several cases where source compression is not a good idea:
@ -1604,16 +1604,18 @@ ScriptSource::setSourceCopy(ExclusiveContext *cx, const jschar *src, uint32_t le
#endif
const size_t TINY_SCRIPT = 256;
const size_t HUGE_SCRIPT = 5 * 1024 * 1024;
if (TINY_SCRIPT <= length && length < HUGE_SCRIPT && canCompressOffThread) {
if (TINY_SCRIPT <= srcBuf.length() && srcBuf.length() < HUGE_SCRIPT && canCompressOffThread) {
task->ss = this;
task->chars = src;
task->chars = srcBuf.get();
ready_ = false;
if (!StartOffThreadCompression(cx, task))
return false;
} else if (srcBuf.ownsChars()) {
data.source = srcBuf.take();
} else {
if (!adjustDataSize(sizeof(jschar) * length))
if (!adjustDataSize(sizeof(jschar) * srcBuf.length()))
return false;
PodCopy(data.source, src, length_);
PodCopy(data.source, srcBuf.get(), length_);
}
return true;

View File

@ -480,8 +480,7 @@ class ScriptSource
}
bool initFromOptions(ExclusiveContext *cx, const ReadOnlyCompileOptions &options);
bool setSourceCopy(ExclusiveContext *cx,
const jschar *src,
uint32_t length,
JS::SourceBufferHolder &srcBuf,
bool argumentsNotIncluded,
SourceCompressionTask *tok);
void setSource(const jschar *src, size_t length);

View File

@ -299,7 +299,8 @@ js::StartOffThreadParseScript(JSContext *cx, const ReadOnlyCompileOptions &optio
// which could require barriers on the atoms compartment.
gc::AutoSuppressGC suppress(cx);
frontend::MaybeCallSourceHandler(cx, options, chars, length);
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
frontend::MaybeCallSourceHandler(cx, options, srcBuf);
EnsureWorkerThreadsInitialized(cx);
@ -860,10 +861,12 @@ WorkerThread::handleParseWorkload()
AutoUnlockWorkerThreadState unlock;
PerThreadData::AutoEnterRuntime enter(threadData.addr(),
parseTask->exclusiveContextGlobal->runtimeFromAnyThread());
SourceBufferHolder srcBuf(parseTask->chars, parseTask->length,
SourceBufferHolder::NoOwnership);
parseTask->script = frontend::CompileScript(parseTask->cx, &parseTask->alloc,
NullPtr(), NullPtr(),
parseTask->options,
parseTask->chars, parseTask->length);
srcBuf);
}
// The callback is invoked while we are still off the main thread.

View File

@ -344,9 +344,9 @@ ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer, void
}
if (buffer->isMappedArrayBuffer())
buffer->changeContents(cx, nullptr);
buffer->setNewOwnedData(cx->runtime()->defaultFreeOp(), nullptr);
else if (newData != buffer->dataPointer())
buffer->changeContents(cx, newData);
buffer->setNewOwnedData(cx->runtime()->defaultFreeOp(), newData);
buffer->setByteLength(0);
buffer->setViewList(nullptr);
@ -371,12 +371,27 @@ ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer, void
}
void
ArrayBufferObject::changeContents(JSContext *cx, void *newData)
ArrayBufferObject::setNewOwnedData(FreeOp* fop, void *newData)
{
JS_ASSERT(!isAsmJSArrayBuffer());
JS_ASSERT(!isSharedArrayBuffer());
JS_ASSERT_IF(isMappedArrayBuffer(), !newData);
if (ownsData()) {
JS_ASSERT(newData != dataPointer());
releaseData(fop);
}
setDataPointer(static_cast<uint8_t *>(newData), OwnsData);
}
void
ArrayBufferObject::changeContents(JSContext *cx, void *newData)
{
// Change buffer contents.
uint8_t* oldDataPointer = dataPointer();
setNewOwnedData(cx->runtime()->defaultFreeOp(), newData);
// Update all views.
ArrayBufferViewObject *viewListHead = viewList();
for (ArrayBufferViewObject *view = viewListHead; view; view = view->nextView()) {
@ -386,18 +401,14 @@ ArrayBufferObject::changeContents(JSContext *cx, void *newData)
uint8_t *viewDataPointer = view->dataPointer();
if (viewDataPointer) {
JS_ASSERT(newData);
viewDataPointer += static_cast<uint8_t *>(newData) - dataPointer();
ptrdiff_t offset = viewDataPointer - oldDataPointer;
viewDataPointer = static_cast<uint8_t *>(newData) + offset;
view->setPrivate(viewDataPointer);
}
// Notify compiled jit code that the base pointer has moved.
MarkObjectStateChange(cx, view);
}
if (ownsData())
releaseData(cx->runtime()->defaultFreeOp());
setDataPointer(static_cast<uint8_t *>(newData), OwnsData);
}
#if defined(JS_CPU_X64)

View File

@ -124,6 +124,7 @@ class ArrayBufferObject : public JSObject
void addView(ArrayBufferViewObject *view);
void setNewOwnedData(FreeOp* fop, void *newData);
void changeContents(JSContext *cx, void *newData);
/*

View File

@ -4658,8 +4658,9 @@ js::EvaluateInEnv(JSContext *cx, Handle<Env*> env, HandleValue thisv, AbstractFr
.setCanLazilyParse(false)
.setIntroductionType("debugger eval");
RootedScript callerScript(cx, frame ? frame.script() : nullptr);
SourceBufferHolder srcBuf(chars.get(), length, SourceBufferHolder::NoOwnership);
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, callerScript,
options, chars.get(), length,
options, srcBuf,
/* source = */ nullptr,
/* staticLevel = */ frame ? 1 : 0));
if (!script)

View File

@ -51,8 +51,9 @@ class TypedArrayObject : public ArrayBufferViewObject
AllocKindForLazyBuffer(size_t nbytes)
{
JS_ASSERT(nbytes <= INLINE_BUFFER_LIMIT);
int dataSlots = (nbytes - 1) / sizeof(Value) + 1;
JS_ASSERT(int(nbytes) <= dataSlots * int(sizeof(Value)));
/* For GGC we need at least one slot in which to store a forwarding pointer. */
size_t dataSlots = Max(size_t(1), AlignBytes(nbytes, sizeof(Value)) / sizeof(Value));
JS_ASSERT(nbytes <= dataSlots * sizeof(Value));
return gc::GetGCObjectKind(FIXED_DATA_START + dataSlots);
}

View File

@ -145,23 +145,25 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *targetObj
JS::CompileOptions options(cx);
options.setFileAndLine(uriStr, 1);
if (!charset.IsVoid()) {
nsString script;
jschar *scriptBuf = nullptr;
size_t scriptLength = 0;
rv = nsScriptLoader::ConvertToUTF16(nullptr, reinterpret_cast<const uint8_t*>(buf.get()), len,
charset, nullptr, script);
charset, nullptr, scriptBuf, scriptLength);
JS::SourceBufferHolder srcBuf(scriptBuf, scriptLength,
JS::SourceBufferHolder::GiveOwnership);
if (NS_FAILED(rv)) {
return ReportError(cx, LOAD_ERROR_BADCHARSET);
}
if (!reuseGlobal) {
*scriptp = JS::Compile(cx, target_obj, options,
script.get(),
script.Length());
*scriptp = JS::Compile(cx, target_obj, options, srcBuf);
} else {
*functionp = JS::CompileFunction(cx, target_obj, options,
nullptr, 0, nullptr,
script.get(),
script.Length());
srcBuf);
}
} else {
// We only use lazy source when no special encoding is specified because
@ -386,10 +388,16 @@ public:
: mObserver(aObserver)
, mPrincipal(aPrincipal)
, mChannel(aChannel)
, mScriptBuf(nullptr)
, mScriptLength(0)
{}
virtual ~ScriptPrecompiler()
{}
{
if (mScriptBuf) {
js_free(mScriptBuf);
}
}
static void OffThreadCallback(void *aToken, void *aData);
@ -400,7 +408,8 @@ private:
nsRefPtr<nsIObserver> mObserver;
nsRefPtr<nsIPrincipal> mPrincipal;
nsRefPtr<nsIChannel> mChannel;
nsString mScript;
jschar* mScriptBuf;
size_t mScriptLength;
};
NS_IMPL_ISUPPORTS1(ScriptPrecompiler, nsIStreamLoaderObserver);
@ -479,7 +488,8 @@ ScriptPrecompiler::OnStreamComplete(nsIStreamLoader* aLoader,
nsAutoString hintCharset;
nsresult rv =
nsScriptLoader::ConvertToUTF16(mChannel, aString, aLength,
hintCharset, nullptr, mScript);
hintCharset, nullptr,
mScriptBuf, mScriptLength);
NS_ENSURE_SUCCESS(rv, NS_OK);
@ -509,7 +519,7 @@ ScriptPrecompiler::OnStreamComplete(nsIStreamLoader* aLoader,
uri->GetSpec(spec);
options.setFile(spec.get());
if (!JS::CanCompileOffThread(cx, options, mScript.Length())) {
if (!JS::CanCompileOffThread(cx, options, mScriptLength)) {
NS_WARNING("Can't compile script off thread!");
return NS_OK;
}
@ -518,7 +528,7 @@ ScriptPrecompiler::OnStreamComplete(nsIStreamLoader* aLoader,
new NotifyPrecompilationCompleteRunnable(this);
if (!JS::CompileOffThread(cx, options,
mScript.get(), mScript.Length(),
mScriptBuf, mScriptLength,
OffThreadCallback,
static_cast<void*>(runnable))) {
NS_WARNING("Failed to compile script off thread!");

View File

@ -2986,17 +2986,17 @@ ReadSourceFromFilename(JSContext *cx, const char *filename, jschar **src, size_t
ptr += bytesRead;
}
nsString decoded;
rv = nsScriptLoader::ConvertToUTF16(scriptChannel, buf, rawLen, EmptyString(),
nullptr, decoded);
nullptr, *src, *len);
NS_ENSURE_SUCCESS(rv, rv);
// Copy to JS engine.
*len = decoded.Length();
*src = static_cast<jschar *>(JS_malloc(cx, decoded.Length()*sizeof(jschar)));
if (!*src)
return NS_ERROR_FAILURE;
memcpy(*src, decoded.get(), decoded.Length()*sizeof(jschar));
// Historically this method used JS_malloc() which updates the GC memory
// accounting. Since ConvertToUTF16() now uses js_malloc() instead we
// update the accounting manually after the fact.
JS_updateMallocCounter(cx, *len);
return NS_OK;
}

View File

@ -485,6 +485,23 @@ MakeContinuationFluid(nsIFrame* aFrame, nsIFrame* aNext)
aNext->SetPrevInFlow(aFrame);
}
static void
MakeContinuationsNonFluidUpParentChain(nsIFrame* aFrame, nsIFrame* aNext)
{
nsIFrame* frame;
nsIFrame* next;
for (frame = aFrame, next = aNext;
frame && next &&
next != frame && next == frame->GetNextInFlow() &&
IsBidiSplittable(frame);
frame = frame->GetParent(), next = next->GetParent()) {
frame->SetNextContinuation(next);
next->SetPrevContinuation(frame);
}
}
// If aFrame is the last child of its parent, convert bidi continuations to
// fluid continuations for all of its inline ancestors.
// If it isn't the last child, make sure that its continuation is fluid.
@ -841,20 +858,7 @@ nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame,
nsIFrame* next = frame->GetNextInFlow();
if (next) {
currentLine->MarkDirty();
nsIFrame* parent = frame;
nsIFrame* nextParent = next;
while (parent && nextParent) {
if (parent == nextParent ||
nextParent != parent->GetNextInFlow() ||
!IsBidiSplittable(parent)) {
break;
}
parent->SetNextContinuation(nextParent);
nextParent->SetPrevContinuation(parent);
parent = parent->GetParent();
nextParent = nextParent->GetParent();
}
MakeContinuationsNonFluidUpParentChain(frame, next);
}
}
frame->AdjustOffsetsForBidi(contentOffset, contentOffset + fragmentLength);
@ -1660,11 +1664,7 @@ nsBidiPresUtils::RemoveBidiContinuation(BidiParagraphData *aBpd,
// fluid continuation (this can happen when re-resolving after dynamic changes
// to content)
nsIFrame* lastFrame = aBpd->FrameAt(aLastIndex);
nsIFrame* next = lastFrame->GetNextInFlow();
if (next && IsBidiSplittable(lastFrame)) {
lastFrame->SetNextContinuation(next);
next->SetPrevContinuation(lastFrame);
}
MakeContinuationsNonFluidUpParentChain(lastFrame, lastFrame->GetNextInFlow());
}
nsresult

View File

@ -214,3 +214,4 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
)
GYP_DIRS['signalingtest'].non_unified_sources += signaling_non_unified_sources
GYP_DIRS['signalingtest'].non_unified_sources += signaling_non_unified_sources_2

Some files were not shown because too many files have changed in this diff Show More