mirror of
https://github.com/roytam1/mozilla45esr.git
synced 2026-05-26 06:25:03 +00:00
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:
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3102,6 +3102,7 @@ static nsIAtom** sPropertiesToTraverseAndUnlink[] =
|
||||
&nsGkAtoms::itemprop,
|
||||
&nsGkAtoms::sandbox,
|
||||
&nsGkAtoms::sizes,
|
||||
&nsGkAtoms::dirAutoSetBy,
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
||||
+13
-5
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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); }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
|
||||
// nsIDOMNode
|
||||
NS_FORWARD_NSIDOMNODE_TO_NSINODE
|
||||
using mozilla::dom::Text::GetParentElement;
|
||||
|
||||
// nsIDOMCharacterData
|
||||
NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_,
|
||||
|
||||
@@ -154,6 +154,8 @@ nsHTMLEditor::~nsHTMLEditor()
|
||||
}
|
||||
|
||||
RemoveEventListeners();
|
||||
|
||||
HideAnonymousEditingUIs();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
|
||||
@@ -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("-");
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -597,6 +597,9 @@ class RRegExpReplace final : public RInstruction
|
||||
|
||||
class RStringReplace final : public RInstruction
|
||||
{
|
||||
private:
|
||||
bool isFlatReplacement_;
|
||||
|
||||
public:
|
||||
RINSTRUCTION_HEADER_(StringReplace)
|
||||
|
||||
|
||||
+26
-5
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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?");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
+4411
-1255
File diff suppressed because it is too large
Load Diff
@@ -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,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
|
||||
|
||||
Reference in New Issue
Block a user