import changes from tenfourfox:

- #375, Bug 1112537 - Optimize String#split('foo').join('bar') pattern. (includes M1235403) r=nbp (36326dfa2)
- #415: M1373195 backport (e880223af)
- #415: M1376936 M1375331 (33344c644)
- #415: M1348095 (consolidated) (d1001e7ef)
- #413: update to HTML colspan/rowspan from M1359822, plus M1271126 + M1373095 (no tests) (6958789e8)
- #416: M1366903 M1371283 M1368576 (baaf2ee89)
- #416: M1368105 (1efa1540f)
- checkin additional JS tests (687ba7579)
- #416: M1374047 M1365413 M1369913 M1371424 M1346590 M1376087 M1322896 M1354796 M1365333 M1373970 M1355168 (1bc1dd390)
- #416: M1265568 M1305036 (257cfd929)
- #419: M1377329 (fb72079d0)
- #418: M1333106 M1337672 (b1cfd7830)
- #416: M1362924 (61ec43889)
- #416: M1365189 M1365875 (d9876efcf)
- #416: M1378147 M1371890 M1380426 (177c87d34)
- #416: note to self on M1377426 (5bcd1c461)
- fix debug bustage, shutdown crash (be4d0ed86)
- #414: new wildcard based blacklist, updated strings (6ccb443e7)
- #416: update certs/pins (797260262)
- fix FontDirWrapper off-by-one bugs and warnings (51e6a2cf9)
- 104fx_copy should also allow copying debug builds (054bbf081)
- #416: M1383000 M1376459 M1372467 M1372383 M1383002 (2f4742e52)
- #416: M1308908 M1342433(no tests) (5757a9534)
- #416: M1368362 (1cf170047)
- #72: additional debugging (0683827d2)
- #416: M1381016 M1371657 (afc820240)
- #416: update certs for FPR2 final (4ca64d74e)
- M1257208 Fix build errors with gcc >= 5 (4c64d8d6d)
with additional nsINode* to nsTextNode* change in ResetDir() in DirectionalityUtils.cpp
This commit is contained in:
2018-05-29 23:38:55 +08:00
parent a291b79d58
commit 50ff970e7e
80 changed files with 5388 additions and 1540 deletions
+1 -2
View File
@@ -597,8 +597,7 @@ static void
MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
{
NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
if (aAtkObj->name &&
!strncmp(aAtkObj->name, newNameUTF8.get(), newNameUTF8.Length()))
if (aAtkObj->name && !strcmp(aAtkObj->name, newNameUTF8.get()))
return;
// Below we duplicate the functionality of atk_object_set_name(),
+7 -10
View File
@@ -314,16 +314,13 @@ nsAccessibilityService::ListenersChanged(nsIArray* aEventChanges)
nsIDocument* ownerDoc = node->OwnerDoc();
DocAccessible* document = GetExistingDocAccessible(ownerDoc);
// Always recreate for onclick changes.
if (document) {
if (nsCoreUtils::HasClickListener(node)) {
if (!document->GetAccessible(node)) {
document->RecreateAccessible(node);
}
} else {
if (document->GetAccessible(node)) {
document->RecreateAccessible(node);
}
// Create an accessible for a inaccessible element having click event
// handler.
if (document && !document->HasAccessible(node) &&
nsCoreUtils::HasClickListener(node)) {
nsIContent* parentEl = node->GetFlattenedTreeParent();
if (parentEl) {
document->ContentInserted(parentEl, node, node->GetNextSibling());
}
break;
}
+23 -2
View File
@@ -11317,6 +11317,21 @@ nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, nsISupports* aOwner,
(void)AddToSessionHistory(aURI, aChannel, aOwner, aCloneSHChildren,
getter_AddRefs(mLSHE));
}
} else if (mSessionHistory && mLSHE && mURIResultedInDocument) {
// Even if we don't add anything to SHistory, ensure the current index
// points to the same SHEntry as our mLSHE.
int32_t index = 0;
mSessionHistory->GetRequestedIndex(&index);
if (index == -1) {
mSessionHistory->GetIndex(&index);
}
nsCOMPtr<nsISHEntry> currentSH;
mSessionHistory->GetEntryAtIndex(index, false, getter_AddRefs(currentSH));
if (currentSH != mLSHE) {
nsCOMPtr<nsISHistoryInternal> shPrivate =
do_QueryInterface(mSessionHistory);
shPrivate->ReplaceEntry(index, mLSHE);
}
}
// If this is a POST request, we do not want to include this in global
@@ -13861,9 +13876,15 @@ DocShellOriginAttributes
nsDocShell::GetOriginAttributes()
{
DocShellOriginAttributes attrs;
nsCOMPtr<nsIDocument> doc;
// It is possible to have a null document. If so, act as if we are
// the topmost docshell, since this usually occurs on shutdown.
RefPtr<nsDocShell> parent = GetParentDocshell();
if (parent) {
nsCOMPtr<nsIPrincipal> parentPrin = parent->GetDocument()->NodePrincipal();
if (MOZ_LIKELY(parent))
doc = parent->GetDocument();
if (MOZ_LIKELY(doc)) {
nsCOMPtr<nsIPrincipal> parentPrin = doc->NodePrincipal();
PrincipalOriginAttributes poa = BasePrincipal::Cast(parentPrin)->OriginAttributesRef();
attrs.InheritFromDocToChildDocShell(poa);
} else {
+75 -34
View File
@@ -209,6 +209,7 @@
#include "nsINode.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/Element.h"
#include "nsIDOMHTMLDocument.h"
@@ -386,7 +387,7 @@ GetDirectionFromText(const nsTextFragment* aFrag,
* know not to return it
* @return the text node containing the character that determined the direction
*/
static nsINode*
static nsTextNode*
WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true,
nsINode* aChangedNode = nullptr)
{
@@ -412,7 +413,7 @@ WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true,
// We found a descendant text node with strong directional characters.
// Set the directionality of aElement to the corresponding value.
aElement->SetDirectionality(textNodeDir, aNotify);
return child;
return static_cast<nsTextNode*>(child);
}
}
child = child->GetNextNode(aElement);
@@ -441,6 +442,7 @@ class nsTextNodeDirectionalityMap
public:
explicit nsTextNodeDirectionalityMap(nsINode* aTextNode)
: mElementToBeRemoved(nullptr)
{
MOZ_ASSERT(aTextNode, "Null text node");
MOZ_COUNT_CTOR(nsTextNodeDirectionalityMap);
@@ -454,27 +456,54 @@ public:
MOZ_COUNT_DTOR(nsTextNodeDirectionalityMap);
}
void AddEntry(nsINode* aTextNode, Element* aElement)
static void
nsTextNodeDirectionalityMapPropertyDestructor(void* aObject,
nsIAtom* aProperty,
void* aPropertyValue,
void* aData)
{
nsTextNode* textNode =
static_cast<nsTextNode*>(aPropertyValue);
nsTextNodeDirectionalityMap* map = GetDirectionalityMap(textNode);
if (map) {
map->RemoveEntryForProperty(static_cast<Element*>(aObject));
}
NS_RELEASE(textNode);
}
void AddEntry(nsTextNode* aTextNode, Element* aElement)
{
if (!mElements.Contains(aElement)) {
mElements.Put(aElement);
aElement->SetProperty(nsGkAtoms::dirAutoSetBy, aTextNode);
NS_ADDREF(aTextNode);
aElement->SetProperty(nsGkAtoms::dirAutoSetBy, aTextNode,
nsTextNodeDirectionalityMapPropertyDestructor);
aElement->SetHasDirAutoSet();
}
}
void RemoveEntry(nsINode* aTextNode, Element* aElement)
void RemoveEntry(nsTextNode* aTextNode, Element* aElement)
{
NS_ASSERTION(mElements.Contains(aElement),
"element already removed from map");
mElements.Remove(aElement);
aElement->ClearHasDirAutoSet();
aElement->UnsetProperty(nsGkAtoms::dirAutoSetBy);
aElement->DeleteProperty(nsGkAtoms::dirAutoSetBy);
}
void RemoveEntryForProperty(Element* aElement)
{
if (mElementToBeRemoved != aElement) {
mElements.Remove(aElement);
}
aElement->ClearHasDirAutoSet();
}
private:
nsCheapSet<nsPtrHashKey<Element> > mElements;
nsCheapSet<nsPtrHashKey<Element>> mElements;
// Only used for comparison.
Element* mElementToBeRemoved;
static nsTextNodeDirectionalityMap* GetDirectionalityMap(nsINode* aTextNode)
{
@@ -498,18 +527,29 @@ private:
return OpNext;
}
struct nsTextNodeDirectionalityMapAndElement
{
nsTextNodeDirectionalityMap* mMap;
nsCOMPtr<nsINode> mNode;
};
static nsCheapSetOperator ResetNodeDirection(nsPtrHashKey<Element>* aEntry, void* aData)
{
MOZ_ASSERT(aEntry->GetKey()->IsElement(), "Must be an Element");
// run the downward propagation algorithm
// and remove the text node from the map
nsINode* oldTextNode = static_cast<Element*>(aData);
nsTextNodeDirectionalityMapAndElement* data =
static_cast<nsTextNodeDirectionalityMapAndElement*>(aData);
nsINode* oldTextNode = data->mNode;
Element* rootNode = aEntry->GetKey();
nsINode* newTextNode = nullptr;
nsTextNode* newTextNode = nullptr;
if (rootNode->GetParentNode() && rootNode->HasDirAuto()) {
newTextNode = WalkDescendantsSetDirectionFromText(rootNode, true,
oldTextNode);
}
AutoRestore<Element*> restore(data->mMap->mElementToBeRemoved);
data->mMap->mElementToBeRemoved = rootNode;
if (newTextNode) {
nsINode* oldDirAutoSetBy =
static_cast<nsTextNode*>(rootNode->GetProperty(nsGkAtoms::dirAutoSetBy));
@@ -520,7 +560,7 @@ private:
nsTextNodeDirectionalityMap::AddEntryToMap(newTextNode, rootNode);
} else {
rootNode->ClearHasDirAutoSet();
rootNode->UnsetProperty(nsGkAtoms::dirAutoSetBy);
rootNode->DeleteProperty(nsGkAtoms::dirAutoSetBy);
}
return OpRemove;
}
@@ -529,7 +569,7 @@ private:
{
Element* rootNode = aEntry->GetKey();
rootNode->ClearHasDirAutoSet();
rootNode->UnsetProperty(nsGkAtoms::dirAutoSetBy);
rootNode->DeleteProperty(nsGkAtoms::dirAutoSetBy);
return OpRemove;
}
@@ -541,24 +581,26 @@ public:
void ResetAutoDirection(nsINode* aTextNode)
{
mElements.EnumerateEntries(ResetNodeDirection, aTextNode);
nsTextNodeDirectionalityMapAndElement data = { this, aTextNode };
mElements.EnumerateEntries(ResetNodeDirection, &data);
}
void EnsureMapIsClear(nsINode* aTextNode)
{
AutoRestore<Element*> restore(mElementToBeRemoved);
DebugOnly<uint32_t> clearedEntries =
mElements.EnumerateEntries(ClearEntry, aTextNode);
MOZ_ASSERT(clearedEntries == 0, "Map should be empty already");
}
static void RemoveElementFromMap(nsINode* aTextNode, Element* aElement)
static void RemoveElementFromMap(nsTextNode* aTextNode, Element* aElement)
{
if (aTextNode->HasTextNodeDirectionalityMap()) {
GetDirectionalityMap(aTextNode)->RemoveEntry(aTextNode, aElement);
}
}
static void AddEntryToMap(nsINode* aTextNode, Element* aElement)
static void AddEntryToMap(nsTextNode* aTextNode, Element* aElement)
{
nsTextNodeDirectionalityMap* map = GetDirectionalityMap(aTextNode);
if (!map) {
@@ -576,12 +618,13 @@ public:
return GetDirectionalityMap(aTextNode)->UpdateAutoDirection(aDir);
}
static void ResetTextNodeDirection(nsINode* aTextNode,
nsINode* aChangedTextNode)
static void ResetTextNodeDirection(nsTextNode* aTextNode,
nsTextNode* aChangedTextNode)
{
MOZ_ASSERT(aTextNode->HasTextNodeDirectionalityMap(),
"Map missing in ResetTextNodeDirection");
GetDirectionalityMap(aTextNode)->ResetAutoDirection(aChangedTextNode);
RefPtr<nsTextNode> textNode = aTextNode;
GetDirectionalityMap(textNode)->ResetAutoDirection(aChangedTextNode);
}
static void EnsureMapIsClearFor(nsINode* aTextNode)
@@ -651,7 +694,7 @@ SetDirectionalityOnDescendants(Element* aElement, Directionality aDir,
void
WalkAncestorsResetAutoDirection(Element* aElement, bool aNotify)
{
nsINode* setByNode;
nsTextNode* setByNode;
Element* parent = aElement->GetParentElement();
while (parent && parent->NodeOrAncestorHasDirAuto()) {
@@ -661,7 +704,7 @@ WalkAncestorsResetAutoDirection(Element* aElement, bool aNotify)
// Remove it from the map and reset its direction by the downward
// propagation algorithm
setByNode =
static_cast<nsINode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
static_cast<nsTextNode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
if (setByNode) {
nsTextNodeDirectionalityMap::RemoveElementFromMap(setByNode, parent);
}
@@ -687,11 +730,9 @@ WalkDescendantsResetAutoDirection(Element* aElement)
continue;
}
if (child->HasTextNodeDirectionalityMap()) {
nsTextNodeDirectionalityMap::ResetTextNodeDirection(child, nullptr);
// Don't call nsTextNodeDirectionalityMap::EnsureMapIsClearFor(child)
// since ResetTextNodeDirection may have kept elements in child's
// DirectionalityMap.
if (child->NodeType() == nsIDOMNode::TEXT_NODE &&
child->HasTextNodeDirectionalityMap()) {
nsTextNodeDirectionalityMap::ResetTextNodeDirection(static_cast<nsTextNode*>(child), nullptr);
}
child = child->GetNextNode(aElement);
}
@@ -733,7 +774,7 @@ WalkDescendantsSetDirAuto(Element* aElement, bool aNotify)
}
}
nsINode* textNode = WalkDescendantsSetDirectionFromText(aElement, aNotify);
nsTextNode* textNode = WalkDescendantsSetDirectionFromText(aElement, aNotify);
if (textNode) {
nsTextNodeDirectionalityMap::AddEntryToMap(textNode, aElement);
}
@@ -754,7 +795,7 @@ WalkDescendantsClearAncestorDirAuto(Element* aElement)
}
}
void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir,
void SetAncestorDirectionIfAuto(nsTextNode* aTextNode, Directionality aDir,
bool aNotify = true)
{
MOZ_ASSERT(aTextNode->NodeType() == nsIDOMNode::TEXT_NODE,
@@ -768,8 +809,8 @@ void SetAncestorDirectionIfAuto(nsINode* aTextNode, Directionality aDir,
if (parent->HasDirAuto()) {
bool resetDirection = false;
nsINode* directionWasSetByTextNode =
static_cast<nsINode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
nsTextNode* directionWasSetByTextNode =
static_cast<nsTextNode*>(parent->GetProperty(nsGkAtoms::dirAutoSetBy));
if (!parent->HasDirAutoSet()) {
// Fast path if parent's direction is not yet set by any descendant
@@ -840,7 +881,7 @@ TextNodeWillChangeDirection(nsIContent* aTextNode, Directionality* aOldDir,
}
void
TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
TextNodeChangedDirection(nsTextNode* aTextNode, Directionality aOldDir,
bool aNotify)
{
Directionality newDir = GetDirectionFromText(aTextNode->GetText());
@@ -870,7 +911,7 @@ TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
}
void
SetDirectionFromNewTextNode(nsIContent* aTextNode)
SetDirectionFromNewTextNode(nsTextNode* aTextNode)
{
if (!NodeAffectsDirAutoAncestor(aTextNode)) {
return;
@@ -957,8 +998,8 @@ OnSetDirAttr(Element* aElement, const nsAttrValue* aNewValue,
WalkDescendantsSetDirAuto(aElement, aNotify);
} else {
if (aElement->HasDirAutoSet()) {
nsINode* setByNode =
static_cast<nsINode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
nsTextNode* setByNode =
static_cast<nsTextNode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
nsTextNodeDirectionalityMap::RemoveElementFromMap(setByNode, aElement);
}
SetDirectionalityOnDescendants(aElement,
@@ -1009,8 +1050,8 @@ SetDirOnBind(mozilla::dom::Element* aElement, nsIContent* aParent)
void ResetDir(mozilla::dom::Element* aElement)
{
if (aElement->HasDirAutoSet()) {
nsINode* setByNode =
static_cast<nsINode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
nsTextNode* setByNode =
static_cast<nsTextNode*>(aElement->GetProperty(nsGkAtoms::dirAutoSetBy));
nsTextNodeDirectionalityMap::RemoveElementFromMap(setByNode, aElement);
}
+2 -2
View File
@@ -89,14 +89,14 @@ bool TextNodeWillChangeDirection(nsIContent* aTextNode, Directionality* aOldDir,
* After the contents of a text node have changed, change the directionality
* of any elements whose directionality is determined by that node
*/
void TextNodeChangedDirection(nsIContent* aTextNode, Directionality aOldDir,
void TextNodeChangedDirection(nsTextNode* aTextNode, Directionality aOldDir,
bool aNotify);
/**
* When a text node is appended to an element, find any ancestors with dir=auto
* whose directionality will be determined by the text node
*/
void SetDirectionFromNewTextNode(nsIContent* aTextNode);
void SetDirectionFromNewTextNode(nsTextNode* aTextNode);
/**
* When a text node is removed from a document, find any ancestors whose
+1
View File
@@ -3102,6 +3102,7 @@ static nsIAtom** sPropertiesToTraverseAndUnlink[] =
&nsGkAtoms::itemprop,
&nsGkAtoms::sandbox,
&nsGkAtoms::sizes,
&nsGkAtoms::dirAutoSetBy,
nullptr
};
+13 -5
View File
@@ -10,6 +10,7 @@
#include "jsapi.h"
#include "jsfriendapi.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/net/WebSocketChannel.h"
#include "mozilla/dom/File.h"
@@ -610,6 +611,10 @@ WebSocketImpl::Disconnect()
AssertIsOnTargetThread();
// DontKeepAliveAnyMore() and DisconnectInternal() can release the object. So
// hold a reference to this until the end of the method.
RefPtr<WebSocketImpl> kungfuDeathGrip = this;
// Disconnect can be called from some control event (such as Notify() of
// WorkerFeature). This will be schedulated before any other sync/async
// runnable. In order to prevent some double Disconnect() calls, we use this
@@ -631,10 +636,6 @@ WebSocketImpl::Disconnect()
rv.SuppressException();
}
// DontKeepAliveAnyMore() can release the object. So hold a reference to this
// until the end of the method.
RefPtr<WebSocketImpl> kungfuDeathGrip = this;
NS_ReleaseOnMainThread(mChannel);
NS_ReleaseOnMainThread(static_cast<nsIWebSocketEventService*>(mService.forget().take()));
@@ -2380,7 +2381,14 @@ WebSocket::Send(nsIInputStream* aMsgStream,
}
// Always increment outgoing buffer len, even if closed
mOutgoingBufferedAmount += aMsgLength;
CheckedUint32 size = mOutgoingBufferedAmount;
size += aMsgLength;
if (MOZ_UNLIKELY(!size.isValid())) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
mOutgoingBufferedAmount = size.value();
if (readyState == CLOSING ||
readyState == CLOSED) {
+34
View File
@@ -1491,6 +1491,40 @@ nsAttrValue::ParseIntWithBounds(const nsAString& aString,
return true;
}
void
nsAttrValue::ParseClampedNonNegativeInt(const nsAString& aString,
int32_t aDefault, int32_t aMin,
int32_t aMax)
{
ResetIfSet();
nsContentUtils::ParseHTMLIntegerResultFlags result;
int32_t val = nsContentUtils::ParseHTMLInteger(aString, &result);
bool nonStrict = (result & nsContentUtils::eParseHTMLInteger_IsPercent) ||
(result & nsContentUtils::eParseHTMLInteger_NonStandard) ||
(result & nsContentUtils::eParseHTMLInteger_DidNotConsumeAllInput);
if (result & nsContentUtils::eParseHTMLInteger_ErrorOverflow) {
if (result & nsContentUtils::eParseHTMLInteger_Negative) {
val = aDefault;
} else {
val = aMax;
}
nonStrict = true;
} else if ((result & nsContentUtils::eParseHTMLInteger_Error) || val < 0) {
val = aDefault;
nonStrict = true;
} else if (val < aMin) {
val = aMin;
nonStrict = true;
} else if (val > aMax) {
val = aMax;
nonStrict = true;
}
SetIntValueAndType(val, eInteger, nonStrict ? &aString : nullptr);
}
bool
nsAttrValue::ParseNonNegativeIntValue(const nsAString& aString)
{
+13
View File
@@ -326,6 +326,19 @@ public:
*/
bool ParseNonNegativeIntValue(const nsAString& aString);
/**
* Parse a string value into a clamped non-negative integer.
* This method follows the rules for parsing non-negative integer from:
* https://html.spec.whatwg.org/multipage/infrastructure.html#clamped-to-the-range
*
* @param aString the string to parse
* @param aDefault value to return for negative or invalid values
* @param aMin minimum value
* @param aMax maximum value
*/
void ParseClampedNonNegativeInt(const nsAString& aString, int32_t aDefault,
int32_t aMin, int32_t aMax);
/**
* Parse a string value into a positive integer.
* This method follows the rules for parsing non-negative integer from:
+13 -1
View File
@@ -92,7 +92,8 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBaseContentList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBaseContentList)
NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsBaseContentList,
LastRelease())
NS_IMETHODIMP
@@ -612,6 +613,17 @@ nsContentList::NodeWillBeDestroyed(const nsINode* aNode)
SetDirty();
}
void
nsContentList::LastRelease()
{
RemoveFromCaches();
if (mRootNode) {
mRootNode->RemoveMutationObserver(this);
mRootNode = nullptr;
}
SetDirty();
}
NS_IMETHODIMP
nsContentList::GetLength(uint32_t* aLength)
{
+5
View File
@@ -95,6 +95,9 @@ public:
{
mElements.SetCapacity(aCapacity);
}
virtual void LastRelease() {}
protected:
virtual ~nsBaseContentList();
@@ -348,6 +351,8 @@ public:
Reset();
}
virtual void LastRelease() override;
protected:
/**
* Returns whether the element matches our criterion
+6 -12
View File
@@ -1057,9 +1057,10 @@ nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
return 0;
}
bool negate = false;
int sign = 1;
if (*iter == char16_t('-')) {
negate = true;
sign = -1;
result |= eParseHTMLInteger_Negative;
++iter;
} else if (*iter == char16_t('+')) {
result |= eParseHTMLInteger_NonStandard;
@@ -1083,7 +1084,7 @@ nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
while (iter != end) {
if (*iter >= char16_t('0') && *iter <= char16_t('9')) {
value = (value * 10) + (*iter - char16_t('0'));
value = (value * 10) + (*iter - char16_t('0')) * sign;
++iter;
if (!value.isValid()) {
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
@@ -1104,16 +1105,9 @@ nsContentUtils::ParseHTMLInteger(const nsAString& aValue,
result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
}
if (value.isValid() && negate) {
value = -value;
// Checking the special case of -0.
if (value == 0) {
result |= eParseHTMLInteger_NonStandard;
}
}
if (value.isValid() &&
(leadingZeros > 1 || (leadingZeros == 1 && !(value == 0)))) {
((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
(sign == -1 && value == 0))) {
result |= eParseHTMLInteger_NonStandard;
}
+3 -1
View File
@@ -439,7 +439,9 @@ public:
// Set if one or more error flags were set.
eParseHTMLInteger_Error = 1 << 3,
eParseHTMLInteger_ErrorNoValue = 1 << 4,
eParseHTMLInteger_ErrorOverflow = 1 << 5
eParseHTMLInteger_ErrorOverflow = 1 << 5,
// Use this flag to detect the difference between overflow and underflow
eParseHTMLInteger_Negative = 1 << 6,
};
static int32_t ParseHTMLInteger(const nsAString& aValue,
ParseHTMLIntegerResultFlags *aResult);
+3
View File
@@ -2826,6 +2826,9 @@ nsDocument::InitCSP(nsIChannel* aChannel)
NS_ENSURE_SUCCESS(rv, rv);
}
// XXX. When we implement CSP sandbox (bug 671389), we need to also
// add bugs 1073952 and 1377426 to avoid a nasty hole.
// ----- Enforce frame-ancestor policy on any applied policies
nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
if (docShell) {
+4 -1
View File
@@ -371,7 +371,10 @@ nsGenericDOMDataNode::SetTextInternal(uint32_t aOffset, uint32_t aCount,
}
if (dirAffectsAncestor) {
TextNodeChangedDirection(this, oldDir, aNotify);
// dirAffectsAncestor being true implies that we have a text node, see
// above.
MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE);
TextNodeChangedDirection(static_cast<nsTextNode*>(this), oldDir, aNotify);
}
// Notify observers
+5 -2
View File
@@ -1615,8 +1615,11 @@ public:
"ClearHasTextNodeDirectionalityMap on non-text node");
ClearBoolFlag(NodeHasTextNodeDirectionalityMap);
}
bool HasTextNodeDirectionalityMap() const
{ return GetBoolFlag(NodeHasTextNodeDirectionalityMap); }
bool HasTextNodeDirectionalityMap() const {
MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
"HasTextNodeDirectionalityMap on non-text node");
return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
}
void SetHasDirAuto() { SetBoolFlag(NodeHasDirAuto); }
void ClearHasDirAuto() { ClearBoolFlag(NodeHasDirAuto); }
+10 -3
View File
@@ -148,15 +148,22 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
}
{
nsAutoScriptBlocker scriptBlocker;
// Calling Notify on observers can modify the list of observers so make
// a local copy.
nsAutoTArray<nsCOMPtr<imgINotificationObserver>, 2> observers;
for (ImageObserver* observer = &mObserverList, *next; observer;
observer = next) {
next = observer->mNext;
if (observer->mObserver) {
observer->mObserver->Notify(aRequest, aType, aData);
observers.AppendElement(observer->mObserver);
}
}
nsAutoScriptBlocker scriptBlocker;
for (auto& observer : observers) {
observer->Notify(aRequest, aType, aData);
}
}
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
+1
View File
@@ -49,6 +49,7 @@ public:
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
using mozilla::dom::Text::GetParentElement;
// nsIDOMCharacterData
NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
+3 -1
View File
@@ -44,11 +44,13 @@ protected:
public:
inline void TraceSelf(JSTracer* trc)
{
// XXX: Until we implement something like bug 1235598 (and its successor
// bug 1238786), we need these null checks.
if (mTypedObj) {
JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mTypedObj");
}
if (mWrappedObj) {
JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mWrappedObj");
JS_CallUnbarrieredObjectTracer(trc, &mWrappedObj, "TypedArray.mWrappedObj");
}
}
+10 -5
View File
@@ -4812,7 +4812,17 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
return;
}
// Flush layout updates
if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
nsContentUtils::FlushLayoutForTree(&window);
}
EnsureTarget();
if (!IsTargetValid()) {
return;
}
// We can't allow web apps to call this until we fix at least the
// following potential security issues:
// -- rendering cross-domain IFRAMEs and then extracting the results
@@ -4826,11 +4836,6 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
return;
}
// Flush layout updates
if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
nsContentUtils::FlushLayoutForTree(&window);
}
RefPtr<nsPresContext> presContext;
nsIDocShell* docshell = window.GetDocShell();
if (docshell) {
+7 -2
View File
@@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/StructuredCloneTags.h"
@@ -132,10 +133,14 @@ CropAndCopyDataSourceSurface(DataSourceSurface* aSurface, const IntRect& aCropRe
+ surfPortion.x * bytesPerPixel;
uint8_t* dstBufferPtr = dstMap.GetData() + dest.y * dstMap.GetStride()
+ dest.x * bytesPerPixel;
const uint32_t copiedBytesPerRaw = surfPortion.width * bytesPerPixel;
CheckedInt<uint32_t> copiedBytesPerRaw =
CheckedInt<uint32_t>(surfPortion.width) * bytesPerPixel;
if (MOZ_UNLIKELY(!copiedBytesPerRaw.isValid())) {
return nullptr;
}
for (int i = 0; i < surfPortion.height; ++i) {
memcpy(dstBufferPtr, srcBufferPtr, copiedBytesPerRaw);
memcpy(dstBufferPtr, srcBufferPtr, copiedBytesPerRaw.value());
srcBufferPtr += srcMap.GetStride();
dstBufferPtr += dstMap.GetStride();
}
+7 -19
View File
@@ -384,28 +384,16 @@ HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
return aResult.ParseIntWithBounds(aValue, 0);
}
if (aAttribute == nsGkAtoms::colspan) {
bool res = aResult.ParseIntWithBounds(aValue, -1);
if (res) {
int32_t val = aResult.GetIntegerValue();
// reset large colspan values as IE and opera do
// quirks mode does not honor the special html 4 value of 0
if (val > MAX_COLSPAN || val < 0 ||
(0 == val && InNavQuirksMode(OwnerDoc()))) {
aResult.SetTo(1, &aValue);
}
}
return res;
aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
return true;
}
if (aAttribute == nsGkAtoms::rowspan) {
bool res = aResult.ParseIntWithBounds(aValue, -1, MAX_ROWSPAN);
if (res) {
int32_t val = aResult.GetIntegerValue();
// quirks mode does not honor the special html 4 value of 0
if (val < 0 || (0 == val && InNavQuirksMode(OwnerDoc()))) {
aResult.SetTo(1, &aValue);
}
aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
// quirks mode does not honor the special html 4 value of 0
if (aResult.GetIntegerValue() == 0 && InNavQuirksMode(OwnerDoc())) {
aResult.SetTo(1, &aValue);
}
return res;
return true;
}
if (aAttribute == nsGkAtoms::height) {
return aResult.ParseSpecialIntValue(aValue);
+2 -2
View File
@@ -37,7 +37,7 @@ public:
}
void SetColSpan(uint32_t aColSpan, ErrorResult& aError)
{
SetHTMLIntAttr(nsGkAtoms::colspan, aColSpan, aError);
SetUnsignedIntAttr(nsGkAtoms::colspan, aColSpan, aError);
}
uint32_t RowSpan() const
{
@@ -45,7 +45,7 @@ public:
}
void SetRowSpan(uint32_t aRowSpan, ErrorResult& aError)
{
SetHTMLIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
SetUnsignedIntAttr(nsGkAtoms::rowspan, aRowSpan, aError);
}
//already_AddRefed<nsDOMSettableTokenList> Headers() const;
void GetHeaders(DOMString& aHeaders)
+8 -3
View File
@@ -597,12 +597,17 @@ ImageDocument::UpdateSizeFromLayout()
{
// Pull an updated size from the content frame to account for any size
// change due to CSS properties like |image-orientation|.
Element* contentElement = mImageContent->AsElement();
if (!contentElement) {
if (!mImageContent) {
return;
}
nsIFrame* contentFrame = contentElement->GetPrimaryFrame(Flush_Frames);
// Need strong ref, because GetPrimaryFrame can run script.
nsCOMPtr<Element> imageContent = mImageContent->AsElement();
if (!imageContent) {
return;
}
nsIFrame* contentFrame = imageContent->GetPrimaryFrame(Flush_Frames);
if (!contentFrame) {
return;
}
+18 -3
View File
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "mozilla/ArrayUtils.h"
#include "nsGkAtoms.h"
#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
#include "nsCRT.h"
#include "nsLayoutStylesheetCache.h"
#include "nsRuleData.h"
@@ -150,8 +151,10 @@ nsMathMLElement::ParseAttribute(int32_t aNamespaceID,
const nsAString& aValue,
nsAttrValue& aResult)
{
MOZ_ASSERT(IsMathMLElement());
if (aNamespaceID == kNameSpaceID_None) {
if (IsMathMLElement(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
if (mNodeInfo->Equals(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
WarnDeprecated(nsGkAtoms::mode->GetUTF16String(),
nsGkAtoms::display->GetUTF16String(), OwnerDoc());
}
@@ -165,6 +168,16 @@ nsMathMLElement::ParseAttribute(int32_t aNamespaceID,
aAttribute == nsGkAtoms::mathbackground_) {
return aResult.ParseColor(aValue);
}
if (mNodeInfo->Equals(nsGkAtoms::mtd_)) {
if (aAttribute == nsGkAtoms::columnspan_) {
aResult.ParseClampedNonNegativeInt(aValue, 1, 1, MAX_COLSPAN);
return true;
}
if (aAttribute == nsGkAtoms::rowspan) {
aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
return true;
}
}
}
return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
@@ -209,6 +222,8 @@ static Element::MappedAttributeEntry sDirStyles[] = {
bool
nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
MOZ_ASSERT(IsMathMLElement());
static const MappedAttributeEntry* const mtableMap[] = {
sMtableStyles,
sCommonPresStyles
@@ -240,10 +255,10 @@ nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
if (IsAnyOfMathMLElements(nsGkAtoms::mstyle_, nsGkAtoms::math))
return FindAttributeDependence(aAttribute, mstyleMap);
if (IsMathMLElement(nsGkAtoms::mtable_))
if (mNodeInfo->Equals(nsGkAtoms::mtable_))
return FindAttributeDependence(aAttribute, mtableMap);
if (IsMathMLElement(nsGkAtoms::mrow_))
if (mNodeInfo->Equals(nsGkAtoms::mrow_))
return FindAttributeDependence(aAttribute, mrowMap);
if (IsAnyOfMathMLElements(nsGkAtoms::maction_,
+2
View File
@@ -154,6 +154,8 @@ nsHTMLEditor::~nsHTMLEditor()
}
RemoveEventListeners();
HideAnonymousEditingUIs();
}
void
+6
View File
@@ -403,6 +403,12 @@ public:
*/
virtual bool RequiresLinearZoom() { return false; }
/**
* Whether the frame->StyleFont().mFont.smoothing field is respected by
* text rendering on this platform.
*/
virtual bool RespectsFontStyleSmoothing() const { return false; }
/**
* Whether to check all font cmaps during system font fallback
*/
+20
View File
@@ -181,6 +181,24 @@ gfxPlatformMac::MakePlatformFont(const nsAString& aFontName,
aLength);
}
// Automates a whole buncha boilerplate.
// Since HTTPS is becoming more common, check that first.
#define HTTP_OR_HTTPS_SUBDIR(x) \
{ \
if (!failed) { \
NS_NAMED_LITERAL_CSTRING(https_, "https://" x); \
spec.Left(loc, https_.Length()); \
if (loc.Equals(https_)) { \
failed = true; \
} else { \
NS_NAMED_LITERAL_CSTRING(http_, "http://" x); \
spec.Left(loc, http_.Length()); \
if (loc.Equals(http_)) \
failed = true; \
} \
} \
}
bool
gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
{
@@ -203,6 +221,8 @@ gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
return true;
}
#undef HTTP_OR_HTTPS_SUBDIR
// these will also move to gfxPlatform once all platforms support the fontlist
nsresult
gfxPlatformMac::GetFontList(nsIAtom *aLangGroup,
+5
View File
@@ -83,6 +83,11 @@ public:
return true;
}
bool RespectsFontStyleSmoothing() const override {
// gfxMacFont respects the font smoothing hint.
return true;
}
bool RequiresAcceleratedGLContextForCompositorOGL() const override {
// On OS X in a VM, unaccelerated CompositorOGL shows black flashes, so we
// require accelerated GL for CompositorOGL but allow unaccelerated GL for
+23 -5
View File
@@ -116,6 +116,10 @@ static const int kSurrogateRangeCount = ArrayLength(kSurrogateRanges);
static const int kLineTerminatorRanges[] = { 0x000A, 0x000B, 0x000D, 0x000E,
0x2028, 0x202A, 0x10000 };
static const int kLineTerminatorRangeCount = ArrayLength(kLineTerminatorRanges);
// bug 1373195
static const int kLineTerminatorAndSurrogateRanges[] = { 0x000A, 0x000B,
0x000D, 0x000E, 0x2028, 0x202A, 0xD800, 0xE000, 0x10000 };
static const int kLineTerminatorAndSurrogateRangeCount = ArrayLength(kLineTerminatorAndSurrogateRanges);
static const int kMaxOneByteCharCode = 0xff;
static const int kMaxUtf16CodeUnit = 0xffff;
@@ -137,10 +141,10 @@ AddClass(const int* elmv, int elmc,
}
}
static void
AddClassNegated(const int* elmv,
int elmc,
CharacterRangeVector* ranges)
void
js::irregexp::AddClassNegated(const int* elmv,
int elmc,
CharacterRangeVector* ranges)
{
elmc--;
MOZ_ASSERT(elmv[elmc] == 0x10000);
@@ -275,7 +279,7 @@ static const size_t kEcma262UnCanonicalizeMaxWidth = 4;
// Returns the number of characters in the equivalence class, omitting those
// that cannot occur in the source string if it is a one byte string.
static int
static MOZ_ALWAYS_INLINE int
GetCaseIndependentLetters(char16_t character,
bool ascii_subject,
bool unicode,
@@ -378,6 +382,10 @@ CharacterRange::AddCaseEquivalents(bool is_ascii, bool unicode, CharacterRangeVe
return;
if (top > kMaxOneByteCharCode)
top = kMaxOneByteCharCode;
} else {
// Nothing to do for surrogates.
if (bottom >= unicode::LeadSurrogateMin && top <= unicode::TrailSurrogateMax)
return;
}
for (char16_t c = bottom;; c++) {
@@ -917,7 +925,17 @@ void TextNode::MakeCaseIndependent(bool is_ascii, bool unicode)
if (cc->is_standard(alloc()))
continue;
// Similarly, there's nothing to do for the character class
// containing all characters except line terminators and surrogates.
// This one is added by UnicodeEverythingAtom.
CharacterRangeVector& ranges = cc->ranges(alloc());
if (CompareInverseRanges(ranges,
kLineTerminatorAndSurrogateRanges,
kLineTerminatorAndSurrogateRangeCount))
{
continue;
}
int range_count = ranges.length();
for (int j = 0; j < range_count; j++)
ranges[j].AddCaseEquivalents(is_ascii, unicode, &ranges);
+3
View File
@@ -1508,6 +1508,9 @@ class Analysis : public NodeVisitor
void operator=(Analysis&) = delete;
};
void
AddClassNegated(const int* elmv, int elmc, CharacterRangeVector* ranges);
} } // namespace js::irregexp
#endif // V8_JSREGEXP_H_
+11 -5
View File
@@ -35,6 +35,14 @@
using namespace js;
using namespace js::irregexp;
// Bug 1373195 put these into RegExpCharacters, but we don't have that
// in this version of irregexp, so this should be kept in sync with
// RegExpEngine.
static const int kLineTerminatorAndSurrogateRanges[] = { 0x000A, 0x000B,
0x000D, 0x000E, 0x2028, 0x202A, 0xD800, 0xE000, 0x10000 };
static const int kLineTerminatorAndSurrogateRangeCount = 9;
// ----------------------------------------------------------------------------
// RegExpBuilder
@@ -1335,11 +1343,9 @@ UnicodeEverythingAtom(LifoAlloc* alloc)
// everything except \x0a, \x0d, \u2028 and \u2029
CharacterRangeVector* ranges = alloc->newInfallible<CharacterRangeVector>(*alloc);
ranges->append(CharacterRange::Range(0x0, 0x09));
ranges->append(CharacterRange::Range(0x0b, 0x0c));
ranges->append(CharacterRange::Range(0x0e, 0x2027));
ranges->append(CharacterRange::Range(0x202A, unicode::LeadSurrogateMin - 1));
ranges->append(CharacterRange::Range(unicode::TrailSurrogateMax + 1, unicode::UTF16Max));
AddClassNegated(kLineTerminatorAndSurrogateRanges,
kLineTerminatorAndSurrogateRangeCount,
ranges);
builder->AddAtom(alloc->newInfallible<RegExpCharacterClass>(ranges, false));
builder->NewAlternative();
@@ -0,0 +1,18 @@
var lfLogBuffer = `
function f() {
var i32 = new Int32Array(1);
var f32 = new Float32Array(i32.buffer);
for (var i = 0; i < 3; i++) {
var { regExp, get, } = gczeal(9,10)
? (yield) : (yield) = call(f32, "i32.store", []);
}
}
f();
`;
loadFile(lfLogBuffer);
function loadFile(lfVarx) {
try {
oomTest(function() { eval(lfVarx); });
} catch (lfVare) {}
}
+21
View File
@@ -72,6 +72,24 @@ function split_join_4(i) {
return i;
}
function split_join_5(i) {
var s = "abca";
assertEq(s.split("a").join("") + i, "bc" + i);
}
function split_join_two_byte_char(i) {
var s1 = "ab";
assertEq(s1.split("").join("\u03c0"), "a\u03c0b");
var s2 = i + "\u03c0" + i;
assertEq(s2.split("\u03c0").join("-"), i + "-" + i);
}
function split_join_underflow(i)
{
var s = "";
assertEq(s.split("").join("x" + i), "");
}
// Check that we do not consider the string argument of join as a replacement
// pattern, as the string replace primitive is supposed to do.
function split_join_pattern(i) {
@@ -104,6 +122,9 @@ for (var i = 0; i < 100; ++i) {
split_join_2(i);
split_join_3(i);
split_join_4(i);
split_join_5(i);
split_join_pattern(i);
split_join_multiple(i);
split_join_two_byte_char(i);
split_join_underflow(i);
}
@@ -0,0 +1,9 @@
var re = /f...................................../i;
var t = new Date;
print("foo".match(re));
print(new Date - t);
var re = /f...................................../ui;
var t = new Date;
print("foo".match(re));
print(new Date - t);
@@ -0,0 +1,10 @@
var str = "i";
for (var i = 1; i < 100; i++ ) {
str += "-i";
str += "->i";
}
for(var i = 0; i < 40000; i++ )
if (i % 2 == 0)
str = str.split("-").join(">");
else
str = str.split(">").join("-");
+5 -1
View File
@@ -1660,6 +1660,7 @@ CodeGenerator::visitRegExpReplace(LRegExpReplace* lir)
}
typedef JSString* (*StringReplaceFn)(JSContext*, HandleString, HandleString, HandleString);
static const VMFunction StringFlatReplaceInfo = FunctionInfo<StringReplaceFn>(js::str_flat_replace_string);
static const VMFunction StringReplaceInfo = FunctionInfo<StringReplaceFn>(StringReplace);
void
@@ -1680,7 +1681,10 @@ CodeGenerator::visitStringReplace(LStringReplace* lir)
else
pushArg(ToRegister(lir->string()));
callVM(StringReplaceInfo, lir);
if (lir->mir()->isFlatReplacement())
callVM(StringFlatReplaceInfo, lir);
else
callVM(StringReplaceInfo, lir);
}
void
+5
View File
@@ -1293,6 +1293,11 @@ IonBuilder::addOsrValueTypeBarrier(uint32_t slot, MInstruction** def_,
osrBlock->insertBefore(osrBlock->lastIns(), barrier);
osrBlock->rewriteSlot(slot, barrier);
def = barrier;
// If the TypeSet is more precise than |type|, adjust |type| for the
// code below.
if (type == MIRType_Value)
type = barrier->type();
} else if (type == MIRType_Null ||
type == MIRType_Undefined ||
type == MIRType_MagicOptimizedArguments)
+8 -6
View File
@@ -4843,20 +4843,20 @@ MTableSwitch::foldsTo(TempAllocator& alloc)
MDefinition*
MArrayJoin::foldsTo(TempAllocator& alloc)
{
// :TODO: Enable this optimization after fixing Bug 977966 test cases.
return this;
MDefinition* arr = array();
if (!arr->isStringSplit())
return this;
this->setRecoveredOnBailout();
setRecoveredOnBailout();
if (arr->hasLiveDefUses()) {
this->setNotRecoveredOnBailout();
setNotRecoveredOnBailout();
return this;
}
// The MStringSplit won't generate any code.
arr->setRecoveredOnBailout();
// We're replacing foo.split(bar).join(baz) by
// foo.replace(bar, baz). MStringSplit could be recovered by
// a bailout. As we are removing its last use, and its result
@@ -4867,7 +4867,9 @@ MArrayJoin::foldsTo(TempAllocator& alloc)
MDefinition* replacement = sep();
setNotRecoveredOnBailout();
return MStringReplace::New(alloc, string, pattern, replacement);
MStringReplace *substr = MStringReplace::New(alloc, string, pattern, replacement);
substr->setFlatReplacement();
return substr;
}
MConvertUnboxedObjectToNative*
+21 -1
View File
@@ -7636,8 +7636,10 @@ class MStringReplace
{
private:
bool isFlatReplacement_;
MStringReplace(MDefinition* string, MDefinition* pattern, MDefinition* replacement)
: MStrReplace< StringPolicy<1> >(string, pattern, replacement)
: MStrReplace< StringPolicy<1> >(string, pattern, replacement), isFlatReplacement_(false)
{
}
@@ -7648,7 +7650,20 @@ class MStringReplace
return new(alloc) MStringReplace(string, pattern, replacement);
}
void setFlatReplacement() {
MOZ_ASSERT(!isFlatReplacement_);
isFlatReplacement_ = true;
}
bool isFlatReplacement() const {
return isFlatReplacement_;
}
bool congruentTo(const MDefinition* ins) const override {
if (!ins->isStringReplace())
return false;
if (isFlatReplacement_ != ins->toStringReplace()->isFlatReplacement())
return false;
return congruentIfOperandsEqual(ins);
}
@@ -7658,6 +7673,11 @@ class MStringReplace
bool writeRecoverData(CompactBufferWriter& writer) const override;
bool canRecoverOnBailout() const override {
if (isFlatReplacement_)
{
MOZ_ASSERT(!pattern()->isRegExp());
return true;
}
if (pattern()->isRegExp())
return !pattern()->toRegExp()->source()->global();
return false;
+7 -2
View File
@@ -1500,11 +1500,14 @@ MStringReplace::writeRecoverData(CompactBufferWriter& writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_StringReplace));
writer.writeByte(isFlatReplacement_);
return true;
}
RStringReplace::RStringReplace(CompactBufferReader& reader)
{ }
{
isFlatReplacement_ = reader.readByte();
}
bool RStringReplace::recover(JSContext* cx, SnapshotIterator& iter) const
{
@@ -1512,7 +1515,9 @@ bool RStringReplace::recover(JSContext* cx, SnapshotIterator& iter) const
RootedString pattern(cx, iter.read().toString());
RootedString replace(cx, iter.read().toString());
JSString* result = js::str_replace_string_raw(cx, string, pattern, replace);
JSString* result = isFlatReplacement_ ? js::str_flat_replace_string(cx, string, pattern, replace) :
js::str_replace_string_raw(cx, string, pattern, replace);
if (!result)
return false;
+3
View File
@@ -597,6 +597,9 @@ class RRegExpReplace final : public RInstruction
class RStringReplace final : public RInstruction
{
private:
bool isFlatReplacement_;
public:
RINSTRUCTION_HEADER_(StringReplace)
+26 -5
View File
@@ -1176,12 +1176,33 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc)
write("(...)");
case JSOP_NEWARRAY:
return write("[]");
case JSOP_REGEXP:
case JSOP_OBJECT:
case JSOP_REGEXP: {
RootedObject obj(cx, script->getRegExp(GET_UINT32_INDEX(pc)));
JSString* str = obj->as<RegExpObject>().toString(cx);
if (!str)
return false;
return write(str);
}
case JSOP_NEWARRAY_COPYONWRITE: {
JSObject* obj = (op == JSOP_REGEXP)
? script->getRegExp(GET_UINT32_INDEX(pc))
: script->getObject(GET_UINT32_INDEX(pc));
RootedObject obj(cx, script->getObject(GET_UINT32_INDEX(pc)));
Handle<ArrayObject*> aobj = obj.as<ArrayObject>();
if (!write("["))
return false;
for (size_t i = 0; i < aobj->getDenseInitializedLength(); i++) {
if (i > 0 && !write(", "))
return false;
RootedValue v(cx, aobj->getDenseElement(i));
MOZ_RELEASE_ASSERT(v.isPrimitive() && !v.isMagic());
JSString* str = ValueToSource(cx, v);
if (!str || !write(str))
return false;
}
return write("]");
}
case JSOP_OBJECT: {
JSObject* obj = script->getObject(GET_UINT32_INDEX(pc));
RootedValue objv(cx, ObjectValue(*obj));
JSString* str = ValueToSource(cx, objv);
if (!str)
+114 -1
View File
@@ -3400,11 +3400,124 @@ StrReplaceString(JSContext* cx, ReplaceData& rdata, const FlatMatch& fm)
return BuildFlatReplacement(cx, rdata.str, rdata.repstr, fm);
}
template <typename StrChar, typename RepChar>
static bool
StrFlatReplaceGlobal(JSContext *cx, JSLinearString *str, JSLinearString *pat, JSLinearString *rep,
StringBuffer &sb)
{
MOZ_ASSERT(str->length() > 0);
AutoCheckCannotGC nogc;
const StrChar *strChars = str->chars<StrChar>(nogc);
const RepChar *repChars = rep->chars<RepChar>(nogc);
// The pattern is empty, so we interleave the replacement string in-between
// each character.
if (!pat->length()) {
CheckedInt<uint32_t> strLength(str->length());
CheckedInt<uint32_t> repLength(rep->length());
CheckedInt<uint32_t> length = repLength * (strLength - 1) + strLength;
if (!length.isValid()) {
ReportAllocationOverflow(cx);
return false;
}
if (!sb.reserve(length.value()))
return false;
for (unsigned i = 0; i < str->length() - 1; ++i, ++strChars) {
sb.infallibleAppend(*strChars);
sb.infallibleAppend(repChars, rep->length());
}
sb.infallibleAppend(*strChars);
return true;
}
// If it's true, we are sure that the result's length is, at least, the same
// length as |str->length()|.
if (rep->length() >= pat->length()) {
if (!sb.reserve(str->length()))
return false;
}
uint32_t start = 0;
for (;;) {
int match = StringMatch(str, pat, start);
if (match < 0)
break;
if (!sb.append(strChars + start, match - start))
return false;
if (!sb.append(repChars, rep->length()))
return false;
start = match + pat->length();
}
if (!sb.append(strChars + start, str->length() - start))
return false;
return true;
}
// This is identical to "str.split(pattern).join(replacement)" except that we
// do some deforestation optimization in Ion.
JSString *
js::str_flat_replace_string(JSContext *cx, HandleString string, HandleString pattern,
HandleString replacement)
{
MOZ_ASSERT(string);
MOZ_ASSERT(pattern);
MOZ_ASSERT(replacement);
if (!string->length())
return string;
RootedLinearString linearRepl(cx, replacement->ensureLinear(cx));
if (!linearRepl)
return nullptr;
RootedLinearString linearPat(cx, pattern->ensureLinear(cx));
if (!linearPat)
return nullptr;
RootedLinearString linearStr(cx, string->ensureLinear(cx));
if (!linearStr)
return nullptr;
StringBuffer sb(cx);
if (linearStr->hasTwoByteChars()) {
if (!sb.ensureTwoByteChars())
return nullptr;
if (linearRepl->hasTwoByteChars()) {
if (!StrFlatReplaceGlobal<char16_t, char16_t>(cx, linearStr, linearPat, linearRepl, sb))
return nullptr;
} else {
if (!StrFlatReplaceGlobal<char16_t, Latin1Char>(cx, linearStr, linearPat, linearRepl, sb))
return nullptr;
}
} else {
if (linearRepl->hasTwoByteChars()) {
if (!sb.ensureTwoByteChars())
return nullptr;
if (!StrFlatReplaceGlobal<Latin1Char, char16_t>(cx, linearStr, linearPat, linearRepl, sb))
return nullptr;
} else {
if (!StrFlatReplaceGlobal<Latin1Char, Latin1Char>(cx, linearStr, linearPat, linearRepl, sb))
return nullptr;
}
}
JSString *str = sb.finishString();
if (!str)
return nullptr;
return str;
}
static const uint32_t ReplaceOptArg = 2;
JSString*
js::str_replace_string_raw(JSContext* cx, HandleString string, HandleString pattern,
HandleString replacement)
HandleString replacement)
{
ReplaceData rdata(cx);
+4
View File
@@ -437,6 +437,10 @@ str_split(JSContext* cx, unsigned argc, Value* vp);
JSObject*
str_split_string(JSContext* cx, HandleObjectGroup group, HandleString str, HandleString sep);
JSString *
str_flat_replace_string(JSContext *cx, HandleString string, HandleString pattern,
HandleString replacement);
JSString*
str_replace_string_raw(JSContext* cx, HandleString string, HandleString pattern,
HandleString replacement);
+1 -1
View File
@@ -327,7 +327,7 @@ InitGlobalLexicalOperation(JSContext* cx, ClonedBlockObject* lexicalScopeArg,
Rooted<ClonedBlockObject*> lexicalScope(cx, lexicalScopeArg);
RootedShape shape(cx, lexicalScope->lookup(cx, script->getName(pc)));
MOZ_ASSERT(shape);
lexicalScope->setSlot(shape->slot(), value);
lexicalScope->setSlotWithType(cx, shape, value);
}
inline bool
+4 -2
View File
@@ -160,8 +160,10 @@ JSDependentString::new_(js::ExclusiveContext* cx, JSLinearString* baseArg, size_
* entirely, however, due to how ropes are flattened.
*/
if (baseArg->isDependent()) {
start += baseArg->asDependent().baseOffset();
baseArg = baseArg->asDependent().base();
if (mozilla::Maybe<size_t> offset = baseArg->asDependent().baseOffset()) {
start += *offset;
baseArg = baseArg->asDependent().base();
}
}
MOZ_ASSERT(start + length <= baseArg->length());
+3 -1
View File
@@ -680,7 +680,9 @@ JSDependentString::dumpRepresentation(FILE* fp, int indent) const
dumpRepresentationHeader(fp, indent, "JSDependentString");
indent += 2;
fprintf(fp, "%*soffset: %zu\n", indent, "", baseOffset());
if (mozilla::Maybe<size_t> offset = baseOffset())
fprintf(fp, "%*soffset: %zu\n", indent, "", *offset);
fprintf(fp, "%*sbase: ", indent, "");
base()->dumpRepresentation(fp, indent);
}
+5 -2
View File
@@ -10,6 +10,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Range.h"
#include "mozilla/Maybe.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@@ -694,16 +695,18 @@ class JSDependentString : public JSLinearString
JSDependentString& asDependent() const = delete;
/* The offset of this string's chars in base->chars(). */
size_t baseOffset() const {
MOZ_ALWAYS_INLINE mozilla::Maybe<size_t> baseOffset() const {
MOZ_ASSERT(JSString::isDependent());
JS::AutoCheckCannotGC nogc;
if (MOZ_UNLIKELY(base()->isUndepended()))
return mozilla::Nothing();
size_t offset;
if (hasTwoByteChars())
offset = twoByteChars(nogc) - base()->twoByteChars(nogc);
else
offset = latin1Chars(nogc) - base()->latin1Chars(nogc);
MOZ_ASSERT(offset < base()->length());
return offset;
return mozilla::Some(offset);
}
public:
+3 -1
View File
@@ -1438,7 +1438,6 @@ js::FinishCompilation(JSContext* cx, HandleScript script, CompilerConstraintList
// after any future changes to the stack type sets.
if (entry.script->hasFreezeConstraints())
continue;
entry.script->setHasFreezeConstraints();
size_t count = TypeScript::NumTypeSets(entry.script);
@@ -1447,6 +1446,9 @@ js::FinishCompilation(JSContext* cx, HandleScript script, CompilerConstraintList
if (!array[i].addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeStack>(entry.script), false))
succeeded = false;
}
if (succeeded)
entry.script->setHasFreezeConstraints();
}
if (!succeeded || types.compilerOutputs->back().pendingInvalidation()) {
+31 -9
View File
@@ -162,9 +162,12 @@ XPCWrappedNativeXrayTraits::getWN(JSObject* wrapper)
}
const JSClass XPCWrappedNativeXrayTraits::HolderClass = {
"NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(2)
"NativePropertyHolder", JSCLASS_HAS_RESERVED_SLOTS(HOLDER_SHARED_SLOT_COUNT)
};
const JSClass XrayTraits::HolderClass = {
"XrayHolder", JSCLASS_HAS_RESERVED_SLOTS(HOLDER_SHARED_SLOT_COUNT)
};
const JSClass JSXrayTraits::HolderClass = {
"JSXrayHolder", JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT)
@@ -1746,7 +1749,7 @@ DOMXrayTraits::preserveWrapper(JSObject* target)
JSObject*
DOMXrayTraits::createHolder(JSContext* cx, JSObject* wrapper)
{
return JS_NewObjectWithGivenProto(cx, nullptr, nullptr);
return JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr);
}
namespace XrayUtils {
@@ -2245,16 +2248,35 @@ XrayWrapper<Base, Traits>::getPrototype(JSContext* cx, JS::HandleObject wrapper,
// only if there's been a set. If there's not an expando, or the expando
// slot is |undefined|, hand back the default proto, appropriately wrapped.
RootedValue v(cx);
if (expando) {
JSAutoCompartment ac(cx, expando);
v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE);
RootedValue v(cx);
{ // Scope for JSAutoCompartment
JSAutoCompartment ac(cx, expando);
v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE);
}
if (!v.isUndefined()) {
protop.set(v.toObjectOrNull());
return JS_WrapObject(cx, protop);
}
}
if (v.isUndefined())
return getPrototypeHelper(cx, wrapper, target, protop);
protop.set(v.toObjectOrNull());
return JS_WrapObject(cx, protop);
// Check our holder, and cache there if we don't have it cached already.
RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper));
if (!holder)
return false;
Value cached = js::GetReservedSlot(holder,
Traits::HOLDER_SLOT_CACHED_PROTO);
if (cached.isUndefined()) {
if (!getPrototypeHelper(cx, wrapper, target, protop))
return false;
js::SetReservedSlot(holder, Traits::HOLDER_SLOT_CACHED_PROTO,
ObjectOrNullValue(protop));
} else {
protop.set(cached.toObjectOrNull());
}
return true;
}
template <typename Base, typename Traits>
+11 -2
View File
@@ -94,6 +94,12 @@ public:
JSObject* ensureExpandoObject(JSContext* cx, JS::HandleObject wrapper,
JS::HandleObject target);
// Slots for holder objects.
enum {
HOLDER_SLOT_CACHED_PROTO = 0,
HOLDER_SHARED_SLOT_COUNT
};
JSObject* getHolder(JSObject* wrapper);
JSObject* ensureHolder(JSContext* cx, JS::HandleObject wrapper);
virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) = 0;
@@ -102,6 +108,9 @@ public:
bool setExpandoChain(JSContext* cx, JS::HandleObject obj, JS::HandleObject chain);
bool cloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
protected:
static const JSClass HolderClass;
private:
bool expandoObjectMatchesConsumer(JSContext* cx, JS::HandleObject expandoObject,
nsIPrincipal* consumerOrigin,
@@ -292,7 +301,7 @@ public:
}
enum {
SLOT_PROTOKEY = 0,
SLOT_PROTOKEY = HOLDER_SHARED_SLOT_COUNT,
SLOT_ISPROTOTYPE,
SLOT_CONSTRUCTOR_FOR,
SLOT_COUNT
@@ -406,7 +415,7 @@ public:
virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override
{
return JS_NewObjectWithGivenProto(cx, nullptr, nullptr);
return JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr);
}
static OpaqueXrayTraits singleton;
+8 -2
View File
@@ -17,6 +17,7 @@
#include "mozilla/HashFunctions.h"
#include "mozilla/MathAlgorithms.h"
#include "nsISVGChildFrame.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsIFrame.h"
@@ -4806,8 +4807,13 @@ nsImageRenderer::PrepareImage()
mImageElementSurface =
nsLayoutUtils::SurfaceFromElement(property->GetReferencedElement());
if (!mImageElementSurface.GetSourceSurface()) {
mPaintServerFrame = property->GetReferencedFrame();
if (!mPaintServerFrame) {
nsIFrame* paintServerFrame = property->GetReferencedFrame();
// If there's no referenced frame, or the referenced frame is
// non-displayable SVG, then we have nothing valid to paint.
if (!paintServerFrame ||
(paintServerFrame->IsFrameOfType(nsIFrame::eSVG) &&
!paintServerFrame->IsFrameOfType(nsIFrame::eSVGPaintServer) &&
!static_cast<nsISVGChildFrame*>(do_QueryFrame(paintServerFrame)))) {
mPrepareResult = DrawResult::BAD_IMAGE;
return false;
}
+4 -1
View File
@@ -968,7 +968,6 @@ void
nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
const nsFrameList& aFrames,
const nsRect& aDirtyRect) {
mFramesMarkedForDisplay.SetCapacity(mFramesMarkedForDisplay.Length() + aFrames.GetLength());
for (nsIFrame* e : aFrames) {
// Skip the AccessibleCaret frame when building no caret.
if (!IsBuildingCaret()) {
@@ -3328,6 +3327,10 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
if (borderBoxHasRoundedCorners ||
(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
mMaybeHitRegion.Or(mMaybeHitRegion, borderBox);
// Avoid quadratic performance as a result of the region growing to include
// an arbitrarily large number of rects, which can happen on some pages.
mMaybeHitRegion.SimplifyOutward(8);
} else {
mHitRegion.Or(mHitRegion, borderBox);
}
+1 -1
View File
@@ -1003,7 +1003,7 @@ private:
PLArenaPool mPool;
nsCOMPtr<nsISelection> mBoundingSelection;
nsAutoTArray<PresShellState,8> mPresShellStates;
nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
nsAutoTArray<nsIFrame*,400> mFramesMarkedForDisplay;
nsAutoTArray<ThemeGeometry,2> mThemeGeometries;
nsDisplayTableItem* mCurrentTableItem;
DisplayListClipState mClipState;
+62 -16
View File
@@ -629,6 +629,15 @@ nsDocumentViewer::Init(nsIWidget* aParentWidget,
nsresult
nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow)
{
// We assert this because initializing the pres shell could otherwise cause
// re-entrancy into nsDocumentViewer methods, which might cause a different
// pres shell to be created. Callers of InitPresentationStuff should ensure
// the call is appropriately bounded by an nsAutoScriptBlocker to decide
// when it is safe for these re-entrant calls to be made.
MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
"InitPresentationStuff must only be called when scripts are "
"blocked");
if (GetIsPrintPreview())
return NS_OK;
@@ -1652,6 +1661,10 @@ nsDocumentViewer::Destroy()
// The document was not put in the bfcache
// Protect against pres shell destruction running scripts and re-entrantly
// creating a new presentation.
nsAutoScriptBlocker scriptBlocker;
if (mPresShell) {
DestroyPresShell();
}
@@ -1817,6 +1830,10 @@ nsDocumentViewer::SetDocumentInternal(nsIDocument* aDocument,
// Replace the current pres shell with a new shell for the new document
// Protect against pres shell destruction running scripts and re-entrantly
// creating a new presentation.
nsAutoScriptBlocker scriptBlocker;
if (mPresShell) {
DestroyPresShell();
}
@@ -2014,7 +2031,17 @@ nsDocumentViewer::Show(void)
}
}
// Hold on to the document so we can use it after the script blocker below
// has been released (which might re-entrantly call into other
// nsDocumentViewer methods).
nsCOMPtr<nsIDocument> document = mDocument;
if (mDocument && !mPresShell) {
// The InitPresentationStuff call below requires a script blocker, because
// its PresShell::Initialize call can cause scripts to run and therefore
// re-entrant calls to nsDocumentViewer methods to be made.
nsAutoScriptBlocker scriptBlocker;
NS_ASSERTION(!mWindow, "Window already created but no presshell?");
nsCOMPtr<nsIBaseWindow> base_win(mContainer);
@@ -2076,7 +2103,7 @@ nsDocumentViewer::Show(void)
// Notify observers that a new page has been shown. This will get run
// from the event loop after we actually draw the page.
NS_DispatchToMainThread(new nsDocumentShownDispatcher(mDocument));
NS_DispatchToMainThread(new nsDocumentShownDispatcher(document));
return NS_OK;
}
@@ -2113,24 +2140,23 @@ nsDocumentViewer::Hide(void)
mPresShell->CaptureHistoryState(getter_AddRefs(layoutState));
}
{
// Do not run ScriptRunners queued by DestroyPresShell() in the intermediate
// state before we're done destroying PresShell, PresContext, ViewManager, etc.
nsAutoScriptBlocker scriptBlocker;
DestroyPresShell();
// Do not run ScriptRunners queued by DestroyPresShell() in the intermediate
// state before we're done destroying PresShell, PresContext, ViewManager, etc.
nsAutoScriptBlocker scriptBlocker;
DestroyPresContext();
DestroyPresShell();
mViewManager = nullptr;
mWindow = nullptr;
mDeviceContext = nullptr;
mParentWidget = nullptr;
DestroyPresContext();
nsCOMPtr<nsIBaseWindow> base_win(mContainer);
mViewManager = nullptr;
mWindow = nullptr;
mDeviceContext = nullptr;
mParentWidget = nullptr;
if (base_win && !mAttachedToParent) {
base_win->SetParentWidget(nullptr);
}
nsCOMPtr<nsIBaseWindow> base_win(mContainer);
if (base_win && !mAttachedToParent) {
base_win->SetParentWidget(nullptr);
}
return NS_OK;
@@ -4153,9 +4179,14 @@ nsDocumentViewer::SetIsPrintPreview(bool aIsPrintPreview)
SetIsPrintingInDocShellTree(docShell, aIsPrintPreview, true);
}
if (!aIsPrintPreview) {
// Dispatch the 'afterprint' event now, if pending:
mBeforeAndAfterPrint = nullptr;
}
#endif
// Protect against pres shell destruction running scripts.
nsAutoScriptBlocker scriptBlocker;
if (!aIsPrintPreview) {
if (mPresShell) {
DestroyPresShell();
@@ -4284,6 +4315,11 @@ NS_IMETHODIMP nsDocumentViewer::SetPageMode(bool aPageMode, nsIPrintSettings* aP
// reftests that require a paginated context
mIsPageMode = aPageMode;
// The DestroyPresShell call requires a script blocker, since the
// PresShell::Destroy call it does can cause scripts to run, which could
// re-entrantly call methods on the nsDocumentViewer.
nsAutoScriptBlocker scriptBlocker;
if (mPresShell) {
DestroyPresShell();
}
@@ -4344,6 +4380,13 @@ nsDocumentViewer::SetIsHidden(bool aHidden)
void
nsDocumentViewer::DestroyPresShell()
{
// We assert this because destroying the pres shell could otherwise cause
// re-entrancy into nsDocumentViewer methods, and all callers of
// DestroyPresShell need to do other cleanup work afterwards before it
// is safe for those re-entrant method calls to be made.
MOZ_ASSERT(!nsContentUtils::IsSafeToRunScript(),
"DestroyPresShell must only be called when scripts are blocked");
// Break circular reference (or something)
mPresShell->EndObservingDocument();
@@ -4351,7 +4394,6 @@ nsDocumentViewer::DestroyPresShell()
if (selection && mSelectionListener)
selection->RemoveSelectionListener(mSelectionListener);
nsAutoScriptBlocker scriptBlocker;
mPresShell->Destroy();
mPresShell = nullptr;
}
@@ -4380,6 +4422,10 @@ nsDocumentViewer::SetPrintPreviewPresentation(nsViewManager* aViewManager,
nsPresContext* aPresContext,
nsIPresShell* aPresShell)
{
// Protect against pres shell destruction running scripts and re-entrantly
// creating a new presentation.
nsAutoScriptBlocker scriptBlocker;
if (mPresShell) {
DestroyPresShell();
}
+10 -2
View File
@@ -131,9 +131,17 @@ nsPresArena::Allocate(uint32_t aCode, size_t aSize)
void* result;
if (len > 0) {
// LIFO behavior for best cache utilization
// Remove from the end of the mEntries array to avoid memmoving entries,
// and use SetLengthAndRetainStorage to avoid a lot of malloc/free
// from ShrinkCapacity on smaller sizes. 500 pointers means the malloc size
// for the array is 4096 bytes or more on a 64-bit system. The next smaller
// size is 2048 (with jemalloc), which we consider not worth compacting.
result = list->mEntries.ElementAt(len - 1);
list->mEntries.RemoveElementAt(len - 1);
if (list->mEntries.Capacity() > 500) {
list->mEntries.RemoveElementAt(len - 1);
} else {
list->mEntries.SetLengthAndRetainStorage(len - 1);
}
#if defined(DEBUG)
{
MOZ_MAKE_MEM_DEFINED(result, list->mEntrySize);
+24 -16
View File
@@ -1601,6 +1601,24 @@ PresShell::EndObservingDocument()
char* nsPresShell_ReflowStackPointerTop;
#endif
class XBLConstructorRunner : public nsRunnable
{
public:
explicit XBLConstructorRunner(nsIDocument* aDocument)
: mDocument(aDocument)
{
}
NS_IMETHOD Run() override
{
mDocument->BindingManager()->ProcessAttachedQueue();
return NS_OK;
}
private:
nsCOMPtr<nsIDocument> mDocument;
};
nsresult
PresShell::Initialize(nscoord aWidth, nscoord aHeight)
{
@@ -1698,24 +1716,14 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
mFrameConstructor->EndUpdate();
}
// nsAutoScriptBlocker going out of scope may have killed us too
// nsAutoCauseReflowNotifier (which sets up a script blocker) going out of
// scope may have killed us too
NS_ENSURE_STATE(!mHaveShutDown);
// Run the XBL binding constructors for any new frames we've constructed
mDocument->BindingManager()->ProcessAttachedQueue();
// Constructors may have killed us too
NS_ENSURE_STATE(!mHaveShutDown);
// Now flush out pending restyles before we actually reflow, in
// case XBL constructors changed styles somewhere.
{
nsAutoScriptBlocker scriptBlocker;
mPresContext->RestyleManager()->ProcessPendingRestyles();
}
// And that might have run _more_ XBL constructors
NS_ENSURE_STATE(!mHaveShutDown);
// Run the XBL binding constructors for any new frames we've constructed.
// (Do this in a script runner, since our caller might have a script
// blocker on the stack.)
nsContentUtils::AddScriptRunner(new XBLConstructorRunner(mDocument));
}
NS_ASSERTION(rootFrame, "How did that happen?");
+19
View File
@@ -180,6 +180,25 @@ public:
nsLayoutUtils::GetTextShadowRectsUnion(mRect, mFrame);
return mRect.Union(shadowRect);
}
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override
{
#ifdef XP_MACOSX
{
#else
if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
#endif
// On OS X, web authors can turn off subpixel text rendering using the
// CSS property -moz-osx-font-smoothing. If they do that, we don't need
// to use component alpha layers for the affected text.
if (mFrame->StyleFont()->mFont.smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
return nsRect();
}
}
bool snap;
return GetBounds(aBuilder, &snap);
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) override;
+12
View File
@@ -4677,6 +4677,18 @@ public:
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) override
{
#ifdef XP_MACOSX
{
#else
if (gfxPlatform::GetPlatform()->RespectsFontStyleSmoothing()) {
#endif
// On OS X, web authors can turn off subpixel text rendering using the
// CSS property -moz-osx-font-smoothing. If they do that, we don't need
// to use component alpha layers for the affected text.
if (mFrame->StyleFont()->mFont.smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
return nsRect();
}
}
bool snap;
return GetBounds(aBuilder, &snap);
}
-41
View File
@@ -1159,47 +1159,6 @@ nsMathMLmtdFrame::Init(nsIContent* aContent,
RemoveStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
}
int32_t
nsMathMLmtdFrame::GetRowSpan()
{
int32_t rowspan = 1;
// Don't look at the content's rowspan if we're not an mtd or a pseudo cell.
if (mContent->IsMathMLElement(nsGkAtoms::mtd_) &&
!StyleContext()->GetPseudo()) {
nsAutoString value;
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rowspan, value);
if (!value.IsEmpty()) {
nsresult error;
rowspan = value.ToInteger(&error);
if (NS_FAILED(error) || rowspan < 0)
rowspan = 1;
rowspan = std::min(rowspan, MAX_ROWSPAN);
}
}
return rowspan;
}
int32_t
nsMathMLmtdFrame::GetColSpan()
{
int32_t colspan = 1;
// Don't look at the content's colspan if we're not an mtd or a pseudo cell.
if (mContent->IsMathMLElement(nsGkAtoms::mtd_) &&
!StyleContext()->GetPseudo()) {
nsAutoString value;
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::columnspan_, value);
if (!value.IsEmpty()) {
nsresult error;
colspan = value.ToInteger(&error);
if (NS_FAILED(error) || colspan < 0 || colspan > MAX_COLSPAN)
colspan = 1;
}
}
return colspan;
}
nsresult
nsMathMLmtdFrame::AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
-2
View File
@@ -256,8 +256,6 @@ public:
nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) override;
virtual int32_t GetRowSpan() override;
virtual int32_t GetColSpan() override;
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML));
+9
View File
@@ -788,6 +788,15 @@ nsSVGIntegrationUtils::DrawableFromPaintServer(nsIFrame* aFrame,
return drawable.forget();
}
#if DEBUG
if (aFrame->IsFrameOfType(nsIFrame::eSVG) &&
!static_cast<nsISVGChildFrame*>(do_QueryFrame(aFrame))) {
MOZ_ASSERT_UNREACHABLE("We should prevent painting of unpaintable SVG "
"before we get here");
return nullptr;
}
#endif
// We don't want to paint into a surface as long as we don't need to, so we
// set up a drawing callback.
RefPtr<gfxDrawingCallback> cb =
+1 -4
View File
@@ -6,6 +6,7 @@
#define CellData_h__
#include "nsISupports.h"
#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN
#include "nsCoord.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/WritingModes.h"
@@ -16,10 +17,6 @@ class nsCellMap;
class BCCellData;
#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes,
// change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
/**
* Data stored by nsCellMap to rationalize rowspan and colspan cells.
*/
+4
View File
@@ -7,6 +7,10 @@
#include "nsQueryFrame.h"
#define MAX_ROWSPAN 65534 // the cellmap can not handle more.
#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes,
// change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly.
/**
* nsITableCellLayout
* interface for layout objects that act like table cells.
+16 -10
View File
@@ -735,16 +735,18 @@ nsTableCellFrame::GetCellBaseline() const
borderPadding;
}
int32_t nsTableCellFrame::GetRowSpan()
int32_t
nsTableCellFrame::GetRowSpan()
{
int32_t rowSpan=1;
nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
// Don't look at the content's rowspan if we're a pseudo cell
if (hc && !StyleContext()->GetPseudo()) {
const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::rowspan);
if (!StyleContext()->GetPseudo()) {
dom::Element* elem = mContent->AsElement();
const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::rowspan);
// Note that we don't need to check the tag name, because only table cells
// and table headers parse the "rowspan" attribute into an integer.
// (including MathML <mtd>) and table headers parse the "rowspan" attribute
// into an integer.
if (attr && attr->Type() == nsAttrValue::eInteger) {
rowSpan = attr->GetIntegerValue();
}
@@ -752,16 +754,20 @@ int32_t nsTableCellFrame::GetRowSpan()
return rowSpan;
}
int32_t nsTableCellFrame::GetColSpan()
int32_t
nsTableCellFrame::GetColSpan()
{
int32_t colSpan=1;
nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
// Don't look at the content's colspan if we're a pseudo cell
if (hc && !StyleContext()->GetPseudo()) {
const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::colspan);
if (!StyleContext()->GetPseudo()) {
dom::Element* elem = mContent->AsElement();
const nsAttrValue* attr = elem->GetParsedAttr(
MOZ_UNLIKELY(elem->IsMathMLElement()) ? nsGkAtoms::columnspan_
: nsGkAtoms::colspan);
// Note that we don't need to check the tag name, because only table cells
// and table headers parse the "colspan" attribute into an integer.
// (including MathML <mtd>) and table headers parse the "colspan" attribute
// into an integer.
if (attr && attr->Type() == nsAttrValue::eInteger) {
colSpan = attr->GetIntegerValue();
}
+3 -3
View File
@@ -168,11 +168,11 @@ public:
/**
* return the cell's specified row span. this is what was specified in the
* content model or in the style info, and is always >= 1.
* content model or in the style info, and is always >= 0.
* to get the effective row span (the actual value that applies), use GetEffectiveRowSpan()
* @see nsTableFrame::GetEffectiveRowSpan()
*/
virtual int32_t GetRowSpan();
int32_t GetRowSpan();
// there is no set row index because row index depends on the cell's parent row only
@@ -194,7 +194,7 @@ public:
* to get the effective col span (the actual value that applies), use GetEffectiveColSpan()
* @see nsTableFrame::GetEffectiveColSpan()
*/
virtual int32_t GetColSpan();
int32_t GetColSpan();
/** return the cell's column index (starting at 0 for the first column) */
virtual nsresult GetColIndex(int32_t &aColIndex) const override;
@@ -1528,6 +1528,9 @@ sdp_result_e sdp_parse_attr_fmtp (sdp_t *sdp_p, sdp_attr_t *attr_p,
temp=PL_strtok_r(NULL, ",", &strtok_state);
iter++;
}
} else {
SDP_FREE(temp_ptr);
return SDP_INVALID_PARAMETER;
}
fmtp_p->fmtp_format = SDP_FMTP_CODEC_INFO;
@@ -1771,7 +1774,12 @@ sdp_result_e sdp_parse_attr_fmtp (sdp_t *sdp_p, sdp_attr_t *attr_p,
}
}
}
fmtp_ptr++;
if (*fmtp_ptr == '\n') {
// reached end of line, stop parsing
done = TRUE;
} else {
fmtp_ptr++;
}
} else {
done = TRUE;
}
+4 -4
View File
@@ -318,10 +318,10 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
// Watch out for the jar:foo.zip!/ (aDir is empty) top-level special case!
nsZipItem *item = nullptr;
const char *entry = PromiseFlatCString(aEntryName).get();
if (*entry) {
const nsCString& entry = PromiseFlatCString(aEntryName);
if (*entry.get()) {
// First check if item exists in jar
item = mZip->GetItem(entry);
item = mZip->GetItem(entry.get());
if (!item) return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
}
nsJARInputStream* jis = new nsJARInputStream();
@@ -330,7 +330,7 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
nsresult rv = NS_OK;
if (!item || item->IsDirectory()) {
rv = jis->InitDirectory(this, aJarDirSpec, entry);
rv = jis->InitDirectory(this, aJarDirSpec, entry.get());
} else {
rv = jis->InitFile(this, item);
}
+4
View File
@@ -897,6 +897,10 @@ nsAtomicFileOutputStream::DoOpen()
nsCOMPtr<nsIFile> file;
file.swap(mOpenParams.localFile);
if(MOZ_UNLIKELY(!file)) {
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv = file->Exists(&mTargetFileExists);
if (NS_FAILED(rv)) {
NS_ERROR("Can't tell if target file exists");
+1 -1
View File
@@ -23,7 +23,7 @@ public:
NS_ASSERTION(mListener, "no stream listener specified");
}
NS_DECL_ISUPPORTS
NS_DECL_THREADSAFE_ISUPPORTS
NS_FORWARD_NSIREQUESTOBSERVER(mListener->)
NS_FORWARD_NSISTREAMLISTENER(mListener->)
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
+2 -2
View File
@@ -824,8 +824,8 @@ nsMIMEHeaderParamImpl::DecodeRFC5987Param(const nsACString& aParamVal,
nsAutoCString value;
uint32_t delimiters = 0;
const char *encoded = PromiseFlatCString(aParamVal).get();
const char *c = encoded;
const nsCString& encoded = PromiseFlatCString(aParamVal);
const char *c = encoded.get();
while (*c) {
char tc = *c++;
+4 -1
View File
@@ -2772,7 +2772,10 @@ Http2Session::WriteSegmentsAgain(nsAHttpSegmentWriter *writer,
LOG3(("Http2Session::WriteSegments %p trying to discard %d bytes of data",
this, count));
if (!count) {
if (!count && mDownstreamState == DISCARDING_DATA_FRAME) {
// Only do this short-cirtuit if we're not discarding a pure padding
// frame, as we need to potentially handle the stream FIN in those cases.
// See bug 1381016 comment 36 for more details.
ResetDownstreamState();
ResumeRecv();
return NS_BASE_STREAM_WOULD_BLOCK;
+70
View File
@@ -90,6 +90,7 @@
#include "nsIDeprecationWarner.h"
#include "nsIDocument.h"
#include "nsICompressConvStats.h"
#include "mozilla/unused.h"
namespace mozilla { namespace net {
@@ -161,6 +162,58 @@ Hash(const char *buf, nsACString &hash)
return NS_OK;
}
bool
IsInSubpathOfAppCacheManifest(nsIApplicationCache *cache, nsACString const& uriSpec)
{
MOZ_ASSERT(cache);
static bool sForbid = true;
static nsresult once = Preferences::AddBoolVarCache(&sForbid, "network.appcache.forbid-fallback-outside-manifest-path", true);
Unused << once;
if (!sForbid) {
return true;
}
nsresult rv;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
if (NS_FAILED(rv)) {
return false;
}
nsCOMPtr<nsIURL> url(do_QueryInterface(uri, &rv));
if (NS_FAILED(rv)) {
return false;
}
nsAutoCString directory;
rv = url->GetDirectory(directory);
if (NS_FAILED(rv)) {
return false;
}
nsCOMPtr<nsIURI> manifestURI;
rv = cache->GetManifestURI(getter_AddRefs(manifestURI));
if (NS_FAILED(rv)) {
return false;
}
nsCOMPtr<nsIURL> manifestURL(do_QueryInterface(manifestURI, &rv));
if (NS_FAILED(rv)) {
return false;
}
nsAutoCString manifestDirectory;
rv = manifestURL->GetDirectory(manifestDirectory);
if (NS_FAILED(rv)) {
return false;
}
return StringBeginsWith(directory, manifestDirectory);
}
} // unnamed namespace
// We only treat 3xx responses as redirects if they have a Location header and
@@ -2753,6 +2806,12 @@ nsHttpChannel::ProcessFallback(bool *waitingForRedirectCallback)
return NS_OK;
}
if (!IsInSubpathOfAppCacheManifest(mApplicationCache, mFallbackKey)) {
// Refuse to fallback if the fallback key is not contained in the same
// path as the cache manifest.
return NS_OK;
}
MOZ_ASSERT(fallbackEntryType & nsIApplicationCache::ITEM_FALLBACK,
"Fallback entry not marked correctly!");
@@ -3676,6 +3735,17 @@ nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntry *aEntry,
if (namespaceType &
nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) {
nsAutoCString namespaceSpec;
rv = namespaceEntry->GetNamespaceSpec(namespaceSpec);
NS_ENSURE_SUCCESS(rv, rv);
// This prevents fallback attacks injected by an insecure subdirectory
// for the whole origin (or a parent directory).
if (!IsInSubpathOfAppCacheManifest(mApplicationCache, namespaceSpec)) {
return NS_OK;
}
rv = namespaceEntry->GetData(mFallbackKey);
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -2831,9 +2831,9 @@ nsHttpConnectionMgr::TimeoutTickCB(const nsACString &key,
LOG(("Force timeout of half open to %s after %.2fms.\n",
ent->mConnInfo->HashKey().get(), delta));
if (half->SocketTransport())
half->SocketTransport()->Close(NS_ERROR_ABORT);
half->SocketTransport()->Close(NS_ERROR_NET_TIMEOUT);
if (half->BackupTransport())
half->BackupTransport()->Close(NS_ERROR_ABORT);
half->BackupTransport()->Close(NS_ERROR_NET_TIMEOUT);
}
// If this half open hangs around for 5 seconds after we've closed() it
@@ -299,6 +299,13 @@ nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
// MODIFIED DATE
char buffer[256] = "";
// ParseFTPList can return time structure with invalid values.
// PR_NormalizeTime will set all values into valid limits.
result.fe_time.tm_params.tp_gmt_offset = 0;
result.fe_time.tm_params.tp_dst_offset = 0;
PR_NormalizeTime(&result.fe_time, PR_GMTParameters);
// Note: The below is the RFC822/1123 format, as required by
// the application/http-index-format specs
// viewers of such a format can then reformat this into the
+1 -13
View File
@@ -171,10 +171,6 @@ static const char kGOOGLE_PIN_RapidSSLFingerprint[] =
static const char kGOOGLE_PIN_SymantecClass3EVG3Fingerprint[] =
"gMxWOrX4PMQesK9qFNbYBxjBfjUvlkn/vN1n+L9lE5E=";
/* GOOGLE_PIN_ThawtePremiumServer */
static const char kGOOGLE_PIN_ThawtePremiumServerFingerprint[] =
"9TwiBZgX3Zb0AGUWOdL4V+IQcKWavtkHlADZ9pVQaQA=";
/* GOOGLE_PIN_UTNDATACorpSGC */
static const char kGOOGLE_PIN_UTNDATACorpSGCFingerprint[] =
"QAL80xHQczFWfnG82XHkYEjI3OjRZZcRdTs9qiommvo=";
@@ -587,23 +583,15 @@ static const StaticFingerprints kPinset_twitterCDN = {
static const char* const kPinset_dropbox_Data[] = {
kEntrust_Root_Certification_Authority___EC1Fingerprint,
kGOOGLE_PIN_ThawtePremiumServerFingerprint,
kthawte_Primary_Root_CA___G3Fingerprint,
kthawte_Primary_Root_CAFingerprint,
kEntrust_net_Premium_2048_Secure_Server_CAFingerprint,
kDigiCert_Assured_ID_Root_CAFingerprint,
kGo_Daddy_Root_Certificate_Authority___G2Fingerprint,
kGOOGLE_PIN_GoDaddySecureFingerprint,
kGeoTrust_Primary_Certification_AuthorityFingerprint,
kGo_Daddy_Class_2_CAFingerprint,
kDigiCert_High_Assurance_EV_Root_CAFingerprint,
kthawte_Primary_Root_CA___G2Fingerprint,
kEntrust_Root_Certification_AuthorityFingerprint,
kEntrust_Root_Certification_Authority___G2Fingerprint,
kGeoTrust_Global_CAFingerprint,
kGeoTrust_Primary_Certification_Authority___G3Fingerprint,
kDigiCert_Global_Root_CAFingerprint,
kGeoTrust_Primary_Certification_Authority___G2Fingerprint,
};
static const StaticFingerprints kPinset_dropbox = {
sizeof(kPinset_dropbox_Data) / sizeof(const char*),
@@ -1176,4 +1164,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1506180744712000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1510159953770000);
File diff suppressed because it is too large Load Diff
+33 -8
View File
@@ -371,6 +371,10 @@ function openTabPrompt(domWin, tabPrompt, args) {
.getInterface(Ci.nsIDOMWindowUtils);
winUtils.enterModalState();
let frameMM = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
frameMM.QueryInterface(Ci.nsIDOMEventTarget);
// We provide a callback so the prompt can close itself. We don't want to
// wait for this event loop to return... Otherwise the presence of other
// prompts on the call stack would in this dialog appearing unresponsive
@@ -384,16 +388,25 @@ function openTabPrompt(domWin, tabPrompt, args) {
if (newPrompt)
tabPrompt.removePrompt(newPrompt);
domWin.removeEventListener("pagehide", pagehide);
frameMM.removeEventListener("pagehide", pagehide, true);
winUtils.leaveModalState();
PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed");
}
domWin.addEventListener("pagehide", pagehide);
function pagehide() {
domWin.removeEventListener("pagehide", pagehide);
frameMM.addEventListener("pagehide", pagehide, true);
function pagehide(e) {
// Check whether the event relates to our window or its ancestors
let window = domWin;
let eventWindow = e.target.defaultView;
while (window != eventWindow && window.parent != window) {
window = window.parent;
}
if (window != eventWindow) {
return;
}
frameMM.removeEventListener("pagehide", pagehide, true);
if (newPrompt) {
newPrompt.abortPrompt();
@@ -442,6 +455,9 @@ function openRemotePrompt(domWin, args, tabPrompt) {
winUtils.enterModalState();
let closed = false;
let frameMM = docShell.getInterface(Ci.nsIContentFrameMessageManager);
frameMM.QueryInterface(Ci.nsIDOMEventTarget);
// It should be hard or impossible to cause a window to create multiple
// prompts, but just in case, give our prompt an ID.
let id = "id" + Cc["@mozilla.org/uuid-generator;1"]
@@ -453,7 +469,7 @@ function openRemotePrompt(domWin, args, tabPrompt) {
}
messageManager.removeMessageListener("Prompt:Close", listener);
domWin.removeEventListener("pagehide", pagehide);
frameMM.removeEventListener("pagehide", pagehide, true);
winUtils.leaveModalState();
PromptUtils.fireDialogEvent(domWin, "DOMModalDialogClosed");
@@ -470,9 +486,18 @@ function openRemotePrompt(domWin, args, tabPrompt) {
closed = true;
});
domWin.addEventListener("pagehide", pagehide);
function pagehide() {
domWin.removeEventListener("pagehide", pagehide);
frameMM.addEventListener("pagehide", pagehide, true);
function pagehide(e) {
// Check whether the event relates to our window or its ancestors
let window = domWin;
let eventWindow = e.target.defaultView;
while (window != eventWindow && window.parent != window) {
window = window.parent;
}
if (window != eventWindow) {
return;
}
frameMM.removeEventListener("pagehide", pagehide, true);
messageManager.sendAsyncMessage("Prompt:ForceClose", { _remoteId: id });
}
+14 -1
View File
@@ -14,6 +14,7 @@
#include "nsIHttpChannel.h"
#include "nsIURL.h"
#include "nsISimpleEnumerator.h"
#include "nsISupportsPriority.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsXPIDLString.h"
@@ -134,7 +135,19 @@ nsPrefetchNode::OpenChannel()
false);
}
return mChannel->AsyncOpen2(this);
// Reduce the priority of prefetch network requests.
nsCOMPtr<nsISupportsPriority> priorityChannel = do_QueryInterface(mChannel);
if (priorityChannel) {
priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_LOWEST);
}
rv = mChannel->AsyncOpen2(this);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Drop the ref to the channel, because we don't want to end up with
// cycles through it.
mChannel = nullptr;
}
return rv;
}
nsresult