зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
903d3e15d5
|
@ -3002,7 +3002,7 @@
|
|||
// otherwise just rely on the panel id for common arrowpanels.
|
||||
let type = this._panel.firstChild.getAttribute("popupid") ||
|
||||
this._panel.id;
|
||||
if (type.startsWith("password-"))
|
||||
if (type == "password")
|
||||
return "passwords";
|
||||
if (type == "editBookmarkPanel")
|
||||
return "bookmarks";
|
||||
|
|
|
@ -54,6 +54,7 @@ let RLSidebar = {
|
|||
addEventListener("unload", () => this.uninit());
|
||||
|
||||
this.list = document.getElementById("list");
|
||||
this.emptyListInfo = document.getElementById("emptyListInfo");
|
||||
this.itemTemplate = document.getElementById("item-template");
|
||||
|
||||
this.list.addEventListener("click", event => this.onListClick(event));
|
||||
|
@ -91,6 +92,8 @@ let RLSidebar = {
|
|||
this.list.appendChild(itemNode);
|
||||
this.itemNodesById.set(item.id, itemNode);
|
||||
this.itemsById.set(item.id, item);
|
||||
|
||||
this.emptyListInfo.hidden = true;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -106,6 +109,8 @@ let RLSidebar = {
|
|||
this.itemsById.delete(item.id);
|
||||
// TODO: ensureListItems doesn't yet cope with needing to add one item.
|
||||
//this.ensureListItems();
|
||||
|
||||
this.emptyListInfo.hidden = (this.numItems > 0);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -148,6 +153,7 @@ let RLSidebar = {
|
|||
log.warn("Error adding item", e);
|
||||
}
|
||||
});
|
||||
this.emptyListInfo.hidden = (this.numItems > 0);
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -350,6 +356,11 @@ let RLSidebar = {
|
|||
if (!itemNode)
|
||||
return;
|
||||
|
||||
if (event.target.classList.contains("remove-button")) {
|
||||
ReadingList.deleteItem(this.getItemFromNode(itemNode));
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeItem = itemNode;
|
||||
this.openActiveItem(event);
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<head>
|
||||
<script src="chrome://browser/content/readinglist/sidebar.js" type="application/javascript;version=1.8"></script>
|
||||
<link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/readinglist/sidebar.css"/>
|
||||
<!-- <title>&readingList.label;</title> -->
|
||||
<title>&readingList.label;</title>
|
||||
</head>
|
||||
|
||||
<body role="application">
|
||||
|
@ -19,12 +19,16 @@
|
|||
<div class="item" role="option" tabindex="-1">
|
||||
<div class="item-thumb-container"></div>
|
||||
<div class="item-summary-container">
|
||||
<div class="item-title"></div>
|
||||
<div class="item-title-lines">
|
||||
<p class="item-title"/>
|
||||
<button class="remove-button" title="&readingList.sidebar.delete.tooltip;"/>
|
||||
</div>
|
||||
<div class="item-domain"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div id="emptyListInfo" hidden="true">&readingList.sidebar.emptyText;</div>
|
||||
<div id="list" role="listbox" tabindex="1"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -9,8 +9,6 @@ const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
|||
const { require } =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const QR = require("devtools/toolkit/qrcode/index");
|
||||
const PROPERTIES = "chrome://browser/locale/devtools/webide.properties";
|
||||
const Strings = Services.strings.createBundle(PROPERTIES);
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
|
@ -33,10 +31,6 @@ function createQR(oob) {
|
|||
}
|
||||
|
||||
function createToken(oob) {
|
||||
let spacedCert = oob.sha256.replace(/:/g, " ").toLowerCase();
|
||||
let certText = Strings.formatStringFromName("wifi_auth_cert",
|
||||
[spacedCert], 1);
|
||||
document.querySelector("#cert").textContent = certText;
|
||||
let token = oob.sha256.replace(/:/g, "").toLowerCase() + oob.k;
|
||||
document.querySelector("#token pre").textContent = token;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
<h3 id="header">&wifi_auth_header;</h3>
|
||||
<div id="scan-request">&wifi_auth_scan_request;</div>
|
||||
<div id="cert"></div>
|
||||
|
||||
<div id="qr-code">
|
||||
<div id="qr-code-wrapper">
|
||||
|
|
|
@ -853,7 +853,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
|||
<!ENTITY readingList.sidebar.showMore.label "Show more…">
|
||||
<!-- Pre-landed string for bug 1133662 -->
|
||||
<!ENTITY readingList.sidebar.emptyText "Add articles to your Reading List to save them for later and find them easily when you need them.">
|
||||
<!-- Pre-landed string for bug 1123525 -->
|
||||
<!ENTITY readingList.sidebar.delete.tooltip "Remove this from your Reading List">
|
||||
<!-- Pre-landed strings for bug 1123519 -->
|
||||
<!ENTITY readingList.sidebar.add.label "Add to Reading List">
|
||||
|
|
|
@ -77,9 +77,3 @@ status_unknown=UNKNOWN
|
|||
|
||||
# Device preferences and settings
|
||||
device_reset_default=Reset to default
|
||||
|
||||
# WiFi Auth
|
||||
# LOCALIZATION NOTE (wifi_auth_cert): Part of the dialog that instructs the
|
||||
# user to transfer an authentication token to the server.
|
||||
# %1$S: The client's cert fingerprint
|
||||
wifi_auth_cert=My Cert: %1$S
|
||||
|
|
|
@ -1195,8 +1195,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="password-save"],
|
||||
.popup-notification-icon[popupid="password-change"] {
|
||||
.popup-notification-icon[popupid="password"] {
|
||||
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ browser.jar:
|
|||
skin/classic/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
skin/classic/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
|
||||
* skin/classic/browser/readinglist/sidebar.css (readinglist/sidebar.css)
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
skin/classic/browser/webRTC-sharingDevice-16.png (../shared/webrtc/webRTC-sharingDevice-16.png)
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* 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/. */
|
||||
|
||||
%include ../../shared/readinglist/sidebar.inc.css
|
||||
|
||||
.item {
|
||||
-moz-padding-end: 0;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
margin: 1px 0 0;
|
||||
}
|
||||
|
||||
.item-title, .item-domain {
|
||||
-moz-margin-end: 6px;
|
||||
}
|
||||
|
||||
.remove-button {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 16, 16, 0);
|
||||
}
|
||||
|
||||
.remove-button:hover {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.remove-button:hover:active {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 48, 16, 32);
|
||||
}
|
|
@ -4220,8 +4220,7 @@ notification[value="loop-sharing-notification"] .messageImage {
|
|||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="password-save"],
|
||||
.popup-notification-icon[popupid="password-change"] {
|
||||
.popup-notification-icon[popupid="password"] {
|
||||
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ browser.jar:
|
|||
skin/classic/browser/reader-mode-16@2x.png (../shared/reader/reader-mode-16@2x.png)
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
skin/classic/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
|
||||
* skin/classic/browser/readinglist/sidebar.css (readinglist/sidebar.css)
|
||||
skin/classic/browser/webRTC-shareDevice-16.png
|
||||
skin/classic/browser/webRTC-shareDevice-16@2x.png
|
||||
skin/classic/browser/webRTC-shareDevice-64.png
|
||||
|
|
|
@ -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/. */
|
||||
|
||||
%include ../../shared/readinglist/sidebar.inc.css
|
||||
|
||||
.item-title {
|
||||
margin: 4px 0 0;
|
||||
}
|
||||
|
||||
.remove-button {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 16, 16, 0);
|
||||
}
|
||||
|
||||
.remove-button:hover {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.remove-button:hover:active {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 48, 16, 32);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.remove-button {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close@2x.png"), 0, 32, 32, 0);
|
||||
}
|
||||
|
||||
.remove-button:hover {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close@2x.png"), 0, 64, 32, 32);
|
||||
}
|
||||
|
||||
.remove-button:hover:active {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close@2x.png"), 0, 96, 32, 64);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
% This 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/.
|
||||
|
||||
:root, body {
|
||||
height: 100%;
|
||||
|
@ -16,6 +16,12 @@ body {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
#emptyListInfo {
|
||||
cursor: default;
|
||||
padding: 3em 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#list {
|
||||
height: 100%;
|
||||
overflow-x: auto;
|
||||
|
@ -52,11 +58,18 @@ body {
|
|||
flex-flow: column;
|
||||
-moz-padding-start: 4px;
|
||||
overflow: hidden;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.item-title-lines {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
overflow: hidden;
|
||||
height: 2.8em;
|
||||
max-height: 2.8em;
|
||||
line-height: 1.4;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.item-domain {
|
||||
|
@ -70,3 +83,16 @@ body {
|
|||
.item:hover .item-domain {
|
||||
color: #008ACB;
|
||||
}
|
||||
|
||||
.item:not(:hover) .remove-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.remove-button {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-size: contain;
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
}
|
||||
|
|
@ -2217,8 +2217,7 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
|||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
||||
.popup-notification-icon[popupid="password-save"],
|
||||
.popup-notification-icon[popupid="password-change"] {
|
||||
.popup-notification-icon[popupid="password"] {
|
||||
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ browser.jar:
|
|||
skin/classic/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
|
||||
skin/classic/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
skin/classic/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
|
||||
* skin/classic/browser/readinglist/sidebar.css (readinglist/sidebar.css)
|
||||
skin/classic/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png)
|
||||
skin/classic/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png)
|
||||
skin/classic/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png)
|
||||
|
@ -584,7 +584,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/reader-mode-16.png (../shared/reader/reader-mode-16.png)
|
||||
skin/classic/aero/browser/readinglist/icons.svg (../shared/readinglist/icons.svg)
|
||||
skin/classic/aero/browser/readinglist/readinglist-icon.svg (../shared/readinglist/readinglist-icon.svg)
|
||||
skin/classic/aero/browser/readinglist/sidebar.css (../shared/readinglist/sidebar.css)
|
||||
* skin/classic/aero/browser/readinglist/sidebar.css (readinglist/sidebar.css)
|
||||
skin/classic/aero/browser/notification-pluginNormal.png (../shared/plugins/notification-pluginNormal.png)
|
||||
skin/classic/aero/browser/notification-pluginAlert.png (../shared/plugins/notification-pluginAlert.png)
|
||||
skin/classic/aero/browser/notification-pluginBlocked.png (../shared/plugins/notification-pluginBlocked.png)
|
||||
|
|
|
@ -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/. */
|
||||
|
||||
%include ../../shared/readinglist/sidebar.inc.css
|
||||
|
||||
.item {
|
||||
-moz-padding-end: 0;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
margin: 1px 0 0;
|
||||
}
|
||||
|
||||
.item-title, .item-domain {
|
||||
-moz-margin-end: 6px;
|
||||
}
|
||||
|
||||
.remove-button {
|
||||
-moz-margin-end: 2px;
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 16, 16, 0);
|
||||
}
|
||||
|
||||
.remove-button:hover {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 32, 16, 16);
|
||||
}
|
||||
|
||||
.remove-button:hover:active {
|
||||
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.png"), 0, 48, 16, 32);
|
||||
}
|
|
@ -470,6 +470,7 @@ freetype/ftbitmap.h
|
|||
freetype/ftxf86.h
|
||||
freetype.h
|
||||
ftcache.h
|
||||
ftfntfmt.h
|
||||
ftglyph.h
|
||||
ftsynth.h
|
||||
ftoutln.h
|
||||
|
|
|
@ -7176,9 +7176,6 @@ if test -z "$MOZ_MEMORY"; then
|
|||
esac
|
||||
else
|
||||
AC_DEFINE(MOZ_MEMORY)
|
||||
if test -n "$NIGHTLY_BUILD"; then
|
||||
MOZ_JEMALLOC3=1
|
||||
fi
|
||||
if test -n "$MOZ_JEMALLOC3"; then
|
||||
AC_DEFINE(MOZ_JEMALLOC3)
|
||||
fi
|
||||
|
|
|
@ -417,12 +417,16 @@ Element::WrapObject(JSContext *aCx)
|
|||
CustomElementData* data = GetCustomElementData();
|
||||
if (obj && data) {
|
||||
// If this is a registered custom element then fix the prototype.
|
||||
JSAutoCompartment ac(aCx, obj);
|
||||
nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
|
||||
JS::Rooted<JSObject*> prototype(aCx);
|
||||
document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &prototype);
|
||||
if (prototype) {
|
||||
if (!JS_WrapObject(aCx, &prototype) || !JS_SetPrototype(aCx, obj, prototype)) {
|
||||
// We want to set the custom prototype in the compartment where it was
|
||||
// registered. In the case that |obj| and |prototype| are in different
|
||||
// compartments, this will set the prototype on the |obj|'s wrapper and
|
||||
// thus only visible in the wrapper's compartment.
|
||||
JSAutoCompartment ac(aCx, prototype);
|
||||
if (!JS_WrapObject(aCx, &obj) || !JS_SetPrototype(aCx, obj, prototype)) {
|
||||
dom::Throw(aCx, NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -6192,16 +6192,30 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
int32_t namespaceID = kNameSpaceID_XHTML;
|
||||
JS::Rooted<JSObject*> protoObject(aCx);
|
||||
{
|
||||
JSAutoCompartment ac(aCx, global);
|
||||
JS::Rooted<JSObject*> htmlProto(aCx);
|
||||
JS::Rooted<JSObject*> svgProto(aCx);
|
||||
{
|
||||
JSAutoCompartment ac(aCx, global);
|
||||
|
||||
JS::Handle<JSObject*> htmlProto(
|
||||
HTMLElementBinding::GetProtoObjectHandle(aCx, global));
|
||||
if (!htmlProto) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
htmlProto = HTMLElementBinding::GetProtoObjectHandle(aCx, global);
|
||||
if (!htmlProto) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
svgProto = SVGElementBinding::GetProtoObjectHandle(aCx, global);
|
||||
if (!svgProto) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aOptions.mPrototype) {
|
||||
if (!JS_WrapObject(aCx, &htmlProto)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
protoObject = JS_NewObjectWithGivenProto(aCx, nullptr, htmlProto);
|
||||
if (!protoObject) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
|
@ -6210,19 +6224,11 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
} else {
|
||||
protoObject = aOptions.mPrototype;
|
||||
|
||||
// We are already operating on the document's (/global's) compartment. Let's
|
||||
// get a view of the passed in proto from this compartment.
|
||||
if (!JS_WrapObject(aCx, &protoObject)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// We also need an unwrapped version of it for various checks.
|
||||
JS::Rooted<JSObject*> protoObjectUnwrapped(aCx,
|
||||
js::CheckedUnwrap(protoObject));
|
||||
// Get the unwrapped prototype to do some checks.
|
||||
JS::Rooted<JSObject*> protoObjectUnwrapped(aCx, js::CheckedUnwrap(protoObject));
|
||||
if (!protoObjectUnwrapped) {
|
||||
// If the documents compartment does not have same origin access
|
||||
// to the compartment of the proto we should just throw.
|
||||
// If the caller's compartment does not have permission to access the
|
||||
// unwrapped prototype then throw.
|
||||
rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
@ -6238,7 +6244,7 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
|
||||
JS::Rooted<JSPropertyDescriptor> descRoot(aCx);
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc(&descRoot);
|
||||
// This check will go through a wrapper, but as we checked above
|
||||
// This check may go through a wrapper, but as we checked above
|
||||
// it should be transparent or an xray. This should be fine for now,
|
||||
// until the spec is sorted out.
|
||||
if (!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", desc)) {
|
||||
|
@ -6251,15 +6257,13 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
return;
|
||||
}
|
||||
|
||||
JS::Handle<JSObject*> svgProto(
|
||||
SVGElementBinding::GetProtoObjectHandle(aCx, global));
|
||||
if (!svgProto) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
JS::Rooted<JSObject*> protoProto(aCx, protoObject);
|
||||
|
||||
if (!JS_WrapObject(aCx, &htmlProto) || !JS_WrapObject(aCx, &svgProto)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> protoProto(aCx, protoObject);
|
||||
|
||||
// If PROTOTYPE's interface inherits from SVGElement, set NAMESPACE to SVG
|
||||
// Namespace.
|
||||
while (protoProto) {
|
||||
|
@ -6277,7 +6281,7 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Done with the checks, leave prototype's compartment.
|
||||
|
||||
// If name was provided and not null...
|
||||
if (!lcName.IsEmpty()) {
|
||||
|
@ -6315,22 +6319,25 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
}
|
||||
} // Leaving the document's compartment for the LifecycleCallbacks init
|
||||
|
||||
JS::Rooted<JSObject*> wrappedProto(aCx, protoObject);
|
||||
if (!JS_WrapObject(aCx, &wrappedProto)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: We call the init from the caller compartment here
|
||||
nsAutoPtr<LifecycleCallbacks> callbacksHolder(new LifecycleCallbacks());
|
||||
JS::RootedValue rootedv(aCx, JS::ObjectValue(*protoObject));
|
||||
JS::RootedValue rootedv(aCx, JS::ObjectValue(*wrappedProto));
|
||||
if (!JS_WrapValue(aCx, &rootedv) || !callbacksHolder->Init(aCx, rootedv)) {
|
||||
rv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Entering the global's compartment again
|
||||
JSAutoCompartment ac(aCx, global);
|
||||
|
||||
// Associate the definition with the custom element.
|
||||
CustomElementHashKey key(namespaceID, typeAtom);
|
||||
LifecycleCallbacks* callbacks = callbacksHolder.forget();
|
||||
CustomElementDefinition* definition =
|
||||
new CustomElementDefinition(protoObject,
|
||||
new CustomElementDefinition(wrappedProto,
|
||||
typeAtom,
|
||||
nameAtom,
|
||||
callbacks,
|
||||
|
@ -6360,9 +6367,13 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
CallQueryInterface(elem, &cache);
|
||||
MOZ_ASSERT(cache, "Element doesn't support wrapper cache?");
|
||||
|
||||
// We want to set the custom prototype in the caller's comparment.
|
||||
// In the case that element is in a different compartment,
|
||||
// this will set the prototype on the element's wrapper and
|
||||
// thus only visible in the wrapper's compartment.
|
||||
JS::RootedObject wrapper(aCx);
|
||||
if ((wrapper = cache->GetWrapper())) {
|
||||
if (!JS_SetPrototype(aCx, wrapper, protoObject)) {
|
||||
if ((wrapper = cache->GetWrapper()) && JS_WrapObject(aCx, &wrapper)) {
|
||||
if (!JS_SetPrototype(aCx, wrapper, wrappedProto)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -6371,23 +6382,38 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
}
|
||||
}
|
||||
|
||||
// Create constructor to return. Store the name of the custom element as the
|
||||
// name of the function.
|
||||
JSFunction* constructor = JS_NewFunction(aCx, nsDocument::CustomElementConstructor, 0,
|
||||
JSFUN_CONSTRUCTOR,
|
||||
NS_ConvertUTF16toUTF8(lcType).get());
|
||||
if (!constructor) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
JS::Rooted<JSFunction*> constructor(aCx);
|
||||
|
||||
{
|
||||
// Go into the document's global compartment when creating the constructor
|
||||
// function because we want to get the correct document (where the
|
||||
// definition is registered) when it is called.
|
||||
JSAutoCompartment ac(aCx, global);
|
||||
|
||||
// Create constructor to return. Store the name of the custom element as the
|
||||
// name of the function.
|
||||
constructor = JS_NewFunction(aCx, nsDocument::CustomElementConstructor, 0,
|
||||
JSFUN_CONSTRUCTOR,
|
||||
NS_ConvertUTF16toUTF8(lcType).get());
|
||||
if (!constructor) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> constructorObj(aCx, JS_GetFunctionObject(constructor));
|
||||
if (!JS_LinkConstructorAndPrototype(aCx, constructorObj, protoObject)) {
|
||||
JS::Rooted<JSObject*> wrappedConstructor(aCx);
|
||||
wrappedConstructor = JS_GetFunctionObject(constructor);
|
||||
if (!JS_WrapObject(aCx, &wrappedConstructor)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aRetval.set(constructorObj);
|
||||
if (!JS_LinkConstructorAndPrototype(aCx, wrappedConstructor, protoObject)) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aRetval.set(wrappedConstructor);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -409,7 +409,8 @@ protected:
|
|||
CandidateMap;
|
||||
|
||||
// Hashtable for custom element definitions in web components.
|
||||
// Custom prototypes are in the document's compartment.
|
||||
// Custom prototypes are stored in the compartment where
|
||||
// registerElement was called.
|
||||
DefinitionMap mCustomDefinitions;
|
||||
|
||||
// The "upgrade candidates map" from the web components spec. Maps from a
|
||||
|
|
|
@ -67,7 +67,7 @@ nsHTMLContentSerializer::AppendDocumentStart(nsIDocument *aDocument,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsHTMLContentSerializer::SerializeHTMLAttributes(nsIContent* aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aTagPrefix,
|
||||
|
@ -78,7 +78,7 @@ nsHTMLContentSerializer::SerializeHTMLAttributes(nsIContent* aContent,
|
|||
{
|
||||
int32_t count = aContent->GetAttrCount();
|
||||
if (!count)
|
||||
return;
|
||||
return true;
|
||||
|
||||
nsresult rv;
|
||||
nsAutoString valueStr;
|
||||
|
@ -169,8 +169,11 @@ nsHTMLContentSerializer::SerializeHTMLAttributes(nsIContent* aContent,
|
|||
valueStr.IsEmpty()) {
|
||||
valueStr = nameStr;
|
||||
}
|
||||
SerializeAttr(prefix, nameStr, valueStr, aStr, !isJS);
|
||||
NS_ENSURE_TRUE(SerializeAttr(prefix, nameStr, valueStr,
|
||||
aStr, !isJS), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -183,10 +186,13 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
nsIContent* content = aElement;
|
||||
|
||||
bool forceFormat = false;
|
||||
if (!CheckElementStart(content, forceFormat, aStr)) {
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
if (!CheckElementStart(content, forceFormat, aStr, rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIAtom *name = content->NodeInfo()->NameAtom();
|
||||
int32_t ns = content->GetNameSpaceID();
|
||||
|
||||
|
@ -194,39 +200,41 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
|
||||
if (mColPos && lineBreakBeforeOpen) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
if (!mColPos) {
|
||||
AppendIndentation(aStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
bool result = AppendToString(char16_t(' '), aStr);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
bool result = AppendToString(char16_t(' '), aStr);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
// Always reset to avoid false newlines in case MaybeAddNewlineForRootNode wasn't
|
||||
// called
|
||||
mAddNewlineForRootNode = false;
|
||||
|
||||
AppendToString(kLessThan, aStr);
|
||||
|
||||
AppendToString(nsDependentAtomString(name), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(kLessThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ENSURE_TRUE(AppendToString(nsDependentAtomString(name), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
MaybeEnterInPreContent(content);
|
||||
|
||||
// for block elements, we increase the indentation
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel())
|
||||
IncrIndentation(name);
|
||||
NS_ENSURE_TRUE(IncrIndentation(name), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Need to keep track of OL and LI elements in order to get ordinal number
|
||||
// for the LI.
|
||||
|
@ -255,22 +263,22 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
mIsFirstChildOfOL = IsFirstChildOfOL(aOriginalElement);
|
||||
if (mIsFirstChildOfOL){
|
||||
// If OL is parent of this LI, serialize attributes in different manner.
|
||||
SerializeLIValueAttribute(aElement, aStr);
|
||||
NS_ENSURE_TRUE(SerializeLIValueAttribute(aElement, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
// Even LI passed above have to go through this
|
||||
// for serializing attributes other than "value".
|
||||
nsAutoString dummyPrefix;
|
||||
SerializeHTMLAttributes(content,
|
||||
aOriginalElement,
|
||||
dummyPrefix,
|
||||
EmptyString(),
|
||||
name,
|
||||
ns,
|
||||
aStr);
|
||||
NS_ENSURE_TRUE(SerializeHTMLAttributes(content,
|
||||
aOriginalElement,
|
||||
dummyPrefix,
|
||||
EmptyString(),
|
||||
name,
|
||||
ns,
|
||||
aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
AppendToString(kGreaterThan, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (ns == kNameSpaceID_XHTML &&
|
||||
(name == nsGkAtoms::script ||
|
||||
|
@ -282,10 +290,10 @@ nsHTMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel() &&
|
||||
LineBreakAfterOpen(ns, name)) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
AfterElementStart(content, aOriginalElement, aStr);
|
||||
NS_ENSURE_TRUE(AfterElementStart(content, aOriginalElement, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -356,30 +364,32 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
|
|||
bool lineBreakBeforeClose = LineBreakBeforeClose(ns, name);
|
||||
|
||||
if (mColPos && lineBreakBeforeClose) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
if (!mColPos) {
|
||||
AppendIndentation(aStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
bool result = AppendToString(char16_t(' '), aStr);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
bool result = AppendToString(char16_t(' '), aStr);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
AppendToString(kEndTag, aStr);
|
||||
AppendToString(nsDependentAtomString(name), aStr);
|
||||
AppendToString(kGreaterThan, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(kEndTag, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(nsDependentAtomString(name), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
MaybeLeaveFromPreContent(content);
|
||||
|
||||
if ((mDoFormat || forceFormat)&& !mDoRaw && !PreLevel()
|
||||
&& LineBreakAfterClose(ns, name)) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
MaybeFlagNewlineForRootNode(aElement);
|
||||
|
@ -451,17 +461,16 @@ uint32_t FindNextBasicEntity(const nsAString& aStr,
|
|||
return aIndex;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mDisableEntityEncoding) {
|
||||
aOutputStr.Append(aStr);
|
||||
return;
|
||||
return aOutputStr.Append(aStr, mozilla::fallible);
|
||||
}
|
||||
|
||||
bool nonBasicEntities =
|
||||
|
@ -479,20 +488,21 @@ nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
|
|||
i = FindNextBasicEntity(aStr, len, i, entityTable, &entity);
|
||||
uint32_t normalTextLen = i - start;
|
||||
if (normalTextLen) {
|
||||
aOutputStr.Append(Substring(aStr, start, normalTextLen));
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(Substring(aStr, start, normalTextLen),
|
||||
mozilla::fallible), false);
|
||||
}
|
||||
if (entity) {
|
||||
aOutputStr.AppendASCII(entity);
|
||||
NS_ENSURE_TRUE(aOutputStr.AppendASCII(entity, mozilla::fallible), false);
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (nonBasicEntities) {
|
||||
nsIParserService* parserService = nsContentUtils::GetParserService();
|
||||
|
||||
if (!parserService) {
|
||||
NS_ERROR("Can't get parser service");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsReadingIterator<char16_t> done_reading;
|
||||
|
@ -563,25 +573,29 @@ nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
|
|||
}
|
||||
}
|
||||
|
||||
aOutputStr.Append(fragmentStart, advanceLength);
|
||||
bool result = aOutputStr.Append(fragmentStart, advanceLength, mozilla::fallible);
|
||||
if (entityText) {
|
||||
aOutputStr.Append(char16_t('&'));
|
||||
AppendASCIItoUTF16(entityText, aOutputStr);
|
||||
aOutputStr.Append(char16_t(';'));
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(char16_t('&'), mozilla::fallible), false);
|
||||
NS_ENSURE_TRUE(AppendASCIItoUTF16(entityText, aOutputStr, mozilla::fallible), false);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(char16_t(';'), mozilla::fallible), false);
|
||||
advanceLength++;
|
||||
}
|
||||
else if (fullConstEntityText) {
|
||||
aOutputStr.AppendASCII(fullConstEntityText);
|
||||
NS_ENSURE_TRUE(aOutputStr.AppendASCII(fullConstEntityText, mozilla::fallible), false);
|
||||
++advanceLength;
|
||||
}
|
||||
// if it comes from nsIEntityConverter, it already has '&' and ';'
|
||||
else if (fullEntityText) {
|
||||
AppendASCIItoUTF16(fullEntityText, aOutputStr);
|
||||
bool ok = AppendASCIItoUTF16(fullEntityText, aOutputStr, mozilla::fallible);
|
||||
nsMemory::Free(fullEntityText);
|
||||
advanceLength += lengthReplaced;
|
||||
NS_ENSURE_TRUE(ok, false);
|
||||
}
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
}
|
||||
} else {
|
||||
nsXMLContentSerializer::AppendAndTranslateEntities(aStr, aOutputStr);
|
||||
NS_ENSURE_TRUE(nsXMLContentSerializer::AppendAndTranslateEntities(aStr, aOutputStr), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ class nsHTMLContentSerializer : public nsXHTMLContentSerializer {
|
|||
nsAString& aStr) MOZ_OVERRIDE;
|
||||
protected:
|
||||
|
||||
virtual void SerializeHTMLAttributes(nsIContent* aContent,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool SerializeHTMLAttributes(nsIContent* aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aTagPrefix,
|
||||
const nsAString& aTagNamespaceURI,
|
||||
|
@ -44,7 +45,8 @@ class nsHTMLContentSerializer : public nsXHTMLContentSerializer {
|
|||
int32_t aNamespace,
|
||||
nsAString& aStr);
|
||||
|
||||
virtual void AppendAndTranslateEntities(const nsAString& aStr,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AppendAndTranslateEntities(const nsAString& aStr,
|
||||
nsAString& aOutputStr) MOZ_OVERRIDE;
|
||||
|
||||
};
|
||||
|
|
|
@ -28,16 +28,11 @@ interface nsIFrame;
|
|||
* become current only when the image is loaded. It is the responsibility of
|
||||
* observers to check which request they are getting notifications for.
|
||||
*
|
||||
* Observers added in mid-load will not get any notifications they
|
||||
* missed. We should NOT freeze this interface without considering
|
||||
* this issue. (It could be that the image status on imgIRequest is
|
||||
* sufficient, when combined with the imageBlockingStatus information.)
|
||||
*
|
||||
* Please make sure to update the MozImageLoadingContent WebIDL
|
||||
* interface to mirror this interface when changing it.
|
||||
*/
|
||||
|
||||
[scriptable, builtinclass, uuid(5794d12b-3195-4526-a814-a2181f6c71fe)]
|
||||
[scriptable, builtinclass, uuid(770f7d84-c917-42d7-bf8d-d1b70649e733)]
|
||||
interface nsIImageLoadingContent : imgINotificationObserver
|
||||
{
|
||||
/**
|
||||
|
@ -100,6 +95,11 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
*/
|
||||
imgIRequest getRequest(in long aRequestType);
|
||||
|
||||
/**
|
||||
* @return true if the current request's size is available.
|
||||
*/
|
||||
[noscript, notxpcom] boolean currentRequestHasSize();
|
||||
|
||||
/**
|
||||
* Used to notify the image loading content node that a frame has been
|
||||
* created.
|
||||
|
|
|
@ -493,6 +493,12 @@ nsImageLoadingContent::GetRequest(int32_t aRequestType,
|
|||
return result.ErrorCode();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
nsImageLoadingContent::CurrentRequestHasSize()
|
||||
{
|
||||
return HaveSize(mCurrentRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
|
||||
{
|
||||
|
|
|
@ -134,24 +134,25 @@ nsXHTMLContentSerializer::AppendText(nsIContent* aText,
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mDoRaw || PreLevel() > 0) {
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoFormat) {
|
||||
AppendToStringFormatedWrapped(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringFormatedWrapped(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoWrap) {
|
||||
AppendToStringWrapped(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringWrapped(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
int32_t lastNewlineOffset = kNotFound;
|
||||
if (HasLongLines(data, lastNewlineOffset)) {
|
||||
// We have long lines, rewrap
|
||||
mDoWrap = true;
|
||||
AppendToStringWrapped(data, aStr);
|
||||
bool result = AppendToStringWrapped(data, aStr);
|
||||
mDoWrap = false;
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +223,7 @@ nsXHTMLContentSerializer::EscapeURI(nsIContent* aContent, const nsAString& aURI,
|
|||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aTagPrefix,
|
||||
|
@ -271,7 +272,7 @@ nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
|||
mIsFirstChildOfOL = IsFirstChildOfOL(aOriginalElement);
|
||||
if (mIsFirstChildOfOL) {
|
||||
// If OL is parent of this LI, serialize attributes in different manner.
|
||||
SerializeLIValueAttribute(aContent, aStr);
|
||||
NS_ENSURE_TRUE(SerializeLIValueAttribute(aContent, aStr), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -281,10 +282,14 @@ nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
|||
if (aAddNSAttr) {
|
||||
if (aTagPrefix.IsEmpty()) {
|
||||
// Serialize default namespace decl
|
||||
SerializeAttr(EmptyString(), xmlnsStr, aTagNamespaceURI, aStr, true);
|
||||
NS_ENSURE_TRUE(SerializeAttr(EmptyString(), xmlnsStr,
|
||||
aTagNamespaceURI,
|
||||
aStr, true), false);
|
||||
} else {
|
||||
// Serialize namespace decl
|
||||
SerializeAttr(xmlnsStr, aTagPrefix, aTagNamespaceURI, aStr, true);
|
||||
NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, aTagPrefix,
|
||||
aTagNamespaceURI,
|
||||
aStr, true), false);
|
||||
}
|
||||
PushNameSpaceDecl(aTagPrefix, aTagNamespaceURI, aOriginalElement);
|
||||
}
|
||||
|
@ -395,19 +400,21 @@ nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
|||
isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
|
||||
}
|
||||
|
||||
SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS);
|
||||
NS_ENSURE_TRUE(SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS), false);
|
||||
|
||||
if (addNSAttr) {
|
||||
NS_ASSERTION(!prefixStr.IsEmpty(),
|
||||
"Namespaced attributes must have a prefix");
|
||||
SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true);
|
||||
NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true), false);
|
||||
PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
nsXHTMLContentSerializer::AppendEndOfElementStart(nsIContent *aOriginalElement,
|
||||
nsIAtom * aName,
|
||||
int32_t aNamespaceID,
|
||||
|
@ -418,9 +425,8 @@ nsXHTMLContentSerializer::AppendEndOfElementStart(nsIContent *aOriginalElement,
|
|||
NS_ASSERTION(!mIsHTMLSerializer, "nsHTMLContentSerializer shouldn't call this method !");
|
||||
|
||||
if (kNameSpaceID_XHTML != aNamespaceID) {
|
||||
nsXMLContentSerializer::AppendEndOfElementStart(aOriginalElement, aName,
|
||||
aNamespaceID, aStr);
|
||||
return;
|
||||
return nsXMLContentSerializer::AppendEndOfElementStart(aOriginalElement, aName,
|
||||
aNamespaceID, aStr);
|
||||
}
|
||||
|
||||
nsIContent* content = aOriginalElement;
|
||||
|
@ -441,17 +447,16 @@ nsXHTMLContentSerializer::AppendEndOfElementStart(nsIContent *aOriginalElement,
|
|||
// for backward compatibility with HTML 4 user agents
|
||||
// only non-container HTML elements can be closed immediatly,
|
||||
// and a space is added before />
|
||||
AppendToString(NS_LITERAL_STRING(" />"), aStr);
|
||||
return;
|
||||
return AppendToString(NS_LITERAL_STRING(" />"), aStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
AppendToString(kGreaterThan, aStr);
|
||||
return AppendToString(kGreaterThan, aStr);
|
||||
}
|
||||
|
||||
void
|
||||
nsXHTMLContentSerializer::AfterElementStart(nsIContent * aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
bool
|
||||
nsXHTMLContentSerializer::AfterElementStart(nsIContent* aContent,
|
||||
nsIContent* aOriginalElement,
|
||||
nsAString& aStr)
|
||||
{
|
||||
if (mRewriteEncodingDeclaration &&
|
||||
|
@ -477,20 +482,22 @@ nsXHTMLContentSerializer::AfterElementStart(nsIContent * aContent,
|
|||
}
|
||||
|
||||
if (!hasMeta) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), false);
|
||||
if (mDoFormat) {
|
||||
AppendIndentation(aStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aStr), false);
|
||||
}
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("<meta http-equiv=\"content-type\""), aStr), false);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(" content=\"text/html; charset="), aStr), false);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_ConvertASCIItoUTF16(mCharset), aStr), false);
|
||||
if (mIsHTMLSerializer) {
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("\">"), aStr), false);
|
||||
} else {
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("\" />"), aStr), false);
|
||||
}
|
||||
AppendToString(NS_LITERAL_STRING("<meta http-equiv=\"content-type\""),
|
||||
aStr);
|
||||
AppendToString(NS_LITERAL_STRING(" content=\"text/html; charset="), aStr);
|
||||
AppendToString(NS_ConvertASCIItoUTF16(mCharset), aStr);
|
||||
if (mIsHTMLSerializer)
|
||||
AppendToString(NS_LITERAL_STRING("\">"), aStr);
|
||||
else
|
||||
AppendToString(NS_LITERAL_STRING("\" />"), aStr);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -520,8 +527,11 @@ nsXHTMLContentSerializer::AppendDocumentStart(nsIDocument *aDocument,
|
|||
bool
|
||||
nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
|
||||
bool & aForceFormat,
|
||||
nsAString& aStr)
|
||||
nsAString& aStr,
|
||||
nsresult& aResult)
|
||||
{
|
||||
aResult = NS_OK;
|
||||
|
||||
// The _moz_dirty attribute is emitted by the editor to
|
||||
// indicate that this element should be pretty printed
|
||||
// even if we're not in pretty printing mode
|
||||
|
@ -531,7 +541,7 @@ nsXHTMLContentSerializer::CheckElementStart(nsIContent * aContent,
|
|||
if (aContent->IsHTMLElement(nsGkAtoms::br) &&
|
||||
(mFlags & nsIDocumentEncoder::OutputNoFormattingInPre) &&
|
||||
PreLevel() > 0) {
|
||||
AppendNewLineToString(aStr);
|
||||
aResult = AppendNewLineToString(aStr) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -591,20 +601,19 @@ nsXHTMLContentSerializer::CheckElementEnd(nsIContent * aContent,
|
|||
return nsXMLContentSerializer::CheckElementEnd(aContent, dummyFormat, aStr);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mDisableEntityEncoding) {
|
||||
aOutputStr.Append(aStr);
|
||||
return;
|
||||
return aOutputStr.Append(aStr, mozilla::fallible);
|
||||
}
|
||||
|
||||
nsXMLContentSerializer::AppendAndTranslateEntities(aStr, aOutputStr);
|
||||
|
||||
return nsXMLContentSerializer::AppendAndTranslateEntities(aStr, aOutputStr);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -884,7 +893,7 @@ nsXHTMLContentSerializer::IsElementPreformatted(nsIContent* aNode)
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXHTMLContentSerializer::SerializeLIValueAttribute(nsIContent* aElement,
|
||||
nsAString& aStr)
|
||||
{
|
||||
|
@ -936,7 +945,8 @@ nsXHTMLContentSerializer::SerializeLIValueAttribute(nsIContent* aElement,
|
|||
if (offset == 0 && found) {
|
||||
// offset = 0 => LI itself has the value attribute and we did not need to traverse back.
|
||||
// Just serialize value attribute like other tags.
|
||||
SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"), valueStr, aStr, false);
|
||||
NS_ENSURE_TRUE(SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"),
|
||||
valueStr, aStr, false), false);
|
||||
}
|
||||
else if (offset == 1 && !found) {
|
||||
/*(offset = 1 && !found) means either LI is the first child node of OL
|
||||
|
@ -951,8 +961,11 @@ nsXHTMLContentSerializer::SerializeLIValueAttribute(nsIContent* aElement,
|
|||
|
||||
//As serializer needs to use this valueAttr we are creating here,
|
||||
valueStr.AppendInt(startVal + offset);
|
||||
SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"), valueStr, aStr, false);
|
||||
NS_ENSURE_TRUE(SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"),
|
||||
valueStr, aStr, false), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -43,16 +43,19 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
|
|||
|
||||
virtual bool CheckElementStart(nsIContent * aContent,
|
||||
bool & aForceFormat,
|
||||
nsAString& aStr) MOZ_OVERRIDE;
|
||||
nsAString& aStr,
|
||||
nsresult& aResult) MOZ_OVERRIDE;
|
||||
|
||||
virtual void AppendEndOfElementStart(nsIContent *aOriginalElement,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AppendEndOfElementStart(nsIContent *aOriginalElement,
|
||||
nsIAtom * aName,
|
||||
int32_t aNamespaceID,
|
||||
nsAString& aStr) MOZ_OVERRIDE;
|
||||
|
||||
virtual void AfterElementStart(nsIContent * aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aStr) MOZ_OVERRIDE;
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AfterElementStart(nsIContent* aContent,
|
||||
nsIContent* aOriginalElement,
|
||||
nsAString& aStr) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool CheckElementEnd(nsIContent * aContent,
|
||||
bool & aForceFormat,
|
||||
|
@ -72,7 +75,8 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
|
|||
virtual void MaybeEnterInPreContent(nsIContent* aNode) MOZ_OVERRIDE;
|
||||
virtual void MaybeLeaveFromPreContent(nsIContent* aNode) MOZ_OVERRIDE;
|
||||
|
||||
virtual void SerializeAttributes(nsIContent* aContent,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool SerializeAttributes(nsIContent* aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aTagPrefix,
|
||||
const nsAString& aTagNamespaceURI,
|
||||
|
@ -83,12 +87,16 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
|
|||
|
||||
bool IsFirstChildOfOL(nsIContent* aElement);
|
||||
|
||||
void SerializeLIValueAttribute(nsIContent* aElement,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool SerializeLIValueAttribute(nsIContent* aElement,
|
||||
nsAString& aStr);
|
||||
bool IsShorthandAttr(const nsIAtom* aAttrName,
|
||||
const nsIAtom* aElementName);
|
||||
virtual void AppendAndTranslateEntities(const nsAString& aStr,
|
||||
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AppendAndTranslateEntities(const nsAString& aStr,
|
||||
nsAString& aOutputStr) MOZ_OVERRIDE;
|
||||
|
||||
nsresult EscapeURI(nsIContent* aContent,
|
||||
const nsAString& aURI,
|
||||
nsAString& aEscapedURI);
|
||||
|
|
|
@ -154,18 +154,22 @@ nsXMLContentSerializer::AppendTextData(nsIContent* aNode,
|
|||
if (frag->Is2b()) {
|
||||
const char16_t *strStart = frag->Get2b() + aStartOffset;
|
||||
if (aTranslateEntities) {
|
||||
AppendAndTranslateEntities(Substring(strStart, strStart + length), aStr);
|
||||
NS_ENSURE_TRUE(AppendAndTranslateEntities(Substring(strStart, strStart + length), aStr),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
aStr.Append(Substring(strStart, strStart + length));
|
||||
NS_ENSURE_TRUE(aStr.Append(Substring(strStart, strStart + length), mozilla::fallible),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (aTranslateEntities) {
|
||||
AppendAndTranslateEntities(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length), aStr);
|
||||
NS_ENSURE_TRUE(AppendAndTranslateEntities(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length), aStr),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
aStr.Append(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length));
|
||||
NS_ENSURE_TRUE(aStr.Append(NS_ConvertASCIItoUTF16(frag->Get1b()+aStartOffset, length), mozilla::fallible),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,16 +192,16 @@ nsXMLContentSerializer::AppendText(nsIContent* aText,
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mDoRaw || PreLevel() > 0) {
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoFormat) {
|
||||
AppendToStringFormatedWrapped(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringFormatedWrapped(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoWrap) {
|
||||
AppendToStringWrapped(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringWrapped(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -215,25 +219,25 @@ nsXMLContentSerializer::AppendCDATASection(nsIContent* aCDATASection,
|
|||
NS_NAMED_LITERAL_STRING(cdata , "<![CDATA[");
|
||||
|
||||
if (mDoRaw || PreLevel() > 0) {
|
||||
AppendToString(cdata, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(cdata, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoFormat) {
|
||||
AppendToStringFormatedWrapped(cdata, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringFormatedWrapped(cdata, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoWrap) {
|
||||
AppendToStringWrapped(cdata, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringWrapped(cdata, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
AppendToString(cdata, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(cdata, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
nsAutoString data;
|
||||
rv = AppendTextData(aCDATASection, aStartOffset, aEndOffset, data, false);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
AppendToString(NS_LITERAL_STRING("]]>"), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("]]>"), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -249,7 +253,7 @@ nsXMLContentSerializer::AppendProcessingInstruction(nsIContent* aPI,
|
|||
nsresult rv;
|
||||
nsAutoString target, data, start;
|
||||
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
rv = pi->GetTarget(target);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
@ -257,30 +261,30 @@ nsXMLContentSerializer::AppendProcessingInstruction(nsIContent* aPI,
|
|||
rv = pi->GetData(data);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
start.AppendLiteral("<?");
|
||||
start.Append(target);
|
||||
NS_ENSURE_TRUE(start.AppendLiteral("<?", mozilla::fallible), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(start.Append(target, mozilla::fallible), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (mDoRaw || PreLevel() > 0) {
|
||||
AppendToString(start, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(start, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoFormat) {
|
||||
if (mAddSpace) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
AppendToStringFormatedWrapped(start, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringFormatedWrapped(start, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoWrap) {
|
||||
AppendToStringWrapped(start, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringWrapped(start, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
AppendToString(start, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(start, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (!data.IsEmpty()) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(' '), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
AppendToString(NS_LITERAL_STRING("?>"), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("?>"), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
MaybeFlagNewlineForRootNode(aPI);
|
||||
|
||||
|
@ -314,30 +318,30 @@ nsXMLContentSerializer::AppendComment(nsIContent* aComment,
|
|||
data.Assign(frag);
|
||||
}
|
||||
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(startComment, "<!--");
|
||||
|
||||
if (mDoRaw || PreLevel() > 0) {
|
||||
AppendToString(startComment, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(startComment, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoFormat) {
|
||||
if (mAddSpace) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
AppendToStringFormatedWrapped(startComment, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringFormatedWrapped(startComment, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mDoWrap) {
|
||||
AppendToStringWrapped(startComment, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringWrapped(startComment, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
AppendToString(startComment, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(startComment, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// Even if mDoformat, we don't format the content because it
|
||||
// could have been preformated by the author
|
||||
AppendToStringConvertLF(data, aStr);
|
||||
AppendToString(NS_LITERAL_STRING("-->"), aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(data, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("-->"), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
MaybeFlagNewlineForRootNode(aComment);
|
||||
|
||||
|
@ -362,35 +366,35 @@ nsXMLContentSerializer::AppendDoctype(nsIContent* aDocType,
|
|||
rv = docType->GetInternalSubset(internalSubset);
|
||||
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
|
||||
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
AppendToString(NS_LITERAL_STRING("<!DOCTYPE "), aStr);
|
||||
AppendToString(name, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING("<!DOCTYPE "), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(name, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
char16_t quote;
|
||||
if (!publicId.IsEmpty()) {
|
||||
AppendToString(NS_LITERAL_STRING(" PUBLIC "), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(" PUBLIC "), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
if (publicId.FindChar(char16_t('"')) == -1) {
|
||||
quote = char16_t('"');
|
||||
}
|
||||
else {
|
||||
quote = char16_t('\'');
|
||||
}
|
||||
AppendToString(quote, aStr);
|
||||
AppendToString(publicId, aStr);
|
||||
AppendToString(quote, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(quote, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(publicId, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(quote, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!systemId.IsEmpty()) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(' '), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
if (systemId.FindChar(char16_t('"')) == -1) {
|
||||
quote = char16_t('"');
|
||||
}
|
||||
else {
|
||||
quote = char16_t('\'');
|
||||
}
|
||||
AppendToString(quote, aStr);
|
||||
AppendToString(systemId, aStr);
|
||||
AppendToString(quote, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(quote, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(systemId, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(quote, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
else if (!systemId.IsEmpty()) {
|
||||
|
@ -400,19 +404,19 @@ nsXMLContentSerializer::AppendDoctype(nsIContent* aDocType,
|
|||
else {
|
||||
quote = char16_t('\'');
|
||||
}
|
||||
AppendToString(NS_LITERAL_STRING(" SYSTEM "), aStr);
|
||||
AppendToString(quote, aStr);
|
||||
AppendToString(systemId, aStr);
|
||||
AppendToString(quote, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(" SYSTEM "), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(quote, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(systemId, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(quote, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
if (!internalSubset.IsEmpty()) {
|
||||
AppendToString(NS_LITERAL_STRING(" ["), aStr);
|
||||
AppendToString(internalSubset, aStr);
|
||||
AppendToString(char16_t(']'), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(" ["), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(internalSubset, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(']'), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
AppendToString(kGreaterThan, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
MaybeFlagNewlineForRootNode(aDocType);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -606,7 +610,7 @@ nsXMLContentSerializer::GenerateNewPrefix(nsAString& aPrefix)
|
|||
AppendASCIItoUTF16(buf, aPrefix);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::SerializeAttr(const nsAString& aPrefix,
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue,
|
||||
|
@ -619,25 +623,26 @@ nsXMLContentSerializer::SerializeAttr(const nsAString& aPrefix,
|
|||
bool rawAppend = mDoRaw && aDoEscapeEntities;
|
||||
nsAString& attrString = (rawAppend) ? aStr : attrString_;
|
||||
|
||||
attrString.Append(char16_t(' '));
|
||||
NS_ENSURE_TRUE(attrString.Append(char16_t(' '), mozilla::fallible), false);
|
||||
if (!aPrefix.IsEmpty()) {
|
||||
attrString.Append(aPrefix);
|
||||
attrString.Append(char16_t(':'));
|
||||
NS_ENSURE_TRUE(attrString.Append(aPrefix, mozilla::fallible), false);
|
||||
NS_ENSURE_TRUE(attrString.Append(char16_t(':'), mozilla::fallible), false);
|
||||
}
|
||||
attrString.Append(aName);
|
||||
NS_ENSURE_TRUE(attrString.Append(aName, mozilla::fallible), false);
|
||||
|
||||
if (aDoEscapeEntities) {
|
||||
// if problem characters are turned into character entity references
|
||||
// then there will be no problem with the value delimiter characters
|
||||
attrString.AppendLiteral("=\"");
|
||||
NS_ENSURE_TRUE(attrString.AppendLiteral("=\"", mozilla::fallible), false);
|
||||
|
||||
mInAttribute = true;
|
||||
AppendAndTranslateEntities(aValue, attrString);
|
||||
bool result = AppendAndTranslateEntities(aValue, attrString);
|
||||
mInAttribute = false;
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
|
||||
attrString.Append(char16_t('"'));
|
||||
NS_ENSURE_TRUE(attrString.Append(char16_t('"'), mozilla::fallible), false);
|
||||
if (rawAppend) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -681,30 +686,32 @@ nsXMLContentSerializer::SerializeAttr(const nsAString& aPrefix,
|
|||
// TRUE TRUE " TRUE
|
||||
char16_t cDelimiter =
|
||||
(bIncludesDouble && !bIncludesSingle) ? char16_t('\'') : char16_t('"');
|
||||
attrString.Append(char16_t('='));
|
||||
attrString.Append(cDelimiter);
|
||||
NS_ENSURE_TRUE(attrString.Append(char16_t('='), mozilla::fallible), false);
|
||||
NS_ENSURE_TRUE(attrString.Append(cDelimiter, mozilla::fallible), false);
|
||||
nsAutoString sValue(aValue);
|
||||
sValue.ReplaceSubstring(NS_LITERAL_STRING("&"),
|
||||
NS_LITERAL_STRING("&"));
|
||||
NS_ENSURE_TRUE(sValue.ReplaceSubstring(NS_LITERAL_STRING("&"),
|
||||
NS_LITERAL_STRING("&"), mozilla::fallible), false);
|
||||
if (bIncludesDouble && bIncludesSingle) {
|
||||
sValue.ReplaceSubstring(NS_LITERAL_STRING("\""),
|
||||
NS_LITERAL_STRING("""));
|
||||
NS_ENSURE_TRUE(sValue.ReplaceSubstring(NS_LITERAL_STRING("\""),
|
||||
NS_LITERAL_STRING("""), mozilla::fallible), false);
|
||||
}
|
||||
attrString.Append(sValue);
|
||||
attrString.Append(cDelimiter);
|
||||
NS_ENSURE_TRUE(attrString.Append(sValue, mozilla::fallible), false);
|
||||
NS_ENSURE_TRUE(attrString.Append(cDelimiter, mozilla::fallible), false);
|
||||
}
|
||||
if (mDoRaw || PreLevel() > 0) {
|
||||
AppendToStringConvertLF(attrString, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(attrString, aStr), false);
|
||||
}
|
||||
else if (mDoFormat) {
|
||||
AppendToStringFormatedWrapped(attrString, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringFormatedWrapped(attrString, aStr), false);
|
||||
}
|
||||
else if (mDoWrap) {
|
||||
AppendToStringWrapped(attrString, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringWrapped(attrString, aStr), false);
|
||||
}
|
||||
else {
|
||||
AppendToStringConvertLF(attrString, aStr);
|
||||
NS_ENSURE_TRUE(AppendToStringConvertLF(attrString, aStr), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -792,7 +799,7 @@ nsXMLContentSerializer::IsJavaScript(nsIContent * aContent, nsIAtom* aAttrNameAt
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aTagPrefix,
|
||||
|
@ -813,11 +820,11 @@ nsXMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
|||
if (aAddNSAttr) {
|
||||
if (aTagPrefix.IsEmpty()) {
|
||||
// Serialize default namespace decl
|
||||
SerializeAttr(EmptyString(), xmlnsStr, aTagNamespaceURI, aStr, true);
|
||||
NS_ENSURE_TRUE(SerializeAttr(EmptyString(), xmlnsStr, aTagNamespaceURI, aStr, true), false);
|
||||
}
|
||||
else {
|
||||
// Serialize namespace decl
|
||||
SerializeAttr(xmlnsStr, aTagPrefix, aTagNamespaceURI, aStr, true);
|
||||
NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, aTagPrefix, aTagNamespaceURI, aStr, true), false);
|
||||
}
|
||||
PushNameSpaceDecl(aTagPrefix, aTagNamespaceURI, aOriginalElement);
|
||||
}
|
||||
|
@ -862,15 +869,17 @@ nsXMLContentSerializer::SerializeAttributes(nsIContent* aContent,
|
|||
nsDependentAtomString nameStr(attrName);
|
||||
bool isJS = IsJavaScript(aContent, attrName, namespaceID, valueStr);
|
||||
|
||||
SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS);
|
||||
NS_ENSURE_TRUE(SerializeAttr(prefixStr, nameStr, valueStr, aStr, !isJS), false);
|
||||
|
||||
if (addNSAttr) {
|
||||
NS_ASSERTION(!prefixStr.IsEmpty(),
|
||||
"Namespaced attributes must have a prefix");
|
||||
SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true);
|
||||
NS_ENSURE_TRUE(SerializeAttr(xmlnsStr, prefixStr, uriStr, aStr, true), false);
|
||||
PushNameSpaceDecl(prefixStr, uriStr, aOriginalElement);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -883,10 +892,13 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
nsIContent* content = aElement;
|
||||
|
||||
bool forceFormat = false;
|
||||
if (!CheckElementStart(content, forceFormat, aStr)) {
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
if (!CheckElementStart(content, forceFormat, aStr, rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString tagPrefix, tagLocalName, tagNamespaceURI;
|
||||
aElement->NodeInfo()->GetPrefix(tagPrefix);
|
||||
aElement->NodeInfo()->GetName(tagLocalName);
|
||||
|
@ -900,25 +912,25 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
|
||||
if (mColPos && lineBreakBeforeOpen) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
if (!mColPos) {
|
||||
AppendIndentation(aStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(' '), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
mAddSpace = false;
|
||||
}
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(' '), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
mAddSpace = false;
|
||||
}
|
||||
else {
|
||||
MaybeAddNewlineForRootNode(aStr);
|
||||
NS_ENSURE_TRUE(MaybeAddNewlineForRootNode(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// Always reset to avoid false newlines in case MaybeAddNewlineForRootNode wasn't
|
||||
|
@ -930,36 +942,38 @@ nsXMLContentSerializer::AppendElementStart(Element* aElement,
|
|||
false);
|
||||
|
||||
// Serialize the qualified name of the element
|
||||
AppendToString(kLessThan, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(kLessThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!tagPrefix.IsEmpty()) {
|
||||
AppendToString(tagPrefix, aStr);
|
||||
AppendToString(NS_LITERAL_STRING(":"), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(tagPrefix, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(":"), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
AppendToString(tagLocalName, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(tagLocalName, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
MaybeEnterInPreContent(content);
|
||||
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()) {
|
||||
IncrIndentation(name);
|
||||
NS_ENSURE_TRUE(IncrIndentation(name), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
SerializeAttributes(content, aOriginalElement, tagPrefix, tagNamespaceURI,
|
||||
name, aStr, skipAttr, addNSAttr);
|
||||
NS_ENSURE_TRUE(SerializeAttributes(content, aOriginalElement, tagPrefix, tagNamespaceURI,
|
||||
name, aStr, skipAttr, addNSAttr),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
AppendEndOfElementStart(aOriginalElement, name, content->GetNameSpaceID(),
|
||||
aStr);
|
||||
NS_ENSURE_TRUE(AppendEndOfElementStart(aOriginalElement, name,
|
||||
content->GetNameSpaceID(), aStr),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()
|
||||
&& LineBreakAfterOpen(content->GetNameSpaceID(), name)) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
AfterElementStart(content, aOriginalElement, aStr);
|
||||
NS_ENSURE_TRUE(AfterElementStart(content, aOriginalElement, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendEndOfElementStart(nsIContent *aOriginalElement,
|
||||
nsIAtom * aName,
|
||||
int32_t aNamespaceID,
|
||||
|
@ -967,10 +981,10 @@ nsXMLContentSerializer::AppendEndOfElementStart(nsIContent *aOriginalElement,
|
|||
{
|
||||
// We don't output a separate end tag for empty elements
|
||||
if (!aOriginalElement->GetChildCount()) {
|
||||
AppendToString(NS_LITERAL_STRING("/>"), aStr);
|
||||
return AppendToString(NS_LITERAL_STRING("/>"), aStr);
|
||||
}
|
||||
else {
|
||||
AppendToString(kGreaterThan, aStr);
|
||||
return AppendToString(kGreaterThan, aStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1014,28 +1028,28 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
|
|||
bool lineBreakBeforeClose = LineBreakBeforeClose(content->GetNameSpaceID(), name);
|
||||
|
||||
if (mColPos && lineBreakBeforeClose) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
if (!mColPos) {
|
||||
AppendIndentation(aStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(' '), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
mAddSpace = false;
|
||||
}
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
AppendToString(char16_t(' '), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(char16_t(' '), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
mAddSpace = false;
|
||||
}
|
||||
|
||||
AppendToString(kEndTag, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(kEndTag, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!tagPrefix.IsEmpty()) {
|
||||
AppendToString(tagPrefix, aStr);
|
||||
AppendToString(NS_LITERAL_STRING(":"), aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(tagPrefix, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(NS_LITERAL_STRING(":"), aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
AppendToString(tagLocalName, aStr);
|
||||
AppendToString(kGreaterThan, aStr);
|
||||
NS_ENSURE_TRUE(AppendToString(tagLocalName, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(AppendToString(kGreaterThan, aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PopNameSpaceDeclsFor(aElement);
|
||||
|
||||
|
@ -1043,7 +1057,7 @@ nsXMLContentSerializer::AppendElementEnd(Element* aElement,
|
|||
|
||||
if ((mDoFormat || forceFormat) && !mDoRaw && !PreLevel()
|
||||
&& LineBreakAfterClose(content->GetNameSpaceID(), name)) {
|
||||
AppendNewLineToString(aStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aStr), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
MaybeFlagNewlineForRootNode(aElement);
|
||||
|
@ -1086,7 +1100,7 @@ nsXMLContentSerializer::AppendDocumentStart(nsIDocument *aDocument,
|
|||
aStr += NS_LITERAL_STRING(" standalone=\"") + standalone + endQuote;
|
||||
}
|
||||
|
||||
aStr.AppendLiteral("?>");
|
||||
NS_ENSURE_TRUE(aStr.AppendLiteral("?>", mozilla::fallible), NS_ERROR_OUT_OF_MEMORY);
|
||||
mAddNewlineForRootNode = true;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1095,8 +1109,10 @@ nsXMLContentSerializer::AppendDocumentStart(nsIDocument *aDocument,
|
|||
bool
|
||||
nsXMLContentSerializer::CheckElementStart(nsIContent * aContent,
|
||||
bool & aForceFormat,
|
||||
nsAString& aStr)
|
||||
nsAString& aStr,
|
||||
nsresult& aResult)
|
||||
{
|
||||
aResult = NS_OK;
|
||||
aForceFormat = false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1111,26 +1127,26 @@ nsXMLContentSerializer::CheckElementEnd(nsIContent * aContent,
|
|||
return aContent->GetChildCount() > 0;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendToString(const char16_t aChar,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
mColPos += 1;
|
||||
aOutputStr.Append(aChar);
|
||||
return aOutputStr.Append(aChar, mozilla::fallible);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendToString(const nsAString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
mColPos += aStr.Length();
|
||||
aOutputStr.Append(aStr);
|
||||
return aOutputStr.Append(aStr, mozilla::fallible);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1155,7 +1171,7 @@ static const char* kAttrEntities[] = {
|
|||
"<", "", ">"
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
|
@ -1188,20 +1204,24 @@ nsXMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
|
|||
}
|
||||
}
|
||||
|
||||
aOutputStr.Append(fragmentStart, advanceLength);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(fragmentStart, advanceLength, mozilla::fallible), false);
|
||||
if (entityText) {
|
||||
AppendASCIItoUTF16(entityText, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendASCIItoUTF16(entityText, aOutputStr, mozilla::fallible), false);
|
||||
advanceLength++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::MaybeAddNewlineForRootNode(nsAString& aStr)
|
||||
{
|
||||
if (mAddNewlineForRootNode) {
|
||||
AppendNewLineToString(aStr);
|
||||
return AppendNewLineToString(aStr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1239,26 +1259,28 @@ nsXMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendNewLineToString(nsAString& aStr)
|
||||
{
|
||||
AppendToString(mLineBreak, aStr);
|
||||
bool result = AppendToString(mLineBreak, aStr);
|
||||
mMayIgnoreLineBreakSequence = true;
|
||||
mColPos = 0;
|
||||
mAddSpace = false;
|
||||
mIsIndentationAddedOnCurrentLine = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendIndentation(nsAString& aStr)
|
||||
{
|
||||
mIsIndentationAddedOnCurrentLine = true;
|
||||
AppendToString(mIndent, aStr);
|
||||
bool result = AppendToString(mIndent, aStr);
|
||||
mAddSpace = false;
|
||||
mMayIgnoreLineBreakSequence = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::IncrIndentation(nsIAtom* aName)
|
||||
{
|
||||
// we want to keep the source readable
|
||||
|
@ -1267,8 +1289,10 @@ nsXMLContentSerializer::IncrIndentation(nsIAtom* aName)
|
|||
++mIndentOverflow;
|
||||
}
|
||||
else {
|
||||
mIndent.AppendLiteral(INDENT_STRING);
|
||||
return mIndent.AppendLiteral(INDENT_STRING, mozilla::fallible);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1304,16 +1328,16 @@ nsXMLContentSerializer::LineBreakAfterClose(int32_t aNamespaceID, nsIAtom* aName
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendToStringConvertLF(const nsAString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mDoRaw) {
|
||||
AppendToString(aStr, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendToString(aStr, aOutputStr), false);
|
||||
}
|
||||
else {
|
||||
// Convert line-endings to mLineBreak
|
||||
|
@ -1323,7 +1347,7 @@ nsXMLContentSerializer::AppendToStringConvertLF(const nsAString& aStr,
|
|||
int32_t eol = aStr.FindChar('\n', start);
|
||||
if (eol == kNotFound) {
|
||||
nsDependentSubstring dataSubstring(aStr, start, theLen - start);
|
||||
AppendToString(dataSubstring, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendToString(dataSubstring, aOutputStr), false);
|
||||
start = theLen;
|
||||
// if there was a line break before this substring
|
||||
// AppendNewLineToString was called, so we should reverse
|
||||
|
@ -1332,15 +1356,17 @@ nsXMLContentSerializer::AppendToStringConvertLF(const nsAString& aStr,
|
|||
}
|
||||
else {
|
||||
nsDependentSubstring dataSubstring(aStr, start, eol - start);
|
||||
AppendToString(dataSubstring, aOutputStr);
|
||||
AppendNewLineToString(aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendToString(dataSubstring, aOutputStr), false);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aOutputStr), false);
|
||||
start = eol + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendFormatedWrapped_WhitespaceSequence(
|
||||
nsASingleFragmentString::const_char_iterator &aPos,
|
||||
const nsASingleFragmentString::const_char_iterator aEnd,
|
||||
|
@ -1393,10 +1419,11 @@ nsXMLContentSerializer::AppendFormatedWrapped_WhitespaceSequence(
|
|||
if (mDoWrap && mColPos + 1 >= mMaxColumn) {
|
||||
// no much sense in delaying, we only have one slot left,
|
||||
// let's write a break now
|
||||
aOutputStr.Append(mLineBreak);
|
||||
bool result = aOutputStr.Append(mLineBreak, mozilla::fallible);
|
||||
mColPos = 0;
|
||||
mIsIndentationAddedOnCurrentLine = false;
|
||||
mMayIgnoreLineBreakSequence = true;
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
}
|
||||
else {
|
||||
// do not write out yet, we may write out either a space or a linebreak
|
||||
|
@ -1410,12 +1437,14 @@ nsXMLContentSerializer::AppendFormatedWrapped_WhitespaceSequence(
|
|||
// transform a linebreak into a space.
|
||||
// Since we only saw linebreaks, but no spaces or tabs,
|
||||
// let's write a linebreak now.
|
||||
AppendNewLineToString(aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aOutputStr), false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
|
||||
nsASingleFragmentString::const_char_iterator &aPos,
|
||||
const nsASingleFragmentString::const_char_iterator aEnd,
|
||||
|
@ -1476,15 +1505,16 @@ nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
|
|||
if (aPos == aEnd || foundWhitespaceInLoop) {
|
||||
// there is enough room for the complete block we found
|
||||
if (mDoFormat && !mColPos) {
|
||||
AppendIndentation(aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aOutputStr), false);
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
aOutputStr.Append(char16_t(' '));
|
||||
bool result = aOutputStr.Append(char16_t(' '), mozilla::fallible);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
}
|
||||
|
||||
mColPos += length;
|
||||
aOutputStr.Append(aSequenceStart, aPos - aSequenceStart);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(aSequenceStart, aPos - aSequenceStart, mozilla::fallible), false);
|
||||
|
||||
// We have not yet reached the max column, we will continue to
|
||||
// fill the current line in the next outer loop iteration
|
||||
|
@ -1501,7 +1531,7 @@ nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
|
|||
// We can avoid to wrap. We try to add the whole block
|
||||
// in an empty new line
|
||||
|
||||
AppendNewLineToString(aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aOutputStr), false);
|
||||
aPos = aSequenceStart;
|
||||
thisSequenceStartsAtBeginningOfLine = true;
|
||||
onceAgainBecauseWeAddedBreakInFront = true;
|
||||
|
@ -1531,15 +1561,16 @@ nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
|
|||
|
||||
if (foundWrapPosition) {
|
||||
if (!mColPos && mDoFormat) {
|
||||
AppendIndentation(aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendIndentation(aOutputStr), false);
|
||||
}
|
||||
else if (mAddSpace) {
|
||||
aOutputStr.Append(char16_t(' '));
|
||||
bool result = aOutputStr.Append(char16_t(' '), mozilla::fallible);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
}
|
||||
aOutputStr.Append(aSequenceStart, wrapPosition);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(aSequenceStart, wrapPosition, mozilla::fallible), false);
|
||||
|
||||
AppendNewLineToString(aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendNewLineToString(aOutputStr), false);
|
||||
aPos = aSequenceStart + wrapPosition;
|
||||
aMayIgnoreStartOfLineWhitespaceSequence = true;
|
||||
}
|
||||
|
@ -1563,23 +1594,26 @@ nsXMLContentSerializer::AppendWrapped_NonWhitespaceSequence(
|
|||
} while (aPos < aEnd);
|
||||
|
||||
if (mAddSpace) {
|
||||
aOutputStr.Append(char16_t(' '));
|
||||
bool result = aOutputStr.Append(char16_t(' '), mozilla::fallible);
|
||||
mAddSpace = false;
|
||||
NS_ENSURE_TRUE(result, false);
|
||||
}
|
||||
aOutputStr.Append(aSequenceStart, aPos - aSequenceStart);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(aSequenceStart, aPos - aSequenceStart, mozilla::fallible), false);
|
||||
}
|
||||
}
|
||||
aSequenceStartAfterAWhiteSpace = false;
|
||||
}
|
||||
} while (onceAgainBecauseWeAddedBreakInFront);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsASingleFragmentString::const_char_iterator pos, end, sequenceStart;
|
||||
|
@ -1609,17 +1643,20 @@ nsXMLContentSerializer::AppendToStringFormatedWrapped(const nsASingleFragmentStr
|
|||
|
||||
// if beginning of a whitespace sequence
|
||||
if (*pos == ' ' || *pos == '\n' || *pos == '\t') {
|
||||
AppendFormatedWrapped_WhitespaceSequence(pos, end, sequenceStart,
|
||||
mayIgnoreStartOfLineWhitespaceSequence, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendFormatedWrapped_WhitespaceSequence(pos, end, sequenceStart,
|
||||
mayIgnoreStartOfLineWhitespaceSequence, aOutputStr), false);
|
||||
}
|
||||
else { // any other non-whitespace char
|
||||
AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart,
|
||||
mayIgnoreStartOfLineWhitespaceSequence, sequenceStartAfterAWhitespace, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart,
|
||||
mayIgnoreStartOfLineWhitespaceSequence, sequenceStartAfterAWhitespace,
|
||||
aOutputStr), false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendWrapped_WhitespaceSequence(
|
||||
nsASingleFragmentString::const_char_iterator &aPos,
|
||||
const nsASingleFragmentString::const_char_iterator aEnd,
|
||||
|
@ -1642,9 +1679,9 @@ nsXMLContentSerializer::AppendWrapped_WhitespaceSequence(
|
|||
// if there are too many spaces on a line, we wrap
|
||||
if (mColPos >= mMaxColumn) {
|
||||
if (lastPos != aPos) {
|
||||
aOutputStr.Append(lastPos, aPos - lastPos);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(lastPos, aPos - lastPos, mozilla::fallible), false);
|
||||
}
|
||||
AppendToString(mLineBreak, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendToString(mLineBreak, aOutputStr), false);
|
||||
mColPos = 0;
|
||||
lastPos = aPos;
|
||||
}
|
||||
|
@ -1654,9 +1691,9 @@ nsXMLContentSerializer::AppendWrapped_WhitespaceSequence(
|
|||
break;
|
||||
case '\n':
|
||||
if (lastPos != aPos) {
|
||||
aOutputStr.Append(lastPos, aPos - lastPos);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(lastPos, aPos - lastPos, mozilla::fallible), false);
|
||||
}
|
||||
AppendToString(mLineBreak, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendToString(mLineBreak, aOutputStr), false);
|
||||
mColPos = 0;
|
||||
++aPos;
|
||||
lastPos = aPos;
|
||||
|
@ -1668,16 +1705,18 @@ nsXMLContentSerializer::AppendWrapped_WhitespaceSequence(
|
|||
} while (!leaveLoop && aPos < aEnd);
|
||||
|
||||
if (lastPos != aPos) {
|
||||
aOutputStr.Append(lastPos, aPos - lastPos);
|
||||
NS_ENSURE_TRUE(aOutputStr.Append(lastPos, aPos - lastPos, mozilla::fallible), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsXMLContentSerializer::AppendToStringWrapped(const nsASingleFragmentString& aStr,
|
||||
nsAString& aOutputStr)
|
||||
{
|
||||
if (mBodyOnly && !mInBody) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
nsASingleFragmentString::const_char_iterator pos, end, sequenceStart;
|
||||
|
@ -1705,13 +1744,17 @@ nsXMLContentSerializer::AppendToStringWrapped(const nsASingleFragmentString& aSt
|
|||
// if beginning of a whitespace sequence
|
||||
if (*pos == ' ' || *pos == '\n' || *pos == '\t') {
|
||||
sequenceStartAfterAWhitespace = true;
|
||||
AppendWrapped_WhitespaceSequence(pos, end, sequenceStart, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendWrapped_WhitespaceSequence(pos, end,
|
||||
sequenceStart, aOutputStr), false);
|
||||
}
|
||||
else { // any other non-whitespace char
|
||||
AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart,
|
||||
mayIgnoreStartOfLineWhitespaceSequence, sequenceStartAfterAWhitespace, aOutputStr);
|
||||
NS_ENSURE_TRUE(AppendWrapped_NonWhitespaceSequence(pos, end, sequenceStart,
|
||||
mayIgnoreStartOfLineWhitespaceSequence,
|
||||
sequenceStartAfterAWhitespace, aOutputStr), false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -72,13 +72,15 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
/**
|
||||
* Appends a char16_t character and increments the column position
|
||||
*/
|
||||
void AppendToString(const char16_t aChar,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendToString(const char16_t aChar,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
/**
|
||||
* Appends a nsAString string and increments the column position
|
||||
*/
|
||||
void AppendToString(const nsAString& aStr,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendToString(const nsAString& aStr,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
/**
|
||||
|
@ -86,32 +88,37 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
* by mLineBreak, except in the case of raw output.
|
||||
* It increments the column position.
|
||||
*/
|
||||
void AppendToStringConvertLF(const nsAString& aStr,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendToStringConvertLF(const nsAString& aStr,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
/**
|
||||
* Appends a string by wrapping it when necessary.
|
||||
* It updates the column position.
|
||||
*/
|
||||
void AppendToStringWrapped(const nsASingleFragmentString& aStr,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendToStringWrapped(const nsASingleFragmentString& aStr,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
/**
|
||||
* Appends a string by formating and wrapping it when necessary
|
||||
* It updates the column position.
|
||||
*/
|
||||
void AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendToStringFormatedWrapped(const nsASingleFragmentString& aStr,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
// used by AppendToStringWrapped
|
||||
void AppendWrapped_WhitespaceSequence(
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendWrapped_WhitespaceSequence(
|
||||
nsASingleFragmentString::const_char_iterator &aPos,
|
||||
const nsASingleFragmentString::const_char_iterator aEnd,
|
||||
const nsASingleFragmentString::const_char_iterator aSequenceStart,
|
||||
nsAString &aOutputStr);
|
||||
|
||||
// used by AppendToStringFormatedWrapped
|
||||
void AppendFormatedWrapped_WhitespaceSequence(
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendFormatedWrapped_WhitespaceSequence(
|
||||
nsASingleFragmentString::const_char_iterator &aPos,
|
||||
const nsASingleFragmentString::const_char_iterator aEnd,
|
||||
const nsASingleFragmentString::const_char_iterator aSequenceStart,
|
||||
|
@ -119,7 +126,8 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
nsAString &aOutputStr);
|
||||
|
||||
// used by AppendToStringWrapped and AppendToStringFormatedWrapped
|
||||
void AppendWrapped_NonWhitespaceSequence(
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendWrapped_NonWhitespaceSequence(
|
||||
nsASingleFragmentString::const_char_iterator &aPos,
|
||||
const nsASingleFragmentString::const_char_iterator aEnd,
|
||||
const nsASingleFragmentString::const_char_iterator aSequenceStart,
|
||||
|
@ -131,14 +139,16 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
* add mLineBreak to the string
|
||||
* It updates the column position and other flags.
|
||||
*/
|
||||
void AppendNewLineToString(nsAString& aOutputStr);
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendNewLineToString(nsAString& aOutputStr);
|
||||
|
||||
|
||||
/**
|
||||
* Appends a string by translating entities
|
||||
* It doesn't increment the column position
|
||||
*/
|
||||
virtual void AppendAndTranslateEntities(const nsAString& aStr,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AppendAndTranslateEntities(const nsAString& aStr,
|
||||
nsAString& aOutputStr);
|
||||
|
||||
/**
|
||||
|
@ -187,7 +197,8 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
nsIContent *aOriginalElement,
|
||||
const nsAString& aTagNamespaceURI);
|
||||
|
||||
virtual void SerializeAttributes(nsIContent* aContent,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool SerializeAttributes(nsIContent* aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aTagPrefix,
|
||||
const nsAString& aTagNamespaceURI,
|
||||
|
@ -196,7 +207,8 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
uint32_t aSkipAttr,
|
||||
bool aAddNSAttr);
|
||||
|
||||
void SerializeAttr(const nsAString& aPrefix,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool SerializeAttr(const nsAString& aPrefix,
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue,
|
||||
nsAString& aStr,
|
||||
|
@ -217,13 +229,15 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
*/
|
||||
virtual bool CheckElementStart(nsIContent * aContent,
|
||||
bool & aForceFormat,
|
||||
nsAString& aStr);
|
||||
nsAString& aStr,
|
||||
nsresult& aResult);
|
||||
|
||||
/**
|
||||
* this method is responsible to finish the start tag,
|
||||
* in particulary to append the "greater than" sign
|
||||
*/
|
||||
virtual void AppendEndOfElementStart(nsIContent *aOriginalElement,
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AppendEndOfElementStart(nsIContent *aOriginalElement,
|
||||
nsIAtom * aName,
|
||||
int32_t aNamespaceID,
|
||||
nsAString& aStr);
|
||||
|
@ -233,9 +247,10 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
* after the serialization ot the start tag.
|
||||
* (called at the end of AppendElementStart)
|
||||
*/
|
||||
virtual void AfterElementStart(nsIContent * aContent,
|
||||
nsIContent *aOriginalElement,
|
||||
nsAString& aStr) { };
|
||||
NS_WARN_UNUSED_RESULT
|
||||
virtual bool AfterElementStart(nsIContent* aContent,
|
||||
nsIContent* aOriginalElement,
|
||||
nsAString& aStr) { return true; };
|
||||
|
||||
/**
|
||||
* This method can be redefined to check if the element can be serialized.
|
||||
|
@ -281,13 +296,17 @@ class nsXMLContentSerializer : public nsIContentSerializer {
|
|||
* add intendation. Call only in the case of formating and if the current
|
||||
* position is at 0. It updates the column position.
|
||||
*/
|
||||
void AppendIndentation(nsAString& aStr);
|
||||
void IncrIndentation(nsIAtom* aName);
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool AppendIndentation(nsAString& aStr);
|
||||
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool IncrIndentation(nsIAtom* aName);
|
||||
void DecrIndentation(nsIAtom* aName);
|
||||
|
||||
// Functions to check for newlines that needs to be added between nodes in
|
||||
// the root of a document. See mAddNewlineForRootNode
|
||||
void MaybeAddNewlineForRootNode(nsAString& aStr);
|
||||
NS_WARN_UNUSED_RESULT
|
||||
bool MaybeAddNewlineForRootNode(nsAString& aStr);
|
||||
void MaybeFlagNewlineForRootNode(nsINode* aNode);
|
||||
|
||||
// Functions to check if we enter in or leave from a preformated content
|
||||
|
|
|
@ -18,6 +18,8 @@ support-files =
|
|||
file_bug1139964.xul
|
||||
fileconstructor_file.png
|
||||
frame_bug814638.xul
|
||||
frame_registerElement_content.html
|
||||
registerElement_ep.js
|
||||
host_bug814638.xul
|
||||
window_nsITextInputProcessor.xul
|
||||
title_window.xul
|
||||
|
@ -61,6 +63,8 @@ skip-if = buildapp == 'mulet'
|
|||
[test_cpows.xul]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_document_register.xul]
|
||||
[test_registerElement_content.xul]
|
||||
[test_registerElement_ep.xul]
|
||||
[test_domparsing.xul]
|
||||
[test_fileconstructor.xul]
|
||||
[test_fileconstructor_tempfile.xul]
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
<x-bar></x-bar>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
var proto = Object.create(HTMLElement.prototype);
|
||||
proto.magicNumber = 42;
|
||||
proto.createdCallback = function() {
|
||||
finishTest(this.magicNumber === 42);
|
||||
};
|
||||
document.registerElement("x-foo", { prototype: proto });
|
||||
|
||||
document.createElement("x-foo");
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
|
||||
-->
|
||||
<window title="Mozilla Bug 1130028"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1130028"
|
||||
target="_blank">Mozilla Bug 1130028</a>
|
||||
<iframe onload="startTests()" id="frame" src="http://example.com/chrome/dom/base/test/chrome/frame_registerElement_content.html"></iframe>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
/** Test for Bug 1130028 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var createdCallbackCount = 0;
|
||||
|
||||
// Callback should be called once by element created in chrome,
|
||||
// and once by element created in content.
|
||||
function createdCallbackCalled() {
|
||||
createdCallbackCount++;
|
||||
ok(true, "Created callback called, should be called twice in test.");
|
||||
is(this.magicNumber, 42, "Callback should be able to see the custom prototype.");
|
||||
if (createdCallbackCount == 2) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
var frame = $("frame");
|
||||
|
||||
var c = frame.contentDocument.registerElement("x-foo");
|
||||
var elem = new c();
|
||||
is(elem.tagName, "X-FOO", "Constructor should create an x-foo element.");
|
||||
|
||||
var proto = Object.create(frame.contentWindow.HTMLElement.prototype);
|
||||
proto.magicNumber = 42;
|
||||
proto.createdCallback = createdCallbackCalled;
|
||||
frame.contentDocument.registerElement("x-bar", { prototype: proto });
|
||||
|
||||
frame.contentDocument.createElement("x-bar");
|
||||
}
|
||||
|
||||
]]></script>
|
||||
</window>
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1130028
|
||||
-->
|
||||
<window title="Mozilla Bug 1130028"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1130028"
|
||||
target="_blank">Mozilla Bug 1130028</a>
|
||||
<iframe onload="startTests()" id="frame" src="http://example.com/chrome/dom/base/test/chrome/frame_registerElement_content.html"></iframe>
|
||||
</body>
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
/** Test for Bug 1130028 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function finishTest(canSeePrototype) {
|
||||
ok(true, "createdCallback called when reigsterElement was called with an extended principal.");
|
||||
ok(canSeePrototype, "createdCallback should be able to see custom prototype.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTests() {
|
||||
var frame = $("frame");
|
||||
|
||||
// Create a sandbox with an extended principal then run a script that registers a custom element in the sandbox.
|
||||
var sandbox = Components.utils.Sandbox([frame.contentWindow], { sandboxPrototype: frame.contentWindow });
|
||||
sandbox.finishTest = finishTest;
|
||||
Services.scriptloader.loadSubScript("chrome://mochitests/content/chrome/dom/base/test/chrome/registerElement_ep.js", sandbox);
|
||||
}
|
||||
|
||||
]]></script>
|
||||
</window>
|
|
@ -14,6 +14,8 @@
|
|||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/DeferredFinalize.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/CallbackObject.h"
|
||||
#include "mozilla/dom/DOMJSClass.h"
|
||||
|
@ -26,8 +28,6 @@
|
|||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
@ -2933,8 +2933,8 @@ struct DeferredFinalizer
|
|||
AddForDeferredFinalization(T* aObject)
|
||||
{
|
||||
typedef DeferredFinalizerImpl<T> Impl;
|
||||
cyclecollector::DeferredFinalize(Impl::AppendDeferredFinalizePointer,
|
||||
Impl::DeferredFinalize, aObject);
|
||||
DeferredFinalize(Impl::AppendDeferredFinalizePointer,
|
||||
Impl::DeferredFinalize, aObject);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2944,7 +2944,7 @@ struct DeferredFinalizer<T, true>
|
|||
static void
|
||||
AddForDeferredFinalization(T* aObject)
|
||||
{
|
||||
cyclecollector::DeferredFinalize(reinterpret_cast<nsISupports*>(aObject));
|
||||
DeferredFinalize(reinterpret_cast<nsISupports*>(aObject));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -141,15 +141,11 @@ WebGLContext::InitWebGL2()
|
|||
gl->GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS,
|
||||
&mGLMaxUniformBufferBindings);
|
||||
|
||||
mBoundTransformFeedbackBuffers =
|
||||
MakeUnique<WebGLRefPtr<WebGLBuffer>[]>(mGLMaxTransformFeedbackSeparateAttribs);
|
||||
mBoundUniformBuffers =
|
||||
MakeUnique<WebGLRefPtr<WebGLBuffer>[]>(mGLMaxUniformBufferBindings);
|
||||
mBoundTransformFeedbackBuffers.SetLength(mGLMaxTransformFeedbackSeparateAttribs);
|
||||
mBoundUniformBuffers.SetLength(mGLMaxUniformBufferBindings);
|
||||
|
||||
mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
|
||||
mBoundTransformFeedback = mDefaultTransformFeedback;
|
||||
auto xfBuffers = new WebGLRefPtr<WebGLBuffer>[mGLMaxTransformFeedbackSeparateAttribs];
|
||||
mBoundTransformFeedbackBuffers.reset(xfBuffers);
|
||||
|
||||
mBypassShaderValidation = true;
|
||||
|
||||
|
|
|
@ -342,14 +342,8 @@ WebGLContext::DestroyResourcesAndContext()
|
|||
mBoundTransformFeedback = nullptr;
|
||||
mDefaultTransformFeedback = nullptr;
|
||||
|
||||
if (mBoundTransformFeedbackBuffers) {
|
||||
for (GLuint i = 0; i < mGLMaxTransformFeedbackSeparateAttribs; i++) {
|
||||
mBoundTransformFeedbackBuffers[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
for (GLuint i = 0; i < mGLMaxUniformBufferBindings; i++)
|
||||
mBoundUniformBuffers[i] = nullptr;
|
||||
mBoundTransformFeedbackBuffers.Clear();
|
||||
mBoundUniformBuffers.Clear();
|
||||
|
||||
while (!mTextures.isEmpty())
|
||||
mTextures.getLast()->DeleteOnce();
|
||||
|
@ -827,6 +821,11 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
|
|||
// If we've already drawn, we should commit the current buffer.
|
||||
PresentScreenBuffer();
|
||||
|
||||
if (IsContextLost()) {
|
||||
GenerateWarning("WebGL context was lost due to swap failure.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ResizeOffscreen scraps the current prod buffer before making a new one.
|
||||
if (!ResizeBackbuffer(width, height)) {
|
||||
GenerateWarning("WebGL context failed to resize.");
|
||||
|
|
|
@ -926,8 +926,8 @@ protected:
|
|||
WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
|
||||
WebGLRefPtr<WebGLBuffer> mBoundUniformBuffer;
|
||||
|
||||
UniquePtr<WebGLRefPtr<WebGLBuffer>[]> mBoundUniformBuffers;
|
||||
UniquePtr<WebGLRefPtr<WebGLBuffer>[]> mBoundTransformFeedbackBuffers;
|
||||
nsTArray<WebGLRefPtr<WebGLBuffer>> mBoundUniformBuffers;
|
||||
nsTArray<WebGLRefPtr<WebGLBuffer>> mBoundTransformFeedbackBuffers;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target);
|
||||
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
|
||||
|
|
|
@ -1828,18 +1828,14 @@ BackgroundRequestChild::BackgroundRequestChild(IDBRequest* aRequest)
|
|||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
MOZ_COUNT_CTOR(indexedDB::BackgroundRequestChild);
|
||||
|
||||
mTransaction->OnNewRequest();
|
||||
}
|
||||
|
||||
BackgroundRequestChild::~BackgroundRequestChild()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT_IF(!IsActorDestroyed(), mTransaction);
|
||||
MOZ_ASSERT(!mTransaction);
|
||||
|
||||
MOZ_COUNT_DTOR(indexedDB::BackgroundRequestChild);
|
||||
|
||||
MaybeFinishTransactionEarly();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1853,19 +1849,6 @@ BackgroundRequestChild::HoldFileInfosUntilComplete(
|
|||
}
|
||||
|
||||
void
|
||||
BackgroundRequestChild::MaybeFinishTransactionEarly()
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (mTransaction) {
|
||||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
mTransaction->OnRequestFinished();
|
||||
mTransaction = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BackgroundRequestChild::HandleResponse(nsresult aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -1874,10 +1857,9 @@ BackgroundRequestChild::HandleResponse(nsresult aResponse)
|
|||
MOZ_ASSERT(mTransaction);
|
||||
|
||||
DispatchErrorEvent(mRequest, aResponse, mTransaction);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(const Key& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -1885,10 +1867,9 @@ BackgroundRequestChild::HandleResponse(const Key& aResponse)
|
|||
ResultHelper helper(mRequest, mTransaction, &aResponse);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -1896,10 +1877,9 @@ BackgroundRequestChild::HandleResponse(const nsTArray<Key>& aResponse)
|
|||
ResultHelper helper(mRequest, mTransaction, &aResponse);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(
|
||||
const SerializedStructuredCloneReadInfo& aResponse)
|
||||
{
|
||||
|
@ -1919,10 +1899,9 @@ BackgroundRequestChild::HandleResponse(
|
|||
ResultHelper helper(mRequest, mTransaction, &cloneReadInfo);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(
|
||||
const nsTArray<SerializedStructuredCloneReadInfo>& aResponse)
|
||||
{
|
||||
|
@ -1957,10 +1936,9 @@ BackgroundRequestChild::HandleResponse(
|
|||
ResultHelper helper(mRequest, mTransaction, &cloneReadInfos);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -1968,10 +1946,9 @@ BackgroundRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
|
|||
ResultHelper helper(mRequest, mTransaction, &aResponse);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
BackgroundRequestChild::HandleResponse(uint64_t aResponse)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -1981,7 +1958,6 @@ BackgroundRequestChild::HandleResponse(uint64_t aResponse)
|
|||
ResultHelper helper(mRequest, mTransaction, &response);
|
||||
|
||||
DispatchSuccessEvent(&helper);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1991,9 +1967,17 @@ BackgroundRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
|||
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
MaybeFinishTransactionEarly();
|
||||
|
||||
NoteActorDestroyed();
|
||||
|
||||
if (mTransaction) {
|
||||
mTransaction->AssertIsOnOwningThread();
|
||||
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
|
||||
aWhy == Deletion);
|
||||
#ifdef DEBUG
|
||||
mTransaction = nullptr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2005,62 +1989,80 @@ BackgroundRequestChild::Recv__delete__(const RequestResponse& aResponse)
|
|||
|
||||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
// Always fire an "error" event with ABORT_ERR if the transaction was aborted,
|
||||
// even if the request succeeded or failed with another error.
|
||||
if (mTransaction->IsAborted()) {
|
||||
return HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
||||
// Always fire an "error" event with ABORT_ERR if the transaction was
|
||||
// aborted, even if the request succeeded or failed with another error.
|
||||
HandleResponse(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
|
||||
} else {
|
||||
switch (aResponse.type()) {
|
||||
case RequestResponse::Tnsresult:
|
||||
HandleResponse(aResponse.get_nsresult());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreAddResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStorePutResponse:
|
||||
HandleResponse(aResponse.get_ObjectStorePutResponse().key());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreGetResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreGetAllResponse().cloneInfos());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllKeysResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse().keys());
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreDeleteResponse:
|
||||
HandleResponse(JS::UndefinedHandleValue);
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreClearResponse:
|
||||
HandleResponse(JS::UndefinedHandleValue);
|
||||
break;
|
||||
|
||||
case RequestResponse::TObjectStoreCountResponse:
|
||||
HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetResponse:
|
||||
HandleResponse(aResponse.get_IndexGetResponse().cloneInfo());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetKeyResponse:
|
||||
HandleResponse(aResponse.get_IndexGetKeyResponse().key());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetAllResponse:
|
||||
HandleResponse(aResponse.get_IndexGetAllResponse().cloneInfos());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexGetAllKeysResponse:
|
||||
HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
|
||||
break;
|
||||
|
||||
case RequestResponse::TIndexCountResponse:
|
||||
HandleResponse(aResponse.get_IndexCountResponse().count());
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown response type!");
|
||||
}
|
||||
}
|
||||
|
||||
switch (aResponse.type()) {
|
||||
case RequestResponse::Tnsresult:
|
||||
return HandleResponse(aResponse.get_nsresult());
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
|
||||
|
||||
case RequestResponse::TObjectStoreAddResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreAddResponse().key());
|
||||
// Null this out so that we don't try to call OnRequestFinished() again in
|
||||
// ActorDestroy.
|
||||
mTransaction = nullptr;
|
||||
|
||||
case RequestResponse::TObjectStorePutResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStorePutResponse().key());
|
||||
|
||||
case RequestResponse::TObjectStoreGetResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreGetResponse().cloneInfo());
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreGetAllResponse()
|
||||
.cloneInfos());
|
||||
|
||||
case RequestResponse::TObjectStoreGetAllKeysResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreGetAllKeysResponse()
|
||||
.keys());
|
||||
|
||||
case RequestResponse::TObjectStoreDeleteResponse:
|
||||
return HandleResponse(JS::UndefinedHandleValue);
|
||||
|
||||
case RequestResponse::TObjectStoreClearResponse:
|
||||
return HandleResponse(JS::UndefinedHandleValue);
|
||||
|
||||
case RequestResponse::TObjectStoreCountResponse:
|
||||
return HandleResponse(aResponse.get_ObjectStoreCountResponse().count());
|
||||
|
||||
case RequestResponse::TIndexGetResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetResponse().cloneInfo());
|
||||
|
||||
case RequestResponse::TIndexGetKeyResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetKeyResponse().key());
|
||||
|
||||
case RequestResponse::TIndexGetAllResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetAllResponse().cloneInfos());
|
||||
|
||||
case RequestResponse::TIndexGetAllKeysResponse:
|
||||
return HandleResponse(aResponse.get_IndexGetAllKeysResponse().keys());
|
||||
|
||||
case RequestResponse::TIndexCountResponse:
|
||||
return HandleResponse(aResponse.get_IndexCountResponse().count());
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown response type!");
|
||||
}
|
||||
|
||||
MOZ_CRASH("Should never get here!");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -2370,7 +2372,8 @@ BackgroundCursorChild::ActorDestroy(ActorDestroyReason aWhy)
|
|||
MaybeCollectGarbageOnIPCMessage();
|
||||
|
||||
if (mStrongRequest && !mStrongCursor && mTransaction) {
|
||||
mTransaction->OnRequestFinished();
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */
|
||||
aWhy == Deletion);
|
||||
}
|
||||
|
||||
if (mCursor) {
|
||||
|
@ -2435,7 +2438,7 @@ BackgroundCursorChild::RecvResponse(const CursorResponse& aResponse)
|
|||
MOZ_CRASH("Should never get here!");
|
||||
}
|
||||
|
||||
mTransaction->OnRequestFinished();
|
||||
mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -561,43 +561,43 @@ class BackgroundRequestChild MOZ_FINAL
|
|||
{
|
||||
friend class BackgroundTransactionChild;
|
||||
friend class BackgroundVersionChangeTransactionChild;
|
||||
friend class IDBTransaction;
|
||||
|
||||
nsRefPtr<IDBTransaction> mTransaction;
|
||||
nsTArray<nsRefPtr<FileInfo>> mFileInfos;
|
||||
|
||||
public:
|
||||
explicit BackgroundRequestChild(IDBRequest* aRequest);
|
||||
|
||||
void
|
||||
HoldFileInfosUntilComplete(nsTArray<nsRefPtr<FileInfo>>& aFileInfos);
|
||||
|
||||
private:
|
||||
// Only created by IDBTransaction.
|
||||
explicit
|
||||
BackgroundRequestChild(IDBRequest* aRequest);
|
||||
|
||||
// Only destroyed by BackgroundTransactionChild or
|
||||
// BackgroundVersionChangeTransactionChild.
|
||||
~BackgroundRequestChild();
|
||||
|
||||
void
|
||||
MaybeFinishTransactionEarly();
|
||||
|
||||
bool
|
||||
HandleResponse(nsresult aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const Key& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const nsTArray<Key>& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const SerializedStructuredCloneReadInfo& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(const nsTArray<SerializedStructuredCloneReadInfo>& aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(JS::Handle<JS::Value> aResponse);
|
||||
|
||||
bool
|
||||
void
|
||||
HandleResponse(uint64_t aResponse);
|
||||
|
||||
// IPDL methods are only called by IPDL.
|
||||
|
|
|
@ -292,9 +292,7 @@ IDBIndex::GetInternal(bool aKeyOnly,
|
|||
IDB_LOG_STRINGIFY(keyRange));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
transaction->StartRequest(actor, params);
|
||||
transaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -375,9 +373,7 @@ IDBIndex::GetAllInternal(bool aKeysOnly,
|
|||
IDB_LOG_STRINGIFY(aLimit));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
transaction->StartRequest(actor, params);
|
||||
transaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -527,9 +523,7 @@ IDBIndex::Count(JSContext* aCx,
|
|||
IDB_LOG_STRINGIFY(this),
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
transaction->StartRequest(actor, params);
|
||||
transaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
|
|
@ -1279,9 +1279,8 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
BackgroundRequestChild* actor = mTransaction->StartRequest(request, params);
|
||||
MOZ_ASSERT(actor);
|
||||
|
||||
if (!fileInfosToKeepAlive.IsEmpty()) {
|
||||
nsTArray<nsRefPtr<FileInfo>> fileInfos;
|
||||
|
@ -1365,9 +1364,7 @@ IDBObjectStore::GetAllInternal(bool aKeysOnly,
|
|||
IDB_LOG_STRINGIFY(aLimit));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -1403,9 +1400,7 @@ IDBObjectStore::Clear(ErrorResult& aRv)
|
|||
IDB_LOG_STRINGIFY(mTransaction),
|
||||
IDB_LOG_STRINGIFY(this));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -1600,9 +1595,7 @@ IDBObjectStore::Get(JSContext* aCx,
|
|||
IDB_LOG_STRINGIFY(this),
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -1657,9 +1650,7 @@ IDBObjectStore::DeleteInternal(JSContext* aCx,
|
|||
IDB_LOG_STRINGIFY(keyRange));
|
||||
}
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
@ -1899,9 +1890,7 @@ IDBObjectStore::Count(JSContext* aCx,
|
|||
IDB_LOG_STRINGIFY(this),
|
||||
IDB_LOG_STRINGIFY(keyRange));
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(request);
|
||||
|
||||
mTransaction->StartRequest(actor, params);
|
||||
mTransaction->StartRequest(request, params);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
|
|
@ -325,25 +325,31 @@ IDBTransaction::SetBackgroundActor(BackgroundTransactionChild* aBackgroundActor)
|
|||
mBackgroundActor.mNormalBackgroundActor = aBackgroundActor;
|
||||
}
|
||||
|
||||
void
|
||||
IDBTransaction::StartRequest(BackgroundRequestChild* aBackgroundActor,
|
||||
const RequestParams& aParams)
|
||||
BackgroundRequestChild*
|
||||
IDBTransaction::StartRequest(IDBRequest* aRequest, const RequestParams& aParams)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aBackgroundActor);
|
||||
MOZ_ASSERT(aRequest);
|
||||
MOZ_ASSERT(aParams.type() != RequestParams::T__None);
|
||||
|
||||
BackgroundRequestChild* actor = new BackgroundRequestChild(aRequest);
|
||||
|
||||
if (mMode == VERSION_CHANGE) {
|
||||
MOZ_ASSERT(mBackgroundActor.mVersionChangeBackgroundActor);
|
||||
|
||||
mBackgroundActor.mVersionChangeBackgroundActor->
|
||||
SendPBackgroundIDBRequestConstructor(aBackgroundActor, aParams);
|
||||
SendPBackgroundIDBRequestConstructor(actor, aParams);
|
||||
} else {
|
||||
MOZ_ASSERT(mBackgroundActor.mNormalBackgroundActor);
|
||||
|
||||
mBackgroundActor.mNormalBackgroundActor->
|
||||
SendPBackgroundIDBRequestConstructor(aBackgroundActor, aParams);
|
||||
SendPBackgroundIDBRequestConstructor(actor, aParams);
|
||||
}
|
||||
|
||||
// Balanced in BackgroundRequestChild::Recv__delete__().
|
||||
OnNewRequest();
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -402,7 +408,7 @@ IDBTransaction::OnNewRequest()
|
|||
}
|
||||
|
||||
void
|
||||
IDBTransaction::OnRequestFinished()
|
||||
IDBTransaction::OnRequestFinished(bool aActorDestroyedNormally)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mPendingRequestCount);
|
||||
|
@ -412,10 +418,24 @@ IDBTransaction::OnRequestFinished()
|
|||
if (!mPendingRequestCount && !mDatabase->IsInvalidated()) {
|
||||
mReadyState = COMMITTING;
|
||||
|
||||
if (NS_SUCCEEDED(mAbortCode)) {
|
||||
SendCommit();
|
||||
if (aActorDestroyedNormally) {
|
||||
if (NS_SUCCEEDED(mAbortCode)) {
|
||||
SendCommit();
|
||||
} else {
|
||||
SendAbort(mAbortCode);
|
||||
}
|
||||
} else {
|
||||
SendAbort(mAbortCode);
|
||||
// Don't try to send any more messages to the parent if the request actor
|
||||
// was killed.
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(!mSentCommitOrAbort);
|
||||
mSentCommitOrAbort = true;
|
||||
#endif
|
||||
IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld]: "
|
||||
"Request actor was killed, transaction will be aborted",
|
||||
"IndexedDB %s: C T[%lld]: IDBTransaction abort",
|
||||
IDB_LOG_ID_STRING(),
|
||||
LoggingSerialNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ class IDBTransaction MOZ_FINAL
|
|||
: public IDBWrapperCache
|
||||
, public nsIRunnable
|
||||
{
|
||||
friend class BackgroundCursorChild;
|
||||
friend class BackgroundRequestChild;
|
||||
|
||||
class WorkerFeature;
|
||||
friend class WorkerFeature;
|
||||
|
||||
|
@ -150,9 +153,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
StartRequest(BackgroundRequestChild* aBackgroundActor,
|
||||
const RequestParams& aParams);
|
||||
BackgroundRequestChild*
|
||||
StartRequest(IDBRequest* aRequest, const RequestParams& aParams);
|
||||
|
||||
void
|
||||
OpenCursor(BackgroundCursorChild* aBackgroundActor,
|
||||
|
@ -161,12 +163,6 @@ public:
|
|||
void
|
||||
RefreshSpec(bool aMayDelete);
|
||||
|
||||
void
|
||||
OnNewRequest();
|
||||
|
||||
void
|
||||
OnRequestFinished();
|
||||
|
||||
bool
|
||||
IsOpen() const;
|
||||
|
||||
|
@ -314,6 +310,12 @@ private:
|
|||
|
||||
void
|
||||
SendAbort(nsresult aResultCode);
|
||||
|
||||
void
|
||||
OnNewRequest();
|
||||
|
||||
void
|
||||
OnRequestFinished(bool aActorDestroyedNormally);
|
||||
};
|
||||
|
||||
} // namespace indexedDB
|
||||
|
|
|
@ -481,8 +481,9 @@ class RemoteInputStream MOZ_FINAL
|
|||
uint64_t mLength;
|
||||
|
||||
public:
|
||||
explicit
|
||||
RemoteInputStream(FileImpl* aBlobImpl);
|
||||
RemoteInputStream(FileImpl* aBlobImpl,
|
||||
uint64_t aStart,
|
||||
uint64_t aLength);
|
||||
|
||||
RemoteInputStream(BlobChild* aActor,
|
||||
FileImpl* aBlobImpl,
|
||||
|
@ -1115,13 +1116,15 @@ BlobDataFromBlobImpl(FileImpl* aBlobImpl, BlobData& aBlobData)
|
|||
&readCount)));
|
||||
}
|
||||
|
||||
RemoteInputStream::RemoteInputStream(FileImpl* aBlobImpl)
|
||||
RemoteInputStream::RemoteInputStream(FileImpl* aBlobImpl,
|
||||
uint64_t aStart,
|
||||
uint64_t aLength)
|
||||
: mMonitor("RemoteInputStream.mMonitor")
|
||||
, mActor(nullptr)
|
||||
, mBlobImpl(aBlobImpl)
|
||||
, mWeakSeekableStream(nullptr)
|
||||
, mStart(0)
|
||||
, mLength(0)
|
||||
, mStart(aStart)
|
||||
, mLength(aLength)
|
||||
{
|
||||
MOZ_ASSERT(aBlobImpl);
|
||||
|
||||
|
@ -2550,9 +2553,9 @@ CreateStreamHelper::RunInternal(RemoteBlobImpl* aBaseRemoteBlobImpl,
|
|||
|
||||
if (!NS_IsMainThread() && GetCurrentThreadWorkerPrivate()) {
|
||||
stream =
|
||||
new RemoteInputStream(actor, aBaseRemoteBlobImpl, mStart, mLength);
|
||||
new RemoteInputStream(actor, mRemoteBlobImpl, mStart, mLength);
|
||||
} else {
|
||||
stream = new RemoteInputStream(aBaseRemoteBlobImpl);
|
||||
stream = new RemoteInputStream(mRemoteBlobImpl, mStart, mLength);
|
||||
}
|
||||
|
||||
InputStreamChild* streamActor = new InputStreamChild(stream);
|
||||
|
|
|
@ -662,8 +662,6 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
|||
XRE_GetProcessType());
|
||||
#endif
|
||||
|
||||
GetCPOWManager();
|
||||
|
||||
SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser);
|
||||
InitProcessAttributes();
|
||||
|
||||
|
|
|
@ -369,7 +369,7 @@ AndroidMediaReader::ImageBufferCallback::operator()(size_t aWidth, size_t aHeigh
|
|||
}
|
||||
|
||||
mImage = image;
|
||||
return image->AsSharedImage()->GetBuffer();
|
||||
return image->GetBuffer();
|
||||
case MPAPI::I420:
|
||||
return CreateI420Image(aWidth, aHeight);
|
||||
default:
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "prlog.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "IMFYCbCrImage.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* GetDemuxerLog();
|
||||
|
@ -29,6 +30,7 @@ PRLogModuleInfo* GetDemuxerLog();
|
|||
|
||||
using mozilla::gfx::ToIntRect;
|
||||
using mozilla::layers::Image;
|
||||
using mozilla::layers::IMFYCbCrImage;
|
||||
using mozilla::layers::LayerManager;
|
||||
using mozilla::layers::LayersBackend;
|
||||
|
||||
|
@ -392,20 +394,26 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
|
|||
|
||||
Microseconds pts = GetSampleTime(aSample);
|
||||
Microseconds duration = GetSampleDuration(aSample);
|
||||
nsRefPtr<VideoData> v = VideoData::Create(mVideoInfo,
|
||||
mImageContainer,
|
||||
aStreamOffset,
|
||||
std::max(0LL, pts),
|
||||
duration,
|
||||
b,
|
||||
false,
|
||||
-1,
|
||||
ToIntRect(mPictureRegion));
|
||||
if (twoDBuffer) {
|
||||
twoDBuffer->Unlock2D();
|
||||
} else {
|
||||
buffer->Unlock();
|
||||
}
|
||||
|
||||
nsRefPtr<layers::PlanarYCbCrImage> image =
|
||||
new IMFYCbCrImage(buffer, twoDBuffer);
|
||||
|
||||
VideoData::SetVideoDataToImage(image,
|
||||
mVideoInfo,
|
||||
b,
|
||||
ToIntRect(mPictureRegion),
|
||||
false);
|
||||
|
||||
nsRefPtr<VideoData> v =
|
||||
VideoData::CreateFromImage(mVideoInfo,
|
||||
mImageContainer,
|
||||
aStreamOffset,
|
||||
std::max(0LL, pts),
|
||||
duration,
|
||||
image.forget(),
|
||||
false,
|
||||
-1,
|
||||
ToIntRect(mPictureRegion));
|
||||
|
||||
v.forget(aOutVideoData);
|
||||
return S_OK;
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "MultipartFileImpl.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsError.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsFormData.h"
|
||||
|
|
|
@ -50,12 +50,12 @@
|
|||
#include "prprf.h"
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsCycleCollector.h"
|
||||
|
||||
// Nasty hack. Maybe we could move some of the classinfo utility methods
|
||||
// (e.g. WrapNative) over to nsContentUtils?
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
#include "mozilla/DeferredFinalize.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
|
@ -74,7 +74,7 @@ XBLFinalize(JSFreeOp *fop, JSObject *obj)
|
|||
{
|
||||
nsXBLDocumentInfo* docInfo =
|
||||
static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj));
|
||||
cyclecollector::DeferredFinalize(docInfo);
|
||||
DeferredFinalize(docInfo);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -91,11 +91,6 @@ struct GCMethods<nsXBLMaybeCompiled<UncompiledT> >
|
|||
|
||||
static nsXBLMaybeCompiled<UncompiledT> initial() { return nsXBLMaybeCompiled<UncompiledT>(); }
|
||||
|
||||
static bool poisoned(nsXBLMaybeCompiled<UncompiledT> function)
|
||||
{
|
||||
return function.IsCompiled() && Base::poisoned(function.GetJSFunction());
|
||||
}
|
||||
|
||||
static bool needsPostBarrier(nsXBLMaybeCompiled<UncompiledT> function)
|
||||
{
|
||||
return function.IsCompiled() && Base::needsPostBarrier(function.GetJSFunction());
|
||||
|
|
|
@ -18,8 +18,7 @@ namespace layers {
|
|||
// passed into SetData(), so that it can be accessed from other D3D devices.
|
||||
// This class also manages the synchronization of the copy, to ensure the
|
||||
// resource is ready to use.
|
||||
class D3D9SurfaceImage : public Image
|
||||
, public ISharedImage {
|
||||
class D3D9SurfaceImage : public Image {
|
||||
public:
|
||||
|
||||
struct Data {
|
||||
|
@ -32,8 +31,6 @@ public:
|
|||
D3D9SurfaceImage();
|
||||
virtual ~D3D9SurfaceImage();
|
||||
|
||||
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
|
||||
|
||||
// Copies the surface into a sharable texture's surface, and initializes
|
||||
// the image.
|
||||
HRESULT SetData(const Data& aData);
|
||||
|
@ -46,7 +43,6 @@ public:
|
|||
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
|
||||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
virtual uint8_t* GetBuffer() MOZ_OVERRIDE { return nullptr; }
|
||||
|
||||
virtual bool IsValid() MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ class GrallocTextureClientOGL;
|
|||
* mPicSize, not mYSize or mCbCrSize.
|
||||
*/
|
||||
class GrallocImage : public PlanarYCbCrImage
|
||||
, public ISharedImage
|
||||
{
|
||||
typedef PlanarYCbCrData Data;
|
||||
static int32_t sColorIdMap[];
|
||||
|
@ -93,8 +92,6 @@ public:
|
|||
|
||||
virtual bool IsValid() { return !!mTextureClient; }
|
||||
|
||||
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
|
||||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
|
||||
virtual GrallocImage* AsGrallocImage() MOZ_OVERRIDE
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IMFYCbCrImage.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
#include "mozilla/layers/CompositableClient.h"
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
IMFYCbCrImage::IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer)
|
||||
: PlanarYCbCrImage(nullptr)
|
||||
, mBuffer(aBuffer)
|
||||
, m2DBuffer(a2DBuffer)
|
||||
{}
|
||||
|
||||
IMFYCbCrImage::~IMFYCbCrImage()
|
||||
{
|
||||
if (m2DBuffer) {
|
||||
m2DBuffer->Unlock2D();
|
||||
}
|
||||
else {
|
||||
mBuffer->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
struct AutoLockTexture
|
||||
{
|
||||
AutoLockTexture(ID3D11Texture2D* aTexture)
|
||||
{
|
||||
aTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mMutex));
|
||||
HRESULT hr = mMutex->AcquireSync(0, 10000);
|
||||
if (hr == WAIT_TIMEOUT) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to lock the texture");
|
||||
}
|
||||
}
|
||||
|
||||
~AutoLockTexture()
|
||||
{
|
||||
HRESULT hr = mMutex->ReleaseSync(0);
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to unlock the texture");
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> mMutex;
|
||||
};
|
||||
|
||||
TextureClient*
|
||||
IMFYCbCrImage::GetTextureClient(CompositableClient* aClient)
|
||||
{
|
||||
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11MediaDevice();
|
||||
if (!device ||
|
||||
aClient->GetForwarder()->GetCompositorBackendType() != LayersBackend::LAYERS_D3D11) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mTextureClient) {
|
||||
return mTextureClient;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> ctx;
|
||||
device->GetImmediateContext(byRef(ctx));
|
||||
|
||||
CD3D11_TEXTURE2D_DESC newDesc(DXGI_FORMAT_A8_UNORM,
|
||||
mData.mYSize.width, mData.mYSize.height, 1, 1);
|
||||
|
||||
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
|
||||
RefPtr<ID3D11Texture2D> textureY;
|
||||
HRESULT hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureY));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
|
||||
|
||||
newDesc.Width = mData.mCbCrSize.width;
|
||||
newDesc.Height = mData.mCbCrSize.height;
|
||||
|
||||
RefPtr<ID3D11Texture2D> textureCb;
|
||||
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCb));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
|
||||
|
||||
RefPtr<ID3D11Texture2D> textureCr;
|
||||
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(textureCr));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
|
||||
|
||||
{
|
||||
AutoLockTexture lockY(textureY);
|
||||
AutoLockTexture lockCb(textureCb);
|
||||
AutoLockTexture lockCr(textureCr);
|
||||
|
||||
ctx->UpdateSubresource(textureY, 0, nullptr, mData.mYChannel,
|
||||
mData.mYStride, mData.mYStride * mData.mYSize.height);
|
||||
ctx->UpdateSubresource(textureCb, 0, nullptr, mData.mCbChannel,
|
||||
mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height);
|
||||
ctx->UpdateSubresource(textureCr, 0, nullptr, mData.mCrChannel,
|
||||
mData.mCbCrStride, mData.mCbCrStride * mData.mCbCrSize.height);
|
||||
}
|
||||
|
||||
RefPtr<DXGIYCbCrTextureClientD3D11> texClient =
|
||||
new DXGIYCbCrTextureClientD3D11(aClient->GetForwarder(), TextureFlags::DEFAULT);
|
||||
texClient->InitWith(textureY, textureCb, textureCr, GetSize());
|
||||
mTextureClient = texClient;
|
||||
|
||||
return mTextureClient;
|
||||
}
|
||||
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_IMFYCBCRIMAGE_H
|
||||
#define GFX_IMFYCBCRIMAGE_H
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "Mfidl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class IMFYCbCrImage : public PlanarYCbCrImage
|
||||
{
|
||||
public:
|
||||
IMFYCbCrImage(IMFMediaBuffer* aBuffer, IMF2DBuffer* a2DBuffer);
|
||||
|
||||
virtual bool IsValid() { return true; }
|
||||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual uint8_t* AllocateBuffer(uint32_t aSize) MOZ_OVERRIDE {
|
||||
MOZ_CRASH("Can't do manual allocations with IMFYCbCrImage");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
~IMFYCbCrImage();
|
||||
|
||||
RefPtr<IMFMediaBuffer> mBuffer;
|
||||
RefPtr<IMF2DBuffer> m2DBuffer;
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
};
|
||||
|
||||
} // namepace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GFX_D3DSURFACEIMAGE_H
|
|
@ -115,18 +115,6 @@ protected:
|
|||
ImageBackendData() {}
|
||||
};
|
||||
|
||||
// sadly we'll need this until we get rid of Deprected image classes
|
||||
class ISharedImage {
|
||||
public:
|
||||
virtual uint8_t* GetBuffer() = 0;
|
||||
|
||||
/**
|
||||
* For use with the CompositableClient only (so that the later can
|
||||
* synchronize the TextureClient with the TextureHost).
|
||||
*/
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class representing a buffer of pixel data. The data can be in one
|
||||
* of various formats including YCbCr.
|
||||
|
@ -145,8 +133,6 @@ class Image {
|
|||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
|
||||
|
||||
public:
|
||||
virtual ISharedImage* AsSharedImage() { return nullptr; }
|
||||
|
||||
ImageFormat GetFormat() { return mFormat; }
|
||||
void* GetImplData() { return mImplData; }
|
||||
|
||||
|
@ -175,6 +161,14 @@ public:
|
|||
|
||||
virtual bool IsValid() { return true; }
|
||||
|
||||
virtual uint8_t* GetBuffer() { return nullptr; }
|
||||
|
||||
/**
|
||||
* For use with the CompositableClient only (so that the later can
|
||||
* synchronize the TextureClient with the TextureHost).
|
||||
*/
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) { return nullptr; }
|
||||
|
||||
protected:
|
||||
Image(void* aImplData, ImageFormat aFormat) :
|
||||
mImplData(aImplData),
|
||||
|
@ -793,8 +787,7 @@ protected:
|
|||
* device output color space. This class is very simple as all backends
|
||||
* have to know about how to deal with drawing a cairo image.
|
||||
*/
|
||||
class CairoImage MOZ_FINAL : public Image,
|
||||
public ISharedImage {
|
||||
class CairoImage MOZ_FINAL : public Image {
|
||||
public:
|
||||
struct Data {
|
||||
gfx::IntSize mSize;
|
||||
|
@ -817,8 +810,6 @@ public:
|
|||
return mSourceSurface.get();
|
||||
}
|
||||
|
||||
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
|
||||
virtual uint8_t* GetBuffer() MOZ_OVERRIDE { return nullptr; }
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
|
||||
virtual gfx::IntSize GetSize() MOZ_OVERRIDE { return mSize; }
|
||||
|
|
|
@ -15,8 +15,7 @@ namespace mozilla {
|
|||
|
||||
namespace layers {
|
||||
|
||||
class MacIOSurfaceImage : public Image,
|
||||
public ISharedImage {
|
||||
class MacIOSurfaceImage : public Image {
|
||||
public:
|
||||
void SetSurface(MacIOSurface* aSurface) { mSurface = aSurface; }
|
||||
MacIOSurface* GetSurface() { return mSurface; }
|
||||
|
@ -25,12 +24,9 @@ public:
|
|||
return gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight());
|
||||
}
|
||||
|
||||
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
|
||||
|
||||
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE;
|
||||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
virtual uint8_t* GetBuffer() MOZ_OVERRIDE { return nullptr; }
|
||||
|
||||
MacIOSurfaceImage() : Image(nullptr, ImageFormat::MAC_IOSURFACE) {}
|
||||
|
||||
|
|
|
@ -158,9 +158,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
|||
return true;
|
||||
}
|
||||
|
||||
RefPtr<TextureClient> texture = image->AsSharedImage()
|
||||
? image->AsSharedImage()->GetTextureClient(this)
|
||||
: nullptr;
|
||||
RefPtr<TextureClient> texture = image->GetTextureClient(this);
|
||||
|
||||
AutoRemoveTexture autoRemoveTexture(this);
|
||||
if (texture != mFrontBuffer) {
|
||||
|
|
|
@ -232,6 +232,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
|||
return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
|
||||
|
||||
case SurfaceDescriptor::TSurfaceDescriptorD3D10:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr:
|
||||
if (Compositor::GetBackend() == LayersBackend::LAYERS_D3D9) {
|
||||
return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
|
||||
} else {
|
||||
|
|
|
@ -158,6 +158,11 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
|
|||
aDesc.get_SurfaceDescriptorD3D10());
|
||||
break;
|
||||
}
|
||||
case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr: {
|
||||
result = new DXGIYCbCrTextureHostD3D11(aFlags,
|
||||
aDesc.get_SurfaceDescriptorDXGIYCbCr());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NS_WARNING("Unsupported SurfaceDescriptor type");
|
||||
}
|
||||
|
@ -499,6 +504,82 @@ TextureClientD3D11::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
|||
return true;
|
||||
}
|
||||
|
||||
DXGIYCbCrTextureClientD3D11::DXGIYCbCrTextureClientD3D11(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags)
|
||||
: TextureClient(aAllocator, aFlags)
|
||||
, mIsLocked(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DXGIYCbCrTextureClientD3D11);
|
||||
}
|
||||
|
||||
class YCbCrKeepAliveD3D11 : public KeepAlive
|
||||
{
|
||||
public:
|
||||
YCbCrKeepAliveD3D11(RefPtr<ID3D11Texture2D> aTextures[3])
|
||||
{
|
||||
mTextures[0] = aTextures[0];
|
||||
mTextures[1] = aTextures[1];
|
||||
mTextures[2] = aTextures[2];
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<ID3D11Texture2D> mTextures[3];
|
||||
};
|
||||
|
||||
DXGIYCbCrTextureClientD3D11::~DXGIYCbCrTextureClientD3D11()
|
||||
{
|
||||
if (mTextures[0] && mActor) {
|
||||
KeepUntilFullDeallocation(MakeUnique<YCbCrKeepAliveD3D11>(mTextures));
|
||||
}
|
||||
MOZ_COUNT_DTOR(DXGIYCbCrTextureClientD3D11);
|
||||
}
|
||||
|
||||
bool
|
||||
DXGIYCbCrTextureClientD3D11::Lock(OpenMode)
|
||||
{
|
||||
MOZ_ASSERT(!mIsLocked);
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
}
|
||||
mIsLocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureClientD3D11::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mIsLocked, "Unlock called while the texture is not locked!");
|
||||
mIsLocked = false;
|
||||
}
|
||||
|
||||
bool
|
||||
DXGIYCbCrTextureClientD3D11::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
if (!IsAllocated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIResource> resource;
|
||||
mTextures[0]->QueryInterface((IDXGIResource**)byRef(resource));
|
||||
|
||||
HANDLE sharedHandleY;
|
||||
HRESULT hr = resource->GetSharedHandle(&sharedHandleY);
|
||||
|
||||
mTextures[1]->QueryInterface((IDXGIResource**)byRef(resource));
|
||||
|
||||
HANDLE sharedHandleCb;
|
||||
hr = resource->GetSharedHandle(&sharedHandleCb);
|
||||
|
||||
mTextures[2]->QueryInterface((IDXGIResource**)byRef(resource));
|
||||
|
||||
HANDLE sharedHandleCr;
|
||||
hr = resource->GetSharedHandle(&sharedHandleCr);
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorDXGIYCbCr((WindowsHandle)sharedHandleY, (WindowsHandle)sharedHandleCb, (WindowsHandle)sharedHandleCr, GetSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
|
||||
const SurfaceDescriptorD3D10& aDescriptor)
|
||||
: TextureHost(aFlags)
|
||||
|
@ -579,6 +660,108 @@ DXGITextureHostD3D11::GetTextureSources()
|
|||
return mTextureSource.get();
|
||||
}
|
||||
|
||||
DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
|
||||
const SurfaceDescriptorDXGIYCbCr& aDescriptor)
|
||||
: TextureHost(aFlags)
|
||||
, mSize(aDescriptor.size())
|
||||
, mIsLocked(false)
|
||||
{
|
||||
mHandles[0] = aDescriptor.handleY();
|
||||
mHandles[1] = aDescriptor.handleCb();
|
||||
mHandles[2] = aDescriptor.handleCr();
|
||||
}
|
||||
|
||||
bool
|
||||
DXGIYCbCrTextureHostD3D11::OpenSharedHandle()
|
||||
{
|
||||
if (!GetDevice()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT hr = GetDevice()->OpenSharedResource((HANDLE)mHandles[0],
|
||||
__uuidof(ID3D11Texture2D),
|
||||
(void**)(ID3D11Texture2D**)byRef(mTextures[0]));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to open shared texture for Y Plane");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = GetDevice()->OpenSharedResource((HANDLE)mHandles[1],
|
||||
__uuidof(ID3D11Texture2D),
|
||||
(void**)(ID3D11Texture2D**)byRef(mTextures[1]));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to open shared texture for Cb Plane");
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = GetDevice()->OpenSharedResource((HANDLE)mHandles[2],
|
||||
__uuidof(ID3D11Texture2D),
|
||||
(void**)(ID3D11Texture2D**)byRef(mTextures[2]));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to open shared texture for Cr Plane");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ID3D11Device*
|
||||
DXGIYCbCrTextureHostD3D11::GetDevice()
|
||||
{
|
||||
return gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
|
||||
}
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureHostD3D11::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
mCompositor = static_cast<CompositorD3D11*>(aCompositor);
|
||||
}
|
||||
|
||||
bool
|
||||
DXGIYCbCrTextureHostD3D11::Lock()
|
||||
{
|
||||
if (!GetDevice()) {
|
||||
NS_WARNING("trying to lock a TextureHost without a D3D device");
|
||||
return false;
|
||||
}
|
||||
if (!mTextureSources[0]) {
|
||||
if (!mTextures[0] && !OpenSharedHandle()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTextureSources[0] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[0]);
|
||||
mTextureSources[1] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[1]);
|
||||
mTextureSources[2] = new DataTextureSourceD3D11(SurfaceFormat::A8, mCompositor, mTextures[2]);
|
||||
mTextureSources[0]->SetNextSibling(mTextureSources[1]);
|
||||
mTextureSources[1]->SetNextSibling(mTextureSources[2]);
|
||||
}
|
||||
|
||||
mIsLocked = LockD3DTexture(mTextureSources[0]->GetD3D11Texture()) &&
|
||||
LockD3DTexture(mTextureSources[1]->GetD3D11Texture()) &&
|
||||
LockD3DTexture(mTextureSources[2]->GetD3D11Texture());
|
||||
|
||||
return mIsLocked;
|
||||
}
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureHostD3D11::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
UnlockD3DTexture(mTextureSources[0]->GetD3D11Texture());
|
||||
UnlockD3DTexture(mTextureSources[1]->GetD3D11Texture());
|
||||
UnlockD3DTexture(mTextureSources[2]->GetD3D11Texture());
|
||||
mIsLocked = false;
|
||||
}
|
||||
|
||||
TextureSource*
|
||||
DXGIYCbCrTextureHostD3D11::GetTextureSources()
|
||||
{
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
// If Lock was successful we must have a valid TextureSource.
|
||||
MOZ_ASSERT(mTextureSources[0] && mTextureSources[1] && mTextureSources[2]);
|
||||
return mTextureSources[0].get();
|
||||
}
|
||||
|
||||
bool
|
||||
DataTextureSourceD3D11::Update(DataSourceSurface* aSurface,
|
||||
nsIntRegion* aDestRegion,
|
||||
|
|
|
@ -78,6 +78,59 @@ protected:
|
|||
bool mNeedsClearWhite;
|
||||
};
|
||||
|
||||
class DXGIYCbCrTextureClientD3D11 : public TextureClient
|
||||
{
|
||||
public:
|
||||
DXGIYCbCrTextureClientD3D11(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags);
|
||||
|
||||
virtual ~DXGIYCbCrTextureClientD3D11();
|
||||
|
||||
// TextureClient
|
||||
|
||||
virtual bool IsAllocated() const MOZ_OVERRIDE{ return !!mTextures[0]; }
|
||||
|
||||
virtual bool Lock(OpenMode aOpenMode) MOZ_OVERRIDE;
|
||||
|
||||
virtual void Unlock() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool IsLocked() const MOZ_OVERRIDE{ return mIsLocked; }
|
||||
|
||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
|
||||
|
||||
void InitWith(ID3D11Texture2D* aTextureY,
|
||||
ID3D11Texture2D* aTextureCb,
|
||||
ID3D11Texture2D* aTextureCr,
|
||||
const gfx::IntSize& aSize)
|
||||
{
|
||||
MOZ_ASSERT(aTextureY && aTextureCb && aTextureCr);
|
||||
MOZ_ASSERT(!mTextures[0]);
|
||||
mTextures[0] = aTextureY;
|
||||
mTextures[1] = aTextureCb;
|
||||
mTextures[2] = aTextureCr;
|
||||
mSize = aSize;
|
||||
}
|
||||
|
||||
virtual gfx::IntSize GetSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
virtual bool HasInternalBuffer() const MOZ_OVERRIDE{ return true; }
|
||||
|
||||
// This TextureClient should not be used in a context where we use CreateSimilar
|
||||
// (ex. component alpha) because the underlying texture data is always created by
|
||||
// an external producer.
|
||||
virtual TemporaryRef<TextureClient>
|
||||
CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE{ return nullptr; }
|
||||
|
||||
private:
|
||||
RefPtr<ID3D11Texture2D> mTextures[3];
|
||||
gfx::IntSize mSize;
|
||||
bool mIsLocked;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TextureSource that provides with the necessary APIs to be composited by a
|
||||
* CompositorD3D11.
|
||||
|
@ -213,6 +266,45 @@ protected:
|
|||
bool mIsLocked;
|
||||
};
|
||||
|
||||
class DXGIYCbCrTextureHostD3D11 : public TextureHost
|
||||
{
|
||||
public:
|
||||
DXGIYCbCrTextureHostD3D11(TextureFlags aFlags,
|
||||
const SurfaceDescriptorDXGIYCbCr& aDescriptor);
|
||||
|
||||
virtual TextureSource* GetTextureSources() MOZ_OVERRIDE;
|
||||
|
||||
virtual void DeallocateDeviceData() MOZ_OVERRIDE{}
|
||||
|
||||
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE{ return gfx::SurfaceFormat::YUV; }
|
||||
|
||||
virtual bool Lock() MOZ_OVERRIDE;
|
||||
|
||||
virtual void Unlock() MOZ_OVERRIDE;
|
||||
|
||||
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE{ return mSize; }
|
||||
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
ID3D11Device* GetDevice();
|
||||
|
||||
bool OpenSharedHandle();
|
||||
|
||||
RefPtr<ID3D11Texture2D> mTextures[3];
|
||||
RefPtr<DataTextureSourceD3D11> mTextureSources[3];
|
||||
|
||||
RefPtr<CompositorD3D11> mCompositor;
|
||||
gfx::IntSize mSize;
|
||||
WindowsHandle mHandles[3];
|
||||
bool mIsLocked;
|
||||
};
|
||||
|
||||
class CompositingRenderTargetD3D11 : public CompositingRenderTarget,
|
||||
public TextureSourceD3D11
|
||||
{
|
||||
|
|
|
@ -50,6 +50,13 @@ struct SurfaceDescriptorD3D10 {
|
|||
IntSize size;
|
||||
};
|
||||
|
||||
struct SurfaceDescriptorDXGIYCbCr {
|
||||
WindowsHandle handleY;
|
||||
WindowsHandle handleCb;
|
||||
WindowsHandle handleCr;
|
||||
IntSize size;
|
||||
};
|
||||
|
||||
struct SurfaceDescriptorMacIOSurface {
|
||||
uint32_t surface;
|
||||
double scaleFactor;
|
||||
|
@ -104,6 +111,7 @@ union SurfaceDescriptor {
|
|||
SurfaceDescriptorD3D9;
|
||||
SurfaceDescriptorDIB;
|
||||
SurfaceDescriptorD3D10;
|
||||
SurfaceDescriptorDXGIYCbCr;
|
||||
SurfaceDescriptorX11;
|
||||
SurfaceTextureDescriptor;
|
||||
EGLImageDescriptor;
|
||||
|
|
|
@ -25,7 +25,6 @@ class SurfaceDescriptor;
|
|||
class TextureClient;
|
||||
|
||||
class SharedPlanarYCbCrImage : public PlanarYCbCrImage
|
||||
, public ISharedImage
|
||||
{
|
||||
public:
|
||||
explicit SharedPlanarYCbCrImage(ImageClient* aCompositable);
|
||||
|
@ -34,7 +33,6 @@ protected:
|
|||
~SharedPlanarYCbCrImage();
|
||||
|
||||
public:
|
||||
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ already_AddRefed<Image> CreateSharedRGBImage(ImageContainer* aImageContainer,
|
|||
* It is assumed that the image width and stride are equal
|
||||
*/
|
||||
class SharedRGBImage : public Image
|
||||
, public ISharedImage
|
||||
{
|
||||
public:
|
||||
explicit SharedRGBImage(ImageClient* aCompositable);
|
||||
|
@ -46,8 +45,6 @@ protected:
|
|||
~SharedRGBImage();
|
||||
|
||||
public:
|
||||
virtual ISharedImage* AsSharedImage() MOZ_OVERRIDE { return this; }
|
||||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE;
|
||||
|
||||
virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
|
||||
|
|
|
@ -29,6 +29,7 @@ EXPORTS += [
|
|||
'ImageContainer.h',
|
||||
'ImageLayers.h',
|
||||
'ImageTypes.h',
|
||||
'IMFYCbCrImage.h',
|
||||
'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h',
|
||||
'Layers.h',
|
||||
'LayerScope.h',
|
||||
|
@ -47,6 +48,7 @@ EXPORTS += [
|
|||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'D3D9SurfaceImage.cpp',
|
||||
'IMFYCbCrImage.cpp',
|
||||
'TextureDIB.cpp',
|
||||
]
|
||||
EXPORTS.mozilla.layers += [
|
||||
|
|
|
@ -450,13 +450,26 @@ public:
|
|||
OSXDisplay()
|
||||
: mDisplayLink(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
}
|
||||
|
||||
~OSXDisplay()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
DisableVsync();
|
||||
}
|
||||
|
||||
static void RetryEnableVsync(nsITimer* aTimer, void* aOsxDisplay)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
OSXDisplay* osxDisplay = static_cast<OSXDisplay*>(aOsxDisplay);
|
||||
MOZ_ASSERT(osxDisplay);
|
||||
osxDisplay->EnableVsync();
|
||||
}
|
||||
|
||||
virtual void EnableVsync() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -469,18 +482,25 @@ public:
|
|||
// situations. According to the docs, it is compatible with all displays running on the computer
|
||||
// But if we have different monitors at different display rates, we may hit issues.
|
||||
if (CVDisplayLinkCreateWithActiveCGDisplays(&mDisplayLink) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not create a display link with all active displays. Falling back to main display\n");
|
||||
NS_WARNING("Could not create a display link with all active displays. Retrying\n");
|
||||
CVDisplayLinkRelease(mDisplayLink);
|
||||
mDisplayLink = nullptr;
|
||||
|
||||
// bug 1142708 - When coming back from sleep, there may be no active displays ready yet,
|
||||
// even if listening for the kIOMessageSystemHasPoweredOn event from OS X sleep notifications.
|
||||
// bug 1142708 - When coming back from sleep,
|
||||
// or when changing displays, active displays may not be ready yet,
|
||||
// even if listening for the kIOMessageSystemHasPoweredOn event
|
||||
// from OS X sleep notifications.
|
||||
// Active displays are those that are drawable.
|
||||
// In these cases, default back to the main display to try to get a vsync event.
|
||||
// The alternative would be to keep polling the CGActiveDisplayList for the displays to be ready.
|
||||
if (CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &mDisplayLink) != kCVReturnSuccess) {
|
||||
MOZ_CRASH("Could not create a CVDisplayLink with either active displays or the main display");
|
||||
}
|
||||
NS_WARNING("Using the CVDisplayLink from the main display\n");
|
||||
// bug 1144638 - When changing display configurations and getting
|
||||
// notifications from CGDisplayReconfigurationCallBack, the
|
||||
// callback gets called twice for each active display
|
||||
// so it's difficult to know when all displays are active.
|
||||
// Instead, try again soon. The delay is arbitrary. 100ms chosen
|
||||
// because on a late 2013 15" retina, it takes about that
|
||||
// long to come back up from sleep.
|
||||
uint32_t delay = 100;
|
||||
mTimer->InitWithFuncCallback(RetryEnableVsync, this, delay, nsITimer::TYPE_ONE_SHOT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CVDisplayLinkSetOutputCallback(mDisplayLink, &VsyncCallback, this) != kCVReturnSuccess) {
|
||||
|
@ -528,6 +548,7 @@ public:
|
|||
private:
|
||||
// Manages the display link render thread
|
||||
CVDisplayLinkRef mDisplayLink;
|
||||
nsRefPtr<nsITimer> mTimer;
|
||||
}; // OSXDisplay
|
||||
|
||||
private:
|
||||
|
|
|
@ -1582,6 +1582,19 @@ gfxWindowsPlatform::GetD3D11ContentDevice()
|
|||
return mD3D11ContentDevice;
|
||||
}
|
||||
|
||||
ID3D11Device*
|
||||
gfxWindowsPlatform::GetD3D11MediaDevice()
|
||||
{
|
||||
if (mD3D11DeviceInitialized) {
|
||||
return mD3D11MediaDevice;
|
||||
}
|
||||
|
||||
InitD3D11Devices();
|
||||
|
||||
return mD3D11MediaDevice;
|
||||
}
|
||||
|
||||
|
||||
ReadbackManagerD3D11*
|
||||
gfxWindowsPlatform::GetReadbackManager()
|
||||
{
|
||||
|
@ -1942,6 +1955,25 @@ gfxWindowsPlatform::InitD3D11Devices()
|
|||
Factory::SetDirect3D11Device(mD3D11ContentDevice);
|
||||
}
|
||||
|
||||
if (!useWARP || gfxPrefs::LayersD3D11ForceWARP()) {
|
||||
hr = E_INVALIDARG;
|
||||
MOZ_SEH_TRY{
|
||||
hr = d3d11CreateDevice(adapter, useWARP ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_UNKNOWN, nullptr,
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
featureLevels.Elements(), featureLevels.Length(),
|
||||
D3D11_SDK_VERSION, byRef(mD3D11MediaDevice), nullptr, nullptr);
|
||||
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||
mD3D11MediaDevice = nullptr;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
d3d11Module.disown();
|
||||
return;
|
||||
}
|
||||
|
||||
mD3D11MediaDevice->SetExceptionMode(0);
|
||||
}
|
||||
|
||||
// We leak these everywhere and we need them our entire runtime anyway, let's
|
||||
// leak it here as well.
|
||||
d3d11Module.disown();
|
||||
|
|
|
@ -246,6 +246,7 @@ public:
|
|||
#endif
|
||||
ID3D11Device *GetD3D11Device();
|
||||
ID3D11Device *GetD3D11ContentDevice();
|
||||
ID3D11Device *GetD3D11MediaDevice();
|
||||
|
||||
mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
|
||||
|
||||
|
@ -286,6 +287,7 @@ private:
|
|||
nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
|
||||
mozilla::RefPtr<ID3D11Device> mD3D11Device;
|
||||
mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
|
||||
mozilla::RefPtr<ID3D11Device> mD3D11MediaDevice;
|
||||
bool mD3D11DeviceInitialized;
|
||||
mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
|
||||
bool mIsWARP;
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
DIRS += ['public', 'src', 'decoders', 'encoders']
|
||||
DIRS += ['build']
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'ImageLib')
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
||||
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
|
||||
|
|
|
@ -542,17 +542,6 @@ void imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aReq
|
|||
if (bMustRevalidate)
|
||||
aCacheEntry->SetMustValidate(bMustRevalidate);
|
||||
}
|
||||
|
||||
// We always need to validate file URIs.
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
channel->GetURI(getter_AddRefs(uri));
|
||||
bool isfile = false;
|
||||
uri->SchemeIs("file", &isfile);
|
||||
if (isfile)
|
||||
aCacheEntry->SetMustValidate(isfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -539,7 +539,6 @@ struct PointerHasher
|
|||
{
|
||||
typedef Key Lookup;
|
||||
static HashNumber hash(const Lookup &l) {
|
||||
MOZ_ASSERT(!JS::IsPoisonedPtr(l));
|
||||
size_t word = reinterpret_cast<size_t>(l) >> zeroBits;
|
||||
static_assert(sizeof(HashNumber) == 4,
|
||||
"subsequent code assumes a four-byte hash");
|
||||
|
@ -553,8 +552,6 @@ struct PointerHasher
|
|||
#endif
|
||||
}
|
||||
static bool match(const Key &k, const Lookup &l) {
|
||||
MOZ_ASSERT(!JS::IsPoisonedPtr(k));
|
||||
MOZ_ASSERT(!JS::IsPoisonedPtr(l));
|
||||
return k == l;
|
||||
}
|
||||
static void rekey(Key &k, const Key& newKey) {
|
||||
|
|
|
@ -126,7 +126,6 @@ SYMBOL_TO_JSID(JS::Symbol *sym)
|
|||
MOZ_ASSERT(sym != nullptr);
|
||||
MOZ_ASSERT((size_t(sym) & JSID_TYPE_MASK) == 0);
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell *>(sym)));
|
||||
MOZ_ASSERT(!JS::IsPoisonedPtr(sym));
|
||||
JSID_BITS(id) = (size_t(sym) | JSID_TYPE_SYMBOL);
|
||||
return id;
|
||||
}
|
||||
|
@ -169,20 +168,9 @@ extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
|
|||
|
||||
namespace js {
|
||||
|
||||
inline bool
|
||||
IsPoisonedId(jsid id)
|
||||
{
|
||||
if (JSID_IS_STRING(id))
|
||||
return JS::IsPoisonedPtr(JSID_TO_STRING(id));
|
||||
if (JSID_IS_SYMBOL(id))
|
||||
return JS::IsPoisonedPtr(JSID_TO_SYMBOL(id));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <> struct GCMethods<jsid>
|
||||
{
|
||||
static jsid initial() { return JSID_VOID; }
|
||||
static bool poisoned(jsid id) { return IsPoisonedId(id); }
|
||||
static bool needsPostBarrier(jsid id) { return false; }
|
||||
static void postBarrier(jsid *idp) {}
|
||||
static void relocate(jsid *idp) {}
|
||||
|
|
|
@ -282,14 +282,12 @@ class Heap : public js::HeapBase<T>
|
|||
|
||||
private:
|
||||
void init(T newPtr) {
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
|
||||
ptr = newPtr;
|
||||
if (js::GCMethods<T>::needsPostBarrier(ptr))
|
||||
post();
|
||||
}
|
||||
|
||||
void set(T newPtr) {
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
|
||||
if (js::GCMethods<T>::needsPostBarrier(newPtr)) {
|
||||
ptr = newPtr;
|
||||
post();
|
||||
|
@ -362,7 +360,6 @@ class TenuredHeap : public js::HeapBase<T>
|
|||
|
||||
void setPtr(T newPtr) {
|
||||
MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
|
||||
if (newPtr)
|
||||
AssertGCThingMustBeTenured(newPtr);
|
||||
bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);
|
||||
|
@ -526,7 +523,6 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
|
|||
|
||||
public:
|
||||
void set(T v) {
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(v));
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
|
@ -642,7 +638,6 @@ template <typename T>
|
|||
struct GCMethods<T *>
|
||||
{
|
||||
static T *initial() { return nullptr; }
|
||||
static bool poisoned(T *v) { return JS::IsPoisonedPtr(v); }
|
||||
static bool needsPostBarrier(T *v) { return false; }
|
||||
static void postBarrier(T **vp) {}
|
||||
static void relocate(T **vp) {}
|
||||
|
@ -652,7 +647,6 @@ template <>
|
|||
struct GCMethods<JSObject *>
|
||||
{
|
||||
static JSObject *initial() { return nullptr; }
|
||||
static bool poisoned(JSObject *v) { return JS::IsPoisonedPtr(v); }
|
||||
static gc::Cell *asGCThingOrNull(JSObject *v) {
|
||||
if (!v)
|
||||
return nullptr;
|
||||
|
@ -674,7 +668,6 @@ template <>
|
|||
struct GCMethods<JSFunction *>
|
||||
{
|
||||
static JSFunction *initial() { return nullptr; }
|
||||
static bool poisoned(JSFunction *v) { return JS::IsPoisonedPtr(v); }
|
||||
static bool needsPostBarrier(JSFunction *v) {
|
||||
return v != nullptr && gc::IsInsideNursery(reinterpret_cast<gc::Cell *>(v));
|
||||
}
|
||||
|
@ -708,8 +701,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
|
|||
this->stack = &cx->thingGCRooters[kind];
|
||||
this->prev = *stack;
|
||||
*stack = reinterpret_cast<Rooted<void*>*>(this);
|
||||
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(ptr));
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -789,7 +780,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
|
|||
* interchangeably with a MutableHandleValue.
|
||||
*/
|
||||
void set(T value) {
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(value));
|
||||
ptr = value;
|
||||
}
|
||||
|
||||
|
@ -889,7 +879,6 @@ class FakeRooted : public RootedBase<T>
|
|||
T ptr;
|
||||
|
||||
void set(const T &value) {
|
||||
MOZ_ASSERT(!GCMethods<T>::poisoned(value));
|
||||
ptr = value;
|
||||
}
|
||||
|
||||
|
@ -912,7 +901,6 @@ class FakeMutableHandle : public js::MutableHandleBase<T>
|
|||
}
|
||||
|
||||
void set(T v) {
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(v));
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
|
@ -1158,7 +1146,6 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
|
|||
private:
|
||||
void set(T value) {
|
||||
MOZ_ASSERT(initialized());
|
||||
MOZ_ASSERT(!js::GCMethods<T>::poisoned(value));
|
||||
ptr = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -395,40 +395,6 @@ ScrambleHashCode(HashNumber h)
|
|||
|
||||
} /* namespace js */
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* Methods for poisoning GC heap pointer words and checking for poisoned words.
|
||||
* These are in this file for use in Value methods and so forth.
|
||||
*
|
||||
* If the moving GC hazard analysis is in use and detects a non-rooted stack
|
||||
* pointer to a GC thing, one byte of that pointer is poisoned to refer to an
|
||||
* invalid location. For both 32 bit and 64 bit systems, the fourth byte of the
|
||||
* pointer is overwritten, to reduce the likelihood of accidentally changing
|
||||
* a live integer value.
|
||||
*/
|
||||
|
||||
inline void PoisonPtr(void *v)
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG)
|
||||
uint8_t *ptr = (uint8_t *) v + 3;
|
||||
*ptr = JS_FREE_PATTERN;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool IsPoisonedPtr(T *v)
|
||||
{
|
||||
#if defined(JSGC_ROOT_ANALYSIS) && defined(JS_DEBUG)
|
||||
uint32_t mask = uintptr_t(v) & 0xff000000;
|
||||
return mask == uint32_t(JS_FREE_PATTERN << 24);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* sixgill annotation defines */
|
||||
#ifndef HAVE_STATIC_ANNOTATIONS
|
||||
# define HAVE_STATIC_ANNOTATIONS
|
||||
|
|
|
@ -1043,17 +1043,14 @@ class Value
|
|||
}
|
||||
|
||||
void setString(JSString *str) {
|
||||
MOZ_ASSERT(!IsPoisonedPtr(str));
|
||||
data = STRING_TO_JSVAL_IMPL(str);
|
||||
}
|
||||
|
||||
void setSymbol(JS::Symbol *sym) {
|
||||
MOZ_ASSERT(!IsPoisonedPtr(sym));
|
||||
data = SYMBOL_TO_JSVAL_IMPL(sym);
|
||||
}
|
||||
|
||||
void setObject(JSObject &obj) {
|
||||
MOZ_ASSERT(!IsPoisonedPtr(&obj));
|
||||
data = OBJECT_TO_JSVAL_IMPL(&obj);
|
||||
}
|
||||
|
||||
|
@ -1641,17 +1638,11 @@ namespace js {
|
|||
template <> struct GCMethods<const JS::Value>
|
||||
{
|
||||
static JS::Value initial() { return JS::UndefinedValue(); }
|
||||
static bool poisoned(const JS::Value &v) {
|
||||
return v.isMarkable() && JS::IsPoisonedPtr(v.toGCThing());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GCMethods<JS::Value>
|
||||
{
|
||||
static JS::Value initial() { return JS::UndefinedValue(); }
|
||||
static bool poisoned(const JS::Value &v) {
|
||||
return v.isMarkable() && JS::IsPoisonedPtr(v.toGCThing());
|
||||
}
|
||||
static gc::Cell *asGCThingOrNull(const JS::Value &v) {
|
||||
return v.isMarkable() ? v.toGCThing() : nullptr;
|
||||
}
|
||||
|
@ -1890,12 +1881,6 @@ IMPL_TO_JSVAL(jsval_layout l)
|
|||
|
||||
namespace JS {
|
||||
|
||||
inline bool
|
||||
IsPoisonedValue(const Value &v)
|
||||
{
|
||||
return js::GCMethods<Value>::poisoned(v);
|
||||
}
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
namespace detail {
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ using JS::BooleanValue;
|
|||
using JS::DoubleValue;
|
||||
using JS::Float32Value;
|
||||
using JS::Int32Value;
|
||||
using JS::IsPoisonedValue;
|
||||
using JS::MagicValue;
|
||||
using JS::NullValue;
|
||||
using JS::NumberValue;
|
||||
|
@ -67,8 +66,6 @@ using JS::PrivateValue;
|
|||
using JS::StringValue;
|
||||
using JS::UndefinedValue;
|
||||
|
||||
using JS::IsPoisonedPtr;
|
||||
|
||||
using JS::Latin1Char;
|
||||
using JS::Latin1Chars;
|
||||
using JS::Latin1CharsZ;
|
||||
|
|
|
@ -565,7 +565,7 @@ template <typename ParseHandler>
|
|||
ObjectBox *
|
||||
Parser<ParseHandler>::newObjectBox(JSObject *obj)
|
||||
{
|
||||
MOZ_ASSERT(obj && !IsPoisonedPtr(obj));
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
/*
|
||||
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
|
||||
|
@ -660,7 +660,7 @@ FunctionBox *
|
|||
Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction *fun, ParseContext<ParseHandler> *outerpc,
|
||||
Directives inheritedDirectives, GeneratorKind generatorKind)
|
||||
{
|
||||
MOZ_ASSERT(fun && !IsPoisonedPtr(fun));
|
||||
MOZ_ASSERT(fun);
|
||||
|
||||
/*
|
||||
* We use JSContext.tempLifoAlloc to allocate parsed objects and place them
|
||||
|
|
|
@ -115,7 +115,6 @@ struct Token
|
|||
|
||||
void setName(PropertyName *name) {
|
||||
MOZ_ASSERT(type == TOK_NAME);
|
||||
MOZ_ASSERT(!IsPoisonedPtr(name));
|
||||
u.name = name;
|
||||
}
|
||||
|
||||
|
@ -123,7 +122,6 @@ struct Token
|
|||
MOZ_ASSERT(type == TOK_STRING ||
|
||||
type == TOK_TEMPLATE_HEAD ||
|
||||
type == TOK_NO_SUBS_TEMPLATE);
|
||||
MOZ_ASSERT(!IsPoisonedPtr(atom));
|
||||
u.atom = atom;
|
||||
}
|
||||
|
||||
|
|
|
@ -427,7 +427,6 @@ class BarrieredBase : public BarrieredBaseMixins<T>
|
|||
|
||||
public:
|
||||
void init(T v) {
|
||||
MOZ_ASSERT(!GCMethods<T>::poisoned(v));
|
||||
this->value = v;
|
||||
}
|
||||
|
||||
|
@ -492,7 +491,6 @@ class PreBarriered : public BarrieredBase<T>
|
|||
private:
|
||||
void set(const T &v) {
|
||||
this->pre();
|
||||
MOZ_ASSERT(!GCMethods<T>::poisoned(v));
|
||||
this->value = v;
|
||||
}
|
||||
};
|
||||
|
@ -518,7 +516,6 @@ class HeapPtr : public BarrieredBase<T>
|
|||
explicit HeapPtr(const HeapPtr<T> &v) : BarrieredBase<T>(v) { post(); }
|
||||
|
||||
void init(T v) {
|
||||
MOZ_ASSERT(!GCMethods<T>::poisoned(v));
|
||||
this->value = v;
|
||||
post();
|
||||
}
|
||||
|
@ -538,7 +535,6 @@ class HeapPtr : public BarrieredBase<T>
|
|||
private:
|
||||
void set(const T &v) {
|
||||
this->pre();
|
||||
MOZ_ASSERT(!GCMethods<T>::poisoned(v));
|
||||
this->value = v;
|
||||
post();
|
||||
}
|
||||
|
@ -625,7 +621,6 @@ class RelocatablePtr : public BarrieredBase<T>
|
|||
protected:
|
||||
void set(const T &v) {
|
||||
this->pre();
|
||||
MOZ_ASSERT(!GCMethods<T>::poisoned(v));
|
||||
if (GCMethods<T>::needsPostBarrier(v)) {
|
||||
this->value = v;
|
||||
post();
|
||||
|
@ -840,14 +835,12 @@ class HeapSlot : public BarrieredBase<Value>
|
|||
explicit HeapSlot(NativeObject *obj, Kind kind, uint32_t slot, const Value &v)
|
||||
: BarrieredBase<Value>(v)
|
||||
{
|
||||
MOZ_ASSERT(!IsPoisonedValue(v));
|
||||
post(obj, kind, slot, v);
|
||||
}
|
||||
|
||||
explicit HeapSlot(NativeObject *obj, Kind kind, uint32_t slot, const HeapSlot &s)
|
||||
: BarrieredBase<Value>(s.value)
|
||||
{
|
||||
MOZ_ASSERT(!IsPoisonedValue(s.value));
|
||||
post(obj, kind, slot, s);
|
||||
}
|
||||
|
||||
|
@ -868,7 +861,6 @@ class HeapSlot : public BarrieredBase<Value>
|
|||
|
||||
void set(NativeObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
MOZ_ASSERT(preconditionForSet(owner, kind, slot));
|
||||
MOZ_ASSERT(!IsPoisonedValue(v));
|
||||
pre();
|
||||
value = v;
|
||||
post(owner, kind, slot, v);
|
||||
|
@ -876,7 +868,6 @@ class HeapSlot : public BarrieredBase<Value>
|
|||
|
||||
void set(Zone *zone, NativeObject *owner, Kind kind, uint32_t slot, const Value &v) {
|
||||
MOZ_ASSERT(preconditionForSet(zone, owner, kind, slot));
|
||||
MOZ_ASSERT(!IsPoisonedValue(v));
|
||||
pre(zone);
|
||||
value = v;
|
||||
post(owner, kind, slot, v);
|
||||
|
|
|
@ -625,6 +625,12 @@ class GCRuntime
|
|||
void startDebugGC(JSGCInvocationKind gckind, SliceBudget &budget);
|
||||
void debugGCSlice(SliceBudget &budget);
|
||||
|
||||
void triggerFullGCForAtoms() {
|
||||
MOZ_ASSERT(fullGCForAtomsRequested_);
|
||||
fullGCForAtomsRequested_ = false;
|
||||
triggerGC(JS::gcreason::ALLOC_TRIGGER);
|
||||
}
|
||||
|
||||
void runDebugGC();
|
||||
inline void poke();
|
||||
|
||||
|
@ -787,6 +793,8 @@ class GCRuntime
|
|||
bool majorGCRequested() const { return majorGCTriggerReason != JS::gcreason::NO_REASON; }
|
||||
bool isGcNeeded() { return minorGCRequested() || majorGCRequested(); }
|
||||
|
||||
bool fullGCForAtomsRequested() { return fullGCForAtomsRequested_; }
|
||||
|
||||
double computeHeapGrowthFactor(size_t lastBytes);
|
||||
size_t computeTriggerBytes(double growthFactor, size_t lastBytes);
|
||||
|
||||
|
@ -901,6 +909,7 @@ class GCRuntime
|
|||
template <class CompartmentIterT> void markWeakReferences(gcstats::Phase phase);
|
||||
void markWeakReferencesInCurrentGroup(gcstats::Phase phase);
|
||||
template <class ZoneIterT, class CompartmentIterT> void markGrayReferences(gcstats::Phase phase);
|
||||
void markBufferedGrayRoots(JS::Zone *zone);
|
||||
void markGrayReferencesInCurrentGroup(gcstats::Phase phase);
|
||||
void markAllWeakReferences(gcstats::Phase phase);
|
||||
void markAllGrayReferences(gcstats::Phase phase);
|
||||
|
@ -1014,6 +1023,16 @@ class GCRuntime
|
|||
/* During shutdown, the GC needs to clean up every possible object. */
|
||||
bool cleanUpEverything;
|
||||
|
||||
// Record gray roots in the first slice for later marking. See the comment
|
||||
// in RootMarking.cpp for details.
|
||||
friend class js::GCMarker;
|
||||
enum class GrayBufferState {
|
||||
Unused,
|
||||
Okay,
|
||||
Failed
|
||||
};
|
||||
GrayBufferState grayBufferState;
|
||||
|
||||
/*
|
||||
* The gray bits can become invalid if UnmarkGray overflows the stack. A
|
||||
* full GC will reset this bit, since it fills in all the gray bits.
|
||||
|
@ -1024,6 +1043,9 @@ class GCRuntime
|
|||
|
||||
JS::gcreason::Reason minorGCTriggerReason;
|
||||
|
||||
/* Perform full GC if rt->keepAtoms() becomes false. */
|
||||
bool fullGCForAtomsRequested_;
|
||||
|
||||
/* Incremented at the start of every major GC. */
|
||||
uint64_t majorGCNumber;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ using namespace js::gc;
|
|||
void
|
||||
js::TraceRuntime(JSTracer *trc)
|
||||
{
|
||||
MOZ_ASSERT(!IS_GC_MARKING_TRACER(trc));
|
||||
MOZ_ASSERT(!IsMarkingTracer(trc));
|
||||
|
||||
JSRuntime *rt = trc->runtime();
|
||||
rt->gc.evictNursery();
|
||||
|
|
|
@ -143,7 +143,7 @@ IsThingPoisoned(T *thing)
|
|||
static GCMarker *
|
||||
AsGCMarker(JSTracer *trc)
|
||||
{
|
||||
MOZ_ASSERT(IS_GC_MARKING_TRACER(trc));
|
||||
MOZ_ASSERT(IsMarkingTracer(trc));
|
||||
return static_cast<GCMarker *>(trc);
|
||||
}
|
||||
|
||||
|
@ -191,14 +191,13 @@ CheckMarkedThing(JSTracer *trc, T **thingp)
|
|||
MOZ_ASSERT(zone->runtimeFromAnyThread() == trc->runtime());
|
||||
MOZ_ASSERT(trc->hasTracingDetails());
|
||||
|
||||
bool isGcMarkingTracer = IS_GC_MARKING_TRACER(trc);
|
||||
MOZ_ASSERT(thing->isAligned());
|
||||
MOZ_ASSERT(MapTypeToTraceKind<T>::kind == GetGCThingTraceKind(thing));
|
||||
|
||||
bool isGcMarkingTracer = IsMarkingGray(trc) || IsMarkingTracer(trc);
|
||||
|
||||
MOZ_ASSERT_IF(zone->requireGCTracer(), isGcMarkingTracer);
|
||||
|
||||
MOZ_ASSERT(thing->isAligned());
|
||||
|
||||
MOZ_ASSERT(MapTypeToTraceKind<T>::kind == GetGCThingTraceKind(thing));
|
||||
|
||||
if (isGcMarkingTracer) {
|
||||
GCMarker *gcMarker = static_cast<GCMarker *>(trc);
|
||||
MOZ_ASSERT_IF(gcMarker->shouldCheckCompartments(),
|
||||
|
@ -299,9 +298,9 @@ MarkInternal(JSTracer *trc, T **thingp)
|
|||
trc->clearTracingDetails();
|
||||
}
|
||||
|
||||
#define JS_ROOT_MARKING_ASSERT(trc) \
|
||||
MOZ_ASSERT_IF(IS_GC_MARKING_TRACER(trc), \
|
||||
trc->runtime()->gc.state() == NO_INCREMENTAL || \
|
||||
#define JS_ROOT_MARKING_ASSERT(trc) \
|
||||
MOZ_ASSERT_IF(IsMarkingTracer(trc), \
|
||||
trc->runtime()->gc.state() == NO_INCREMENTAL || \
|
||||
trc->runtime()->gc.state() == MARK_ROOTS);
|
||||
|
||||
namespace js {
|
||||
|
@ -954,7 +953,7 @@ gc::MarkObjectSlots(JSTracer *trc, NativeObject *obj, uint32_t start, uint32_t n
|
|||
static bool
|
||||
ShouldMarkCrossCompartment(JSTracer *trc, JSObject *src, Cell *cell)
|
||||
{
|
||||
if (!IS_GC_MARKING_TRACER(trc))
|
||||
if (!IsMarkingTracer(trc))
|
||||
return true;
|
||||
|
||||
uint32_t color = AsGCMarker(trc)->markColor();
|
||||
|
@ -1708,6 +1707,9 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
|||
goto scan_unboxed;
|
||||
}
|
||||
if (clasp == &UnboxedPlainObject::class_) {
|
||||
JSObject *expando = obj->as<UnboxedPlainObject>().maybeExpando();
|
||||
if (expando && mark(expando))
|
||||
repush(expando);
|
||||
const UnboxedLayout &layout = obj->as<UnboxedPlainObject>().layout();
|
||||
unboxedTraceList = layout.traceList();
|
||||
if (!unboxedTraceList)
|
||||
|
|
|
@ -374,6 +374,7 @@ static const PhaseInfo phases[] = {
|
|||
{ PHASE_TRACE_HEAP, "Trace Heap", PHASE_NO_PARENT },
|
||||
/* PHASE_MARK_ROOTS */
|
||||
{ PHASE_MARK_ROOTS, "Mark Roots", PHASE_MULTI_PARENTS },
|
||||
{ PHASE_BUFFER_GRAY_ROOTS, "Buffer Gray Roots", PHASE_MARK_ROOTS },
|
||||
{ PHASE_MARK_CCWS, "Mark Cross Compartment Wrappers", PHASE_MARK_ROOTS },
|
||||
{ PHASE_MARK_ROOTERS, "Mark Rooters", PHASE_MARK_ROOTS },
|
||||
{ PHASE_MARK_RUNTIME_DATA, "Mark Runtime-wide Data", PHASE_MARK_ROOTS },
|
||||
|
|
|
@ -75,6 +75,7 @@ enum Phase {
|
|||
PHASE_EVICT_NURSERY,
|
||||
PHASE_TRACE_HEAP,
|
||||
PHASE_MARK_ROOTS,
|
||||
PHASE_BUFFER_GRAY_ROOTS,
|
||||
PHASE_MARK_CCWS,
|
||||
PHASE_MARK_ROOTERS,
|
||||
PHASE_MARK_RUNTIME_DATA,
|
||||
|
|
|
@ -517,7 +517,6 @@ GCMarker::GCMarker(JSRuntime *rt)
|
|||
color(BLACK),
|
||||
unmarkedArenaStackTop(nullptr),
|
||||
markLaterArenas(0),
|
||||
grayBufferState(GRAY_BUFFER_UNUSED),
|
||||
started(false),
|
||||
strictCompartmentChecking(false)
|
||||
{
|
||||
|
@ -556,7 +555,7 @@ GCMarker::stop()
|
|||
stack.reset();
|
||||
|
||||
resetBufferedGrayRoots();
|
||||
grayBufferState = GRAY_BUFFER_UNUSED;
|
||||
runtime()->gc.grayBufferState = GCRuntime::GrayBufferState::Unused;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -650,30 +649,29 @@ GCMarker::checkZone(void *p)
|
|||
bool
|
||||
GCMarker::hasBufferedGrayRoots() const
|
||||
{
|
||||
return grayBufferState == GRAY_BUFFER_OK;
|
||||
return runtime()->gc.grayBufferState == GCRuntime::GrayBufferState::Okay;
|
||||
}
|
||||
|
||||
void
|
||||
GCMarker::startBufferingGrayRoots()
|
||||
{
|
||||
MOZ_ASSERT(grayBufferState == GRAY_BUFFER_UNUSED);
|
||||
grayBufferState = GRAY_BUFFER_OK;
|
||||
MOZ_ASSERT(runtime()->gc.grayBufferState == GCRuntime::GrayBufferState::Unused);
|
||||
runtime()->gc.grayBufferState = GCRuntime::GrayBufferState::Okay;
|
||||
for (GCZonesIter zone(runtime()); !zone.done(); zone.next())
|
||||
MOZ_ASSERT(zone->gcGrayRoots.empty());
|
||||
|
||||
MOZ_ASSERT(!callback);
|
||||
callback = GrayCallback;
|
||||
MOZ_ASSERT(IS_GC_MARKING_TRACER(this));
|
||||
MOZ_ASSERT(IsMarkingGray(this));
|
||||
}
|
||||
|
||||
void
|
||||
GCMarker::endBufferingGrayRoots()
|
||||
{
|
||||
MOZ_ASSERT(callback == GrayCallback);
|
||||
MOZ_ASSERT(IsMarkingGray(this));
|
||||
callback = nullptr;
|
||||
MOZ_ASSERT(IS_GC_MARKING_TRACER(this));
|
||||
MOZ_ASSERT(grayBufferState == GRAY_BUFFER_OK ||
|
||||
grayBufferState == GRAY_BUFFER_FAILED);
|
||||
MOZ_ASSERT(runtime()->gc.grayBufferState == GCRuntime::GrayBufferState::Okay ||
|
||||
runtime()->gc.grayBufferState == GCRuntime::GrayBufferState::Failed);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -684,16 +682,16 @@ GCMarker::resetBufferedGrayRoots()
|
|||
}
|
||||
|
||||
void
|
||||
GCMarker::markBufferedGrayRoots(JS::Zone *zone)
|
||||
GCRuntime::markBufferedGrayRoots(JS::Zone *zone)
|
||||
{
|
||||
MOZ_ASSERT(grayBufferState == GRAY_BUFFER_OK);
|
||||
MOZ_ASSERT(grayBufferState == GrayBufferState::Okay);
|
||||
MOZ_ASSERT(zone->isGCMarkingGray() || zone->isGCCompacting());
|
||||
|
||||
for (GrayRoot *elem = zone->gcGrayRoots.begin(); elem != zone->gcGrayRoots.end(); elem++) {
|
||||
#ifdef DEBUG
|
||||
setTracingDetails(elem->debugPrinter, elem->debugPrintArg, elem->debugPrintIndex);
|
||||
marker.setTracingDetails(elem->debugPrinter, elem->debugPrintArg, elem->debugPrintIndex);
|
||||
#endif
|
||||
MarkKind(this, &elem->thing, elem->kind);
|
||||
MarkKind(&marker, &elem->thing, elem->kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -702,7 +700,7 @@ GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind)
|
|||
{
|
||||
MOZ_ASSERT(started);
|
||||
|
||||
if (grayBufferState == GRAY_BUFFER_FAILED)
|
||||
if (runtime()->gc.grayBufferState == GCRuntime::GrayBufferState::Failed)
|
||||
return;
|
||||
|
||||
GrayRoot root(thing, kind);
|
||||
|
@ -730,7 +728,7 @@ GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind)
|
|||
}
|
||||
if (!zone->gcGrayRoots.append(root)) {
|
||||
resetBufferedGrayRoots();
|
||||
grayBufferState = GRAY_BUFFER_FAILED;
|
||||
runtime()->gc.grayBufferState = GCRuntime::GrayBufferState::Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,7 +214,6 @@ class GCMarker : public JSTracer
|
|||
void startBufferingGrayRoots();
|
||||
void endBufferingGrayRoots();
|
||||
void resetBufferedGrayRoots();
|
||||
void markBufferedGrayRoots(JS::Zone *zone);
|
||||
|
||||
static void GrayCallback(JSTracer *trc, void **thing, JSGCTraceKind kind);
|
||||
|
||||
|
@ -320,7 +319,6 @@ class GCMarker : public JSTracer
|
|||
|
||||
void markAndScanString(JSObject *source, JSString *str);
|
||||
void markAndScanSymbol(JSObject *source, JS::Symbol *sym);
|
||||
bool markObject(JSObject *source, JSObject *obj);
|
||||
|
||||
void appendGrayRoot(void *thing, JSGCTraceKind kind);
|
||||
|
||||
|
@ -333,13 +331,6 @@ class GCMarker : public JSTracer
|
|||
/* Count of arenas that are currently in the stack. */
|
||||
mozilla::DebugOnly<size_t> markLaterArenas;
|
||||
|
||||
enum GrayBufferState {
|
||||
GRAY_BUFFER_UNUSED,
|
||||
GRAY_BUFFER_OK,
|
||||
GRAY_BUFFER_FAILED
|
||||
};
|
||||
GrayBufferState grayBufferState;
|
||||
|
||||
/* Assert that start and stop are called with correct ordering. */
|
||||
mozilla::DebugOnly<bool> started;
|
||||
|
||||
|
@ -353,12 +344,25 @@ class GCMarker : public JSTracer
|
|||
void
|
||||
SetMarkStackLimit(JSRuntime *rt, size_t limit);
|
||||
|
||||
// Return true if this trace is happening on behalf of gray buffering during
|
||||
// the marking phase of incremental GC.
|
||||
inline bool
|
||||
IsMarkingGray(JSTracer *trc)
|
||||
{
|
||||
return trc->callback == js::GCMarker::GrayCallback;
|
||||
}
|
||||
|
||||
// Return true if this trace is happening on behalf of the marking phase of GC.
|
||||
inline bool
|
||||
IsMarkingTracer(JSTracer *trc)
|
||||
{
|
||||
// If we call this on the gray-buffering tracer, then we have encountered a
|
||||
// marking path that will be wrong when tracing with a callback marker to
|
||||
// enqueue for deferred gray marking.
|
||||
MOZ_ASSERT(!IsMarkingGray(trc));
|
||||
return trc->callback == nullptr;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Macro to test if a traversal is the marking phase of the GC.
|
||||
*/
|
||||
#define IS_GC_MARKING_TRACER(trc) \
|
||||
((trc)->callback == nullptr || (trc)->callback == GCMarker::GrayCallback)
|
||||
|
||||
#endif /* js_Tracer_h */
|
||||
|
|
|
@ -2564,6 +2564,10 @@ CodeGenerator::visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic *lir)
|
|||
}
|
||||
|
||||
if (mir->numUnboxedGroups()) {
|
||||
// The guard requires that unboxed objects not have expandos.
|
||||
bailoutCmpPtr(Assembler::NotEqual, Address(obj, JSObject::offsetOfShape()),
|
||||
ImmWord(0), lir->snapshot());
|
||||
|
||||
masm.loadObjGroup(obj, temp);
|
||||
|
||||
for (size_t i = 0; i < mir->numUnboxedGroups(); i++) {
|
||||
|
|
|
@ -10521,7 +10521,7 @@ IonBuilder::addShapeGuardsForGetterSetter(MDefinition *obj, JSObject *holder, Sh
|
|||
MDefinition *holderDef = constantMaybeNursery(holder);
|
||||
addShapeGuard(holderDef, holderShape, Bailout_ShapeGuard);
|
||||
|
||||
return addShapeGuardPolymorphic(obj, receiverShapes, receiverUnboxedGroups);
|
||||
return addGuardReceiverPolymorphic(obj, receiverShapes, receiverUnboxedGroups);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -10787,7 +10787,7 @@ IonBuilder::getPropTryInlineAccess(bool *emitted, MDefinition *obj, PropertyName
|
|||
return false;
|
||||
|
||||
if (sameSlot && unboxedGroups.empty()) {
|
||||
obj = addShapeGuardPolymorphic(obj, nativeShapes, unboxedGroups);
|
||||
obj = addGuardReceiverPolymorphic(obj, nativeShapes, unboxedGroups);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
@ -11467,7 +11467,7 @@ IonBuilder::setPropTryInlineAccess(bool *emitted, MDefinition *obj,
|
|||
return false;
|
||||
|
||||
if (sameSlot && unboxedGroups.empty()) {
|
||||
obj = addShapeGuardPolymorphic(obj, nativeShapes, unboxedGroups);
|
||||
obj = addGuardReceiverPolymorphic(obj, nativeShapes, unboxedGroups);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
@ -12379,11 +12379,12 @@ IonBuilder::addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bail
|
|||
}
|
||||
|
||||
MInstruction *
|
||||
IonBuilder::addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bailoutKind)
|
||||
IonBuilder::addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bailoutKind,
|
||||
bool checkUnboxedExpando)
|
||||
{
|
||||
MGuardObjectGroup *guard = MGuardObjectGroup::New(alloc(), obj, group,
|
||||
/* bailOnEquality = */ false,
|
||||
bailoutKind);
|
||||
bailoutKind, checkUnboxedExpando);
|
||||
current->add(guard);
|
||||
|
||||
// If a shape guard failed in the past, don't optimize group guards.
|
||||
|
@ -12398,15 +12399,19 @@ IonBuilder::addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bail
|
|||
}
|
||||
|
||||
MInstruction *
|
||||
IonBuilder::addShapeGuardPolymorphic(MDefinition *obj,
|
||||
const BaselineInspector::ShapeVector &shapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups)
|
||||
IonBuilder::addGuardReceiverPolymorphic(MDefinition *obj,
|
||||
const BaselineInspector::ShapeVector &shapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups)
|
||||
{
|
||||
if (shapes.length() == 1 && unboxedGroups.empty())
|
||||
return addShapeGuard(obj, shapes[0], Bailout_ShapeGuard);
|
||||
|
||||
if (shapes.empty() && unboxedGroups.length() == 1)
|
||||
return addGroupGuard(obj, unboxedGroups[0], Bailout_ShapeGuard);
|
||||
if (shapes.empty() && unboxedGroups.length() == 1) {
|
||||
// The guard requires that unboxed objects not have expando objects.
|
||||
// An inline cache will be used in these cases.
|
||||
return addGroupGuard(obj, unboxedGroups[0], Bailout_ShapeGuard,
|
||||
/* checkUnboxedExpando = */ true);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(shapes.length() + unboxedGroups.length() > 1);
|
||||
|
||||
|
|
|
@ -398,12 +398,13 @@ class IonBuilder
|
|||
MDefinition *addMaybeCopyElementsForWrite(MDefinition *object);
|
||||
MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
|
||||
MInstruction *addShapeGuard(MDefinition *obj, Shape *const shape, BailoutKind bailoutKind);
|
||||
MInstruction *addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bailoutKind);
|
||||
MInstruction *addGroupGuard(MDefinition *obj, ObjectGroup *group, BailoutKind bailoutKind,
|
||||
bool checkUnboxedExpando = false);
|
||||
|
||||
MInstruction *
|
||||
addShapeGuardPolymorphic(MDefinition *obj,
|
||||
const BaselineInspector::ShapeVector &shapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups);
|
||||
addGuardReceiverPolymorphic(MDefinition *obj,
|
||||
const BaselineInspector::ShapeVector &shapes,
|
||||
const BaselineInspector::ObjectGroupVector &unboxedGroups);
|
||||
|
||||
MDefinition *convertShiftToMaskForStaticTypedArray(MDefinition *id,
|
||||
Scalar::Type viewType);
|
||||
|
|
|
@ -699,6 +699,41 @@ IsCacheableGetPropCallPropertyOp(JSObject *obj, JSObject *holder, Shape *shape)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
TestMatchingReceiver(MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
Register object, JSObject *obj, Label *failure,
|
||||
bool alwaysCheckGroup = false)
|
||||
{
|
||||
if (Shape *shape = obj->maybeShape()) {
|
||||
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
|
||||
Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(shape), failure);
|
||||
|
||||
if (alwaysCheckGroup)
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
|
||||
} else {
|
||||
MOZ_ASSERT(obj->is<UnboxedPlainObject>());
|
||||
MOZ_ASSERT(failure);
|
||||
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
|
||||
Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
|
||||
if (UnboxedExpandoObject *expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
|
||||
masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), failure);
|
||||
Label success;
|
||||
masm.push(object);
|
||||
masm.loadPtr(expandoAddress, object);
|
||||
masm.branchTestObjShape(Assembler::Equal, object, expando->lastProperty(),
|
||||
&success);
|
||||
masm.pop(object);
|
||||
masm.jump(failure);
|
||||
masm.bind(&success);
|
||||
masm.pop(object);
|
||||
} else {
|
||||
masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
EmitLoadSlot(MacroAssembler &masm, NativeObject *holder, Shape *shape, Register holderReg,
|
||||
TypedOrValueRegister output, Register scratchReg)
|
||||
|
@ -791,14 +826,16 @@ CheckDOMProxyExpandoDoesNotShadow(JSContext *cx, MacroAssembler &masm, JSObject
|
|||
|
||||
static void
|
||||
GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, NativeObject *holder,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, JSObject *holder,
|
||||
Shape *shape, Register object, TypedOrValueRegister output,
|
||||
Label *failures = nullptr)
|
||||
{
|
||||
// If there's a single jump to |failures|, we can patch the shape guard
|
||||
// jump directly. Otherwise, jump to the end of the stub, so there's a
|
||||
// common point to patch.
|
||||
bool multipleFailureJumps = (obj != holder) || (failures != nullptr && failures->used());
|
||||
bool multipleFailureJumps = (obj != holder)
|
||||
|| obj->is<UnboxedPlainObject>()
|
||||
|| (failures != nullptr && failures->used());
|
||||
|
||||
// If we have multiple failure jumps but didn't get a label from the
|
||||
// outside, make one ourselves.
|
||||
|
@ -806,18 +843,7 @@ GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
|||
if (multipleFailureJumps && !failures)
|
||||
failures = &failures_;
|
||||
|
||||
// Guard on the shape or type of the object, depending on whether it is native.
|
||||
if (obj->isNative()) {
|
||||
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
|
||||
Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->as<NativeObject>().lastProperty()),
|
||||
failures);
|
||||
} else {
|
||||
attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
|
||||
Address(object, JSObject::offsetOfGroup()),
|
||||
ImmGCPtr(obj->group()),
|
||||
failures);
|
||||
}
|
||||
TestMatchingReceiver(masm, attacher, object, obj, failures);
|
||||
|
||||
// If we need a scratch register, use either an output register or the
|
||||
// object register. After this point, we cannot jump directly to
|
||||
|
@ -825,7 +851,10 @@ GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
|||
bool restoreScratch = false;
|
||||
Register scratchReg = Register::FromCode(0); // Quell compiler warning.
|
||||
|
||||
if (obj != holder || !holder->isFixedSlot(shape->slot())) {
|
||||
if (obj != holder ||
|
||||
obj->is<UnboxedPlainObject>() ||
|
||||
!holder->as<NativeObject>().isFixedSlot(shape->slot()))
|
||||
{
|
||||
if (output.hasValue()) {
|
||||
scratchReg = output.valueReg().scratchReg();
|
||||
} else if (output.type() == MIRType_Double) {
|
||||
|
@ -839,7 +868,7 @@ GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
|||
|
||||
// Fast path: single failure jump, no prototype guards.
|
||||
if (!multipleFailureJumps) {
|
||||
EmitLoadSlot(masm, holder, shape, object, output, scratchReg);
|
||||
EmitLoadSlot(masm, &holder->as<NativeObject>(), shape, object, output, scratchReg);
|
||||
if (restoreScratch)
|
||||
masm.pop(scratchReg);
|
||||
attacher.jumpRejoin(masm);
|
||||
|
@ -860,7 +889,7 @@ GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
|||
masm.movePtr(ImmMaybeNurseryPtr(holder), holderReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
ImmGCPtr(holder->as<NativeObject>().lastProperty()),
|
||||
&prototypeFailures);
|
||||
} else {
|
||||
// The property does not exist. Guard on everything in the
|
||||
|
@ -883,13 +912,17 @@ GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
|||
|
||||
holderReg = InvalidReg;
|
||||
}
|
||||
} else if (obj->is<UnboxedPlainObject>()) {
|
||||
holder = obj->as<UnboxedPlainObject>().maybeExpando();
|
||||
holderReg = scratchReg;
|
||||
masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), holderReg);
|
||||
} else {
|
||||
holderReg = object;
|
||||
}
|
||||
|
||||
// Slot access.
|
||||
if (holder)
|
||||
EmitLoadSlot(masm, holder, shape, holderReg, output, scratchReg);
|
||||
EmitLoadSlot(masm, &holder->as<NativeObject>(), shape, holderReg, output, scratchReg);
|
||||
else
|
||||
masm.moveValue(UndefinedValue(), output.valueReg());
|
||||
|
||||
|
@ -1098,15 +1131,6 @@ EmitGetterCall(JSContext *cx, MacroAssembler &masm,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
TestMatchingReceiver(MacroAssembler &masm, Register object, JSObject *obj, Label *failure)
|
||||
{
|
||||
if (Shape *shape = obj->maybeShape())
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, shape, failure);
|
||||
else
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
|
||||
}
|
||||
|
||||
static bool
|
||||
GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, PropertyName *name,
|
||||
|
@ -1119,7 +1143,7 @@ GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
|||
Label stubFailure;
|
||||
failures = failures ? failures : &stubFailure;
|
||||
|
||||
TestMatchingReceiver(masm, object, obj, failures);
|
||||
TestMatchingReceiver(masm, attacher, object, obj, failures);
|
||||
|
||||
Register scratchReg = output.valueReg().scratchReg();
|
||||
bool spillObjReg = scratchReg == object;
|
||||
|
@ -1428,6 +1452,35 @@ GetPropertyIC::tryAttachUnboxed(JSContext *cx, HandleScript outerScript, IonScri
|
|||
return linkAndAttachStub(cx, masm, attacher, ion, "read unboxed");
|
||||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachUnboxedExpando(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted)
|
||||
{
|
||||
MOZ_ASSERT(canAttachStub());
|
||||
MOZ_ASSERT(!*emitted);
|
||||
MOZ_ASSERT(outerScript->ionScript() == ion);
|
||||
|
||||
if (!obj->is<UnboxedPlainObject>())
|
||||
return true;
|
||||
Rooted<UnboxedExpandoObject *> expando(cx, obj->as<UnboxedPlainObject>().maybeExpando());
|
||||
if (!expando)
|
||||
return true;
|
||||
|
||||
Shape *shape = expando->lookup(cx, name);
|
||||
if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
|
||||
return true;
|
||||
|
||||
*emitted = true;
|
||||
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, obj,
|
||||
shape, object(), output());
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "read unboxed expando");
|
||||
}
|
||||
|
||||
bool
|
||||
GetPropertyIC::tryAttachTypedArrayLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool *emitted)
|
||||
|
@ -1867,6 +1920,9 @@ GetPropertyIC::tryAttachStub(JSContext *cx, HandleScript outerScript, IonScript
|
|||
if (!*emitted && !tryAttachUnboxed(cx, outerScript, ion, obj, name, returnAddr, emitted))
|
||||
return false;
|
||||
|
||||
if (!*emitted && !tryAttachUnboxedExpando(cx, outerScript, ion, obj, name, returnAddr, emitted))
|
||||
return false;
|
||||
|
||||
if (!*emitted && !tryAttachTypedArrayLength(cx, outerScript, ion, obj, name, emitted))
|
||||
return false;
|
||||
|
||||
|
@ -1997,37 +2053,33 @@ CheckTypeSetForWrite(MacroAssembler &masm, JSObject *obj, jsid id,
|
|||
|
||||
static void
|
||||
GenerateSetSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
NativeObject *obj, Shape *shape, Register object, ConstantOrRegister value,
|
||||
JSObject *obj, Shape *shape, Register object, ConstantOrRegister value,
|
||||
bool needsTypeBarrier, bool checkTypeset)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
Label failures, failurePopObject;
|
||||
|
||||
Label failures, barrierFailure;
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(object, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(obj->lastProperty()), &failures);
|
||||
TestMatchingReceiver(masm, attacher, object, obj, &failures, needsTypeBarrier);
|
||||
|
||||
// Guard that the incoming value is in the type set for the property
|
||||
// if a type barrier is required.
|
||||
if (needsTypeBarrier) {
|
||||
// We can't do anything that would change the HeapTypeSet, so
|
||||
// just guard that it's already there.
|
||||
|
||||
// Obtain and guard on the ObjectGroup of the object.
|
||||
ObjectGroup *group = obj->group();
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(object, JSObject::offsetOfGroup()),
|
||||
ImmGCPtr(group), &failures);
|
||||
|
||||
if (checkTypeset) {
|
||||
masm.push(object);
|
||||
CheckTypeSetForWrite(masm, obj, shape->propid(), object, value, &barrierFailure);
|
||||
CheckTypeSetForWrite(masm, obj, shape->propid(), object, value, &failurePopObject);
|
||||
masm.pop(object);
|
||||
}
|
||||
}
|
||||
|
||||
NativeObject::slotsSizeMustNotOverflow();
|
||||
if (obj->isFixedSlot(shape->slot())) {
|
||||
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
obj = obj->as<UnboxedPlainObject>().maybeExpando();
|
||||
masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), object);
|
||||
}
|
||||
|
||||
if (obj->as<NativeObject>().isFixedSlot(shape->slot())) {
|
||||
Address addr(object, NativeObject::getFixedSlotOffset(shape->slot()));
|
||||
|
||||
if (cx->zone()->needsIncrementalBarrier())
|
||||
|
@ -2038,7 +2090,7 @@ GenerateSetSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
Register slotsReg = object;
|
||||
masm.loadPtr(Address(object, NativeObject::offsetOfSlots()), slotsReg);
|
||||
|
||||
Address addr(slotsReg, obj->dynamicSlotIndex(shape->slot()) * sizeof(Value));
|
||||
Address addr(slotsReg, obj->as<NativeObject>().dynamicSlotIndex(shape->slot()) * sizeof(Value));
|
||||
|
||||
if (cx->zone()->needsIncrementalBarrier())
|
||||
masm.callPreBarrier(addr, MIRType_Value);
|
||||
|
@ -2048,8 +2100,8 @@ GenerateSetSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
|
||||
attacher.jumpRejoin(masm);
|
||||
|
||||
if (barrierFailure.used()) {
|
||||
masm.bind(&barrierFailure);
|
||||
if (failurePopObject.used()) {
|
||||
masm.bind(&failurePopObject);
|
||||
masm.pop(object);
|
||||
}
|
||||
|
||||
|
@ -2059,7 +2111,7 @@ GenerateSetSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
|
||||
bool
|
||||
SetPropertyIC::attachSetSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleNativeObject obj, HandleShape shape, bool checkTypeset)
|
||||
HandleObject obj, HandleShape shape, bool checkTypeset)
|
||||
{
|
||||
MacroAssembler masm(cx, ion, outerScript, profilerLeavePc_);
|
||||
RepatchStubAppender attacher(*this);
|
||||
|
@ -2663,7 +2715,7 @@ SetPropertyIC::attachCallSetter(JSContext *cx, HandleScript outerScript, IonScri
|
|||
RepatchStubAppender attacher(*this);
|
||||
|
||||
Label failure;
|
||||
TestMatchingReceiver(masm, object(), obj, &failure);
|
||||
TestMatchingReceiver(masm, attacher, object(), obj, &failure);
|
||||
|
||||
if (!GenerateCallSetter(cx, ion, masm, attacher, obj, holder, shape, strict(),
|
||||
object(), value(), &failure, liveRegs_, returnAddr))
|
||||
|
@ -2683,31 +2735,42 @@ SetPropertyIC::attachCallSetter(JSContext *cx, HandleScript outerScript, IonScri
|
|||
|
||||
static void
|
||||
GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
NativeObject *obj, Shape *oldShape, ObjectGroup *oldGroup,
|
||||
JSObject *obj, Shape *oldShape, ObjectGroup *oldGroup,
|
||||
Register object, ConstantOrRegister value,
|
||||
bool checkTypeset)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
Label failures, failuresPopObject;
|
||||
|
||||
Label failures;
|
||||
// Use a modified version of TestMatchingReceiver that uses the old shape and group.
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, object, oldGroup, &failures);
|
||||
if (obj->maybeShape()) {
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, oldShape, &failures);
|
||||
} else {
|
||||
MOZ_ASSERT(obj->is<UnboxedPlainObject>());
|
||||
|
||||
// Guard the type of the object
|
||||
masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfGroup()),
|
||||
ImmGCPtr(oldGroup), &failures);
|
||||
Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
|
||||
masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), &failures);
|
||||
|
||||
// Guard shapes along prototype chain.
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, oldShape, &failures);
|
||||
masm.push(object);
|
||||
masm.loadPtr(expandoAddress, object);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, object, oldShape, &failuresPopObject);
|
||||
masm.pop(object);
|
||||
}
|
||||
|
||||
Shape *newShape = obj->maybeShape();
|
||||
if (!newShape)
|
||||
newShape = obj->as<UnboxedPlainObject>().maybeExpando()->lastProperty();
|
||||
|
||||
Label failuresPopObject;
|
||||
masm.push(object); // save object reg because we clobber it
|
||||
|
||||
// Guard that the incoming value is in the type set for the property
|
||||
// if a type barrier is required.
|
||||
if (checkTypeset) {
|
||||
CheckTypeSetForWrite(masm, obj, obj->lastProperty()->propid(), object, value, &failuresPopObject);
|
||||
CheckTypeSetForWrite(masm, obj, newShape->propid(), object, value, &failuresPopObject);
|
||||
masm.loadPtr(Address(StackPointer, 0), object);
|
||||
}
|
||||
|
||||
// Guard shapes along prototype chain.
|
||||
JSObject *proto = obj->getProto();
|
||||
Register protoReg = object;
|
||||
while (proto) {
|
||||
|
@ -2724,14 +2787,19 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
|
||||
masm.pop(object); // restore object reg
|
||||
|
||||
// Changing object shape. Write the object's new shape.
|
||||
Shape *newShape = obj->lastProperty();
|
||||
// Write the object or expando object's new shape.
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
obj = obj->as<UnboxedPlainObject>().maybeExpando();
|
||||
masm.loadPtr(Address(object, UnboxedPlainObject::offsetOfExpando()), object);
|
||||
}
|
||||
Address shapeAddr(object, JSObject::offsetOfShape());
|
||||
if (cx->zone()->needsIncrementalBarrier())
|
||||
masm.callPreBarrier(shapeAddr, MIRType_Shape);
|
||||
masm.storePtr(ImmGCPtr(newShape), shapeAddr);
|
||||
|
||||
if (oldGroup != obj->group()) {
|
||||
MOZ_ASSERT(!obj->is<UnboxedPlainObject>());
|
||||
|
||||
// Changing object's group from a partially to fully initialized group,
|
||||
// per the acquired properties analysis. Only change the group if the
|
||||
// old group still has a newScript.
|
||||
|
@ -2759,7 +2827,7 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
// Set the value on the object. Since this is an add, obj->lastProperty()
|
||||
// must be the shape of the property we are adding.
|
||||
NativeObject::slotsSizeMustNotOverflow();
|
||||
if (obj->isFixedSlot(newShape->slot())) {
|
||||
if (obj->as<NativeObject>().isFixedSlot(newShape->slot())) {
|
||||
Address addr(object, NativeObject::getFixedSlotOffset(newShape->slot()));
|
||||
masm.storeConstantOrRegister(value, addr);
|
||||
} else {
|
||||
|
@ -2767,7 +2835,7 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
|
||||
masm.loadPtr(Address(object, NativeObject::offsetOfSlots()), slotsReg);
|
||||
|
||||
Address addr(slotsReg, obj->dynamicSlotIndex(newShape->slot()) * sizeof(Value));
|
||||
Address addr(slotsReg, obj->as<NativeObject>().dynamicSlotIndex(newShape->slot()) * sizeof(Value));
|
||||
masm.storeConstantOrRegister(value, addr);
|
||||
}
|
||||
|
||||
|
@ -2784,7 +2852,7 @@ GenerateAddSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &att
|
|||
|
||||
bool
|
||||
SetPropertyIC::attachAddSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleNativeObject obj, HandleShape oldShape, HandleObjectGroup oldGroup,
|
||||
HandleObject obj, HandleShape oldShape, HandleObjectGroup oldGroup,
|
||||
bool checkTypeset)
|
||||
{
|
||||
MOZ_ASSERT_IF(!needsTypeBarrier(), !checkTypeset);
|
||||
|
@ -2860,7 +2928,33 @@ IsPropertySetInlineable(NativeObject *obj, HandleId id, MutableHandleShape pshap
|
|||
}
|
||||
|
||||
static bool
|
||||
IsPropertyAddInlineable(NativeObject *obj, HandleId id, ConstantOrRegister val, uint32_t oldSlots,
|
||||
PrototypeChainShadowsPropertyAdd(JSObject *obj, jsid id)
|
||||
{
|
||||
// Walk up the object prototype chain and ensure that all prototypes
|
||||
// are native, and that all prototypes have no getter or setter
|
||||
// defined on the property
|
||||
for (JSObject *proto = obj->getProto(); proto; proto = proto->getProto()) {
|
||||
// If prototype is non-native, don't optimize
|
||||
if (!proto->isNative())
|
||||
return true;
|
||||
|
||||
// If prototype defines this property in a non-plain way, don't optimize
|
||||
Shape *protoShape = proto->as<NativeObject>().lookupPure(id);
|
||||
if (protoShape && !protoShape->hasDefaultSetter())
|
||||
return true;
|
||||
|
||||
// Otherwise, if there's no such property, watch out for a resolve
|
||||
// hook that would need to be invoked and thus prevent inlining of
|
||||
// property addition.
|
||||
if (proto->getClass()->resolve)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsPropertyAddInlineable(NativeObject *obj, HandleId id, ConstantOrRegister val,
|
||||
HandleShape oldShape, bool needsTypeBarrier, bool *checkTypeset)
|
||||
{
|
||||
// If the shape of the object did not change, then this was not an add.
|
||||
|
@ -2886,35 +2980,18 @@ IsPropertyAddInlineable(NativeObject *obj, HandleId id, ConstantOrRegister val,
|
|||
if (!obj->nonProxyIsExtensible() || !shape->writable())
|
||||
return false;
|
||||
|
||||
// Walk up the object prototype chain and ensure that all prototypes
|
||||
// are native, and that all prototypes have no getter or setter
|
||||
// defined on the property
|
||||
for (JSObject *proto = obj->getProto(); proto; proto = proto->getProto()) {
|
||||
// If prototype is non-native, don't optimize
|
||||
if (!proto->isNative())
|
||||
return false;
|
||||
|
||||
// If prototype defines this property in a non-plain way, don't optimize
|
||||
Shape *protoShape = proto->as<NativeObject>().lookupPure(id);
|
||||
if (protoShape && !protoShape->hasDefaultSetter())
|
||||
return false;
|
||||
|
||||
// Otherwise, if there's no such property, watch out for a resolve
|
||||
// hook that would need to be invoked and thus prevent inlining of
|
||||
// property addition.
|
||||
if (proto->getClass()->resolve)
|
||||
return false;
|
||||
}
|
||||
if (PrototypeChainShadowsPropertyAdd(obj, id))
|
||||
return false;
|
||||
|
||||
// Only add a IC entry if the dynamic slots didn't change when the shapes
|
||||
// changed. Need to ensure that a shape change for a subsequent object
|
||||
// won't involve reallocating the slot array.
|
||||
if (obj->numDynamicSlots() != oldSlots)
|
||||
if (obj->numDynamicSlots() != NativeObject::dynamicSlotsCount(oldShape))
|
||||
return false;
|
||||
|
||||
// Don't attach if we are adding a property to an object which the new
|
||||
// script properties analysis hasn't been performed for yet, as there
|
||||
// may be a shape change required here afterwards.
|
||||
// may be a group change required here afterwards.
|
||||
if (obj->group()->newScript() && !obj->group()->newScript()->analyzed())
|
||||
return false;
|
||||
|
||||
|
@ -2946,7 +3023,7 @@ CanAttachNativeSetProp(JSContext *cx, HandleObject obj, HandleId id, ConstantOrR
|
|||
// a stub to add the property until we do the VM call to add. If the
|
||||
// property exists as a data property on the prototype, we should add
|
||||
// a new, shadowing property.
|
||||
if (!shape || (obj != holder && shape->hasDefaultSetter() && shape->hasSlot()))
|
||||
if (obj->isNative() && (!shape || (obj != holder && shape->hasDefaultSetter() && shape->hasSlot())))
|
||||
return SetPropertyIC::MaybeCanAttachAddSlot;
|
||||
|
||||
if (IsImplicitNonNativeProperty(shape))
|
||||
|
@ -3041,6 +3118,58 @@ CanAttachSetUnboxed(JSContext *cx, HandleObject obj, HandleId id, ConstantOrRegi
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CanAttachSetUnboxedExpando(JSContext *cx, HandleObject obj, HandleId id, ConstantOrRegister val,
|
||||
bool needsTypeBarrier, bool *checkTypeset, Shape **pshape)
|
||||
{
|
||||
if (!obj->is<UnboxedPlainObject>())
|
||||
return false;
|
||||
|
||||
Rooted<UnboxedExpandoObject *> expando(cx, obj->as<UnboxedPlainObject>().maybeExpando());
|
||||
if (!expando)
|
||||
return false;
|
||||
|
||||
Shape *shape = expando->lookupPure(id);
|
||||
if (!shape || !shape->hasDefaultSetter() || !shape->hasSlot() || !shape->writable())
|
||||
return false;
|
||||
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
*pshape = shape;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CanAttachAddUnboxedExpando(JSContext *cx, HandleObject obj, HandleShape oldShape,
|
||||
HandleId id, ConstantOrRegister val,
|
||||
bool needsTypeBarrier, bool *checkTypeset)
|
||||
{
|
||||
if (!obj->is<UnboxedPlainObject>())
|
||||
return false;
|
||||
|
||||
Rooted<UnboxedExpandoObject *> expando(cx, obj->as<UnboxedPlainObject>().maybeExpando());
|
||||
if (!expando || expando->inDictionaryMode())
|
||||
return false;
|
||||
|
||||
Shape *newShape = expando->lastProperty();
|
||||
if (newShape->propid() != id || newShape->previous() != oldShape)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(newShape->hasDefaultSetter() && newShape->hasSlot() && newShape->writable());
|
||||
|
||||
if (PrototypeChainShadowsPropertyAdd(obj, id))
|
||||
return false;
|
||||
|
||||
if (NativeObject::dynamicSlotsCount(oldShape) != NativeObject::dynamicSlotsCount(newShape))
|
||||
return false;
|
||||
|
||||
if (needsTypeBarrier && !CanInlineSetPropTypeCheck(obj, id, val, checkTypeset))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex, HandleObject obj,
|
||||
HandleValue value)
|
||||
|
@ -3109,9 +3238,9 @@ SetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex
|
|||
checkTypeset = false;
|
||||
uint32_t unboxedOffset;
|
||||
JSValueType unboxedType;
|
||||
if (!addedSetterStub && CanAttachSetUnboxed(cx, obj, id, cache.value(),
|
||||
cache.needsTypeBarrier(),
|
||||
&checkTypeset, &unboxedOffset, &unboxedType))
|
||||
if (!addedSetterStub &&
|
||||
CanAttachSetUnboxed(cx, obj, id, cache.value(), cache.needsTypeBarrier(),
|
||||
&checkTypeset, &unboxedOffset, &unboxedType))
|
||||
{
|
||||
if (!cache.attachSetUnboxed(cx, outerScript, ion, obj, id, unboxedOffset, unboxedType,
|
||||
checkTypeset))
|
||||
|
@ -3120,10 +3249,23 @@ SetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex
|
|||
}
|
||||
addedSetterStub = true;
|
||||
}
|
||||
|
||||
checkTypeset = false;
|
||||
if (!addedSetterStub &&
|
||||
CanAttachSetUnboxedExpando(cx, obj, id, cache.value(), cache.needsTypeBarrier(),
|
||||
&checkTypeset, shape.address()))
|
||||
{
|
||||
if (!cache.attachSetSlot(cx, outerScript, ion, obj, shape, checkTypeset))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t oldSlots = obj->is<NativeObject>() ? obj->as<NativeObject>().numDynamicSlots() : 0;
|
||||
RootedShape oldShape(cx, obj->maybeShape());
|
||||
if (!oldShape) {
|
||||
if (UnboxedExpandoObject *expando = obj->as<UnboxedPlainObject>().maybeExpando())
|
||||
oldShape = expando->lastProperty();
|
||||
}
|
||||
|
||||
// Set/Add the property on the object, the inlined cache are setup for the next execution.
|
||||
if (!SetProperty(cx, obj, name, value, cache.strict(), cache.pc()))
|
||||
|
@ -3132,12 +3274,20 @@ SetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex
|
|||
// The property did not exist before, now we can try to inline the property add.
|
||||
bool checkTypeset;
|
||||
if (!addedSetterStub && canCache == MaybeCanAttachAddSlot &&
|
||||
IsPropertyAddInlineable(&obj->as<NativeObject>(), id,
|
||||
cache.value(), oldSlots, oldShape, cache.needsTypeBarrier(),
|
||||
&checkTypeset))
|
||||
IsPropertyAddInlineable(&obj->as<NativeObject>(), id, cache.value(), oldShape,
|
||||
cache.needsTypeBarrier(), &checkTypeset))
|
||||
{
|
||||
RootedNativeObject nobj(cx, &obj->as<NativeObject>());
|
||||
if (!cache.attachAddSlot(cx, outerScript, ion, nobj, oldShape, oldGroup, checkTypeset))
|
||||
if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
|
||||
checkTypeset = false;
|
||||
if (!addedSetterStub && cache.canAttachStub() &&
|
||||
CanAttachAddUnboxedExpando(cx, obj, oldShape, id, cache.value(),
|
||||
cache.needsTypeBarrier(), &checkTypeset))
|
||||
{
|
||||
if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset))
|
||||
return false;
|
||||
addedSetterStub = true;
|
||||
}
|
||||
|
|
|
@ -670,6 +670,10 @@ class GetPropertyIC : public RepatchIonCache
|
|||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachUnboxedExpando(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name,
|
||||
void *returnAddr, bool *emitted);
|
||||
|
||||
bool tryAttachTypedArrayLength(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandlePropertyName name, bool *emitted);
|
||||
|
||||
|
@ -739,14 +743,14 @@ class SetPropertyIC : public RepatchIonCache
|
|||
};
|
||||
|
||||
bool attachSetSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleNativeObject obj, HandleShape shape, bool checkTypeset);
|
||||
HandleObject obj, HandleShape shape, bool checkTypeset);
|
||||
|
||||
bool attachCallSetter(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleObject obj, HandleObject holder, HandleShape shape,
|
||||
void *returnAddr);
|
||||
|
||||
bool attachAddSlot(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
HandleNativeObject obj, HandleShape oldShape, HandleObjectGroup oldGroup,
|
||||
HandleObject obj, HandleShape oldShape, HandleObjectGroup oldGroup,
|
||||
bool checkTypeset);
|
||||
|
||||
bool attachSetUnboxed(JSContext *cx, HandleScript outerScript, IonScript *ion,
|
||||
|
|
|
@ -184,6 +184,8 @@ LoopUnroller::go(LoopIterationBound *bound)
|
|||
// the original header.
|
||||
for (size_t i = 0; i < remainingIterationsInequality.numTerms(); i++) {
|
||||
MDefinition *def = remainingIterationsInequality.term(i).term;
|
||||
if (def->isDiscarded())
|
||||
return;
|
||||
if (def->block()->id() < header->id())
|
||||
continue;
|
||||
if (def->block() == header && def->isPhi())
|
||||
|
|
|
@ -5024,7 +5024,8 @@ AddGroupGuard(TempAllocator &alloc, MBasicBlock *current, MDefinition *obj,
|
|||
|
||||
if (key->isGroup()) {
|
||||
guard = MGuardObjectGroup::New(alloc, obj, key->group(), bailOnEquality,
|
||||
Bailout_ObjectIdentityOrTypeGuard);
|
||||
Bailout_ObjectIdentityOrTypeGuard,
|
||||
/* checkUnboxedExpando = */ false);
|
||||
} else {
|
||||
MConstant *singletonConst = MConstant::NewConstraintlessObject(alloc, key->singleton());
|
||||
current->add(singletonConst);
|
||||
|
|
|
@ -7494,7 +7494,7 @@ class MElements
|
|||
AliasSet getAliasSet() const MOZ_OVERRIDE {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
bool mightAlias(const MDefinition *store) const;
|
||||
bool mightAlias(const MDefinition *store) const MOZ_OVERRIDE;
|
||||
|
||||
ALLOW_CLONE(MElements)
|
||||
};
|
||||
|
@ -7682,7 +7682,7 @@ class MInitializedLength
|
|||
AliasSet getAliasSet() const MOZ_OVERRIDE {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
bool mightAlias(const MDefinition *store) const;
|
||||
bool mightAlias(const MDefinition *store) const MOZ_OVERRIDE;
|
||||
|
||||
void computeRange(TempAllocator &alloc) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -8186,7 +8186,7 @@ class MLoadElement
|
|||
AliasSet getAliasSet() const MOZ_OVERRIDE {
|
||||
return AliasSet::Load(AliasSet::Element);
|
||||
}
|
||||
bool mightAlias(const MDefinition *store) const;
|
||||
bool mightAlias(const MDefinition *store) const MOZ_OVERRIDE;
|
||||
|
||||
ALLOW_CLONE(MLoadElement)
|
||||
};
|
||||
|
@ -10160,13 +10160,15 @@ class MGuardObjectGroup
|
|||
AlwaysTenured<ObjectGroup *> group_;
|
||||
bool bailOnEquality_;
|
||||
BailoutKind bailoutKind_;
|
||||
bool checkUnboxedExpando_;
|
||||
|
||||
MGuardObjectGroup(MDefinition *obj, ObjectGroup *group, bool bailOnEquality,
|
||||
BailoutKind bailoutKind)
|
||||
BailoutKind bailoutKind, bool checkUnboxedExpando)
|
||||
: MUnaryInstruction(obj),
|
||||
group_(group),
|
||||
bailOnEquality_(bailOnEquality),
|
||||
bailoutKind_(bailoutKind)
|
||||
bailoutKind_(bailoutKind),
|
||||
checkUnboxedExpando_(checkUnboxedExpando)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
|
@ -10181,8 +10183,10 @@ class MGuardObjectGroup
|
|||
INSTRUCTION_HEADER(GuardObjectGroup)
|
||||
|
||||
static MGuardObjectGroup *New(TempAllocator &alloc, MDefinition *obj, ObjectGroup *group,
|
||||
bool bailOnEquality, BailoutKind bailoutKind) {
|
||||
return new(alloc) MGuardObjectGroup(obj, group, bailOnEquality, bailoutKind);
|
||||
bool bailOnEquality, BailoutKind bailoutKind,
|
||||
bool checkUnboxedExpando) {
|
||||
return new(alloc) MGuardObjectGroup(obj, group, bailOnEquality, bailoutKind,
|
||||
checkUnboxedExpando);
|
||||
}
|
||||
|
||||
MDefinition *obj() const {
|
||||
|
@ -10197,6 +10201,9 @@ class MGuardObjectGroup
|
|||
BailoutKind bailoutKind() const {
|
||||
return bailoutKind_;
|
||||
}
|
||||
bool checkUnboxedExpando() const {
|
||||
return checkUnboxedExpando_;
|
||||
}
|
||||
bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE {
|
||||
if (!ins->isGuardObjectGroup())
|
||||
return false;
|
||||
|
|
|
@ -1373,8 +1373,7 @@ MacroAssembler::initGCThing(Register obj, Register temp, JSObject *templateObj,
|
|||
offset += sizeof(uintptr_t);
|
||||
}
|
||||
} else if (templateObj->is<UnboxedPlainObject>()) {
|
||||
storePtr(ImmWord(0), Address(obj, JSObject::offsetOfShape()));
|
||||
|
||||
storePtr(ImmWord(0), Address(obj, UnboxedPlainObject::offsetOfExpando()));
|
||||
if (initContents)
|
||||
initUnboxedObjectContents(obj, &templateObj->as<UnboxedPlainObject>());
|
||||
} else {
|
||||
|
|
|
@ -1662,6 +1662,13 @@ CodeGeneratorARM::visitGuardObjectGroup(LGuardObjectGroup *guard)
|
|||
{
|
||||
Register obj = ToRegister(guard->input());
|
||||
Register tmp = ToRegister(guard->tempInt());
|
||||
MOZ_ASSERT(obj != tmp);
|
||||
|
||||
if (guard->mir()->checkUnboxedExpando()) {
|
||||
masm.ma_ldr(DTRAddr(obj, DtrOffImm(UnboxedPlainObject::offsetOfExpando())), tmp);
|
||||
masm.ma_cmp(tmp, ImmWord(0));
|
||||
bailoutIf(Assembler::NotEqual, guard->snapshot());
|
||||
}
|
||||
|
||||
masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfGroup())), tmp);
|
||||
masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->group()));
|
||||
|
|
|
@ -1751,6 +1751,12 @@ CodeGeneratorMIPS::visitGuardObjectGroup(LGuardObjectGroup *guard)
|
|||
{
|
||||
Register obj = ToRegister(guard->input());
|
||||
Register tmp = ToRegister(guard->tempInt());
|
||||
MOZ_ASSERT(obj != tmp);
|
||||
|
||||
if (guard->mir()->checkUnboxedExpando()) {
|
||||
masm.loadPtr(Address(obj, UnboxedPlainObject::offsetOfExpando()), tmp);
|
||||
bailoutCmpPtr(Assembler::NotEqual, tmp, ImmWord(0), guard->snapshot());
|
||||
}
|
||||
|
||||
masm.loadPtr(Address(obj, JSObject::offsetOfGroup()), tmp);
|
||||
Assembler::Condition cond = guard->mir()->bailOnEquality()
|
||||
|
|
|
@ -226,8 +226,6 @@ class ImmMaybeNurseryPtr
|
|||
public:
|
||||
explicit ImmMaybeNurseryPtr(const gc::Cell *ptr) : value(ptr)
|
||||
{
|
||||
MOZ_ASSERT(!IsPoisonedPtr(ptr));
|
||||
|
||||
// asm.js shouldn't be creating GC things
|
||||
MOZ_ASSERT(!IsCompilingAsmJS());
|
||||
}
|
||||
|
@ -257,7 +255,6 @@ class ImmGCPtr
|
|||
|
||||
explicit ImmGCPtr(const gc::Cell *ptr) : value(ptr)
|
||||
{
|
||||
MOZ_ASSERT(!IsPoisonedPtr(ptr));
|
||||
MOZ_ASSERT_IF(ptr, ptr->isTenured());
|
||||
|
||||
// asm.js shouldn't be creating GC things
|
||||
|
@ -266,7 +263,6 @@ class ImmGCPtr
|
|||
|
||||
explicit ImmGCPtr(IonNurseryPtr ptr) : value(ptr.ptr)
|
||||
{
|
||||
MOZ_ASSERT(!IsPoisonedPtr(value));
|
||||
MOZ_ASSERT(value);
|
||||
|
||||
// asm.js shouldn't be creating GC things
|
||||
|
@ -279,8 +275,6 @@ class ImmGCPtr
|
|||
friend class AssemblerShared;
|
||||
explicit ImmGCPtr(ImmMaybeNurseryPtr ptr) : value(ptr.value)
|
||||
{
|
||||
MOZ_ASSERT(!IsPoisonedPtr(ptr.value));
|
||||
|
||||
// asm.js shouldn't be creating GC things
|
||||
MOZ_ASSERT(!IsCompilingAsmJS());
|
||||
}
|
||||
|
|
|
@ -2070,6 +2070,12 @@ void
|
|||
CodeGeneratorX86Shared::visitGuardObjectGroup(LGuardObjectGroup *guard)
|
||||
{
|
||||
Register obj = ToRegister(guard->input());
|
||||
|
||||
if (guard->mir()->checkUnboxedExpando()) {
|
||||
masm.cmpPtr(Address(obj, UnboxedPlainObject::offsetOfExpando()), ImmWord(0));
|
||||
bailoutIf(Assembler::NotEqual, guard->snapshot());
|
||||
}
|
||||
|
||||
masm.cmpPtr(Operand(obj, JSObject::offsetOfGroup()), ImmGCPtr(guard->mir()->group()));
|
||||
|
||||
Assembler::Condition cond =
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче