Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-03-19 14:18:10 +01:00
Родитель 7bbf025233 f8581d6c76
Коммит 903d3e15d5
157 изменённых файлов: 2431 добавлений и 2139 удалений

Просмотреть файл

@ -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("&amp;"));
NS_ENSURE_TRUE(sValue.ReplaceSubstring(NS_LITERAL_STRING("&"),
NS_LITERAL_STRING("&amp;"), mozilla::fallible), false);
if (bIncludesDouble && bIncludesSingle) {
sValue.ReplaceSubstring(NS_LITERAL_STRING("\""),
NS_LITERAL_STRING("&quot;"));
NS_ENSURE_TRUE(sValue.ReplaceSubstring(NS_LITERAL_STRING("\""),
NS_LITERAL_STRING("&quot;"), 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[] = {
"&lt;", "", "&gt;"
};
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 =

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше