Merge mozilla-central to autoland r=merge

This commit is contained in:
Dorel Luca 2018-01-23 19:54:54 +02:00
Родитель 86cfc3f0ce e3cba77cee
Коммит bad2421650
674 изменённых файлов: 196480 добавлений и 19008 удалений

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

@ -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

36
build/gn.mozbuild Normal file
Просмотреть файл

@ -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) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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