зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland r=merge
This commit is contained in:
Коммит
bad2421650
|
@ -834,7 +834,7 @@ logging::Node(const char* aDescr, nsINode* aNode)
|
|||
}
|
||||
|
||||
nsINode* parentNode = aNode->GetParentNode();
|
||||
int32_t idxInParent = parentNode ? parentNode->IndexOf(aNode) : - 1;
|
||||
int32_t idxInParent = parentNode ? parentNode->ComputeIndexOf(aNode) : - 1;
|
||||
|
||||
if (aNode->IsNodeOfType(nsINode::eTEXT)) {
|
||||
printf("%s: %p, text node, idx in parent: %d\n",
|
||||
|
|
|
@ -428,7 +428,7 @@ HyperTextAccessible::OffsetToDOMPoint(int32_t aOffset)
|
|||
nsINode* node = child->GetNode();
|
||||
nsINode* parentNode = node->GetParentNode();
|
||||
return parentNode ?
|
||||
DOMPoint(parentNode, parentNode->IndexOf(node) + innerOffset) :
|
||||
DOMPoint(parentNode, parentNode->ComputeIndexOf(node) + innerOffset) :
|
||||
DOMPoint();
|
||||
}
|
||||
|
||||
|
@ -2081,7 +2081,7 @@ HyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame* aFrame, int32_t aOffset,
|
|||
|
||||
nsIContent* parent = content->GetParent();
|
||||
|
||||
aPoint->idx = parent->IndexOf(content) + 1;
|
||||
aPoint->idx = parent->ComputeIndexOf(content) + 1;
|
||||
aPoint->node = parent;
|
||||
|
||||
} else if (aFrame->IsTextFrame()) {
|
||||
|
@ -2101,7 +2101,7 @@ HyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame* aFrame, int32_t aOffset,
|
|||
nsIContent* parent = content->GetParent();
|
||||
NS_ENSURE_STATE(parent);
|
||||
|
||||
aPoint->idx = parent->IndexOf(content);
|
||||
aPoint->idx = parent->ComputeIndexOf(content);
|
||||
aPoint->node = parent;
|
||||
}
|
||||
|
||||
|
|
|
@ -4480,7 +4480,6 @@
|
|||
window.addEventListener("MozAfterPaint", this);
|
||||
window.addEventListener("MozLayerTreeReady", this);
|
||||
window.addEventListener("MozLayerTreeCleared", this);
|
||||
window.addEventListener("TabBrowserDiscarded", this);
|
||||
window.addEventListener("TabRemotenessChange", this);
|
||||
window.addEventListener("sizemodechange", this);
|
||||
window.addEventListener("occlusionstatechange", this);
|
||||
|
@ -4525,7 +4524,6 @@
|
|||
window.removeEventListener("MozAfterPaint", this);
|
||||
window.removeEventListener("MozLayerTreeReady", this);
|
||||
window.removeEventListener("MozLayerTreeCleared", this);
|
||||
window.removeEventListener("TabBrowserDiscarded", this);
|
||||
window.removeEventListener("TabRemotenessChange", this);
|
||||
window.removeEventListener("sizemodechange", this);
|
||||
window.removeEventListener("occlusionstatechange", this);
|
||||
|
@ -4969,12 +4967,6 @@
|
|||
}
|
||||
},
|
||||
|
||||
// Called when a tab is discarded
|
||||
onTabDiscarded(tab) {
|
||||
this.logState(`onTabDiscarded(${tab._tPos})`);
|
||||
this.setTabStateNoAction(tab, this.STATE_UNLOADED);
|
||||
},
|
||||
|
||||
// Called when a tab has been removed, and the browser node is
|
||||
// about to be removed from the DOM.
|
||||
onTabRemoved(tab) {
|
||||
|
@ -5211,8 +5203,6 @@
|
|||
this.onLayersCleared(event.originalTarget);
|
||||
} else if (event.type == "TabRemotenessChange") {
|
||||
this.onRemotenessChange(event.target);
|
||||
} else if (event.type == "TabBrowserDiscarded") {
|
||||
this.onTabDiscarded(event.target);
|
||||
} else if (event.type == "sizemodechange" ||
|
||||
event.type == "occlusionstatechange") {
|
||||
this.onSizeModeOrOcclusionStateChange();
|
||||
|
@ -6229,7 +6219,8 @@
|
|||
if (this.selectedBrowser == browser) {
|
||||
TabCrashHandler.onSelectedBrowserCrash(browser);
|
||||
} else {
|
||||
this.discardBrowser(browser);
|
||||
this.updateBrowserRemoteness(browser, false);
|
||||
SessionStore.reviveCrashedTab(tab);
|
||||
}
|
||||
|
||||
tab.removeAttribute("soundplaying");
|
||||
|
|
|
@ -1903,12 +1903,8 @@ var SessionStoreInternal = {
|
|||
|
||||
// Only restore if browser has been lazy.
|
||||
if (aTab.__SS_lazyData && !browser.__SS_restoreState && TabStateCache.get(browser)) {
|
||||
if (TabCrashHandler.willShowCrashedTab(browser)) {
|
||||
this.enterCrashedState(browser);
|
||||
} else {
|
||||
let tabState = TabState.clone(aTab);
|
||||
this.restoreTab(aTab, tabState);
|
||||
}
|
||||
let tabState = TabState.clone(aTab);
|
||||
this.restoreTab(aTab, tabState);
|
||||
}
|
||||
|
||||
// The browser has been inserted now, so lazy data is no longer relevant.
|
||||
|
@ -2124,7 +2120,20 @@ var SessionStoreInternal = {
|
|||
|
||||
if (browser.__SS_restoreState &&
|
||||
browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
|
||||
// If __SS_restoreState is still on the browser and it is
|
||||
// TAB_STATE_NEEDS_RESTORE, then then we haven't restored
|
||||
// this tab yet.
|
||||
//
|
||||
// It's possible that this tab was recently revived, and that
|
||||
// we've deferred showing the tab crashed page for it (if the
|
||||
// tab crashed in the background). If so, we need to re-enter
|
||||
// the crashed state, since we'll be showing the tab crashed
|
||||
// page.
|
||||
if (TabCrashHandler.willShowCrashedTab(browser)) {
|
||||
this.enterCrashedState(browser);
|
||||
} else {
|
||||
this.restoreTabContent(tab);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2883,7 +2892,19 @@ var SessionStoreInternal = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Sanity check - the browser to be revived should not be remote
|
||||
// at this point.
|
||||
if (browser.isRemoteBrowser) {
|
||||
throw new Error("SessionStore.reviveCrashedTab: " +
|
||||
"Somehow a crashed browser is still remote.");
|
||||
}
|
||||
|
||||
// We put the browser at about:blank in case the user is
|
||||
// restoring tabs on demand. This way, the user won't see
|
||||
// a flash of the about:tabcrashed page after selecting
|
||||
// the revived tab.
|
||||
aTab.removeAttribute("crashed");
|
||||
browser.loadURI("about:blank", null, null);
|
||||
|
||||
let data = TabState.collect(aTab);
|
||||
this.restoreTab(aTab, data, {
|
||||
|
|
|
@ -81,13 +81,22 @@ async function crashBackgroundTabs(tabs) {
|
|||
Assert.ok(tab.linkedBrowser.isRemoteBrowser, "tab is remote");
|
||||
}
|
||||
|
||||
let remotenessChangePromises = tabs.map((t) => {
|
||||
return BrowserTestUtils.waitForEvent(t, "TabRemotenessChange");
|
||||
});
|
||||
|
||||
let tabsRevived = tabs.map((t) => {
|
||||
return promiseTabRestoring(t);
|
||||
});
|
||||
|
||||
await BrowserTestUtils.crashBrowser(tabs[0].linkedBrowser, false);
|
||||
await Promise.all(remotenessChangePromises);
|
||||
await Promise.all(tabsRevived);
|
||||
|
||||
// Both background tabs should now be in the pending restore
|
||||
// state.
|
||||
for (let tab of tabs) {
|
||||
Assert.ok(!tab.linkedPanel, "The tab should be initially discarded.");
|
||||
Assert.ok(tab.linkedBrowser.isRemoteBrowser, "tab is still remote");
|
||||
Assert.ok(!tab.linkedBrowser.isRemoteBrowser, "tab is not remote");
|
||||
Assert.ok(!tab.linkedBrowser.hasAttribute("crashed"), "tab is not crashed");
|
||||
Assert.ok(tab.hasAttribute("pending"), "tab is pending");
|
||||
}
|
||||
|
@ -117,9 +126,9 @@ add_task(async function test_background_crash_simple() {
|
|||
|
||||
// Selecting the first tab should now send it to the tab crashed page.
|
||||
let tabCrashedPagePromise =
|
||||
BrowserTestUtils.waitForEvent(window,
|
||||
"AboutTabCrashedReady",
|
||||
false, null, true);
|
||||
BrowserTestUtils.waitForContentEvent(tab1.linkedBrowser,
|
||||
"AboutTabCrashedReady",
|
||||
false, null, true);
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab1);
|
||||
await tabCrashedPagePromise;
|
||||
|
||||
|
|
|
@ -32,11 +32,15 @@ add_task(async function test_revive_bg_tabs_on_demand() {
|
|||
await TabStateFlusher.flush(browser2);
|
||||
|
||||
// Now crash the selected tab
|
||||
let windowReady = BrowserTestUtils.waitForEvent(window, "SSWindowStateReady");
|
||||
await BrowserTestUtils.crashBrowser(browser1);
|
||||
|
||||
ok(newTab1.hasAttribute("crashed"), "Selected tab should be crashed");
|
||||
ok(!newTab2.hasAttribute("crashed"), "Background tab should not be crashed");
|
||||
|
||||
// Wait until we've had a chance to restore all tabs immediately
|
||||
await windowReady;
|
||||
|
||||
// But we should not have restored the background tab
|
||||
ok(newTab2.hasAttribute("pending"), "Background tab should be pending");
|
||||
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
ac_add_options --disable-debug
|
||||
ac_add_options --enable-optimize="-O2 -gline-tables-only"
|
||||
|
||||
#add-on signing is checked but not enforced
|
||||
MOZ_REQUIRE_SIGNING=0
|
||||
# Enable MOZ_ALLOW_LEGACY_EXTENSIONS
|
||||
ac_add_options "MOZ_ALLOW_LEGACY_EXTENSIONS=1"
|
||||
|
||||
. $topsrcdir/build/mozconfig.stylo
|
||||
|
||||
# ASan specific options on Linux
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
gn_vars = {}
|
||||
|
||||
if CONFIG['MOZ_DEBUG']:
|
||||
gn_vars['is_debug'] = True
|
||||
else:
|
||||
gn_vars['is_debug'] = False
|
||||
|
||||
os = CONFIG['OS_TARGET']
|
||||
|
||||
flavors = {
|
||||
'WINNT': 'win',
|
||||
'Android': 'android',
|
||||
'Linux': 'linux',
|
||||
'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
|
||||
'SunOS': 'solaris',
|
||||
'GNU/kFreeBSD': 'freebsd',
|
||||
'DragonFly': 'dragonfly',
|
||||
'FreeBSD': 'freebsd',
|
||||
'NetBSD': 'netbsd',
|
||||
'OpenBSD': 'openbsd',
|
||||
}
|
||||
gn_vars['target_os'] = flavors.get(os)
|
||||
|
||||
arches = {
|
||||
'x86_64': 'x64',
|
||||
'aarch64': 'arm64',
|
||||
}
|
||||
|
||||
gn_vars['host_cpu'] = arches.get(CONFIG['HOST_CPU_ARCH'], CONFIG['HOST_CPU_ARCH'])
|
||||
gn_vars['target_cpu'] = arches.get(CONFIG['CPU_ARCH'], CONFIG['CPU_ARCH'])
|
|
@ -279,14 +279,14 @@ Attr::GetChildAt_Deprecated(uint32_t aIndex) const
|
|||
}
|
||||
|
||||
int32_t
|
||||
Attr::IndexOf(const nsINode* aPossibleChild) const
|
||||
Attr::ComputeIndexOf(const nsINode* aPossibleChild) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Attr::InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
Attr::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -63,9 +63,9 @@ public:
|
|||
virtual bool IsNodeOfType(uint32_t aFlags) const override;
|
||||
virtual uint32_t GetChildCount() const override;
|
||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||
virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
|
|
|
@ -554,7 +554,7 @@ int32_t
|
|||
nsAttrChildContentList::IndexOf(nsIContent* aContent)
|
||||
{
|
||||
if (mNode) {
|
||||
return mNode->IndexOf(aContent);
|
||||
return mNode->ComputeIndexOf(aContent);
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -1157,9 +1157,9 @@ nsIContent::SetXBLInsertionPoint(nsIContent* aContent)
|
|||
}
|
||||
|
||||
nsresult
|
||||
FragmentOrElement::InsertChildAt(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
FragmentOrElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(aKid, "null ptr");
|
||||
|
||||
|
@ -1182,7 +1182,7 @@ FragmentOrElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
|||
{
|
||||
// Let's keep the node alive.
|
||||
nsCOMPtr<nsIContent> kungFuDeathGrip = aKid;
|
||||
doRemoveChildAt(IndexOf(aKid), aNotify, aKid, mAttrsAndChildren);
|
||||
doRemoveChildAt(ComputeIndexOf(aKid), aNotify, aKid, mAttrsAndChildren);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2140,7 +2140,7 @@ FragmentOrElement::GetChildAt_Deprecated(uint32_t aIndex) const
|
|||
}
|
||||
|
||||
int32_t
|
||||
FragmentOrElement::IndexOf(const nsINode* aPossibleChild) const
|
||||
FragmentOrElement::ComputeIndexOf(const nsINode* aPossibleChild) const
|
||||
{
|
||||
return mAttrsAndChildren.IndexOfChild(aPossibleChild);
|
||||
}
|
||||
|
|
|
@ -119,9 +119,9 @@ public:
|
|||
// nsINode interface methods
|
||||
virtual uint32_t GetChildCount() const override;
|
||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||
virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
|
|
|
@ -178,7 +178,7 @@ public:
|
|||
|
||||
MOZ_ASSERT(mRef);
|
||||
MOZ_ASSERT(mRef->GetParentNode() == mParent);
|
||||
mOffset = mozilla::Some(mParent->IndexOf(mRef) + 1);
|
||||
mOffset = mozilla::Some(mParent->ComputeIndexOf(mRef) + 1);
|
||||
|
||||
return mOffset.value();
|
||||
}
|
||||
|
|
|
@ -1686,7 +1686,7 @@ Selection::GetPrimaryFrameForFocusNode(nsIFrame** aReturnFrame,
|
|||
if (NS_WARN_IF(!parent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
int32_t offset = parent->IndexOf(content);
|
||||
int32_t offset = parent->ComputeIndexOf(content);
|
||||
|
||||
return GetPrimaryOrCaretFrameForNodeOffset(parent, offset, aReturnFrame,
|
||||
aOffsetUsed, aVisual);
|
||||
|
@ -2585,7 +2585,7 @@ Selection::Collapse(const RawRangeBoundary& aPoint, ErrorResult& aRv)
|
|||
// done yet. However, it's called only when the container is a text
|
||||
// node. In such case, offset has always been set since it cannot have
|
||||
// any children. So, this doesn't cause computing offset with expensive
|
||||
// method, nsINode::IndexOf().
|
||||
// method, nsINode::ComputeIndexOf().
|
||||
if ((aPoint.Container()->AsContent() == f->GetContent() &&
|
||||
f->GetContentEnd() == static_cast<int32_t>(aPoint.Offset())) ||
|
||||
(aPoint.Container() == f->GetContent()->GetParentNode() &&
|
||||
|
|
|
@ -182,8 +182,8 @@ protected:
|
|||
// end to the common ancestor. If we used the index array, we would pay the
|
||||
// price up front for n, and then pay the cost for m on the fly later on.
|
||||
// With the simple cache, we only "pay as we go". Either way, we call
|
||||
// IndexOf() once for each change of level in the hierarchy. Since a trivial
|
||||
// index is much simpler, we use it for the subtree iterator.
|
||||
// ComputeIndexOf() once for each change of level in the hierarchy. Since
|
||||
// a trivial index is much simpler, we use it for the subtree iterator.
|
||||
|
||||
bool mIsDone;
|
||||
bool mPre;
|
||||
|
@ -563,7 +563,7 @@ nsContentIterator::RebuildIndexStack()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mIndexes.InsertElementAt(0, parent->IndexOf(current));
|
||||
mIndexes.InsertElementAt(0, parent->ComputeIndexOf(current));
|
||||
|
||||
current = parent;
|
||||
}
|
||||
|
@ -689,12 +689,12 @@ nsContentIterator::GetNextSibling(nsINode* aNode,
|
|||
NS_WARNING_ASSERTION(indx >= 0, "bad indx");
|
||||
|
||||
// reverify that the index of the current node hasn't changed.
|
||||
// not super cheap, but a lot cheaper than IndexOf(), and still O(1).
|
||||
// ignore result this time - the index may now be out of range.
|
||||
// not super cheap, but a lot cheaper than ComputeIndexOf(), and still
|
||||
// O(1). ignore result this time - the index may now be out of range.
|
||||
nsIContent* sib = parent->GetChildAt_Deprecated(indx);
|
||||
if (sib != aNode) {
|
||||
// someone changed our index - find the new index the painful way
|
||||
indx = parent->IndexOf(aNode);
|
||||
indx = parent->ComputeIndexOf(aNode);
|
||||
NS_WARNING_ASSERTION(indx >= 0, "bad indx");
|
||||
}
|
||||
|
||||
|
@ -755,7 +755,7 @@ nsContentIterator::GetPrevSibling(nsINode* aNode,
|
|||
nsIContent* sib = parent->GetChildAt_Deprecated(indx);
|
||||
if (sib != aNode) {
|
||||
// someone changed our index - find the new index the painful way
|
||||
indx = parent->IndexOf(aNode);
|
||||
indx = parent->ComputeIndexOf(aNode);
|
||||
NS_WARNING_ASSERTION(indx >= 0, "bad indx");
|
||||
}
|
||||
|
||||
|
@ -826,14 +826,14 @@ nsContentIterator::NextNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
|
|||
}
|
||||
|
||||
// reverify that the index of the current node hasn't changed. not super
|
||||
// cheap, but a lot cheaper than IndexOf(), and still O(1). ignore result
|
||||
// this time - the index may now be out of range.
|
||||
// cheap, but a lot cheaper than ComputeIndexOf(), and still O(1). ignore
|
||||
// result this time - the index may now be out of range.
|
||||
if (indx >= 0) {
|
||||
sibling = parent->GetChildAt_Deprecated(indx);
|
||||
}
|
||||
if (sibling != node) {
|
||||
// someone changed our index - find the new index the painful way
|
||||
indx = parent->IndexOf(node);
|
||||
indx = parent->ComputeIndexOf(node);
|
||||
NS_WARNING_ASSERTION(indx >= 0, "bad indx");
|
||||
}
|
||||
|
||||
|
@ -895,8 +895,8 @@ nsContentIterator::PrevNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
|
|||
}
|
||||
|
||||
// reverify that the index of the current node hasn't changed. not super
|
||||
// cheap, but a lot cheaper than IndexOf(), and still O(1). ignore result
|
||||
// this time - the index may now be out of range.
|
||||
// cheap, but a lot cheaper than ComputeIndexOf(), and still O(1).
|
||||
// ignore result this time - the index may now be out of range.
|
||||
if (indx >= 0) {
|
||||
sibling = parent->GetChildAt_Deprecated(indx);
|
||||
NS_WARNING_ASSERTION(sibling, "GetChildAt_Deprecated returned null");
|
||||
|
@ -904,7 +904,7 @@ nsContentIterator::PrevNode(nsINode* aNode, nsTArray<int32_t>* aIndexes)
|
|||
|
||||
if (sibling != node) {
|
||||
// someone changed our index - find the new index the painful way
|
||||
indx = parent->IndexOf(node);
|
||||
indx = parent->ComputeIndexOf(node);
|
||||
NS_WARNING_ASSERTION(indx >= 0, "bad indx");
|
||||
}
|
||||
|
||||
|
@ -1098,9 +1098,9 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
|
|||
|
||||
// Get a list of the parents up to the root, then compare the new node with
|
||||
// entries in that array until we find a match (lowest common ancestor). If
|
||||
// no match, use IndexOf, take the parent, and repeat. This avoids using
|
||||
// IndexOf() N times on possibly large arrays. We still end up doing it a
|
||||
// fair bit. It's better to use Clone() if possible.
|
||||
// no match, use ComputeIndexOf, take the parent, and repeat. This avoids
|
||||
// using ComputeIndexOf() N times on possibly large arrays. We still end
|
||||
// up doing it a fair bit. It's better to use Clone() if possible.
|
||||
|
||||
// we know the depth we're down (though we may not have started at the top).
|
||||
oldParentStack.SetCapacity(mIndexes.Length() + 1);
|
||||
|
@ -1140,7 +1140,7 @@ nsContentIterator::PositionAt(nsINode* aCurNode)
|
|||
break;
|
||||
}
|
||||
|
||||
int32_t indx = parent->IndexOf(newCurNode);
|
||||
int32_t indx = parent->ComputeIndexOf(newCurNode);
|
||||
NS_WARNING_ASSERTION(indx >= 0, "bad indx");
|
||||
|
||||
// insert at the head!
|
||||
|
|
|
@ -2314,7 +2314,7 @@ nsContentUtils::InProlog(nsINode *aNode)
|
|||
nsIDocument* doc = static_cast<nsIDocument*>(parent);
|
||||
nsIContent* root = doc->GetRootElement();
|
||||
|
||||
return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
|
||||
return !root || doc->ComputeIndexOf(aNode) < doc->ComputeIndexOf(root);
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
|
@ -2659,7 +2659,7 @@ nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode* aNode,
|
|||
nsIContent* parent = child->GetParent();
|
||||
while (parent) {
|
||||
aAncestorNodes->AppendElement(parent);
|
||||
aAncestorOffsets->AppendElement(parent->IndexOf(child));
|
||||
aAncestorOffsets->AppendElement(parent->ComputeIndexOf(child));
|
||||
child = parent;
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
@ -2769,8 +2769,8 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
|||
{
|
||||
if (aParent1 == aParent2) {
|
||||
// XXX This is odd. aOffset1 and/or aOffset2 may be -1, e.g., it's result
|
||||
// of nsINode::IndexOf(), but this compares such invalid offset with
|
||||
// valid offset.
|
||||
// of nsINode::ComputeIndexOf(), but this compares such invalid
|
||||
// offset with valid offset.
|
||||
return aOffset1 < aOffset2 ? -1 :
|
||||
aOffset1 > aOffset2 ? 1 :
|
||||
0;
|
||||
|
@ -2807,7 +2807,7 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
|||
nsINode* child1 = parents1.ElementAt(--pos1);
|
||||
nsINode* child2 = parents2.ElementAt(--pos2);
|
||||
if (child1 != child2) {
|
||||
return parent->IndexOf(child1) < parent->IndexOf(child2) ? -1 : 1;
|
||||
return parent->ComputeIndexOf(child1) < parent->ComputeIndexOf(child2) ? -1 : 1;
|
||||
}
|
||||
parent = child1;
|
||||
}
|
||||
|
@ -2823,13 +2823,13 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
|||
nsINode* child2 = parents2.ElementAt(--pos2);
|
||||
// XXX aOffset1 may be -1 as mentioned above. So, why does this return
|
||||
// it's *before* of the valid DOM point?
|
||||
return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
|
||||
return aOffset1 <= parent->ComputeIndexOf(child2) ? -1 : 1;
|
||||
}
|
||||
|
||||
nsINode* child1 = parents1.ElementAt(--pos1);
|
||||
// XXX aOffset2 may be -1 as mentioned above. So, why does this return it's
|
||||
// *after* of the valid DOM point?
|
||||
return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
|
||||
return parent->ComputeIndexOf(child1) < aOffset2 ? -1 : 1;
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -3144,7 +3144,7 @@ nsContentUtils::GenerateStateKey(nsIContent* aContent,
|
|||
nsINode* parent = aContent->GetParentNode();
|
||||
nsINode* content = aContent;
|
||||
while (parent) {
|
||||
KeyAppendInt(parent->IndexOf(content), aKey);
|
||||
KeyAppendInt(parent->ComputeIndexOf(content), aKey);
|
||||
content = parent;
|
||||
parent = content->GetParentNode();
|
||||
}
|
||||
|
|
|
@ -4351,7 +4351,7 @@ nsDocument::GetChildAt_Deprecated(uint32_t aIndex) const
|
|||
}
|
||||
|
||||
int32_t
|
||||
nsDocument::IndexOf(const nsINode* aPossibleChild) const
|
||||
nsDocument::ComputeIndexOf(const nsINode* aPossibleChild) const
|
||||
{
|
||||
return mChildren.IndexOfChild(aPossibleChild);
|
||||
}
|
||||
|
@ -4363,8 +4363,8 @@ nsDocument::GetChildCount() const
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
nsDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
if (aKid->IsElement() && GetRootElement()) {
|
||||
NS_WARNING("Inserting root element when we already have one");
|
||||
|
@ -4417,7 +4417,7 @@ nsDocument::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
|||
// Any call before that point would restore this soon-to-be-obsolete cached
|
||||
// answer, and our clearing here would be fruitless.)
|
||||
mCachedRootElement = nullptr;
|
||||
doRemoveChildAt(IndexOf(aKid), aNotify, aKid, mChildren);
|
||||
doRemoveChildAt(ComputeIndexOf(aKid), aNotify, aKid, mChildren);
|
||||
MOZ_ASSERT(mCachedRootElement != aKid,
|
||||
"Stale pointer in mCachedRootElement, after we tried to clear it "
|
||||
"(maybe somebody called GetRootElement() too early?)");
|
||||
|
@ -6881,7 +6881,7 @@ nsDocument::SetTitle(const nsAString& aTitle)
|
|||
if (!title) {
|
||||
return NS_OK;
|
||||
}
|
||||
rootElement->InsertChildAt(title, 0, true);
|
||||
rootElement->InsertChildAt_Deprecated(title, 0, true);
|
||||
}
|
||||
} else if (rootElement->IsHTMLElement()) {
|
||||
if (!title) {
|
||||
|
|
|
@ -555,10 +555,10 @@ public:
|
|||
// nsINode
|
||||
virtual bool IsNodeOfType(uint32_t aFlags) const override;
|
||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||
virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual uint32_t GetChildCount() const override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
|
|
|
@ -1797,7 +1797,7 @@ nsHTMLCopyEncoder::GetNodeLocation(nsIDOMNode *inChild,
|
|||
if (!cChild || !content)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*outOffset = content->IndexOf(cChild);
|
||||
*outOffset = content->ComputeIndexOf(cChild);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -3372,7 +3372,7 @@ nsFocusManager::GetNextTabbableMapArea(bool aForward,
|
|||
uint32_t count = mapContent->GetChildCount();
|
||||
// First see if the the start content is in this map
|
||||
|
||||
int32_t index = mapContent->IndexOf(aStartContent);
|
||||
int32_t index = mapContent->ComputeIndexOf(aStartContent);
|
||||
int32_t tabIndex;
|
||||
if (index < 0 || (aStartContent->IsFocusable(&tabIndex) &&
|
||||
tabIndex != aCurrentTabIndex)) {
|
||||
|
|
|
@ -646,14 +646,15 @@ nsGenericDOMDataNode::GetChildAt_Deprecated(uint32_t aIndex) const
|
|||
|
||||
|
||||
int32_t
|
||||
nsGenericDOMDataNode::IndexOf(const nsINode* aPossibleChild) const
|
||||
nsGenericDOMDataNode::ComputeIndexOf(const nsINode* aPossibleChild) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericDOMDataNode::InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
nsGenericDOMDataNode::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -754,11 +755,11 @@ nsGenericDOMDataNode::SplitData(uint32_t aOffset, nsIContent** aReturn,
|
|||
|
||||
nsCOMPtr<nsINode> parent = GetParentNode();
|
||||
if (parent) {
|
||||
int32_t insertionIndex = parent->IndexOf(this);
|
||||
int32_t insertionIndex = parent->ComputeIndexOf(this);
|
||||
if (aCloneAfterOriginal) {
|
||||
++insertionIndex;
|
||||
}
|
||||
parent->InsertChildAt(newContent, insertionIndex, true);
|
||||
parent->InsertChildAt_Deprecated(newContent, insertionIndex, true);
|
||||
}
|
||||
|
||||
newContent.swap(*aReturn);
|
||||
|
@ -820,7 +821,7 @@ nsGenericDOMDataNode::GetWholeText(nsAString& aWholeText)
|
|||
if (!parent)
|
||||
return GetData(aWholeText);
|
||||
|
||||
int32_t index = parent->IndexOf(this);
|
||||
int32_t index = parent->ComputeIndexOf(this);
|
||||
NS_WARNING_ASSERTION(index >= 0,
|
||||
"Trying to use .wholeText with an anonymous"
|
||||
"text node child of a binding parent?");
|
||||
|
|
|
@ -106,9 +106,9 @@ public:
|
|||
// nsINode methods
|
||||
virtual uint32_t GetChildCount() const override;
|
||||
virtual nsIContent *GetChildAt_Deprecated(uint32_t aIndex) const override;
|
||||
virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual void GetTextContentInternal(nsAString& aTextContent,
|
||||
|
|
|
@ -607,7 +607,7 @@ nsINode::RemoveChild(nsINode& aOldChild, ErrorResult& aError)
|
|||
nsContentUtils::MaybeFireNodeRemoved(&aOldChild, this, OwnerDoc());
|
||||
}
|
||||
|
||||
int32_t index = IndexOf(&aOldChild);
|
||||
int32_t index = ComputeIndexOf(&aOldChild);
|
||||
if (index == -1) {
|
||||
// aOldChild isn't one of our children.
|
||||
aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
|
@ -721,7 +721,7 @@ nsINode::Normalize()
|
|||
"Should always have a parent unless "
|
||||
"mutation events messed us up");
|
||||
if (parent) {
|
||||
parent->RemoveChildAt_Deprecated(parent->IndexOf(node), true);
|
||||
parent->RemoveChildAt_Deprecated(parent->ComputeIndexOf(node), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1005,9 +1005,9 @@ nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
|
|||
const nsINode* child2 = parents2.ElementAt(--pos2);
|
||||
if (child1 != child2) {
|
||||
// child1 or child2 can be an attribute here. This will work fine since
|
||||
// IndexOf will return -1 for the attribute making the attribute be
|
||||
// considered before any child.
|
||||
return parent->IndexOf(child1) < parent->IndexOf(child2) ?
|
||||
// ComputeIndexOf will return -1 for the attribute making the
|
||||
// attribute be considered before any child.
|
||||
return parent->ComputeIndexOf(child1) < parent->ComputeIndexOf(child2) ?
|
||||
static_cast<uint16_t>(nsIDOMNode::DOCUMENT_POSITION_PRECEDING) :
|
||||
static_cast<uint16_t>(nsIDOMNode::DOCUMENT_POSITION_FOLLOWING);
|
||||
}
|
||||
|
@ -1474,7 +1474,7 @@ nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
|
|||
nsIContent* parent = tmp->GetParent();
|
||||
if (parent && !parent->UnoptimizableCCNode() &&
|
||||
parent->HasKnownLiveWrapper()) {
|
||||
MOZ_ASSERT(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
|
||||
MOZ_ASSERT(parent->ComputeIndexOf(tmp) >= 0, "Parent doesn't own us?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1930,7 +1930,7 @@ nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
|
|||
// nsDocument::RemoveChildNode().
|
||||
MOZ_ASSERT(aKid && aKid->GetParentNode() == this &&
|
||||
aKid == GetChildAt_Deprecated(aIndex) &&
|
||||
IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
|
||||
ComputeIndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
|
||||
MOZ_ASSERT(!IsNodeOfType(nsINode::eATTRIBUTE));
|
||||
|
||||
nsMutationGuard::DidMutate();
|
||||
|
@ -2025,8 +2025,8 @@ bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
|
|||
return true;
|
||||
}
|
||||
|
||||
int32_t doctypeIndex = aParent->IndexOf(docTypeContent);
|
||||
int32_t insertIndex = aParent->IndexOf(aRefChild);
|
||||
int32_t doctypeIndex = aParent->ComputeIndexOf(docTypeContent);
|
||||
int32_t insertIndex = aParent->ComputeIndexOf(aRefChild);
|
||||
|
||||
// Now we're OK in the following two cases only:
|
||||
// 1) We're replacing something that's not before the doctype
|
||||
|
@ -2061,8 +2061,8 @@ bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
|
|||
return false;
|
||||
}
|
||||
|
||||
int32_t rootIndex = aParent->IndexOf(rootElement);
|
||||
int32_t insertIndex = aParent->IndexOf(aRefChild);
|
||||
int32_t rootIndex = aParent->ComputeIndexOf(rootElement);
|
||||
int32_t insertIndex = aParent->ComputeIndexOf(aRefChild);
|
||||
|
||||
// Now we're OK if and only if insertIndex <= rootIndex. Indeed, either
|
||||
// we end up replacing aRefChild or we end up before it. Either one is
|
||||
|
@ -2180,7 +2180,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
// Scope firing mutation events so that we don't carry any state that
|
||||
// might be stale
|
||||
{
|
||||
// This check happens again further down (though then using IndexOf).
|
||||
// This check happens again further down (though then using
|
||||
// ComputeIndexOf).
|
||||
// We're only checking this here to avoid firing mutation events when
|
||||
// none should be fired.
|
||||
// It's ok that we do the check twice in the case when firing mutation
|
||||
|
@ -2240,7 +2241,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
nsIContent* newContent = aNewChild->AsContent();
|
||||
nsCOMPtr<nsINode> oldParent = newContent->GetParentNode();
|
||||
if (oldParent) {
|
||||
int32_t removeIndex = oldParent->IndexOf(newContent);
|
||||
int32_t removeIndex = oldParent->ComputeIndexOf(newContent);
|
||||
if (removeIndex < 0) {
|
||||
// newContent is anonymous. We can't deal with this, so just bail
|
||||
NS_ERROR("How come our flags didn't catch this?");
|
||||
|
@ -2415,7 +2416,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
// parent list.
|
||||
int32_t insPos;
|
||||
if (nodeToInsertBefore) {
|
||||
insPos = IndexOf(nodeToInsertBefore);
|
||||
insPos = ComputeIndexOf(nodeToInsertBefore);
|
||||
if (insPos < 0) {
|
||||
// XXXbz How the heck would _that_ happen, exactly?
|
||||
aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
|
@ -2491,8 +2492,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
for (uint32_t i = 0; i < count; ++i, ++insPos) {
|
||||
// XXXbz how come no reparenting here? That seems odd...
|
||||
// Insert the child.
|
||||
aError = InsertChildAt(fragChildren->ElementAt(i), insPos,
|
||||
!appending);
|
||||
aError = InsertChildAt_Deprecated(fragChildren->ElementAt(i), insPos,
|
||||
!appending);
|
||||
if (aError.Failed()) {
|
||||
// Make sure to notify on any children that we did succeed to insert
|
||||
if (appending && i != 0) {
|
||||
|
@ -2534,7 +2535,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
mb.SetPrevSibling(GetChildAt_Deprecated(insPos - 1));
|
||||
mb.SetNextSibling(GetChildAt_Deprecated(insPos));
|
||||
}
|
||||
aError = InsertChildAt(newContent, insPos, true);
|
||||
aError = InsertChildAt_Deprecated(newContent, insPos, true);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -519,7 +519,7 @@ public:
|
|||
* If the return value is not -1, then calling GetChildAt_Deprecated() with
|
||||
* that value will return aPossibleChild.
|
||||
*/
|
||||
virtual int32_t IndexOf(const nsINode* aPossibleChild) const = 0;
|
||||
virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the "node document" of this node.
|
||||
|
@ -736,8 +736,8 @@ public:
|
|||
*
|
||||
* @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
|
||||
*/
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) = 0;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Append a content node to the end of the child list. This method handles
|
||||
|
@ -759,7 +759,7 @@ public:
|
|||
*/
|
||||
nsresult AppendChildTo(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
return InsertChildAt(aKid, GetChildCount(), aNotify);
|
||||
return InsertChildAt_Deprecated(aKid, GetChildCount(), aNotify);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2093,7 +2093,7 @@ protected:
|
|||
nsAttrAndChildArray& aChildArray);
|
||||
|
||||
/**
|
||||
* Most of the implementation of the nsINode InsertChildAt method.
|
||||
* Most of the implementation of the nsINode InsertChildAt_Deprecated method.
|
||||
* Should only be called on document, element, and document fragment
|
||||
* nodes. The aChildArray passed in should be the one for |this|.
|
||||
*
|
||||
|
|
|
@ -123,7 +123,7 @@ nsRange::CompareNodeToRange(nsINode* aNode, nsRange* aRange,
|
|||
nodeEnd = static_cast<int32_t>(childCount);
|
||||
}
|
||||
else {
|
||||
nodeStart = parent->IndexOf(aNode);
|
||||
nodeStart = parent->ComputeIndexOf(aNode);
|
||||
nodeEnd = nodeStart + 1;
|
||||
MOZ_ASSERT(nodeStart < nodeEnd, "nodeStart shouldn't be INT32_MAX");
|
||||
}
|
||||
|
@ -969,7 +969,7 @@ nsRange::IntersectsNode(nsINode& aNode, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
// Step 5.
|
||||
int32_t nodeIndex = parent->IndexOf(&aNode);
|
||||
int32_t nodeIndex = parent->ComputeIndexOf(&aNode);
|
||||
|
||||
// Steps 6-7.
|
||||
// Note: if disconnected is true, ComparePoints returns 1.
|
||||
|
@ -1104,7 +1104,7 @@ IndexOf(nsINode* aChild)
|
|||
{
|
||||
nsINode* parent = aChild->GetParentNode();
|
||||
|
||||
return parent ? parent->IndexOf(aChild) : -1;
|
||||
return parent ? parent->ComputeIndexOf(aChild) : -1;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1571,9 +1571,10 @@ nsRange::SelectNodesInContainer(nsINode* aContainer,
|
|||
nsIContent* aEndContent)
|
||||
{
|
||||
MOZ_ASSERT(aContainer);
|
||||
MOZ_ASSERT(aContainer->IndexOf(aStartContent) <= aContainer->IndexOf(aEndContent));
|
||||
MOZ_ASSERT(aStartContent && aContainer->IndexOf(aStartContent) != -1);
|
||||
MOZ_ASSERT(aEndContent && aContainer->IndexOf(aEndContent) != -1);
|
||||
MOZ_ASSERT(aContainer->ComputeIndexOf(aStartContent) <=
|
||||
aContainer->ComputeIndexOf(aEndContent));
|
||||
MOZ_ASSERT(aStartContent && aContainer->ComputeIndexOf(aStartContent) != -1);
|
||||
MOZ_ASSERT(aEndContent && aContainer->ComputeIndexOf(aEndContent) != -1);
|
||||
|
||||
nsINode* newRoot = ComputeRootNode(aContainer, mMaySpanAnonymousSubtrees);
|
||||
MOZ_ASSERT(newRoot);
|
||||
|
@ -1780,7 +1781,7 @@ nsRange::SelectNode(nsINode& aNode, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t index = container->IndexOf(&aNode);
|
||||
int32_t index = container->ComputeIndexOf(&aNode);
|
||||
// MOZ_ASSERT(index != -1);
|
||||
// We need to compute the index here unfortunately, because, while we have
|
||||
// support for XBL, |container| may be the node's binding parent without
|
||||
|
@ -3676,7 +3677,7 @@ nsRange::ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges)
|
|||
if (content && content->HasIndependentSelection()) {
|
||||
nsINode* parent = startContainer->GetParent();
|
||||
if (parent) {
|
||||
startOffset = parent->IndexOf(startContainer);
|
||||
startOffset = parent->ComputeIndexOf(startContainer);
|
||||
startContainer = parent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -257,7 +257,7 @@ public:
|
|||
if (!parentNode) {
|
||||
return nullptr;
|
||||
}
|
||||
int32_t indexInParent = parentNode->IndexOf(aNode);
|
||||
int32_t indexInParent = parentNode->ComputeIndexOf(aNode);
|
||||
if (NS_WARN_IF(indexInParent < 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ public:
|
|||
if (!parentNode) {
|
||||
return nullptr;
|
||||
}
|
||||
int32_t indexInParent = parentNode->IndexOf(aNode);
|
||||
int32_t indexInParent = parentNode->ComputeIndexOf(aNode);
|
||||
if (NS_WARN_IF(indexInParent < 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -475,8 +475,8 @@ protected:
|
|||
/**
|
||||
* XXX nsRange should accept 0 - UINT32_MAX as offset. However, users of
|
||||
* nsRange treat offset as int32_t. Additionally, some other internal
|
||||
* APIs like nsINode::IndexOf() use int32_t. Therefore, nsRange should
|
||||
* accept only 0 - INT32_MAX as valid offset for now.
|
||||
* APIs like nsINode::ComputeIndexOf() use int32_t. Therefore,
|
||||
* nsRange should accept only 0 - INT32_MAX as valid offset for now.
|
||||
*/
|
||||
static bool IsValidOffset(uint32_t aOffset)
|
||||
{
|
||||
|
|
|
@ -1208,7 +1208,7 @@ ContentEventHandler::SetRawRangeFromFlatTextOffset(
|
|||
if (NS_WARN_IF(!startNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
startNodeOffset = startNode->IndexOf(content);
|
||||
startNodeOffset = startNode->ComputeIndexOf(content);
|
||||
if (NS_WARN_IF(startNodeOffset == -1)) {
|
||||
// The content is being removed from the parent!
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1219,7 +1219,7 @@ ContentEventHandler::SetRawRangeFromFlatTextOffset(
|
|||
if (NS_WARN_IF(!startNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
startNodeOffset = startNode->IndexOf(content) + 1;
|
||||
startNodeOffset = startNode->ComputeIndexOf(content) + 1;
|
||||
if (NS_WARN_IF(startNodeOffset == 0)) {
|
||||
// The content is being removed from the parent!
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1312,7 +1312,7 @@ ContentEventHandler::SetRawRangeFromFlatTextOffset(
|
|||
if (NS_WARN_IF(!endNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
int32_t indexInParent = endNode->IndexOf(content);
|
||||
int32_t indexInParent = endNode->ComputeIndexOf(content);
|
||||
if (NS_WARN_IF(indexInParent == -1)) {
|
||||
// The content is being removed from the parent!
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -2871,7 +2871,7 @@ ContentEventHandler::GetFlatTextLengthInRange(
|
|||
// array of children of its parent. So, be careful to handle this case.
|
||||
if (aIsRemovingNode) {
|
||||
DebugOnly<nsIContent*> parent = aStartPosition.Container()->GetParent();
|
||||
MOZ_ASSERT(parent && parent->IndexOf(aStartPosition.Container()) == -1,
|
||||
MOZ_ASSERT(parent && parent->ComputeIndexOf(aStartPosition.Container()) == -1,
|
||||
"At removing the node, the node shouldn't be in the array of children "
|
||||
"of its parent");
|
||||
MOZ_ASSERT(aStartPosition.Container() == endPosition.Container(),
|
||||
|
@ -2912,7 +2912,7 @@ ContentEventHandler::GetFlatTextLengthInRange(
|
|||
if (NS_WARN_IF(!parentContent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
int32_t indexInParent = parentContent->IndexOf(endPosition.Container());
|
||||
int32_t indexInParent = parentContent->ComputeIndexOf(endPosition.Container());
|
||||
if (NS_WARN_IF(indexInParent < 0)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -3158,8 +3158,8 @@ static void AdjustRangeForSelection(nsIContent* aRoot,
|
|||
}
|
||||
|
||||
*aNode = node->GetParent();
|
||||
MOZ_ASSERT((*aNode)->IndexOf(node) != -1);
|
||||
*aNodeOffset = (*aNode)->IndexOf(node) + 1;
|
||||
MOZ_ASSERT((*aNode)->ComputeIndexOf(node) != -1);
|
||||
*aNodeOffset = (*aNode)->ComputeIndexOf(node) + 1;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -319,7 +319,8 @@ Request::Constructor(const GlobalObject& aGlobal,
|
|||
nsAutoString requestURL;
|
||||
nsCString fragment;
|
||||
if (NS_IsMainThread()) {
|
||||
nsIDocument* doc = GetEntryDocument();
|
||||
nsCOMPtr<nsPIDOMWindowInner> inner(do_QueryInterface(global));
|
||||
nsIDocument* doc = inner ? inner->GetExtantDoc() : nullptr;
|
||||
if (doc) {
|
||||
GetRequestURLFromDocument(doc, input, requestURL, fragment, aRv);
|
||||
} else {
|
||||
|
@ -368,7 +369,8 @@ Request::Constructor(const GlobalObject& aGlobal,
|
|||
} else {
|
||||
nsAutoString referrerURL;
|
||||
if (NS_IsMainThread()) {
|
||||
nsIDocument* doc = GetEntryDocument();
|
||||
nsCOMPtr<nsPIDOMWindowInner> inner(do_QueryInterface(global));
|
||||
nsIDocument* doc = inner ? inner->GetExtantDoc() : nullptr;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (doc) {
|
||||
uri = ParseURLFromDocument(doc, referrer, aRv);
|
||||
|
|
|
@ -100,7 +100,8 @@ Response::Redirect(const GlobalObject& aGlobal, const nsAString& aUrl,
|
|||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsIDocument* doc = GetEntryDocument();
|
||||
nsCOMPtr<nsPIDOMWindowInner> inner(do_QueryInterface(aGlobal.GetAsSupports()));
|
||||
nsIDocument* doc = inner ? inner->GetExtantDoc() : nullptr;
|
||||
if (doc) {
|
||||
baseURI = doc->GetBaseURI();
|
||||
}
|
||||
|
|
|
@ -140,8 +140,9 @@ HTMLFieldSetElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission)
|
|||
}
|
||||
|
||||
nsresult
|
||||
HTMLFieldSetElement::InsertChildAt(nsIContent* aChild, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
HTMLFieldSetElement::InsertChildAt_Deprecated(nsIContent* aChild,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
bool firstLegendHasChanged = false;
|
||||
|
||||
|
@ -152,14 +153,15 @@ HTMLFieldSetElement::InsertChildAt(nsIContent* aChild, uint32_t aIndex,
|
|||
} else {
|
||||
// If mFirstLegend is before aIndex, we do not change it.
|
||||
// Otherwise, mFirstLegend is now aChild.
|
||||
if (int32_t(aIndex) <= IndexOf(mFirstLegend)) {
|
||||
if (int32_t(aIndex) <= ComputeIndexOf(mFirstLegend)) {
|
||||
mFirstLegend = aChild;
|
||||
firstLegendHasChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericHTMLFormElement::InsertChildAt(aChild, aIndex, aNotify);
|
||||
nsresult rv =
|
||||
nsGenericHTMLFormElement::InsertChildAt_Deprecated(aChild, aIndex, aNotify);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (firstLegendHasChanged) {
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
nsIPrincipal* aSubjectPrincipal,
|
||||
bool aNotify) override;
|
||||
|
||||
virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aChild, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ static bool IsPreviousSibling(nsINode *aSubject, nsINode *aNode)
|
|||
|
||||
nsINode *parent = aSubject->GetParentNode();
|
||||
if (parent && parent == aNode->GetParentNode()) {
|
||||
return parent->IndexOf(aSubject) < parent->IndexOf(aNode);
|
||||
return parent->ComputeIndexOf(aSubject) < parent->ComputeIndexOf(aNode);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -75,12 +75,13 @@ HTMLOptGroupElement::GetSelect()
|
|||
}
|
||||
|
||||
nsresult
|
||||
HTMLOptGroupElement::InsertChildAt(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
HTMLOptGroupElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
SafeOptionListMutation safeMutation(GetSelect(), this, aKid, aIndex, aNotify);
|
||||
nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
|
||||
nsresult rv = nsGenericHTMLElement::InsertChildAt_Deprecated(aKid, aIndex,
|
||||
aNotify);
|
||||
if (NS_FAILED(rv)) {
|
||||
safeMutation.MutationFailed();
|
||||
}
|
||||
|
@ -98,8 +99,8 @@ HTMLOptGroupElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
void
|
||||
HTMLOptGroupElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
SafeOptionListMutation safeMutation(GetSelect(), this, nullptr, IndexOf(aKid),
|
||||
aNotify);
|
||||
SafeOptionListMutation safeMutation(GetSelect(), this, nullptr,
|
||||
ComputeIndexOf(aKid), aNotify);
|
||||
nsGenericHTMLElement::RemoveChildNode(aKid, aNotify);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ public:
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsINode
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
|
|
|
@ -83,9 +83,9 @@ HTMLPictureElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
|||
}
|
||||
|
||||
nsresult
|
||||
HTMLPictureElement::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify)
|
||||
HTMLPictureElement::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex, bool aNotify)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
|
||||
nsresult rv = nsGenericHTMLElement::InsertChildAt_Deprecated(aKid, aIndex, aNotify);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(aKid, rv);
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
bool aPreallocateChildren) const override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex, bool aNotify) override;
|
||||
|
||||
protected:
|
||||
virtual ~HTMLPictureElement();
|
||||
|
|
|
@ -204,13 +204,14 @@ HTMLSelectElement::GetAutocompleteInfo(AutocompleteInfo& aInfo)
|
|||
}
|
||||
|
||||
nsresult
|
||||
HTMLSelectElement::InsertChildAt(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
HTMLSelectElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
SafeOptionListMutation safeMutation(this, this, aKid, aIndex, aNotify);
|
||||
nsresult rv = nsGenericHTMLFormElementWithState::InsertChildAt(aKid, aIndex,
|
||||
aNotify);
|
||||
nsresult rv =
|
||||
nsGenericHTMLFormElementWithState::InsertChildAt_Deprecated(aKid, aIndex,
|
||||
aNotify);
|
||||
if (NS_FAILED(rv)) {
|
||||
safeMutation.MutationFailed();
|
||||
}
|
||||
|
@ -227,7 +228,8 @@ HTMLSelectElement::RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify)
|
|||
void
|
||||
HTMLSelectElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
|
||||
{
|
||||
SafeOptionListMutation safeMutation(this, this, nullptr, IndexOf(aKid), aNotify);
|
||||
SafeOptionListMutation safeMutation(this, this, nullptr,
|
||||
ComputeIndexOf(aKid), aNotify);
|
||||
nsGenericHTMLFormElementWithState::RemoveChildNode(aKid, aNotify);
|
||||
}
|
||||
|
||||
|
@ -499,7 +501,7 @@ HTMLSelectElement::GetOptionIndexAfter(nsIContent* aOptions)
|
|||
nsCOMPtr<nsIContent> parent = aOptions->GetParent();
|
||||
|
||||
if (parent) {
|
||||
int32_t index = parent->IndexOf(aOptions);
|
||||
int32_t index = parent->ComputeIndexOf(aOptions);
|
||||
int32_t count = parent->GetChildCount();
|
||||
|
||||
retval = GetFirstChildOptionIndex(parent, index+1, count);
|
||||
|
|
|
@ -291,8 +291,8 @@ public:
|
|||
EventChainPostVisitor& aVisitor) override;
|
||||
|
||||
virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t* aTabIndex) override;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ CompareTextTracks::TrackChildPosition(TextTrack* aTextTrack) const {
|
|||
if (!trackElement) {
|
||||
return -1;
|
||||
}
|
||||
return mMediaElement->IndexOf(trackElement);
|
||||
return mMediaElement->ComputeIndexOf(trackElement);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -527,7 +527,7 @@ private:
|
|||
if (aEvent->mTrack) {
|
||||
HTMLTrackElement* trackElement = aEvent->mTrack->GetTrackElement();
|
||||
if (trackElement) {
|
||||
return mMediaElement->IndexOf(trackElement);
|
||||
return mMediaElement->ComputeIndexOf(trackElement);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -559,7 +559,7 @@ nsGenericHTMLElement::FindAncestorForm(HTMLFormElement* aCurrentForm)
|
|||
// anonymous. Check for this the hard way.
|
||||
for (nsIContent* child = this; child != content;
|
||||
child = child->GetParent()) {
|
||||
NS_ASSERTION(child->GetParent()->IndexOf(child) != -1,
|
||||
NS_ASSERTION(child->GetParent()->ComputeIndexOf(child) != -1,
|
||||
"Walked too far?");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ SinkContext::Node::Add(nsIContent *child)
|
|||
if (mInsertionPoint != -1) {
|
||||
NS_ASSERTION(mNumFlushed == mContent->GetChildCount(),
|
||||
"Inserting multiple children without flushing.");
|
||||
mContent->InsertChildAt(child, mInsertionPoint++, false);
|
||||
mContent->InsertChildAt_Deprecated(child, mInsertionPoint++, false);
|
||||
} else {
|
||||
mContent->AppendChildTo(child, false);
|
||||
}
|
||||
|
@ -983,7 +983,7 @@ HTMLContentSink::NotifyRootInsertion()
|
|||
// document; in those cases we just want to put all the attrs on one
|
||||
// tag.
|
||||
mNotifiedRootInsertion = true;
|
||||
int32_t index = mDocument->IndexOf(mRoot);
|
||||
int32_t index = mDocument->ComputeIndexOf(mRoot);
|
||||
NS_ASSERTION(index != -1, "mRoot not child of document?");
|
||||
NotifyInsert(nullptr, mRoot, index);
|
||||
|
||||
|
|
|
@ -84,3 +84,5 @@ BlockScriptWithWrongMimeType=Script from “%1$S” was blocked because of a dis
|
|||
|
||||
# LOCALIZATION NOTE: Do not translate "data: URI".
|
||||
BlockTopLevelDataURINavigation=Navigation to toplevel data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
BlockSubresourceRedirectToData=Redirecting to insecure data: URI not allowed (Blocked loading of: “%1$S”)
|
||||
|
||||
|
|
|
@ -3163,11 +3163,15 @@ ScriptLoader::ParsingComplete(bool aTerminated)
|
|||
}
|
||||
|
||||
void
|
||||
ScriptLoader::PreloadURI(nsIURI* aURI, const nsAString& aCharset,
|
||||
ScriptLoader::PreloadURI(nsIURI* aURI,
|
||||
const nsAString& aCharset,
|
||||
const nsAString& aType,
|
||||
const nsAString& aCrossOrigin,
|
||||
const nsAString& aIntegrity,
|
||||
bool aScriptFromHead, bool aAsync, bool aDefer,
|
||||
bool aScriptFromHead,
|
||||
bool aAsync,
|
||||
bool aDefer,
|
||||
bool aNoModule,
|
||||
const mozilla::net::ReferrerPolicy aReferrerPolicy)
|
||||
{
|
||||
NS_ENSURE_TRUE_VOID(mDocument);
|
||||
|
@ -3176,9 +3180,16 @@ ScriptLoader::PreloadURI(nsIURI* aURI, const nsAString& aCharset,
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Preload module scripts.
|
||||
if (mDocument->ModuleScriptsEnabled() && aType.LowerCaseEqualsASCII("module")) {
|
||||
return;
|
||||
if (mDocument->ModuleScriptsEnabled()) {
|
||||
// Don't load nomodule scripts.
|
||||
if (aNoModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Preload module scripts.
|
||||
if (aType.LowerCaseEqualsASCII("module")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SRIMetadata sriMetadata;
|
||||
|
|
|
@ -296,11 +296,15 @@ public:
|
|||
* @param aIntegrity The expect hash url, if avail, of the request
|
||||
* @param aScriptFromHead Whether or not the script was a child of head
|
||||
*/
|
||||
virtual void PreloadURI(nsIURI* aURI, const nsAString& aCharset,
|
||||
virtual void PreloadURI(nsIURI* aURI,
|
||||
const nsAString& aCharset,
|
||||
const nsAString& aType,
|
||||
const nsAString& aCrossOrigin,
|
||||
const nsAString& aIntegrity,
|
||||
bool aScriptFromHead, bool aAsync, bool aDefer,
|
||||
bool aScriptFromHead,
|
||||
bool aAsync,
|
||||
bool aDefer,
|
||||
bool aNoModule,
|
||||
const mozilla::net::ReferrerPolicy aReferrerPolicy);
|
||||
|
||||
/**
|
||||
|
|
|
@ -606,6 +606,36 @@ nsContentSecurityManager::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
|||
Unused << NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI));
|
||||
NS_ENSURE_STATE(oldPrincipal && newURI);
|
||||
|
||||
// Do not allow insecure redirects to data: URIs
|
||||
if (loadInfo && loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SCRIPT) {
|
||||
bool isDataURI = (NS_SUCCEEDED(newURI->SchemeIs("data", &isDataURI)) && isDataURI);
|
||||
if (isDataURI) {
|
||||
nsAutoCString dataSpec;
|
||||
newURI->GetSpec(dataSpec);
|
||||
if (dataSpec.Length() > 50) {
|
||||
dataSpec.Truncate(50);
|
||||
dataSpec.AppendLiteral("...");
|
||||
}
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsINode* node = loadInfo->LoadingNode();
|
||||
if (node) {
|
||||
doc = node->OwnerDoc();
|
||||
}
|
||||
NS_ConvertUTF8toUTF16 specUTF16(NS_UnescapeURL(dataSpec));
|
||||
const char16_t* params[] = { specUTF16.get() };
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DATA_URI_BLOCKED"),
|
||||
doc,
|
||||
nsContentUtils::eSECURITY_PROPERTIES,
|
||||
"BlockSubresourceRedirectToData",
|
||||
params, ArrayLength(params));
|
||||
|
||||
// cancel the old channel and return an error
|
||||
aOldChannel->Cancel(NS_ERROR_CONTENT_BLOCKED);
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t flags =
|
||||
nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT |
|
||||
nsIScriptSecurityManager::DISALLOW_SCRIPT;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
"use strict";
|
||||
|
||||
let SCRIPT_DATA = "alert('this alert should be blocked');";
|
||||
let WORKER_DATA = "onmessage = function(event) { postMessage('worker-loaded'); }";
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
const query = request.queryString;
|
||||
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setStatusLine("1.1", 302, "Found");
|
||||
|
||||
if (query === "script" || query === "modulescript") {
|
||||
response.setHeader("Location", "data:text/javascript," + escape(SCRIPT_DATA), false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query === "worker") {
|
||||
response.setHeader("Location", "data:text/javascript," + escape(WORKER_DATA), false);
|
||||
return;
|
||||
}
|
||||
|
||||
// we should never get here; just in case return something unexpected
|
||||
response.write("do'h");
|
||||
}
|
|
@ -7,6 +7,7 @@ support-files =
|
|||
file_block_toplevel_data_navigation2.html
|
||||
file_block_toplevel_data_navigation3.html
|
||||
file_block_toplevel_data_redirect.sjs
|
||||
file_block_subresource_redir_to_data.sjs
|
||||
|
||||
[test_contentpolicytype_targeted_link_iframe.html]
|
||||
[test_nosniff.html]
|
||||
|
@ -19,3 +20,4 @@ skip-if = toolkit == 'android' # intermittent failure
|
|||
skip-if = toolkit == 'android'
|
||||
[test_allow_opening_data_json.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_block_subresource_redir_to_data.html]
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1428793: Block insecure redirects to data: URIs</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script id="testScriptRedirectToData"></script>
|
||||
<script id="testModuleScriptRedirectToData" type="module"></script>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const NUM_TESTS = 3;
|
||||
|
||||
var testCounter = 0;
|
||||
function checkFinish() {
|
||||
testCounter++;
|
||||
if (testCounter === NUM_TESTS) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// --- test regular scripts
|
||||
let testScriptRedirectToData = document.getElementById("testScriptRedirectToData");
|
||||
testScriptRedirectToData.onerror = function() {
|
||||
ok(true, "script that redirects to data: URI should not load");
|
||||
checkFinish();
|
||||
}
|
||||
testScriptRedirectToData.onload = function() {
|
||||
ok(false, "script that redirects to data: URI should not load");
|
||||
checkFinish();
|
||||
}
|
||||
testScriptRedirectToData.src = "file_block_subresource_redir_to_data.sjs?script";
|
||||
|
||||
// --- test workers
|
||||
let worker = new Worker("file_block_subresource_redir_to_data.sjs?worker");
|
||||
worker.onerror = function() {
|
||||
// please note that workers need to be same origin, hence the data: URI
|
||||
// redirect is blocked by worker code and not the content security manager!
|
||||
ok(true, "worker script that redirects to data: URI should not load");
|
||||
checkFinish();
|
||||
}
|
||||
worker.onmessage = function() {
|
||||
ok(false, "worker script that redirects to data: URI should not load");
|
||||
checkFinish();
|
||||
};
|
||||
worker.postMessage("dummy");
|
||||
|
||||
// --- test script modules
|
||||
SpecialPowers.pushPrefEnv({set: [["dom.moduleScripts.enabled", true]]}, function() {
|
||||
let testModuleScriptRedirectToData = document.getElementById("testModuleScriptRedirectToData");
|
||||
testModuleScriptRedirectToData.onerror = function() {
|
||||
ok(true, "module script that redirects to data: URI should not load");
|
||||
checkFinish();
|
||||
}
|
||||
testModuleScriptRedirectToData.onload = function() {
|
||||
ok(false, "module script that redirects to data: URI should not load");
|
||||
checkFinish();
|
||||
}
|
||||
testModuleScriptRedirectToData.src = "file_block_subresource_redir_to_data.sjs?modulescript";
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -35,19 +35,20 @@ namespace dom {
|
|||
// nsISupports methods:
|
||||
|
||||
nsresult
|
||||
SVGDocument::InsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify)
|
||||
SVGDocument::InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
if (aKid->IsElement() && !aKid->IsSVGElement()) {
|
||||
// We can get here when well formed XML with a non-SVG root element is
|
||||
// served with the SVG MIME type, for example. In that case we need to load
|
||||
// the non-SVG UA sheets or else we can get bugs like bug 1016145. Note
|
||||
// that we have to do this _before_ the XMLDocument::InsertChildAt call,
|
||||
// since that can try to construct frames, and we need to have the sheets
|
||||
// loaded by then.
|
||||
// that we have to do this _before_ the
|
||||
// XMLDocument::InsertChildAt_Deprecated call, since that can try to
|
||||
// construct frames, and we need to have the sheets loaded by then.
|
||||
EnsureNonSVGUserAgentStyleSheetsLoaded();
|
||||
}
|
||||
|
||||
return XMLDocument::InsertChildAt(aKid, aIndex, aNotify);
|
||||
return XMLDocument::InsertChildAt_Deprecated(aKid, aIndex, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -29,8 +29,8 @@ public:
|
|||
mType = eSVG;
|
||||
}
|
||||
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
bool aPreallocateChildren) const override;
|
||||
|
||||
|
|
|
@ -82,11 +82,12 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSwitchElement)
|
|||
// nsINode methods
|
||||
|
||||
nsresult
|
||||
SVGSwitchElement::InsertChildAt(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
SVGSwitchElement::InsertChildAt_Deprecated(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
bool aNotify)
|
||||
{
|
||||
nsresult rv = SVGSwitchElementBase::InsertChildAt(aKid, aIndex, aNotify);
|
||||
nsresult rv = SVGSwitchElementBase::InsertChildAt_Deprecated(aKid, aIndex,
|
||||
aNotify);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
MaybeInvalidate();
|
||||
}
|
||||
|
|
|
@ -40,8 +40,8 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSwitchElement,
|
||||
SVGSwitchElementBase)
|
||||
// nsINode
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual nsresult InsertChildAt_Deprecated(nsIContent* aKid, uint32_t aIndex,
|
||||
bool aNotify) override;
|
||||
virtual void RemoveChildAt_Deprecated(uint32_t aIndex, bool aNotify) override;
|
||||
virtual void RemoveChildNode(nsIContent* aKid, bool aNotify) override;
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ nsAnonymousContentList::IndexOf(nsIContent* aContent)
|
|||
index += point->InsertedChildrenLength();
|
||||
}
|
||||
else {
|
||||
int32_t insIndex = point->IndexOf(aContent);
|
||||
int32_t insIndex = point->ComputeIndexOf(aContent);
|
||||
if (insIndex != -1) {
|
||||
return index + insIndex;
|
||||
}
|
||||
|
|
|
@ -483,7 +483,8 @@ nsXBLPrototypeBinding::LocateInstance(Element* aBoundElement,
|
|||
if (!copyParent)
|
||||
return nullptr;
|
||||
|
||||
nsIContent* child = copyParent->GetChildAt_Deprecated(templParent->IndexOf(aTemplChild));
|
||||
nsIContent* child =
|
||||
copyParent->GetChildAt_Deprecated(templParent->ComputeIndexOf(aTemplChild));
|
||||
if (child && child->IsElement()) {
|
||||
return child->AsElement();
|
||||
}
|
||||
|
|
|
@ -388,7 +388,7 @@ nsXMLContentSink::OnTransformDone(nsresult aResult,
|
|||
// documentElement?
|
||||
nsIContent *rootElement = mDocument->GetRootElement();
|
||||
if (rootElement) {
|
||||
NS_ASSERTION(mDocument->IndexOf(rootElement) != -1,
|
||||
NS_ASSERTION(mDocument->ComputeIndexOf(rootElement) != -1,
|
||||
"rootElement not in doc?");
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
nsNodeUtils::ContentInserted(mDocument, rootElement);
|
||||
|
|
|
@ -576,7 +576,7 @@ txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
|
|||
return node < otherNode ? -1 : 1;
|
||||
}
|
||||
|
||||
return parent->IndexOf(node) < parent->IndexOf(otherNode) ?
|
||||
return parent->ComputeIndexOf(node) < parent->ComputeIndexOf(otherNode) ?
|
||||
-1 : 1;
|
||||
}
|
||||
|
||||
|
@ -613,8 +613,8 @@ txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
|
|||
return node < otherNode ? -1 : 1;
|
||||
}
|
||||
|
||||
int32_t index = parent->IndexOf(node);
|
||||
int32_t otherIndex = parent->IndexOf(otherNode);
|
||||
int32_t index = parent->ComputeIndexOf(node);
|
||||
int32_t otherIndex = parent->ComputeIndexOf(otherNode);
|
||||
NS_ASSERTION(index != otherIndex && index >= 0 && otherIndex >= 0,
|
||||
"invalid index in compareTreePosition");
|
||||
|
||||
|
|
|
@ -2089,7 +2089,7 @@ XULDocument::PrepareToWalk()
|
|||
|
||||
uint32_t piInsertionPoint = 0;
|
||||
if (mState != eState_Master) {
|
||||
int32_t indexOfRoot = IndexOf(GetRootElement());
|
||||
int32_t indexOfRoot = ComputeIndexOf(GetRootElement());
|
||||
NS_ASSERTION(indexOfRoot >= 0,
|
||||
"No root content when preparing to walk overlay!");
|
||||
piInsertionPoint = indexOfRoot;
|
||||
|
@ -2161,7 +2161,7 @@ XULDocument::CreateAndInsertPI(const nsXULPrototypePI* aProtoPI,
|
|||
rv = InsertXULOverlayPI(aProtoPI, aParent, aIndex, node);
|
||||
} else {
|
||||
// No special processing, just add the PI to the document.
|
||||
rv = aParent->InsertChildAt(node, aIndex, false);
|
||||
rv = aParent->InsertChildAt_Deprecated(node, aIndex, false);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -2185,7 +2185,7 @@ XULDocument::InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI,
|
|||
ssle->SetEnableUpdates(false);
|
||||
ssle->OverrideBaseURI(mCurrentPrototype->GetURI());
|
||||
|
||||
rv = aParent->InsertChildAt(aPINode, aIndex, false);
|
||||
rv = aParent->InsertChildAt_Deprecated(aPINode, aIndex, false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
ssle->SetEnableUpdates(true);
|
||||
|
@ -2217,7 +2217,7 @@ XULDocument::InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI,
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = aParent->InsertChildAt(aPINode, aIndex, false);
|
||||
rv = aParent->InsertChildAt_Deprecated(aPINode, aIndex, false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// xul-overlay PI is special only in prolog
|
||||
|
@ -3983,11 +3983,11 @@ XULDocument::InsertElement(nsINode* aParent, nsIContent* aChild, bool aNotify)
|
|||
free(str);
|
||||
|
||||
if (content) {
|
||||
int32_t pos = aParent->IndexOf(content);
|
||||
int32_t pos = aParent->ComputeIndexOf(content);
|
||||
|
||||
if (pos != -1) {
|
||||
pos = isInsertAfter ? pos + 1 : pos;
|
||||
nsresult rv = aParent->InsertChildAt(aChild, pos, aNotify);
|
||||
nsresult rv = aParent->InsertChildAt_Deprecated(aChild, pos, aNotify);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -4009,7 +4009,7 @@ XULDocument::InsertElement(nsINode* aParent, nsIContent* aChild, bool aNotify)
|
|||
// appending.
|
||||
if (NS_SUCCEEDED(rv) && pos > 0 &&
|
||||
uint32_t(pos - 1) <= aParent->GetChildCount()) {
|
||||
rv = aParent->InsertChildAt(aChild, pos - 1, aNotify);
|
||||
rv = aParent->InsertChildAt_Deprecated(aChild, pos - 1, aNotify);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
wasInserted = true;
|
||||
// If the insertion fails, then we should still
|
||||
|
@ -4029,7 +4029,7 @@ XULDocument::InsertElement(nsINode* aParent, nsIContent* aChild, bool aNotify)
|
|||
nsresult
|
||||
XULDocument::RemoveElement(nsINode* aParent, nsINode* aChild)
|
||||
{
|
||||
int32_t nodeOffset = aParent->IndexOf(aChild);
|
||||
int32_t nodeOffset = aParent->ComputeIndexOf(aChild);
|
||||
|
||||
aParent->RemoveChildAt_Deprecated(nodeOffset, true);
|
||||
return NS_OK;
|
||||
|
|
|
@ -1122,7 +1122,7 @@ EditorBase::BeginningOfDocument()
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(parent->IndexOf(firstNode) == 0,
|
||||
MOZ_ASSERT(parent->ComputeIndexOf(firstNode) == 0,
|
||||
"How come the first node isn't the left most child in its parent?");
|
||||
return selection->Collapse(parent, 0);
|
||||
}
|
||||
|
@ -1618,7 +1618,7 @@ EditorBase::JoinNodes(nsINode& aLeftNode,
|
|||
|
||||
// Remember some values; later used for saved selection updating.
|
||||
// Find the offset between the nodes to be joined.
|
||||
int32_t offset = parent->IndexOf(&aRightNode);
|
||||
int32_t offset = parent->ComputeIndexOf(&aRightNode);
|
||||
// Find the number of children of the lefthand node
|
||||
uint32_t oldLeftNodeLen = aLeftNode.Length();
|
||||
|
||||
|
@ -1912,7 +1912,7 @@ EditorBase::MoveNode(nsIContent* aNode,
|
|||
if (NS_WARN_IF(!oldParent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
int32_t oldOffset = oldParent->IndexOf(aNode);
|
||||
int32_t oldOffset = oldParent->ComputeIndexOf(aNode);
|
||||
|
||||
if (aOffset == -1) {
|
||||
// Magic value meaning "move to end of aParent"
|
||||
|
@ -3447,23 +3447,23 @@ EditorBase::GetChildOffset(nsINode* aChild,
|
|||
MOZ_ASSERT(aChild);
|
||||
MOZ_ASSERT(aParent);
|
||||
|
||||
// nsINode::IndexOf() is expensive. So, if we can return index without
|
||||
// calling it, we should do that.
|
||||
// nsINode::ComputeIndexOf() is expensive. So, if we can return index
|
||||
// without calling it, we should do that.
|
||||
|
||||
// If there is no previous siblings, it means that it's the first child.
|
||||
if (aParent->GetFirstChild() == aChild) {
|
||||
MOZ_ASSERT(aParent->IndexOf(aChild) == 0);
|
||||
MOZ_ASSERT(aParent->ComputeIndexOf(aChild) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If there is no next siblings, it means that it's the last child.
|
||||
if (aParent->GetLastChild() == aChild) {
|
||||
int32_t lastChildIndex = static_cast<int32_t>(aParent->Length() - 1);
|
||||
MOZ_ASSERT(aParent->IndexOf(aChild) == lastChildIndex);
|
||||
MOZ_ASSERT(aParent->ComputeIndexOf(aChild) == lastChildIndex);
|
||||
return lastChildIndex;
|
||||
}
|
||||
|
||||
int32_t index = aParent->IndexOf(aChild);
|
||||
int32_t index = aParent->ComputeIndexOf(aChild);
|
||||
MOZ_ASSERT(index != -1);
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -351,7 +351,7 @@ public:
|
|||
const_cast<SelfType*>(this)->mOffset = mozilla::Some(0);
|
||||
} else {
|
||||
const_cast<SelfType*>(this)->mOffset =
|
||||
mozilla::Some(mParent->IndexOf(mChild));
|
||||
mozilla::Some(mParent->ComputeIndexOf(mChild));
|
||||
}
|
||||
return mOffset.value();
|
||||
}
|
||||
|
|
|
@ -836,7 +836,7 @@ HTMLEditRules::GetAlignment(bool* aMixed,
|
|||
OwningNonNull<Element> root = *htmlEditor->GetRoot();
|
||||
|
||||
int32_t rootOffset = root->GetParentNode() ?
|
||||
root->GetParentNode()->IndexOf(root) : -1;
|
||||
root->GetParentNode()->ComputeIndexOf(root) : -1;
|
||||
|
||||
nsRange* firstRange = selection->GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
|
@ -2361,7 +2361,7 @@ HTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
|||
bool moveOnly = true;
|
||||
|
||||
selNode = visNode->GetParentNode();
|
||||
selOffset = selNode ? selNode->IndexOf(visNode) : -1;
|
||||
selOffset = selNode ? selNode->ComputeIndexOf(visNode) : -1;
|
||||
|
||||
bool interLineIsRight;
|
||||
rv = aSelection->GetInterlinePosition(&interLineIsRight);
|
||||
|
@ -5450,12 +5450,12 @@ HTMLEditRules::CheckForInvisibleBR(Element& aBlock,
|
|||
|
||||
testNode = rightmostNode->GetParentNode();
|
||||
// Since rightmostNode is always the last child, its index is equal to the
|
||||
// child count, so instead of IndexOf() we use the faster GetChildCount(),
|
||||
// and assert the equivalence below.
|
||||
// child count, so instead of ComputeIndexOf() we use the faster
|
||||
// GetChildCount(), and assert the equivalence below.
|
||||
testOffset = testNode->GetChildCount();
|
||||
|
||||
// Use offset + 1, so last node is included in our evaluation
|
||||
MOZ_ASSERT(testNode->IndexOf(rightmostNode) + 1 == testOffset);
|
||||
MOZ_ASSERT(testNode->ComputeIndexOf(rightmostNode) + 1 == testOffset);
|
||||
} else if (aOffset) {
|
||||
testNode = &aBlock;
|
||||
// We'll check everything to the left of the input position
|
||||
|
@ -5559,7 +5559,7 @@ HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
|
|||
}
|
||||
selStartNode = wsObj.mStartReasonNode->GetParentNode();
|
||||
selStartOffset = selStartNode ?
|
||||
selStartNode->IndexOf(wsObj.mStartReasonNode) : -1;
|
||||
selStartNode->ComputeIndexOf(wsObj.mStartReasonNode) : -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5579,7 +5579,7 @@ HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
|
|||
}
|
||||
selEndNode = wsObj.mEndReasonNode->GetParentNode();
|
||||
selEndOffset = selEndNode
|
||||
? selEndNode->IndexOf(wsObj.mEndReasonNode) + 1 : 0;
|
||||
? selEndNode->ComputeIndexOf(wsObj.mEndReasonNode) + 1 : 0;
|
||||
} else if (wsType == WSType::thisBlock) {
|
||||
// We want to keep looking up. But stop if we are crossing table
|
||||
// element boundaries, or if we hit the root.
|
||||
|
@ -5589,7 +5589,7 @@ HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
|
|||
break;
|
||||
}
|
||||
selEndNode = wsObj.mEndReasonNode->GetParentNode();
|
||||
selEndOffset = 1 + selEndNode->IndexOf(wsObj.mEndReasonNode);
|
||||
selEndOffset = 1 + selEndNode->ComputeIndexOf(wsObj.mEndReasonNode);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -6772,7 +6772,7 @@ HTMLEditRules::ReturnInHeader(Selection& aSelection,
|
|||
|
||||
// Remember where the header is
|
||||
nsCOMPtr<nsINode> headerParent = aHeader.GetParentNode();
|
||||
int32_t offset = headerParent ? headerParent->IndexOf(&aHeader) : -1;
|
||||
int32_t offset = headerParent ? headerParent->ComputeIndexOf(&aHeader) : -1;
|
||||
|
||||
// Get ws code to adjust any ws
|
||||
nsCOMPtr<nsINode> node = &aNode;
|
||||
|
@ -7187,7 +7187,7 @@ HTMLEditRules::ReturnInListItem(Selection& aSelection,
|
|||
RefPtr<nsAtom> nodeAtom = aListItem.NodeInfo()->NameAtom();
|
||||
if (nodeAtom == nsGkAtoms::dd || nodeAtom == nsGkAtoms::dt) {
|
||||
nsCOMPtr<nsINode> list = aListItem.GetParentNode();
|
||||
int32_t itemOffset = list ? list->IndexOf(&aListItem) : -1;
|
||||
int32_t itemOffset = list ? list->ComputeIndexOf(&aListItem) : -1;
|
||||
|
||||
nsAtom* listAtom = nodeAtom == nsGkAtoms::dt ? nsGkAtoms::dd
|
||||
: nsGkAtoms::dt;
|
||||
|
@ -7649,7 +7649,7 @@ HTMLEditRules::JoinNodesSmart(nsIContent& aNodeLeft,
|
|||
if (NS_WARN_IF(!parent)) {
|
||||
return EditorDOMPoint();
|
||||
}
|
||||
int32_t parOffset = parent->IndexOf(&aNodeLeft);
|
||||
int32_t parOffset = parent->ComputeIndexOf(&aNodeLeft);
|
||||
nsCOMPtr<nsINode> rightParent = aNodeRight.GetParentNode();
|
||||
|
||||
// If they don't have the same parent, first move the right node to after the
|
||||
|
|
|
@ -537,7 +537,7 @@ HTMLEditor::BeginningOfDocument()
|
|||
done = true;
|
||||
} else if (visType == WSType::br || visType == WSType::special) {
|
||||
selNode = visNode->GetParentNode();
|
||||
selOffset = selNode ? selNode->IndexOf(visNode) : -1;
|
||||
selOffset = selNode ? selNode->ComputeIndexOf(visNode) : -1;
|
||||
done = true;
|
||||
} else if (visType == WSType::otherBlock) {
|
||||
// By definition of WSRunObject, a block element terminates a
|
||||
|
@ -554,7 +554,7 @@ HTMLEditor::BeginningOfDocument()
|
|||
// makes sense if it is visible by itself, like a <hr>. We want to
|
||||
// place the caret in front of that block.
|
||||
selNode = visNode->GetParentNode();
|
||||
selOffset = selNode ? selNode->IndexOf(visNode) : -1;
|
||||
selOffset = selNode ? selNode->ComputeIndexOf(visNode) : -1;
|
||||
done = true;
|
||||
} else {
|
||||
bool isEmptyBlock;
|
||||
|
@ -562,7 +562,7 @@ HTMLEditor::BeginningOfDocument()
|
|||
isEmptyBlock) {
|
||||
// Skip the empty block
|
||||
curNode = visNode->GetParentNode();
|
||||
curOffset = curNode ? curNode->IndexOf(visNode) : -1;
|
||||
curOffset = curNode ? curNode->ComputeIndexOf(visNode) : -1;
|
||||
curOffset++;
|
||||
} else {
|
||||
curNode = visNode;
|
||||
|
@ -1598,7 +1598,7 @@ HTMLEditor::SelectElement(nsIDOMElement* aElement)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
int32_t offsetInParent = parent->IndexOf(element);
|
||||
int32_t offsetInParent = parent->ComputeIndexOf(element);
|
||||
|
||||
// Collapse selection to just before desired element,
|
||||
nsresult rv = selection->Collapse(parent, offsetInParent);
|
||||
|
|
|
@ -838,7 +838,7 @@ HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange)
|
|||
|
||||
if (HTMLEditUtils::IsNamedAnchor(parent)) {
|
||||
startNode = parent->GetParentNode();
|
||||
startOffset = startNode ? startNode->IndexOf(parent) : -1;
|
||||
startOffset = startNode ? startNode->ComputeIndexOf(parent) : -1;
|
||||
}
|
||||
|
||||
parent = endNode;
|
||||
|
@ -850,7 +850,7 @@ HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange)
|
|||
|
||||
if (HTMLEditUtils::IsNamedAnchor(parent)) {
|
||||
endNode = parent->GetParentNode();
|
||||
endOffset = endNode ? endNode->IndexOf(parent) + 1 : 0;
|
||||
endOffset = endNode ? endNode->ComputeIndexOf(parent) + 1 : 0;
|
||||
}
|
||||
|
||||
nsresult rv = aRange.SetStartAndEnd(startNode, startOffset,
|
||||
|
@ -874,7 +874,7 @@ HTMLEditor::PromoteInlineRange(nsRange& aRange)
|
|||
IsEditable(startNode) && IsAtFrontOfNode(*startNode, startOffset)) {
|
||||
nsCOMPtr<nsINode> parent = startNode->GetParentNode();
|
||||
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
|
||||
startOffset = parent->IndexOf(startNode);
|
||||
startOffset = parent->ComputeIndexOf(startNode);
|
||||
startNode = parent;
|
||||
}
|
||||
|
||||
|
@ -883,7 +883,7 @@ HTMLEditor::PromoteInlineRange(nsRange& aRange)
|
|||
nsCOMPtr<nsINode> parent = endNode->GetParentNode();
|
||||
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
|
||||
// We are AFTER this node
|
||||
endOffset = 1 + parent->IndexOf(endNode);
|
||||
endOffset = 1 + parent->ComputeIndexOf(endNode);
|
||||
endNode = parent;
|
||||
}
|
||||
|
||||
|
@ -910,7 +910,7 @@ HTMLEditor::IsAtFrontOfNode(nsINode& aNode,
|
|||
|
||||
nsCOMPtr<nsIContent> firstNode = GetFirstEditableChild(aNode);
|
||||
NS_ENSURE_TRUE(firstNode, true);
|
||||
if (aNode.IndexOf(firstNode) < aOffset) {
|
||||
if (aNode.ComputeIndexOf(firstNode) < aOffset) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -930,7 +930,7 @@ HTMLEditor::IsAtEndOfNode(nsINode& aNode,
|
|||
|
||||
nsCOMPtr<nsIContent> lastNode = GetLastEditableChild(aNode);
|
||||
NS_ENSURE_TRUE(lastNode, true);
|
||||
if (aNode.IndexOf(lastNode) < aOffset) {
|
||||
if (aNode.ComputeIndexOf(lastNode) < aOffset) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -672,7 +672,7 @@ HTMLEditor::InsertTableRow(int32_t aNumber,
|
|||
// The row parent and offset where we will insert new row
|
||||
nsCOMPtr<nsINode> parentOfRow = parentRow->GetParentNode();
|
||||
NS_ENSURE_TRUE(parentOfRow, NS_ERROR_NULL_POINTER);
|
||||
int32_t newRowOffset = parentOfRow->IndexOf(parentRow);
|
||||
int32_t newRowOffset = parentOfRow->ComputeIndexOf(parentRow);
|
||||
|
||||
// Adjust for when adding past the end
|
||||
if (aAfter && startRowIndex >= rowCount) {
|
||||
|
|
|
@ -264,7 +264,7 @@ RangeUpdater::SelAdjDeleteNode(nsINode* aNode)
|
|||
}
|
||||
|
||||
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
|
||||
int32_t offset = parent ? parent->IndexOf(aNode) : -1;
|
||||
int32_t offset = parent ? parent->ComputeIndexOf(aNode) : -1;
|
||||
|
||||
// check for range endpoints that are after aNode and in the same parent
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
|
|
|
@ -143,7 +143,7 @@ WSRunObject::PrepareToDeleteNode(HTMLEditor* aHTMLEditor,
|
|||
|
||||
nsCOMPtr<nsINode> parent = aContent->GetParentNode();
|
||||
NS_ENSURE_STATE(parent);
|
||||
int32_t offset = parent->IndexOf(aContent);
|
||||
int32_t offset = parent->ComputeIndexOf(aContent);
|
||||
|
||||
WSRunObject leftWSObj(aHTMLEditor, parent, offset);
|
||||
WSRunObject rightWSObj(aHTMLEditor, parent, offset + 1);
|
||||
|
|
|
@ -250,7 +250,7 @@ ContentToParentOffset(nsIContent* aContent, nsIContent** aParent,
|
|||
if (!parent)
|
||||
return;
|
||||
|
||||
*aOffset = parent->IndexOf(aContent);
|
||||
*aOffset = parent->ComputeIndexOf(aContent);
|
||||
parent.forget(aParent);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
function toint32() {
|
||||
|
||||
// The test case to trigger MToInt32 operation.
|
||||
// The test case to trigger MToNumberInt32 operation.
|
||||
var ToInteger = getSelfHostedValue("ToInteger");
|
||||
|
||||
// Case1: The input operand is constant int32.
|
||||
|
|
|
@ -175,7 +175,7 @@ function not() {
|
|||
}
|
||||
test(setupNot, not);
|
||||
|
||||
// MToInt32
|
||||
// MToNumberInt32
|
||||
var str = "can haz cheezburger? okthxbye;";
|
||||
function setupToInt32() {
|
||||
f32[0] = 0;
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
// Test multiple concurrent off-thread parse jobs.
|
||||
|
||||
if (helperThreadCount() === 0)
|
||||
quit();
|
||||
|
||||
function assertFails(f) {
|
||||
let failed = false;
|
||||
try {
|
||||
f();
|
||||
} catch (e) {
|
||||
failed = true;
|
||||
}
|
||||
assertEq(failed, true);
|
||||
}
|
||||
|
||||
function encodeScript(source)
|
||||
{
|
||||
let entry = cacheEntry(source);
|
||||
let global = newGlobal({ cloneSingletons: true });
|
||||
evaluate(entry, { global: global, saveBytecode: true });
|
||||
return entry;
|
||||
}
|
||||
|
||||
let a, b, c;
|
||||
|
||||
// Calling run functions without arguments assumes a single off-thread job.
|
||||
|
||||
// Test run functions fail when no jobs exist.
|
||||
|
||||
assertFails(() => runOffThreadScript());
|
||||
|
||||
assertFails(() => finishOffThreadModule());
|
||||
|
||||
assertFails(() => runOffThreadDecodedScript());
|
||||
|
||||
// Test run functions fail when multiple jobs exist and no ID specified.
|
||||
|
||||
a = offThreadCompileScript("");
|
||||
b = offThreadCompileScript("");
|
||||
assertFails(() => runOffThreadScript());
|
||||
runOffThreadScript(a);
|
||||
runOffThreadScript(b);
|
||||
|
||||
a = offThreadCompileModule("");
|
||||
b = offThreadCompileModule("");
|
||||
assertFails(() => finishOffThreadModule());
|
||||
finishOffThreadModule(a);
|
||||
finishOffThreadModule(b);
|
||||
|
||||
a = offThreadDecodeScript(encodeScript(""));
|
||||
b = offThreadDecodeScript(encodeScript(""));
|
||||
assertFails(() => runOffThreadScript());
|
||||
runOffThreadDecodedScript(a);
|
||||
runOffThreadDecodedScript(b);
|
||||
|
||||
// Test fun functions succeed when a single job exist and no ID specified.
|
||||
|
||||
offThreadCompileScript("42");
|
||||
assertEq(runOffThreadScript(), 42);
|
||||
|
||||
offThreadCompileModule("");
|
||||
assertEq(typeof finishOffThreadModule(), "object");
|
||||
|
||||
offThreadDecodeScript(encodeScript("23"));
|
||||
assertEq(runOffThreadDecodedScript(), 23);
|
||||
|
||||
// Run functions take an ID argument returned from the compile function.
|
||||
|
||||
// Test bad ID type and unknown ID.
|
||||
|
||||
offThreadCompileScript("");
|
||||
assertFails(() => runOffThreadScript("foo"));
|
||||
assertFails(() => runOffThreadScript(42));
|
||||
runOffThreadScript();
|
||||
|
||||
offThreadCompileModule("");
|
||||
assertFails(() => finishOffThreadModule("foo"));
|
||||
assertFails(() => finishOffThreadModule(42));
|
||||
finishOffThreadModule();
|
||||
|
||||
offThreadDecodeScript(encodeScript(""));
|
||||
assertFails(() => runOffThreadDecodedScript("foo"));
|
||||
assertFails(() => runOffThreadDecodedScript(42));
|
||||
runOffThreadDecodedScript();
|
||||
|
||||
// Test stale ID.
|
||||
|
||||
a = offThreadCompileScript("");
|
||||
runOffThreadScript(a);
|
||||
assertFails(() => runOffThreadScript(a));
|
||||
|
||||
a = offThreadCompileModule("");
|
||||
finishOffThreadModule(a);
|
||||
assertFails(() => finishOffThreadModule(a));
|
||||
|
||||
a = offThreadDecodeScript(encodeScript(""));
|
||||
runOffThreadDecodedScript(a);
|
||||
assertFails(() => runOffThreadDecodedScript(a));
|
||||
|
||||
// Test wrong job kind.
|
||||
|
||||
a = offThreadCompileScript("");
|
||||
b = offThreadCompileModule("");
|
||||
c = offThreadDecodeScript(encodeScript(""));
|
||||
assertFails(() => runOffThreadScript(b));
|
||||
assertFails(() => runOffThreadScript(c));
|
||||
assertFails(() => finishOffThreadModule(a));
|
||||
assertFails(() => finishOffThreadModule(c));
|
||||
assertFails(() => runOffThreadDecodedScript(a));
|
||||
assertFails(() => runOffThreadDecodedScript(b));
|
||||
runOffThreadScript(a);
|
||||
finishOffThreadModule(b);
|
||||
runOffThreadDecodedScript(c);
|
||||
|
||||
// Test running multiple jobs.
|
||||
|
||||
a = offThreadCompileScript("1");
|
||||
b = offThreadCompileScript("2");
|
||||
assertEq(runOffThreadScript(a), 1);
|
||||
assertEq(runOffThreadScript(b), 2);
|
||||
|
||||
a = offThreadCompileModule("");
|
||||
b = offThreadCompileModule("");
|
||||
assertEq(typeof finishOffThreadModule(a), "object");
|
||||
assertEq(typeof finishOffThreadModule(b), "object");
|
||||
|
||||
a = offThreadDecodeScript(encodeScript("3"));
|
||||
b = offThreadDecodeScript(encodeScript("4"));
|
||||
assertEq(runOffThreadDecodedScript(a), 3);
|
||||
assertEq(runOffThreadDecodedScript(b), 4);
|
||||
|
||||
// Test many jobs.
|
||||
|
||||
const count = 100;
|
||||
let jobs;
|
||||
|
||||
jobs = new Array(count);
|
||||
for (let i = 0; i < jobs.length; i++)
|
||||
jobs[i] = offThreadCompileScript(`${i} * ${i}`);
|
||||
for (let i = 0; i < jobs.length; i++)
|
||||
assertEq(runOffThreadScript(jobs[i]), i * i);
|
||||
|
||||
jobs = new Array(count);
|
||||
for (let i = 0; i < jobs.length; i++)
|
||||
jobs[i] = offThreadCompileModule("");
|
||||
for (let i = 0; i < jobs.length; i++)
|
||||
assertEq(typeof finishOffThreadModule(jobs[i]), "object");
|
||||
|
||||
jobs = new Array(count);
|
||||
for (let i = 0; i < jobs.length; i++)
|
||||
jobs[i] = offThreadDecodeScript(encodeScript(`${i} * ${i}`));
|
||||
for (let i = 0; i < jobs.length; i++)
|
||||
assertEq(runOffThreadDecodedScript(jobs[i]), i * i);
|
|
@ -3432,7 +3432,7 @@ IonBuilder::powTrySpecialized(bool* emitted, MDefinition* base, MDefinition* pow
|
|||
|
||||
// Cast to the right type
|
||||
if (outputType == MIRType::Int32 && output->type() != MIRType::Int32) {
|
||||
MToInt32* toInt = MToInt32::New(alloc(), output);
|
||||
auto* toInt = MToNumberInt32::New(alloc(), output);
|
||||
current->add(toInt);
|
||||
output = toInt;
|
||||
}
|
||||
|
@ -7838,7 +7838,7 @@ IonBuilder::checkTypedObjectIndexInBounds(uint32_t elemSize,
|
|||
BoundsCheckKind kind)
|
||||
{
|
||||
// Ensure index is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), index);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
current->add(idInt32);
|
||||
|
||||
// If we know the length statically from the type, just embed it.
|
||||
|
@ -8319,7 +8319,7 @@ IonBuilder::getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index
|
|||
}
|
||||
|
||||
// Emit fast path for string[index].
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), index);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
current->add(idInt32);
|
||||
index = idInt32;
|
||||
|
||||
|
@ -8363,7 +8363,7 @@ IonBuilder::getElemTryArguments(bool* emitted, MDefinition* obj, MDefinition* in
|
|||
current->add(length);
|
||||
|
||||
// Ensure index is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), index);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
current->add(idInt32);
|
||||
index = idInt32;
|
||||
|
||||
|
@ -8448,7 +8448,7 @@ IonBuilder::getElemTryArgumentsInlinedIndex(bool* emitted, MDefinition* obj, MDe
|
|||
MOZ_ASSERT(!info().argsObjAliasesFormals());
|
||||
|
||||
// Ensure index is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), index);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
current->add(idInt32);
|
||||
index = idInt32;
|
||||
|
||||
|
@ -8613,7 +8613,7 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index)
|
|||
knownType = GetElemKnownType(needsHoleCheck, types);
|
||||
|
||||
// Ensure index is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), index);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
current->add(idInt32);
|
||||
index = idInt32;
|
||||
|
||||
|
@ -8810,7 +8810,7 @@ IonBuilder::jsop_getelem_typed(MDefinition* obj, MDefinition* index,
|
|||
bool allowDouble = types->hasType(TypeSet::DoubleType());
|
||||
|
||||
// Ensure id is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), index);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), index);
|
||||
current->add(idInt32);
|
||||
index = idInt32;
|
||||
|
||||
|
@ -9270,7 +9270,7 @@ IonBuilder::initOrSetElemDense(TemporaryTypeSet::DoubleConversion conversion,
|
|||
*emitted = true;
|
||||
|
||||
// Ensure id is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), id);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), id);
|
||||
current->add(idInt32);
|
||||
id = idInt32;
|
||||
|
||||
|
@ -9377,7 +9377,7 @@ IonBuilder::jsop_setelem_typed(Scalar::Type arrayType,
|
|||
spew("Emitting OOB TypedArray SetElem");
|
||||
|
||||
// Ensure id is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), id);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), id);
|
||||
current->add(idInt32);
|
||||
id = idInt32;
|
||||
|
||||
|
@ -12908,7 +12908,7 @@ IonBuilder::inTryDense(bool* emitted, MDefinition* obj, MDefinition* id)
|
|||
bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
|
||||
|
||||
// Ensure id is an integer.
|
||||
MInstruction* idInt32 = MToInt32::New(alloc(), id);
|
||||
MInstruction* idInt32 = MToNumberInt32::New(alloc(), id);
|
||||
current->add(idInt32);
|
||||
id = idInt32;
|
||||
|
||||
|
|
|
@ -2181,14 +2181,14 @@ LIRGenerator::visitToFloat32(MToFloat32* convert)
|
|||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitToInt32(MToInt32* convert)
|
||||
LIRGenerator::visitToNumberInt32(MToNumberInt32* convert)
|
||||
{
|
||||
MDefinition* opd = convert->input();
|
||||
|
||||
switch (opd->type()) {
|
||||
case MIRType::Value:
|
||||
{
|
||||
LValueToInt32* lir =
|
||||
auto* lir =
|
||||
new(alloc()) LValueToInt32(useBox(opd), tempDouble(), temp(), LValueToInt32::NORMAL);
|
||||
assignSnapshot(lir, Bailout_NonPrimitiveInput);
|
||||
define(lir, convert);
|
||||
|
|
|
@ -170,7 +170,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitOsrArgumentsObject(MOsrArgumentsObject* object) override;
|
||||
void visitToDouble(MToDouble* convert) override;
|
||||
void visitToFloat32(MToFloat32* convert) override;
|
||||
void visitToInt32(MToInt32* convert) override;
|
||||
void visitToNumberInt32(MToNumberInt32* convert) override;
|
||||
void visitTruncateToInt32(MTruncateToInt32* truncate) override;
|
||||
void visitWasmTruncateToInt32(MWasmTruncateToInt32* truncate) override;
|
||||
void visitWrapInt64ToInt32(MWrapInt64ToInt32* ins) override;
|
||||
|
|
|
@ -1862,7 +1862,7 @@ IonBuilder::inlineStrCharCodeAt(CallInfo& callInfo)
|
|||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MInstruction* index = MToInt32::New(alloc(), callInfo.getArg(0));
|
||||
MInstruction* index = MToNumberInt32::New(alloc(), callInfo.getArg(0));
|
||||
current->add(index);
|
||||
|
||||
MStringLength* length = MStringLength::New(alloc(), callInfo.thisArg());
|
||||
|
@ -1972,7 +1972,7 @@ IonBuilder::inlineStrCharAt(CallInfo& callInfo)
|
|||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MInstruction* index = MToInt32::New(alloc(), callInfo.getArg(0));
|
||||
MInstruction* index = MToNumberInt32::New(alloc(), callInfo.getArg(0));
|
||||
current->add(index);
|
||||
|
||||
MStringLength* length = MStringLength::New(alloc(), callInfo.thisArg());
|
||||
|
@ -3142,7 +3142,7 @@ IonBuilder::inlineToInteger(CallInfo& callInfo)
|
|||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MToInt32* toInt32 = MToInt32::New(alloc(), callInfo.getArg(0));
|
||||
auto* toInt32 = MToNumberInt32::New(alloc(), callInfo.getArg(0));
|
||||
current->add(toInt32);
|
||||
current->push(toInt32);
|
||||
return InliningStatus_Inlined;
|
||||
|
@ -4261,7 +4261,7 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, M
|
|||
if (!ElementAccessIsTypedArray(constraints(), array, *index, arrayType))
|
||||
return false;
|
||||
|
||||
MInstruction* indexAsInt32 = MToInt32::New(alloc(), *index);
|
||||
MInstruction* indexAsInt32 = MToNumberInt32::New(alloc(), *index);
|
||||
current->add(indexAsInt32);
|
||||
*index = indexAsInt32;
|
||||
|
||||
|
|
|
@ -4312,7 +4312,7 @@ MResumePoint::isRecoverableOperand(MUse* u) const
|
|||
}
|
||||
|
||||
MDefinition*
|
||||
MToInt32::foldsTo(TempAllocator& alloc)
|
||||
MToNumberInt32::foldsTo(TempAllocator& alloc)
|
||||
{
|
||||
MDefinition* input = getOperand(0);
|
||||
|
||||
|
@ -4356,7 +4356,7 @@ MToInt32::foldsTo(TempAllocator& alloc)
|
|||
}
|
||||
|
||||
void
|
||||
MToInt32::analyzeEdgeCasesBackward()
|
||||
MToNumberInt32::analyzeEdgeCasesBackward()
|
||||
{
|
||||
if (!NeedNegativeZeroCheck(this))
|
||||
setCanBeNegativeZero(false);
|
||||
|
@ -5505,11 +5505,11 @@ DefinitelyDifferentValue(MDefinition* ins1, MDefinition* ins2)
|
|||
if (ins1 == ins2)
|
||||
return false;
|
||||
|
||||
// Drop the MToInt32 added by the TypePolicy for double and float values.
|
||||
if (ins1->isToInt32())
|
||||
return DefinitelyDifferentValue(ins1->toToInt32()->input(), ins2);
|
||||
if (ins2->isToInt32())
|
||||
return DefinitelyDifferentValue(ins2->toToInt32()->input(), ins1);
|
||||
// Drop the MToNumberInt32 added by the TypePolicy for double and float values.
|
||||
if (ins1->isToNumberInt32())
|
||||
return DefinitelyDifferentValue(ins1->toToNumberInt32()->input(), ins2);
|
||||
if (ins2->isToNumberInt32())
|
||||
return DefinitelyDifferentValue(ins2->toToNumberInt32()->input(), ins1);
|
||||
|
||||
// Ignore the bounds check, which in most cases will contain the same info.
|
||||
if (ins1->isBoundsCheck())
|
||||
|
|
|
@ -3415,7 +3415,7 @@ class MNewArrayCopyOnWrite
|
|||
|
||||
class MNewArrayDynamicLength
|
||||
: public MUnaryInstruction,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
CompilerObject templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
@ -3494,7 +3494,7 @@ class MNewTypedArray
|
|||
|
||||
class MNewTypedArrayDynamicLength
|
||||
: public MUnaryInstruction,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
CompilerObject templateObject_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
@ -3841,7 +3841,7 @@ class MNewDerivedTypedObject
|
|||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>,
|
||||
ObjectPolicy<1>,
|
||||
IntPolicy<2> >::Data
|
||||
UnboxedInt32Policy<2> >::Data
|
||||
{
|
||||
private:
|
||||
TypedObjectPrediction prediction_;
|
||||
|
@ -4357,7 +4357,7 @@ class MCallDOMNative : public MCall
|
|||
// fun.apply(self, arguments)
|
||||
class MApplyArgs
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, IntPolicy<1>, BoxPolicy<2> >::Data
|
||||
public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, BoxPolicy<2> >::Data
|
||||
{
|
||||
protected:
|
||||
// Monomorphic cache of single target from TI, or nullptr.
|
||||
|
@ -4367,6 +4367,7 @@ class MApplyArgs
|
|||
: MTernaryInstruction(classOpcode, fun, argc, self),
|
||||
target_(target)
|
||||
{
|
||||
MOZ_ASSERT(argc->type() == MIRType::Int32);
|
||||
setResultType(MIRType::Value);
|
||||
}
|
||||
|
||||
|
@ -5670,18 +5671,21 @@ class MInt64ToFloatingPoint
|
|||
}
|
||||
};
|
||||
|
||||
// Converts a primitive (either typed or untyped) to an int32. If the input is
|
||||
// not primitive at runtime, a bailout occurs. If the input cannot be converted
|
||||
// to an int32 without loss (i.e. "5.5" or undefined) then a bailout occurs.
|
||||
class MToInt32
|
||||
// Applies ECMA's ToNumber on a primitive (either typed or untyped) and expects
|
||||
// the result to be precisely representable as an Int32, otherwise bails.
|
||||
//
|
||||
// If the input is not primitive at runtime, a bailout occurs. If the input
|
||||
// cannot be converted to an int32 without loss (i.e. 5.5 or undefined) then a
|
||||
// bailout occurs.
|
||||
class MToNumberInt32
|
||||
: public MUnaryInstruction,
|
||||
public ToInt32Policy::Data
|
||||
{
|
||||
bool canBeNegativeZero_;
|
||||
MacroAssembler::IntConversionInputKind conversion_;
|
||||
|
||||
explicit MToInt32(MDefinition* def, MacroAssembler::IntConversionInputKind conversion =
|
||||
MacroAssembler::IntConversion_Any)
|
||||
explicit MToNumberInt32(MDefinition* def, MacroAssembler::IntConversionInputKind conversion
|
||||
= MacroAssembler::IntConversion_Any)
|
||||
: MUnaryInstruction(classOpcode, def),
|
||||
canBeNegativeZero_(true),
|
||||
conversion_(conversion)
|
||||
|
@ -5696,7 +5700,7 @@ class MToInt32
|
|||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(ToInt32)
|
||||
INSTRUCTION_HEADER(ToNumberInt32)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
|
@ -5716,7 +5720,7 @@ class MToInt32
|
|||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!ins->isToInt32() || ins->toToInt32()->conversion() != conversion())
|
||||
if (!ins->isToNumberInt32() || ins->toToNumberInt32()->conversion() != conversion())
|
||||
return false;
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
|
@ -5731,7 +5735,7 @@ class MToInt32
|
|||
bool isConsistentFloat32Use(MUse* use) const override { return true; }
|
||||
#endif
|
||||
|
||||
ALLOW_CLONE(MToInt32)
|
||||
ALLOW_CLONE(MToNumberInt32)
|
||||
};
|
||||
|
||||
// Converts a value or typed input to a truncated int32, for use with bitwise
|
||||
|
@ -7527,7 +7531,7 @@ class MConcat
|
|||
|
||||
class MCharCodeAt
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<StringPolicy<0>, IntPolicy<1> >::Data
|
||||
public MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1> >::Data
|
||||
{
|
||||
MCharCodeAt(MDefinition* str, MDefinition* index)
|
||||
: MBinaryInstruction(classOpcode, str, index)
|
||||
|
@ -7561,7 +7565,7 @@ class MCharCodeAt
|
|||
|
||||
class MFromCharCode
|
||||
: public MUnaryInstruction,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
explicit MFromCharCode(MDefinition* code)
|
||||
: MUnaryInstruction(classOpcode, code)
|
||||
|
@ -7591,7 +7595,7 @@ class MFromCharCode
|
|||
|
||||
class MFromCodePoint
|
||||
: public MUnaryInstruction,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
explicit MFromCodePoint(MDefinition* codePoint)
|
||||
: MUnaryInstruction(classOpcode, codePoint)
|
||||
|
@ -8486,7 +8490,7 @@ class MRegExpMatcher
|
|||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>,
|
||||
StringPolicy<1>,
|
||||
IntPolicy<2> >::Data
|
||||
UnboxedInt32Policy<2> >::Data
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -8518,7 +8522,7 @@ class MRegExpSearcher
|
|||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>,
|
||||
StringPolicy<1>,
|
||||
IntPolicy<2> >::Data
|
||||
UnboxedInt32Policy<2> >::Data
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -8549,7 +8553,7 @@ class MRegExpTester
|
|||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>,
|
||||
StringPolicy<1>,
|
||||
IntPolicy<2> >::Data
|
||||
UnboxedInt32Policy<2> >::Data
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -8696,7 +8700,7 @@ class MStringReplace
|
|||
|
||||
class MSubstr
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<StringPolicy<0>, IntPolicy<1>, IntPolicy<2>>::Data
|
||||
public MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -9013,7 +9017,7 @@ class MConvertElementsToDoubles
|
|||
// double. Else return the original value.
|
||||
class MMaybeToDoubleElement
|
||||
: public MBinaryInstruction,
|
||||
public IntPolicy<1>::Data
|
||||
public UnboxedInt32Policy<1>::Data
|
||||
{
|
||||
MMaybeToDoubleElement(MDefinition* elements, MDefinition* value)
|
||||
: MBinaryInstruction(classOpcode, elements, value)
|
||||
|
@ -9451,7 +9455,7 @@ class MNot
|
|||
// (unsigned comparisons may be used).
|
||||
class MBoundsCheck
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<IntPolicy<0>, IntPolicy<1>>::Data
|
||||
public MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>>::Data
|
||||
{
|
||||
// Range over which to perform the bounds check, may be modified by GVN.
|
||||
int32_t minimum_;
|
||||
|
@ -9516,7 +9520,7 @@ class MBoundsCheck
|
|||
// Bailout if index < minimum.
|
||||
class MBoundsCheckLower
|
||||
: public MUnaryInstruction,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
int32_t minimum_;
|
||||
bool fallible_;
|
||||
|
@ -9551,7 +9555,7 @@ class MBoundsCheckLower
|
|||
|
||||
class MSpectreMaskIndex
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<IntPolicy<0>, IntPolicy<1>>::Data
|
||||
public MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>>::Data
|
||||
{
|
||||
MSpectreMaskIndex(MDefinition* index, MDefinition* length)
|
||||
: MBinaryInstruction(classOpcode, index, length)
|
||||
|
@ -10179,7 +10183,7 @@ class MArrayPush
|
|||
// Array.prototype.slice on a dense array.
|
||||
class MArraySlice
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2>>::Data
|
||||
public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>::Data
|
||||
{
|
||||
CompilerObject templateObj_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
@ -12290,7 +12294,7 @@ class MCallSetElement
|
|||
|
||||
class MCallInitElementArray
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, IntPolicy<1>, BoxPolicy<2> >::Data
|
||||
public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, BoxPolicy<2> >::Data
|
||||
{
|
||||
MCallInitElementArray(MDefinition* obj, MDefinition* index, MDefinition* val)
|
||||
: MTernaryInstruction(classOpcode, obj, index, val)
|
||||
|
@ -12967,7 +12971,7 @@ class MArgumentsLength : public MNullaryInstruction
|
|||
// This MIR instruction is used to get an argument from the actual arguments.
|
||||
class MGetFrameArgument
|
||||
: public MUnaryInstruction,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
bool scriptHasSetArg_;
|
||||
|
||||
|
@ -13069,7 +13073,7 @@ class MRestCommon
|
|||
class MRest
|
||||
: public MUnaryInstruction,
|
||||
public MRestCommon,
|
||||
public IntPolicy<0>::Data
|
||||
public UnboxedInt32Policy<0>::Data
|
||||
{
|
||||
MRest(TempAllocator& alloc, CompilerConstraintList* constraints, MDefinition* numActuals,
|
||||
unsigned numFormals, ArrayObject* templateObject)
|
||||
|
@ -13264,7 +13268,7 @@ class MPostWriteBarrier : public MBinaryInstruction, public ObjectPolicy<0>::Dat
|
|||
// index, update the generational store buffer if the value is in the nursery
|
||||
// and object is in the tenured heap.
|
||||
class MPostWriteElementBarrier : public MTernaryInstruction
|
||||
, public MixPolicy<ObjectPolicy<0>, IntPolicy<2>>::Data
|
||||
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<2>>::Data
|
||||
{
|
||||
MPostWriteElementBarrier(MDefinition* obj, MDefinition* value, MDefinition* index)
|
||||
: MTernaryInstruction(classOpcode, obj, value, index)
|
||||
|
@ -13885,7 +13889,7 @@ public:
|
|||
|
||||
class MCompareExchangeTypedArrayElement
|
||||
: public MQuaternaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2>, TruncateToInt32Policy<3>>::Data
|
||||
public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, TruncateToInt32Policy<2>, TruncateToInt32Policy<3>>::Data
|
||||
{
|
||||
Scalar::Type arrayType_;
|
||||
|
||||
|
@ -13920,7 +13924,7 @@ class MCompareExchangeTypedArrayElement
|
|||
|
||||
class MAtomicExchangeTypedArrayElement
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2>>::Data
|
||||
public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, TruncateToInt32Policy<2>>::Data
|
||||
{
|
||||
Scalar::Type arrayType_;
|
||||
|
||||
|
@ -13952,7 +13956,7 @@ class MAtomicExchangeTypedArrayElement
|
|||
|
||||
class MAtomicTypedArrayElementBinop
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy< ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2> >::Data
|
||||
public MixPolicy< ObjectPolicy<0>, UnboxedInt32Policy<1>, TruncateToInt32Policy<2> >::Data
|
||||
{
|
||||
private:
|
||||
AtomicOp op_;
|
||||
|
@ -14092,7 +14096,7 @@ class MDebugCheckSelfHosted
|
|||
|
||||
class MFinishBoundFunctionInit
|
||||
: public MTernaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, IntPolicy<2>>::Data
|
||||
public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, UnboxedInt32Policy<2>>::Data
|
||||
{
|
||||
MFinishBoundFunctionInit(MDefinition* bound, MDefinition* target, MDefinition* argCount)
|
||||
: MTernaryInstruction(classOpcode, bound, target, argCount)
|
||||
|
|
|
@ -126,7 +126,7 @@ namespace jit {
|
|||
_(AssertRange) \
|
||||
_(ToDouble) \
|
||||
_(ToFloat32) \
|
||||
_(ToInt32) \
|
||||
_(ToNumberInt32) \
|
||||
_(TruncateToInt32) \
|
||||
_(WrapInt64ToInt32) \
|
||||
_(ExtendInt32ToInt64) \
|
||||
|
|
|
@ -2292,8 +2292,11 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
}
|
||||
|
||||
enum IntConversionBehavior {
|
||||
// These two try to convert the input to an int32 using ToNumber and
|
||||
// will fail if the resulting int32 isn't strictly equal to the input.
|
||||
IntConversion_Normal,
|
||||
IntConversion_NegativeZeroCheck,
|
||||
// These two will convert the input to an int32 with loss of precision.
|
||||
IntConversion_Truncate,
|
||||
IntConversion_ClampToUint8,
|
||||
};
|
||||
|
@ -2335,9 +2338,8 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void convertTypedOrValueToInt(TypedOrValueRegister src, FloatRegister temp, Register output,
|
||||
Label* fail, IntConversionBehavior behavior);
|
||||
|
||||
//
|
||||
// Convenience functions for converting values to int32.
|
||||
//
|
||||
// This carries over the MToNumberInt32 operation on the ValueOperand
|
||||
// input; see comment at the top of this class.
|
||||
void convertValueToInt32(ValueOperand value, MDefinition* input,
|
||||
FloatRegister temp, Register output, Label* fail,
|
||||
bool negativeZeroCheck,
|
||||
|
@ -2350,9 +2352,8 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
conversion);
|
||||
}
|
||||
|
||||
//
|
||||
// Convenience functions for truncating values to int32.
|
||||
//
|
||||
// This carries over the MTruncateToInt32 operation on the ValueOperand
|
||||
// input; see the comment at the top of this class.
|
||||
void truncateValueToInt32(ValueOperand value, MDefinition* input,
|
||||
Label* handleStringEntry, Label* handleStringRejoin,
|
||||
Label* truncateDoubleSlow,
|
||||
|
|
|
@ -599,8 +599,8 @@ Range::Range(const MDefinition* def)
|
|||
// mimick a possible truncation.
|
||||
switch (def->type()) {
|
||||
case MIRType::Int32:
|
||||
// MToInt32 cannot truncate. So we can safely clamp.
|
||||
if (def->isToInt32())
|
||||
// MToNumberInt32 cannot truncate. So we can safely clamp.
|
||||
if (def->isToNumberInt32())
|
||||
clampToInt32();
|
||||
else
|
||||
wrapAroundToInt32();
|
||||
|
@ -1743,7 +1743,7 @@ MTruncateToInt32::computeRange(TempAllocator& alloc)
|
|||
}
|
||||
|
||||
void
|
||||
MToInt32::computeRange(TempAllocator& alloc)
|
||||
MToNumberInt32::computeRange(TempAllocator& alloc)
|
||||
{
|
||||
// No clamping since this computes the range *before* bailouts.
|
||||
setRange(new(alloc) Range(getOperand(0)));
|
||||
|
@ -2861,7 +2861,7 @@ TruncateTest(TempAllocator& alloc, MTest* test)
|
|||
if (!alloc.ensureBallast())
|
||||
return false;
|
||||
MBasicBlock* block = inner->block();
|
||||
inner = MToInt32::New(alloc, inner);
|
||||
inner = MToNumberInt32::New(alloc, inner);
|
||||
block->insertBefore(block->lastIns(), inner->toInstruction());
|
||||
}
|
||||
MOZ_ASSERT(inner->type() == MIRType::Int32);
|
||||
|
@ -3049,7 +3049,7 @@ RemoveTruncatesOnOutput(MDefinition* truncated)
|
|||
|
||||
for (MUseDefIterator use(truncated); use; use++) {
|
||||
MDefinition* def = use.def();
|
||||
if (!def->isTruncateToInt32() || !def->isToInt32())
|
||||
if (!def->isTruncateToInt32() || !def->isToNumberInt32())
|
||||
continue;
|
||||
|
||||
def->replaceAllUsesWith(truncated);
|
||||
|
@ -3074,7 +3074,7 @@ AdjustTruncatedInputs(TempAllocator& alloc, MDefinition* truncated)
|
|||
} else {
|
||||
MInstruction* op;
|
||||
if (kind == MDefinition::TruncateAfterBailouts)
|
||||
op = MToInt32::New(alloc, truncated->getOperand(i));
|
||||
op = MToNumberInt32::New(alloc, truncated->getOperand(i));
|
||||
else
|
||||
op = MTruncateToInt32::New(alloc, truncated->getOperand(i));
|
||||
|
||||
|
@ -3385,7 +3385,7 @@ MMod::collectRangeInfoPreTrunc()
|
|||
}
|
||||
|
||||
void
|
||||
MToInt32::collectRangeInfoPreTrunc()
|
||||
MToNumberInt32::collectRangeInfoPreTrunc()
|
||||
{
|
||||
Range inputRange(input());
|
||||
if (!inputRange.canBeNegativeZero())
|
||||
|
|
|
@ -865,8 +865,8 @@ IndexOf(MDefinition* ins, int32_t* res)
|
|||
indexDef = indexDef->toSpectreMaskIndex()->index();
|
||||
if (indexDef->isBoundsCheck())
|
||||
indexDef = indexDef->toBoundsCheck()->index();
|
||||
if (indexDef->isToInt32())
|
||||
indexDef = indexDef->toToInt32()->getOperand(0);
|
||||
if (indexDef->isToNumberInt32())
|
||||
indexDef = indexDef->toToNumberInt32()->getOperand(0);
|
||||
MConstant* indexDefConst = indexDef->maybeConstantValue();
|
||||
if (!indexDefConst || indexDefConst->type() != MIRType::Int32)
|
||||
return false;
|
||||
|
|
|
@ -86,7 +86,7 @@ ArithPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
else if (ins->type() == MIRType::Float32)
|
||||
replace = MToFloat32::New(alloc, in);
|
||||
else
|
||||
replace = MToInt32::New(alloc, in);
|
||||
replace = MToNumberInt32::New(alloc, in);
|
||||
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(i, replace);
|
||||
|
@ -242,7 +242,7 @@ ComparePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
|
|||
{
|
||||
convert = MacroAssembler::IntConversion_NumbersOrBoolsOnly;
|
||||
}
|
||||
replace = MToInt32::New(alloc, in, convert);
|
||||
replace = MToNumberInt32::New(alloc, in, convert);
|
||||
break;
|
||||
}
|
||||
case MIRType::Object:
|
||||
|
@ -400,7 +400,7 @@ PowPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
// Power may be an int32 or a double. Integers receive a faster path.
|
||||
if (specialization == MIRType::Double)
|
||||
return DoublePolicy<1>::staticAdjustInputs(alloc, ins);
|
||||
return IntPolicy<1>::staticAdjustInputs(alloc, ins);
|
||||
return UnboxedInt32Policy<1>::staticAdjustInputs(alloc, ins);
|
||||
}
|
||||
|
||||
template <unsigned Op>
|
||||
|
@ -463,7 +463,7 @@ template bool BooleanPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstru
|
|||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
IntPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
|
||||
UnboxedInt32Policy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
|
||||
{
|
||||
MDefinition* in = def->getOperand(Op);
|
||||
if (in->type() == MIRType::Int32)
|
||||
|
@ -476,10 +476,10 @@ IntPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
|
|||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template bool IntPolicy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool IntPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool IntPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool IntPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool UnboxedInt32Policy<0>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool UnboxedInt32Policy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool UnboxedInt32Policy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
template bool UnboxedInt32Policy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
|
@ -489,7 +489,7 @@ ConvertToInt32Policy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction*
|
|||
if (in->type() == MIRType::Int32)
|
||||
return true;
|
||||
|
||||
MToInt32* replace = MToInt32::New(alloc, in);
|
||||
auto* replace = MToNumberInt32::New(alloc, in);
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(Op, replace);
|
||||
|
||||
|
@ -726,11 +726,11 @@ ToDoublePolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
bool
|
||||
ToInt32Policy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->isToInt32() || ins->isTruncateToInt32());
|
||||
MOZ_ASSERT(ins->isToNumberInt32() || ins->isTruncateToInt32());
|
||||
|
||||
MacroAssembler::IntConversionInputKind conversion = MacroAssembler::IntConversion_Any;
|
||||
if (ins->isToInt32())
|
||||
conversion = ins->toToInt32()->conversion();
|
||||
if (ins->isToNumberInt32())
|
||||
conversion = ins->toToNumberInt32()->conversion();
|
||||
|
||||
MDefinition* in = ins->getOperand(0);
|
||||
switch (in->type()) {
|
||||
|
@ -857,7 +857,7 @@ SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
if (in->type() == MIRType::Int32)
|
||||
continue;
|
||||
|
||||
MInstruction* replace = MToInt32::New(alloc, in, MacroAssembler::IntConversion_NumbersOnly);
|
||||
auto* replace = MToNumberInt32::New(alloc, in, MacroAssembler::IntConversion_NumbersOnly);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(s->numVectors() + i, replace);
|
||||
if (!replace->typePolicy()->adjustInputs(alloc, replace))
|
||||
|
@ -1218,67 +1218,67 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
_(ToStringPolicy) \
|
||||
_(TypeBarrierPolicy)
|
||||
|
||||
#define TEMPLATE_TYPE_POLICY_LIST(_) \
|
||||
_(BoxExceptPolicy<0, MIRType::Object>) \
|
||||
_(BoxPolicy<0>) \
|
||||
_(ConvertToInt32Policy<0>) \
|
||||
_(ConvertToStringPolicy<0>) \
|
||||
_(ConvertToStringPolicy<2>) \
|
||||
_(DoublePolicy<0>) \
|
||||
_(FloatingPointPolicy<0>) \
|
||||
_(IntPolicy<0>) \
|
||||
_(IntPolicy<1>) \
|
||||
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, ObjectPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, IntPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, ObjectPolicy<2> >) \
|
||||
_(MixPolicy<StringPolicy<0>, IntPolicy<1>, IntPolicy<2>>) \
|
||||
_(MixPolicy<StringPolicy<0>, ObjectPolicy<1>, StringPolicy<2> >) \
|
||||
_(MixPolicy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1>, IntPolicy<2>>) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2>, IntPolicy<3>>) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2>, TruncateToInt32Policy<3> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, CacheIdPolicy<1>, NoFloatPolicy<2>>) \
|
||||
_(MixPolicy<SimdScalarPolicy<0>, SimdScalarPolicy<1>, SimdScalarPolicy<2>, SimdScalarPolicy<3> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxExceptPolicy<1, MIRType::Object>, CacheIdPolicy<2>>) \
|
||||
_(MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<ConvertToStringPolicy<0>, ConvertToStringPolicy<1> >) \
|
||||
_(MixPolicy<ConvertToStringPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<DoublePolicy<0>, DoublePolicy<1> >) \
|
||||
_(MixPolicy<IntPolicy<0>, IntPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >) \
|
||||
_(MixPolicy<BoxExceptPolicy<0, MIRType::Object>, CacheIdPolicy<1>>) \
|
||||
_(MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, IntPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<3> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<1>, ConvertToStringPolicy<0> >) \
|
||||
_(MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdSameAsReturnedTypePolicy<1> >) \
|
||||
_(MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdScalarPolicy<1> >) \
|
||||
_(MixPolicy<StringPolicy<0>, IntPolicy<1> >) \
|
||||
_(MixPolicy<StringPolicy<0>, StringPolicy<1> >) \
|
||||
_(MixPolicy<BoxPolicy<0>, BoxPolicy<1> >) \
|
||||
_(NoFloatPolicy<0>) \
|
||||
_(NoFloatPolicyAfter<0>) \
|
||||
_(NoFloatPolicyAfter<1>) \
|
||||
_(NoFloatPolicyAfter<2>) \
|
||||
_(ObjectPolicy<0>) \
|
||||
_(ObjectPolicy<1>) \
|
||||
_(ObjectPolicy<3>) \
|
||||
_(SimdPolicy<0>) \
|
||||
_(SimdSameAsReturnedTypePolicy<0>) \
|
||||
_(SimdScalarPolicy<0>) \
|
||||
#define TEMPLATE_TYPE_POLICY_LIST(_) \
|
||||
_(BoxExceptPolicy<0, MIRType::Object>) \
|
||||
_(BoxPolicy<0>) \
|
||||
_(ConvertToInt32Policy<0>) \
|
||||
_(ConvertToStringPolicy<0>) \
|
||||
_(ConvertToStringPolicy<2>) \
|
||||
_(DoublePolicy<0>) \
|
||||
_(FloatingPointPolicy<0>) \
|
||||
_(UnboxedInt32Policy<0>) \
|
||||
_(UnboxedInt32Policy<1>) \
|
||||
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, ObjectPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, TruncateToInt32Policy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, BoxPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, UnboxedInt32Policy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, ObjectPolicy<2> >) \
|
||||
_(MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>>) \
|
||||
_(MixPolicy<StringPolicy<0>, ObjectPolicy<1>, StringPolicy<2> >) \
|
||||
_(MixPolicy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1>, UnboxedInt32Policy<2>>) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<2>, UnboxedInt32Policy<3>>) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>, TruncateToInt32Policy<2>, TruncateToInt32Policy<3> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, CacheIdPolicy<1>, NoFloatPolicy<2>>) \
|
||||
_(MixPolicy<SimdScalarPolicy<0>, SimdScalarPolicy<1>, SimdScalarPolicy<2>, SimdScalarPolicy<3> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxExceptPolicy<1, MIRType::Object>, CacheIdPolicy<2>>) \
|
||||
_(MixPolicy<BoxPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<ConvertToStringPolicy<0>, ConvertToStringPolicy<1> >) \
|
||||
_(MixPolicy<ConvertToStringPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<DoublePolicy<0>, DoublePolicy<1> >) \
|
||||
_(MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, BoxPolicy<1> >) \
|
||||
_(MixPolicy<BoxExceptPolicy<0, MIRType::Object>, CacheIdPolicy<1>>) \
|
||||
_(MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, NoFloatPolicy<3> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, StringPolicy<1> >) \
|
||||
_(MixPolicy<ObjectPolicy<0>, ConvertToStringPolicy<2> >) \
|
||||
_(MixPolicy<ObjectPolicy<1>, ConvertToStringPolicy<0> >) \
|
||||
_(MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdSameAsReturnedTypePolicy<1> >) \
|
||||
_(MixPolicy<SimdSameAsReturnedTypePolicy<0>, SimdScalarPolicy<1> >) \
|
||||
_(MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1> >) \
|
||||
_(MixPolicy<StringPolicy<0>, StringPolicy<1> >) \
|
||||
_(MixPolicy<BoxPolicy<0>, BoxPolicy<1> >) \
|
||||
_(NoFloatPolicy<0>) \
|
||||
_(NoFloatPolicyAfter<0>) \
|
||||
_(NoFloatPolicyAfter<1>) \
|
||||
_(NoFloatPolicyAfter<2>) \
|
||||
_(ObjectPolicy<0>) \
|
||||
_(ObjectPolicy<1>) \
|
||||
_(ObjectPolicy<3>) \
|
||||
_(SimdPolicy<0>) \
|
||||
_(SimdSameAsReturnedTypePolicy<0>) \
|
||||
_(SimdScalarPolicy<0>) \
|
||||
_(StringPolicy<0>)
|
||||
|
||||
|
||||
|
|
|
@ -182,9 +182,9 @@ class BooleanPolicy final : private TypePolicy
|
|||
}
|
||||
};
|
||||
|
||||
// Expect an Int for operand Op. If the input is a Value, it is unboxed.
|
||||
// Expects either an Int32 or a boxed Int32 for operand Op; may unbox if needed.
|
||||
template <unsigned Op>
|
||||
class IntPolicy final : private TypePolicy
|
||||
class UnboxedInt32Policy final : private TypePolicy
|
||||
{
|
||||
public:
|
||||
EMPTY_DATA_;
|
||||
|
|
|
@ -4375,9 +4375,9 @@ class LValueToInt32 : public LInstructionHelper<1, BOX_PIECES, 2>
|
|||
const LDefinition* temp() {
|
||||
return getTemp(1);
|
||||
}
|
||||
MToInt32* mirNormal() const {
|
||||
MToNumberInt32* mirNormal() const {
|
||||
MOZ_ASSERT(mode_ == NORMAL);
|
||||
return mir_->toToInt32();
|
||||
return mir_->toToNumberInt32();
|
||||
}
|
||||
MTruncateToInt32* mirTruncate() const {
|
||||
MOZ_ASSERT(mode_ == TRUNCATE);
|
||||
|
@ -4401,8 +4401,8 @@ class LDoubleToInt32 : public LInstructionHelper<1, 1, 0>
|
|||
setOperand(0, in);
|
||||
}
|
||||
|
||||
MToInt32* mir() const {
|
||||
return mir_->toToInt32();
|
||||
MToNumberInt32* mir() const {
|
||||
return mir_->toToNumberInt32();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4419,8 +4419,8 @@ class LFloat32ToInt32 : public LInstructionHelper<1, 1, 0>
|
|||
setOperand(0, in);
|
||||
}
|
||||
|
||||
MToInt32* mir() const {
|
||||
return mir_->toToInt32();
|
||||
MToNumberInt32* mir() const {
|
||||
return mir_->toToNumberInt32();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -230,132 +230,209 @@ InstallCoverageSignalHandlers()
|
|||
}
|
||||
#endif
|
||||
|
||||
class OffThreadState {
|
||||
// An off-thread parse or decode job.
|
||||
class js::shell::OffThreadJob {
|
||||
enum State {
|
||||
IDLE, /* ready to work; no token, no source */
|
||||
COMPILING, /* working; no token, have source */
|
||||
DONE /* compilation done: have token and source */
|
||||
RUNNING, // Working; no token.
|
||||
DONE, // Finished; have token.
|
||||
CANCELLED // Cancelled due to error.
|
||||
};
|
||||
|
||||
public:
|
||||
OffThreadState()
|
||||
: monitor(mutexid::ShellOffThreadState),
|
||||
state(IDLE),
|
||||
runtime(nullptr),
|
||||
token(),
|
||||
source(nullptr)
|
||||
{ }
|
||||
using Source = mozilla::Variant<JS::UniqueTwoByteChars, JS::TranscodeBuffer>;
|
||||
|
||||
bool startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource);
|
||||
|
||||
bool startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr);
|
||||
|
||||
void abandon(JSContext* cx);
|
||||
OffThreadJob(ShellContext* sc, ScriptKind kind, Source&& source);
|
||||
~OffThreadJob();
|
||||
|
||||
void cancel();
|
||||
void markDone(void* newToken);
|
||||
void* waitUntilDone(JSContext* cx);
|
||||
|
||||
void* waitUntilDone(JSContext* cx, ScriptKind kind);
|
||||
char16_t* sourceChars() { return source.as<UniqueTwoByteChars>().get(); }
|
||||
JS::TranscodeBuffer& xdrBuffer() { return source.as<JS::TranscodeBuffer>(); }
|
||||
|
||||
JS::TranscodeBuffer& xdrBuffer() { return xdr; }
|
||||
public:
|
||||
const int32_t id;
|
||||
const ScriptKind kind;
|
||||
|
||||
private:
|
||||
js::Monitor monitor;
|
||||
ScriptKind scriptKind;
|
||||
js::Monitor& monitor;
|
||||
State state;
|
||||
JSRuntime* runtime;
|
||||
void* token;
|
||||
char16_t* source;
|
||||
JS::TranscodeBuffer xdr;
|
||||
Source source;
|
||||
};
|
||||
static OffThreadState* gOffThreadState;
|
||||
|
||||
bool
|
||||
OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource)
|
||||
static OffThreadJob*
|
||||
NewOffThreadJob(JSContext* cx, ScriptKind kind, OffThreadJob::Source&& source)
|
||||
{
|
||||
AutoLockMonitor alm(monitor);
|
||||
if (state != IDLE)
|
||||
return false;
|
||||
ShellContext* sc = GetShellContext(cx);
|
||||
UniquePtr<OffThreadJob> job(cx->new_<OffThreadJob>(sc, kind, Move(source)));
|
||||
if (!job)
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(!token);
|
||||
if (!sc->offThreadJobs.append(job.get())) {
|
||||
JS_ReportErrorASCII(cx, "OOM adding off-thread job");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
source = newSource.forget();
|
||||
|
||||
scriptKind = kind;
|
||||
runtime = cx->runtime();
|
||||
state = COMPILING;
|
||||
return true;
|
||||
return job.release();
|
||||
}
|
||||
|
||||
bool
|
||||
OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr)
|
||||
static OffThreadJob*
|
||||
GetSingleOffThreadJob(JSContext* cx, ScriptKind kind)
|
||||
{
|
||||
AutoLockMonitor alm(monitor);
|
||||
if (state != IDLE)
|
||||
return false;
|
||||
ShellContext* sc = GetShellContext(cx);
|
||||
const auto& jobs = sc->offThreadJobs;
|
||||
if (jobs.empty()) {
|
||||
JS_ReportErrorASCII(cx, "No off-thread jobs are pending");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!token);
|
||||
if (jobs.length() > 1) {
|
||||
JS_ReportErrorASCII(cx, "Multiple off-thread jobs are pending: must specify job ID");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
xdr = mozilla::Move(newXdr);
|
||||
OffThreadJob* job = jobs[0];
|
||||
if (job->kind != kind) {
|
||||
JS_ReportErrorASCII(cx, "Off-thread job is the wrong kind");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scriptKind = kind;
|
||||
runtime = cx->runtime();
|
||||
state = COMPILING;
|
||||
return true;
|
||||
return job;
|
||||
}
|
||||
|
||||
static OffThreadJob*
|
||||
LookupOffThreadJobByID(JSContext* cx, ScriptKind kind, int32_t id)
|
||||
{
|
||||
if (id <= 0) {
|
||||
JS_ReportErrorASCII(cx, "Bad off-thread job ID");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ShellContext* sc = GetShellContext(cx);
|
||||
const auto& jobs = sc->offThreadJobs;
|
||||
if (jobs.empty()) {
|
||||
JS_ReportErrorASCII(cx, "No off-thread jobs are pending");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OffThreadJob* job = nullptr;
|
||||
for (auto someJob : jobs) {
|
||||
if (someJob->id == id) {
|
||||
job = someJob;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!job) {
|
||||
JS_ReportErrorASCII(cx, "Off-thread job not found");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (job->kind != kind) {
|
||||
JS_ReportErrorASCII(cx, "Off-thread job is the wrong kind");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
static OffThreadJob*
|
||||
LookupOffThreadJobForArgs(JSContext* cx, ScriptKind kind, const CallArgs& args, size_t arg)
|
||||
{
|
||||
// If the optional ID argument isn't present, get the single pending job.
|
||||
if (args.length() <= arg)
|
||||
return GetSingleOffThreadJob(cx, kind);
|
||||
|
||||
// Lookup the job using the specified ID.
|
||||
int32_t id = 0;
|
||||
RootedValue value(cx, args[arg]);
|
||||
if (!ToInt32(cx, value, &id))
|
||||
return nullptr;
|
||||
|
||||
return LookupOffThreadJobByID(cx, kind, id);
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteOffThreadJob(JSContext* cx, OffThreadJob* job)
|
||||
{
|
||||
ShellContext* sc = GetShellContext(cx);
|
||||
for (size_t i = 0; i < sc->offThreadJobs.length(); i++) {
|
||||
if (sc->offThreadJobs[i] == job) {
|
||||
sc->offThreadJobs.erase(&sc->offThreadJobs[i]);
|
||||
js_delete(job);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_CRASH("Off-thread job not found");
|
||||
}
|
||||
|
||||
static void
|
||||
CancelAllOffThreadJobs(JSContext* cx)
|
||||
{
|
||||
// Parse jobs may be blocked waiting on GC.
|
||||
gc::FinishGC(cx);
|
||||
|
||||
CancelOffThreadParses(cx->runtime());
|
||||
|
||||
ShellContext* sc = GetShellContext(cx);
|
||||
while (!sc->offThreadJobs.empty())
|
||||
js_delete(sc->offThreadJobs.popCopy());
|
||||
}
|
||||
|
||||
mozilla::Atomic<int32_t> gOffThreadJobSerial(1);
|
||||
|
||||
OffThreadJob::OffThreadJob(ShellContext* sc, ScriptKind kind, Source&& source)
|
||||
: id(gOffThreadJobSerial++),
|
||||
kind(kind),
|
||||
monitor(sc->offThreadMonitor),
|
||||
state(RUNNING),
|
||||
token(nullptr),
|
||||
source(Move(source))
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(id > 0, "Off-thread job IDs exhausted");
|
||||
}
|
||||
|
||||
OffThreadJob::~OffThreadJob()
|
||||
{
|
||||
MOZ_ASSERT(state != RUNNING);
|
||||
}
|
||||
|
||||
void
|
||||
OffThreadState::abandon(JSContext* cx)
|
||||
OffThreadJob::cancel()
|
||||
{
|
||||
AutoLockMonitor alm(monitor);
|
||||
MOZ_ASSERT(state == COMPILING);
|
||||
MOZ_ASSERT(state == RUNNING);
|
||||
MOZ_ASSERT(!token);
|
||||
MOZ_ASSERT(source || !xdr.empty());
|
||||
|
||||
if (source)
|
||||
js_free(source);
|
||||
source = nullptr;
|
||||
xdr.clearAndFree();
|
||||
|
||||
state = IDLE;
|
||||
state = CANCELLED;
|
||||
}
|
||||
|
||||
void
|
||||
OffThreadState::markDone(void* newToken)
|
||||
OffThreadJob::markDone(void* newToken)
|
||||
{
|
||||
AutoLockMonitor alm(monitor);
|
||||
MOZ_ASSERT(state == COMPILING);
|
||||
MOZ_ASSERT(state == RUNNING);
|
||||
MOZ_ASSERT(!token);
|
||||
MOZ_ASSERT(source || !xdr.empty());
|
||||
MOZ_ASSERT(newToken);
|
||||
|
||||
token = newToken;
|
||||
state = DONE;
|
||||
alm.notify();
|
||||
alm.notifyAll();
|
||||
}
|
||||
|
||||
void*
|
||||
OffThreadState::waitUntilDone(JSContext* cx, ScriptKind kind)
|
||||
OffThreadJob::waitUntilDone(JSContext* cx)
|
||||
{
|
||||
AutoLockMonitor alm(monitor);
|
||||
if (state == IDLE || cx->runtime() != runtime || scriptKind != kind)
|
||||
return nullptr;
|
||||
MOZ_ASSERT(state != CANCELLED);
|
||||
|
||||
if (state == COMPILING) {
|
||||
while (state != DONE)
|
||||
alm.wait();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(source || !xdr.empty());
|
||||
if (source)
|
||||
js_free(source);
|
||||
source = nullptr;
|
||||
xdr.clearAndFree();
|
||||
while (state != DONE)
|
||||
alm.wait();
|
||||
|
||||
MOZ_ASSERT(token);
|
||||
void* holdToken = token;
|
||||
token = nullptr;
|
||||
state = IDLE;
|
||||
return holdToken;
|
||||
return token;
|
||||
}
|
||||
|
||||
struct ShellCompartmentPrivate {
|
||||
|
@ -505,9 +582,15 @@ ShellContext::ShellContext(JSContext* cx)
|
|||
quitting(false),
|
||||
readLineBufPos(0),
|
||||
errFilePtr(nullptr),
|
||||
outFilePtr(nullptr)
|
||||
outFilePtr(nullptr),
|
||||
offThreadMonitor(mutexid::ShellOffThreadState)
|
||||
{}
|
||||
|
||||
ShellContext::~ShellContext()
|
||||
{
|
||||
MOZ_ASSERT(offThreadJobs.empty());
|
||||
}
|
||||
|
||||
ShellContext*
|
||||
js::shell::GetShellContext(JSContext* cx)
|
||||
{
|
||||
|
@ -3597,6 +3680,7 @@ WorkerMain(void* arg)
|
|||
return;
|
||||
|
||||
auto guard = mozilla::MakeScopeExit([&] {
|
||||
CancelAllOffThreadJobs(cx);
|
||||
JS_DestroyContext(cx);
|
||||
js_delete(sc);
|
||||
if (input->siblingContext) {
|
||||
|
@ -4564,7 +4648,8 @@ SyntaxParse(JSContext* cx, unsigned argc, Value* vp)
|
|||
static void
|
||||
OffThreadCompileScriptCallback(void* token, void* callbackData)
|
||||
{
|
||||
gOffThreadState->markDone(token);
|
||||
auto job = static_cast<OffThreadJob*>(callbackData);
|
||||
job->markDone(token);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -4619,21 +4704,19 @@ OffThreadCompileScript(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
|
||||
size_t length = scriptContents->length();
|
||||
const char16_t* chars = stableChars.twoByteRange().begin().get();
|
||||
const char16_t* chars = stableChars.twoByteChars();
|
||||
|
||||
// Make sure we own the string's chars, so that they are not freed before
|
||||
// the compilation is finished.
|
||||
ScopedJSFreePtr<char16_t> ownedChars;
|
||||
UniqueTwoByteChars ownedChars;
|
||||
if (stableChars.maybeGiveOwnershipToCaller()) {
|
||||
ownedChars = const_cast<char16_t*>(chars);
|
||||
ownedChars.reset(const_cast<char16_t*>(chars));
|
||||
} else {
|
||||
char16_t* copy = cx->pod_malloc<char16_t>(length);
|
||||
if (!copy)
|
||||
ownedChars.reset(cx->pod_malloc<char16_t>(length));
|
||||
if (!ownedChars)
|
||||
return false;
|
||||
|
||||
mozilla::PodCopy(copy, chars, length);
|
||||
ownedChars = copy;
|
||||
chars = copy;
|
||||
mozilla::PodCopy(ownedChars.get(), chars, length);
|
||||
}
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options, length)) {
|
||||
|
@ -4641,20 +4724,20 @@ OffThreadCompileScript(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!gOffThreadState->startIfIdle(cx, ScriptKind::Script, ownedChars)) {
|
||||
JS_ReportErrorASCII(cx, "called offThreadCompileScript without calling runOffThreadScript"
|
||||
" to receive prior off-thread compilation");
|
||||
OffThreadJob* job = NewOffThreadJob(cx, ScriptKind::Script,
|
||||
OffThreadJob::Source(Move(ownedChars)));
|
||||
if (!job)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS::CompileOffThread(cx, options, chars, length,
|
||||
OffThreadCompileScriptCallback, nullptr))
|
||||
if (!JS::CompileOffThread(cx, options, job->sourceChars(), length,
|
||||
OffThreadCompileScriptCallback, job))
|
||||
{
|
||||
gOffThreadState->abandon(cx);
|
||||
job->cancel();
|
||||
DeleteOffThreadJob(cx, job);
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
args.rval().setInt32(job->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4666,11 +4749,14 @@ runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (OffThreadParsingMustWaitForGC(cx->runtime()))
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = gOffThreadState->waitUntilDone(cx, ScriptKind::Script);
|
||||
if (!token) {
|
||||
JS_ReportErrorASCII(cx, "called runOffThreadScript when no compilation is pending");
|
||||
OffThreadJob* job = LookupOffThreadJobForArgs(cx, ScriptKind::Script, args, 0);
|
||||
if (!job)
|
||||
return false;
|
||||
}
|
||||
|
||||
void* token = job->waitUntilDone(cx);
|
||||
MOZ_ASSERT(token);
|
||||
|
||||
DeleteOffThreadJob(cx, job);
|
||||
|
||||
RootedScript script(cx, JS::FinishOffThreadScript(cx, token));
|
||||
if (!script)
|
||||
|
@ -4704,21 +4790,19 @@ OffThreadCompileModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
|
||||
size_t length = scriptContents->length();
|
||||
const char16_t* chars = stableChars.twoByteRange().begin().get();
|
||||
const char16_t* chars = stableChars.twoByteChars();
|
||||
|
||||
// Make sure we own the string's chars, so that they are not freed before
|
||||
// the compilation is finished.
|
||||
ScopedJSFreePtr<char16_t> ownedChars;
|
||||
UniqueTwoByteChars ownedChars;
|
||||
if (stableChars.maybeGiveOwnershipToCaller()) {
|
||||
ownedChars = const_cast<char16_t*>(chars);
|
||||
ownedChars.reset(const_cast<char16_t*>(chars));
|
||||
} else {
|
||||
char16_t* copy = cx->pod_malloc<char16_t>(length);
|
||||
if (!copy)
|
||||
ownedChars.reset(cx->pod_malloc<char16_t>(length));
|
||||
if (!ownedChars)
|
||||
return false;
|
||||
|
||||
mozilla::PodCopy(copy, chars, length);
|
||||
ownedChars = copy;
|
||||
chars = copy;
|
||||
mozilla::PodCopy(ownedChars.get(), chars, length);
|
||||
}
|
||||
|
||||
if (!JS::CanCompileOffThread(cx, options, length)) {
|
||||
|
@ -4726,20 +4810,20 @@ OffThreadCompileModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!gOffThreadState->startIfIdle(cx, ScriptKind::Module, ownedChars)) {
|
||||
JS_ReportErrorASCII(cx, "called offThreadCompileModule without receiving prior off-thread "
|
||||
"compilation");
|
||||
OffThreadJob* job = NewOffThreadJob(cx, ScriptKind::Module,
|
||||
OffThreadJob::Source(Move(ownedChars)));
|
||||
if (!job)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS::CompileOffThreadModule(cx, options, chars, length,
|
||||
OffThreadCompileScriptCallback, nullptr))
|
||||
if (!JS::CompileOffThreadModule(cx, options, job->sourceChars(), length,
|
||||
OffThreadCompileScriptCallback, job))
|
||||
{
|
||||
gOffThreadState->abandon(cx);
|
||||
job->cancel();
|
||||
DeleteOffThreadJob(cx, job);
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
args.rval().setInt32(job->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4751,11 +4835,14 @@ FinishOffThreadModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (OffThreadParsingMustWaitForGC(cx->runtime()))
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = gOffThreadState->waitUntilDone(cx, ScriptKind::Module);
|
||||
if (!token) {
|
||||
JS_ReportErrorASCII(cx, "called finishOffThreadModule when no compilation is pending");
|
||||
OffThreadJob* job = LookupOffThreadJobForArgs(cx, ScriptKind::Module, args, 0);
|
||||
if (!job)
|
||||
return false;
|
||||
}
|
||||
|
||||
void* token = job->waitUntilDone(cx);
|
||||
MOZ_ASSERT(token);
|
||||
|
||||
DeleteOffThreadJob(cx, job);
|
||||
|
||||
RootedObject module(cx, JS::FinishOffThreadModule(cx, token));
|
||||
if (!module)
|
||||
|
@ -4828,20 +4915,20 @@ OffThreadDecodeScript(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!gOffThreadState->startIfIdle(cx, ScriptKind::DecodeScript, mozilla::Move(loadBuffer))) {
|
||||
JS_ReportErrorASCII(cx, "called offThreadDecodeScript without calling "
|
||||
"runOffThreadDecodedScript to receive prior off-thread compilation");
|
||||
OffThreadJob* job = NewOffThreadJob(cx, ScriptKind::DecodeScript,
|
||||
OffThreadJob::Source(Move(loadBuffer)));
|
||||
if (!job)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS::DecodeOffThreadScript(cx, options, gOffThreadState->xdrBuffer(), 0,
|
||||
OffThreadCompileScriptCallback, nullptr))
|
||||
if (!JS::DecodeOffThreadScript(cx, options, job->xdrBuffer(), 0,
|
||||
OffThreadCompileScriptCallback, job))
|
||||
{
|
||||
gOffThreadState->abandon(cx);
|
||||
job->cancel();
|
||||
DeleteOffThreadJob(cx, job);
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
args.rval().setInt32(job->id);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4853,11 +4940,14 @@ runOffThreadDecodedScript(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (OffThreadParsingMustWaitForGC(cx->runtime()))
|
||||
gc::FinishGC(cx);
|
||||
|
||||
void* token = gOffThreadState->waitUntilDone(cx, ScriptKind::DecodeScript);
|
||||
if (!token) {
|
||||
JS_ReportErrorASCII(cx, "called runOffThreadDecodedScript when no compilation is pending");
|
||||
OffThreadJob* job = LookupOffThreadJobForArgs(cx, ScriptKind::DecodeScript, args, 0);
|
||||
if (!job)
|
||||
return false;
|
||||
}
|
||||
|
||||
void* token = job->waitUntilDone(cx);
|
||||
MOZ_ASSERT(token);
|
||||
|
||||
DeleteOffThreadJob(cx, job);
|
||||
|
||||
RootedScript script(cx, JS::FinishOffThreadScriptDecoder(cx, token));
|
||||
if (!script)
|
||||
|
@ -6858,8 +6948,9 @@ JS_FN_HELP("parseBin", BinParse, 1, 0,
|
|||
|
||||
JS_FN_HELP("offThreadCompileScript", OffThreadCompileScript, 1, 0,
|
||||
"offThreadCompileScript(code[, options])",
|
||||
" Compile |code| on a helper thread. To wait for the compilation to finish\n"
|
||||
" and run the code, call |runOffThreadScript|. If present, |options| may\n"
|
||||
" Compile |code| on a helper thread, returning a job ID.\n"
|
||||
" To wait for the compilation to finish and run the code, call\n"
|
||||
" |runOffThreadScript| passing the job ID. If present, |options| may\n"
|
||||
" have properties saying how the code should be compiled:\n"
|
||||
" noScriptRval: use the no-script-rval compiler option (default: false)\n"
|
||||
" fileName: filename for error messages and debug info\n"
|
||||
|
@ -6871,36 +6962,39 @@ JS_FN_HELP("parseBin", BinParse, 1, 0,
|
|||
" any DOM element.\n"
|
||||
" elementAttributeName: if present and not undefined, the name of\n"
|
||||
" property of 'element' that holds this code. This is what\n"
|
||||
" Debugger.Source.prototype.elementAttributeName returns.\n"),
|
||||
" Debugger.Source.prototype.elementAttributeName returns."),
|
||||
|
||||
JS_FN_HELP("runOffThreadScript", runOffThreadScript, 0, 0,
|
||||
"runOffThreadScript()",
|
||||
" Wait for off-thread compilation to complete. If an error occurred,\n"
|
||||
"runOffThreadScript([jobID])",
|
||||
" Wait for an off-thread compilation job to complete. The job ID can be\n"
|
||||
" ommitted if there is only one job pending. If an error occurred,\n"
|
||||
" throw the appropriate exception; otherwise, run the script and return\n"
|
||||
" its value."),
|
||||
|
||||
JS_FN_HELP("offThreadCompileModule", OffThreadCompileModule, 1, 0,
|
||||
"offThreadCompileModule(code)",
|
||||
" Compile |code| on a helper thread. To wait for the compilation to finish\n"
|
||||
" and get the module object, call |finishOffThreadModule|."),
|
||||
" Compile |code| on a helper thread, returning a job ID. To wait for the\n"
|
||||
" compilation to finish and and get the module record object call\n"
|
||||
" |finishOffThreadModule| passing the job ID."),
|
||||
|
||||
JS_FN_HELP("finishOffThreadModule", FinishOffThreadModule, 0, 0,
|
||||
"finishOffThreadModule()",
|
||||
" Wait for off-thread compilation to complete. If an error occurred,\n"
|
||||
" throw the appropriate exception; otherwise, return the module object"),
|
||||
"finishOffThreadModule([jobID])",
|
||||
" Wait for an off-thread compilation job to complete. The job ID can be\n"
|
||||
" ommitted if there is only one job pending. If an error occurred,\n"
|
||||
" throw the appropriate exception; otherwise, return the module record object."),
|
||||
|
||||
JS_FN_HELP("offThreadDecodeScript", OffThreadDecodeScript, 1, 0,
|
||||
"offThreadDecodeScript(cacheEntry[, options])",
|
||||
" Decode |code| on a helper thread. To wait for the compilation to finish\n"
|
||||
" and run the code, call |runOffThreadScript|. If present, |options| may\n"
|
||||
" have properties saying how the code should be compiled.\n"
|
||||
" (see also offThreadCompileScript)\n"),
|
||||
" Decode |code| on a helper thread, returning a job ID. To wait for the\n"
|
||||
" decoding to finish and run the code, call |runOffThreadDecodeScript| passing\n"
|
||||
" the job ID. If present, |options| may have properties saying how the code\n"
|
||||
" should be compiled (see also offThreadCompileScript)."),
|
||||
|
||||
JS_FN_HELP("runOffThreadDecodedScript", runOffThreadDecodedScript, 0, 0,
|
||||
"runOffThreadDecodedScript()",
|
||||
" Wait for off-thread decoding to complete. If an error occurred,\n"
|
||||
" throw the appropriate exception; otherwise, run the script and return\n"
|
||||
" its value."),
|
||||
"runOffThreadDecodedScript([jobID])",
|
||||
" Wait for off-thread decoding to complete. The job ID can be ommitted if there\n"
|
||||
" is only one job pending. If an error occurred, throw the appropriate\n"
|
||||
" exception; otherwise, run the script and return its value."),
|
||||
|
||||
JS_FN_HELP("timeout", Timeout, 1, 0,
|
||||
"timeout([seconds], [func])",
|
||||
|
@ -9121,13 +9215,6 @@ main(int argc, char** argv, char** envp)
|
|||
});
|
||||
JS::InitConsumeStreamCallback(cx, ConsumeBufferSource);
|
||||
|
||||
gOffThreadState = js_new<OffThreadState>();
|
||||
if (!gOffThreadState)
|
||||
return 1;
|
||||
auto deleteOffThreadState = MakeScopeExit([] {
|
||||
js_delete(gOffThreadState);
|
||||
});
|
||||
|
||||
JS_SetNativeStackQuota(cx, gMaxStackSize);
|
||||
|
||||
JS::dbg::SetDebuggerMallocSizeOf(cx, moz_malloc_size_of);
|
||||
|
@ -9180,6 +9267,8 @@ main(int argc, char** argv, char** envp)
|
|||
|
||||
DestructSharedArrayBufferMailbox();
|
||||
|
||||
CancelAllOffThreadJobs(cx);
|
||||
|
||||
JS_DestroyContext(cx);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
|
@ -131,10 +132,13 @@ using MarkBitObservers = JS::WeakCache<NonshrinkingGCObjectVector>;
|
|||
using StackChars = Vector<char16_t, 0, SystemAllocPolicy>;
|
||||
#endif
|
||||
|
||||
class OffThreadJob;
|
||||
|
||||
// Per-context shell state.
|
||||
struct ShellContext
|
||||
{
|
||||
explicit ShellContext(JSContext* cx);
|
||||
~ShellContext();
|
||||
|
||||
bool isWorker;
|
||||
double timeoutInterval;
|
||||
|
@ -172,6 +176,11 @@ struct ShellContext
|
|||
|
||||
JS::UniqueChars moduleLoadPath;
|
||||
UniquePtr<MarkBitObservers> markObservers;
|
||||
|
||||
// Off-thread parse state.
|
||||
js::Monitor offThreadMonitor;
|
||||
Vector<OffThreadJob*, 0, SystemAllocPolicy> offThreadJobs;
|
||||
|
||||
};
|
||||
|
||||
extern ShellContext*
|
||||
|
|
|
@ -1192,12 +1192,7 @@ GlobalHelperThreadState::maxParseThreads() const
|
|||
{
|
||||
if (IsHelperThreadSimulatingOOM(js::THREAD_TYPE_PARSE))
|
||||
return 1;
|
||||
|
||||
// Don't allow simultaneous off thread parses, to reduce contention on the
|
||||
// atoms table. Note that wasm compilation depends on this to avoid
|
||||
// stalling the helper thread, as off thread parse tasks can trigger and
|
||||
// block on other off thread wasm compilation tasks.
|
||||
return 1;
|
||||
return cpuCount;
|
||||
}
|
||||
|
||||
size_t
|
||||
|
|
|
@ -1862,8 +1862,8 @@ nsLayoutUtils::DoCompareTreePosition(nsIContent* aContent1,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t index1 = parent->IndexOf(content1Ancestor);
|
||||
int32_t index2 = parent->IndexOf(content2Ancestor);
|
||||
int32_t index1 = parent->ComputeIndexOf(content1Ancestor);
|
||||
int32_t index2 = parent->ComputeIndexOf(content2Ancestor);
|
||||
if (index1 < 0 || index2 < 0) {
|
||||
// one of them must be anonymous; we can't determine the order
|
||||
return 0;
|
||||
|
|
|
@ -222,7 +222,7 @@ nsIFrame::ContentOffsets BRFrame::CalcContentOffsetsFromFramePoint(const nsPoint
|
|||
ContentOffsets offsets;
|
||||
offsets.content = mContent->GetParent();
|
||||
if (offsets.content) {
|
||||
offsets.offset = offsets.content->IndexOf(mContent);
|
||||
offsets.offset = offsets.content->ComputeIndexOf(mContent);
|
||||
offsets.secondaryOffset = offsets.offset;
|
||||
offsets.associate = CARET_ASSOCIATE_AFTER;
|
||||
}
|
||||
|
|
|
@ -2265,7 +2265,7 @@ nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
|
|||
int32_t offset = 0;
|
||||
if (newContent) {
|
||||
// XXXbz there has GOT to be a better way of determining this!
|
||||
offset = newContent->IndexOf(mContent);
|
||||
offset = newContent->ComputeIndexOf(mContent);
|
||||
}
|
||||
|
||||
//look up to see what selection(s) are on this frame
|
||||
|
@ -4004,7 +4004,7 @@ nsFrame::GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
|
|||
nsCOMPtr<nsIContent> parentContent = tableOrCellContent->GetParent();
|
||||
if (!parentContent) return NS_ERROR_FAILURE;
|
||||
|
||||
int32_t offset = parentContent->IndexOf(tableOrCellContent);
|
||||
int32_t offset = parentContent->ComputeIndexOf(tableOrCellContent);
|
||||
// Not likely?
|
||||
if (offset < 0) return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -4739,7 +4739,7 @@ static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
|
|||
}
|
||||
if (type == LayoutFrameType::Br) {
|
||||
parent = content->GetParent();
|
||||
int32_t beginOffset = parent->IndexOf(content);
|
||||
int32_t beginOffset = parent->ComputeIndexOf(content);
|
||||
return FrameContentRange(parent, beginOffset, beginOffset);
|
||||
}
|
||||
// Loop to deal with anonymous content, which has no index; this loop
|
||||
|
@ -4747,7 +4747,7 @@ static FrameContentRange GetRangeForFrame(nsIFrame* aFrame) {
|
|||
do {
|
||||
parent = content->GetParent();
|
||||
if (parent) {
|
||||
int32_t beginOffset = parent->IndexOf(content);
|
||||
int32_t beginOffset = parent->ComputeIndexOf(content);
|
||||
if (beginOffset >= 0)
|
||||
return FrameContentRange(parent, beginOffset, beginOffset + 1);
|
||||
content = parent;
|
||||
|
@ -7621,7 +7621,7 @@ int32_t nsFrame::ContentIndexInContainer(const nsIFrame* aFrame)
|
|||
if (content) {
|
||||
nsIContent* parentContent = content->GetParent();
|
||||
if (parentContent) {
|
||||
result = parentContent->IndexOf(content);
|
||||
result = parentContent->ComputeIndexOf(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7965,7 +7965,7 @@ nsFrame::GetPointFromOffset(int32_t inOffset, nsPoint* outPoint)
|
|||
{
|
||||
nsIContent* newContent = mContent->GetParent();
|
||||
if (newContent){
|
||||
int32_t newOffset = newContent->IndexOf(mContent);
|
||||
int32_t newOffset = newContent->ComputeIndexOf(mContent);
|
||||
|
||||
// Find the direction of the frame from the EmbeddingLevelProperty,
|
||||
// which is the resolved bidi level set in
|
||||
|
@ -8174,7 +8174,7 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsPresContext* aPresContext,
|
|||
if (parent)
|
||||
{
|
||||
aPos->mResultContent = parent;
|
||||
aPos->mContentOffset = parent->IndexOf(content);
|
||||
aPos->mContentOffset = parent->ComputeIndexOf(content);
|
||||
aPos->mAttach = CARET_ASSOCIATE_BEFORE;
|
||||
if ((point.x - offset.x+ tempRect.x)>tempRect.width)
|
||||
{
|
||||
|
@ -8325,7 +8325,7 @@ FindBlockFrameOrBR(nsIFrame* aFrame, nsDirection aDirection)
|
|||
// to avoid crashing here.
|
||||
NS_ASSERTION(result.mContent, "Unexpected orphan content");
|
||||
if (result.mContent)
|
||||
result.mOffset = result.mContent->IndexOf(content) +
|
||||
result.mOffset = result.mContent->ComputeIndexOf(content) +
|
||||
(aDirection == eDirPrevious ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -624,7 +624,7 @@ ParentOffset(nsINode *aNode, int32_t *aChildOffset)
|
|||
nsIContent* parent = aNode->GetParent();
|
||||
if (parent)
|
||||
{
|
||||
*aChildOffset = parent->IndexOf(aNode);
|
||||
*aChildOffset = parent->ComputeIndexOf(aNode);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
@ -2791,7 +2791,7 @@ nsFrameSelection::SelectCellElement(nsIContent *aCellElement)
|
|||
nsIContent *parent = aCellElement->GetParent();
|
||||
|
||||
// Get child offset
|
||||
int32_t offset = parent->IndexOf(aCellElement);
|
||||
int32_t offset = parent->ComputeIndexOf(aCellElement);
|
||||
|
||||
return CreateAndAddRange(parent, offset);
|
||||
}
|
||||
|
|
|
@ -1922,7 +1922,7 @@ nsImageFrame::ShouldDisplaySelection()
|
|||
nsCOMPtr<nsIContent> parentContent = mContent->GetParent();
|
||||
if (parentContent)
|
||||
{
|
||||
int32_t thisOffset = parentContent->IndexOf(mContent);
|
||||
int32_t thisOffset = parentContent->ComputeIndexOf(mContent);
|
||||
nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(parentContent);
|
||||
nsCOMPtr<nsIDOMNode> rangeNode;
|
||||
uint32_t rangeOffset;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
XPIDL_SOURCES += [
|
||||
'nsIPrintProgress.idl',
|
||||
'nsIPrintProgressParams.idl',
|
||||
'nsIPrintStatusFeedback.idl',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.layout += [
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDocShell;
|
||||
interface mozIDOMWindowProxy;
|
||||
|
||||
/**
|
||||
* XXX This interface seems to be unimplemented and unused.
|
||||
*/
|
||||
[scriptable, uuid(8eb6ffc9-715c-487e-927c-c56139229548)]
|
||||
interface nsIPrintStatusFeedback : nsISupports {
|
||||
void showStatusString(in wstring status);
|
||||
void startMeteors();
|
||||
void stopMeteors();
|
||||
void showProgress(in long percent);
|
||||
[noscript] void setDocShell(in nsIDocShell shell, in mozIDOMWindowProxy window);
|
||||
void closeWindow();
|
||||
};
|
||||
|
|
@ -2529,7 +2529,7 @@ GetCorrespondingNodeInDocument(const nsINode* aNode, nsIDocument* aDoc)
|
|||
nsTArray<int32_t> indexArray;
|
||||
const nsINode* child = aNode;
|
||||
while (const nsINode* parent = child->GetParentNode()) {
|
||||
int32_t index = parent->IndexOf(child);
|
||||
int32_t index = parent->ComputeIndexOf(child);
|
||||
MOZ_ASSERT(index >= 0);
|
||||
indexArray.AppendElement(index);
|
||||
child = parent;
|
||||
|
|
|
@ -2683,7 +2683,7 @@ nsTableFrame::HomogenousInsertFrames(ChildListID aListID,
|
|||
}
|
||||
nsCOMPtr<nsIContent> container = content->GetParent();
|
||||
if (MOZ_LIKELY(container)) { // XXX need this null-check, see bug 411823.
|
||||
int32_t newIndex = container->IndexOf(content);
|
||||
int32_t newIndex = container->ComputeIndexOf(content);
|
||||
nsIFrame* kidFrame;
|
||||
nsTableColGroupFrame* lastColGroup = nullptr;
|
||||
if (isColGroup) {
|
||||
|
@ -2707,7 +2707,7 @@ nsTableFrame::HomogenousInsertFrames(ChildListID aListID,
|
|||
(content = pseudoFrame->GetContent()))) {
|
||||
pseudoFrame = pseudoFrame->PrincipalChildList().FirstChild();
|
||||
}
|
||||
int32_t index = container->IndexOf(content);
|
||||
int32_t index = container->ComputeIndexOf(content);
|
||||
if (index > lastIndex && index < newIndex) {
|
||||
lastIndex = index;
|
||||
aPrevFrame = kidFrame;
|
||||
|
|
|
@ -1156,7 +1156,7 @@ nsListBoxBodyFrame::GetFirstItemBox(int32_t aOffset, bool* aCreated)
|
|||
// We need to insert rows before the top frame
|
||||
nsIContent* topContent = mTopFrame->GetContent();
|
||||
nsIContent* topParent = topContent->GetParent();
|
||||
int32_t contentIndex = topParent->IndexOf(topContent);
|
||||
int32_t contentIndex = topParent->ComputeIndexOf(topContent);
|
||||
contentIndex -= aOffset;
|
||||
if (contentIndex < 0)
|
||||
return nullptr;
|
||||
|
@ -1217,7 +1217,7 @@ nsListBoxBodyFrame::GetNextItemBox(nsIFrame* aBox, int32_t aOffset,
|
|||
nsIContent* prevContent = aBox->GetContent();
|
||||
nsIContent* parentContent = prevContent->GetParent();
|
||||
|
||||
int32_t i = parentContent->IndexOf(prevContent);
|
||||
int32_t i = parentContent->ComputeIndexOf(prevContent);
|
||||
|
||||
uint32_t childCount = parentContent->GetChildCount();
|
||||
if (((uint32_t)i + aOffset + 1) < childCount) {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче