Merge m-c to b2ginbound a=merge

This commit is contained in:
Wes Kocher 2015-03-27 17:18:16 -07:00
Родитель 48b71c9bb0 e4585cf145
Коммит c3a8e32831
175 изменённых файлов: 2304 добавлений и 1125 удалений

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

@ -10,6 +10,7 @@
#include "AccessibleWrap.h"
#include "DocAccessible.h"
#include "nsMai.h"
#include "ProxyAccessible.h"
#include "mozilla/Likely.h"
using namespace mozilla::a11y;
@ -46,12 +47,14 @@ documentInterfaceInitCB(AtkDocumentIface *aIface)
const gchar *
getDocumentLocaleCB(AtkDocument *aDocument)
{
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
if (!accWrap)
return nullptr;
nsAutoString locale;
accWrap->Language(locale);
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
if (accWrap) {
accWrap->Language(locale);
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aDocument))) {
proxy->Language(locale);
}
return locale.IsEmpty() ? nullptr : AccessibleWrap::ReturnString(locale);
}
@ -71,24 +74,30 @@ prependToList(GSList *aList, const char *const aName, const nsAutoString &aValue
AtkAttributeSet *
getDocumentAttributesCB(AtkDocument *aDocument)
{
nsAutoString url;
nsAutoString w3cDocType;
nsAutoString mimeType;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
if (!accWrap || !accWrap->IsDoc())
if (accWrap) {
if (!accWrap->IsDoc()) {
return nullptr;
}
DocAccessible* document = accWrap->AsDoc();
document->URL(url);
document->DocType(w3cDocType);
document->MimeType(mimeType);
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aDocument))) {
proxy->URLDocTypeMimeType(url, w3cDocType, mimeType);
} else {
return nullptr;
}
// according to atkobject.h, AtkAttributeSet is a GSList
GSList* attributes = nullptr;
DocAccessible* document = accWrap->AsDoc();
nsAutoString aURL;
document->URL(aURL);
attributes = prependToList(attributes, kDocUrlName, aURL);
nsAutoString aW3CDocType;
document->DocType(aW3CDocType);
attributes = prependToList(attributes, kDocTypeName, aW3CDocType);
nsAutoString aMimeType;
document->MimeType(aMimeType);
attributes = prependToList(attributes, kMimeTypeName, aMimeType);
attributes = prependToList(attributes, kDocUrlName, url);
attributes = prependToList(attributes, kDocTypeName, w3cDocType);
attributes = prependToList(attributes, kMimeTypeName, mimeType);
return attributes;
}
@ -97,20 +106,44 @@ const gchar *
getDocumentAttributeValueCB(AtkDocument *aDocument,
const gchar *aAttrName)
{
ProxyAccessible* proxy = nullptr;
DocAccessible* document = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aDocument));
if (!accWrap || !accWrap->IsDoc())
return nullptr;
if (accWrap) {
if (!accWrap->IsDoc()) {
return nullptr;
}
document = accWrap->AsDoc();
} else {
proxy = GetProxy(ATK_OBJECT(aDocument));
if (!proxy) {
return nullptr;
}
}
DocAccessible* document = accWrap->AsDoc();
nsAutoString attrValue;
if (!strcasecmp(aAttrName, kDocTypeName))
document->DocType(attrValue);
else if (!strcasecmp(aAttrName, kDocUrlName))
document->URL(attrValue);
else if (!strcasecmp(aAttrName, kMimeTypeName))
document->MimeType(attrValue);
else
if (!strcasecmp(aAttrName, kDocTypeName)) {
if (document) {
document->DocType(attrValue);
} else {
proxy->DocType(attrValue);
}
} else if (!strcasecmp(aAttrName, kDocUrlName)) {
if (document) {
document->URL(attrValue);
} else {
proxy->URL(attrValue);
}
} else if (!strcasecmp(aAttrName, kMimeTypeName)) {
if (document) {
document->MimeType(attrValue);
} else {
proxy->MimeType(attrValue);
}
} else {
return nullptr;
}
return attrValue.IsEmpty() ? nullptr : AccessibleWrap::ReturnString(attrValue);
}

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

@ -1631,5 +1631,70 @@ DocAccessibleChild::RecvBounds(const uint64_t& aID,
return false;
}
bool
DocAccessibleChild::RecvLanguage(const uint64_t& aID,
nsString* aLocale)
{
Accessible* acc = IdToAccessible(aID);
if (acc) {
acc->Language(*aLocale);
}
return true;
}
bool
DocAccessibleChild::RecvDocType(const uint64_t& aID,
nsString* aType)
{
Accessible* acc = IdToAccessible(aID);
if (acc && acc->IsDoc()) {
acc->AsDoc()->DocType(*aType);
}
return true;
}
bool
DocAccessibleChild::RecvURL(const uint64_t& aID,
nsString* aURL)
{
Accessible* acc = IdToAccessible(aID);
if (acc && acc->IsDoc()) {
acc->AsDoc()->URL(*aURL);
}
return true;
}
bool
DocAccessibleChild::RecvMimeType(const uint64_t& aID,
nsString* aMime)
{
Accessible* acc = IdToAccessible(aID);
if (acc && acc->IsDoc()) {
acc->AsDoc()->MimeType(*aMime);
}
return true;
}
bool
DocAccessibleChild::RecvURLDocTypeMimeType(const uint64_t& aID,
nsString* aURL,
nsString* aDocType,
nsString* aMimeType)
{
Accessible* acc = IdToAccessible(aID);
if (acc && acc->IsDoc()) {
DocAccessible* doc = acc->AsDoc();
doc->URL(*aURL);
doc->DocType(*aDocType);
doc->MimeType(*aMimeType);
}
return true;
}
}
}

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

@ -401,6 +401,15 @@ public:
bool* aOk) override;
virtual bool RecvBounds(const uint64_t& aID, nsIntRect* aRect) override;
virtual bool RecvLanguage(const uint64_t& aID, nsString* aLocale) override;
virtual bool RecvDocType(const uint64_t& aID, nsString* aType) override;
virtual bool RecvURL(const uint64_t& aID, nsString* aURL) override;
virtual bool RecvMimeType(const uint64_t& aID, nsString* aMime) override;
virtual bool RecvURLDocTypeMimeType(const uint64_t& aID,
nsString* aURL,
nsString* aDocType,
nsString* aMimeType) override;
private:
Accessible* IdToAccessible(const uint64_t& aID) const;

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

@ -209,6 +209,12 @@ child:
prio(high) sync ChildAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aWhich)
returns(uint64_t aChild, bool aOk);
prio(high) sync Bounds(uint64_t aID) returns(nsIntRect aRect);
prio(high) sync Language(uint64_t aID) returns(nsString aLocale);
prio(high) sync DocType(uint64_t aID) returns(nsString aType);
prio(high) sync URL(uint64_t aID) returns(nsString aURL);
prio(high) sync MimeType(uint64_t aID) returns(nsString aMime);
prio(high) sync URLDocTypeMimeType(uint64_t aID) returns(nsString aURL, nsString aDocType, nsString aMimeType);
};
}

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

@ -911,5 +911,36 @@ ProxyAccessible::Bounds()
return rect;
}
void
ProxyAccessible::Language(nsString& aLocale)
{
unused << mDoc->SendLanguage(mID, &aLocale);
}
void
ProxyAccessible::DocType(nsString& aType)
{
unused << mDoc->SendDocType(mID, &aType);
}
void
ProxyAccessible::URL(nsString& aURL)
{
unused << mDoc->SendURL(mID, &aURL);
}
void
ProxyAccessible::MimeType(nsString aMime)
{
unused << mDoc->SendMimeType(mID, &aMime);
}
void
ProxyAccessible::URLDocTypeMimeType(nsString& aURL, nsString& aDocType,
nsString& aMimeType)
{
unused << mDoc->SendURLDocTypeMimeType(mID, &aURL, &aDocType, &aMimeType);
}
}
}

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

@ -276,6 +276,13 @@ public:
Accessible::EWhichChildAtPoint aWhichChild);
nsIntRect Bounds();
void Language(nsString& aLocale);
void DocType(nsString& aType);
void URL(nsString& aURL);
void MimeType(nsString aMime);
void URLDocTypeMimeType(nsString& aURL, nsString& aDocType,
nsString& aMimeType);
/**
* Allow the platform to store a pointers worth of data on us.
*/

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

@ -540,8 +540,7 @@ struct RoleDescrComparator
nsAutoString value;
mGeckoAccessible->Value(value);
return value.IsEmpty() ? nil : [NSString stringWithCharacters:reinterpret_cast<const unichar*>(value.BeginReading())
length:value.Length()];
return nsCocoaUtils::ToNSString(value);
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
@ -585,8 +584,7 @@ struct RoleDescrComparator
nsAutoString helpText;
mGeckoAccessible->Help(helpText);
return helpText.IsEmpty() ? nil : [NSString stringWithCharacters:reinterpret_cast<const unichar*>(helpText.BeginReading())
length:helpText.Length()];
return nsCocoaUtils::ToNSString(helpText);
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}

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

@ -46,6 +46,12 @@ searchbar {
-moz-binding: url("chrome://browser/content/search/search.xml#searchbar");
}
/* Prevent shrinking the page content to 0 height and width */
.browserStack > browser {
min-height: 25px;
min-width: 25px;
}
.browserStack > browser {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-browser");
}

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

@ -661,7 +661,7 @@
setfocus="false"
tooltip="tabbrowser-tab-tooltip"
stopwatchid="FX_TAB_CLICK_MS">
<tab class="tabbrowser-tab" selected="true" fadein="true"/>
<tab class="tabbrowser-tab" selected="true" visuallyselected="true" fadein="true"/>
</tabs>
<toolbarbutton id="new-tab-button"

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

@ -1203,7 +1203,7 @@
// We need to explicitly focus the new tab, because
// tabbox.xml does this only in some cases.
this.mCurrentTab.focus();
} else if (gMultiProcessBrowser) {
} else if (gMultiProcessBrowser && document.activeElement !== newBrowser) {
// Clear focus so that _adjustFocusAfterTabSwitch can detect if
// some element has been focused and respect that.
document.activeElement.blur();
@ -1215,6 +1215,14 @@
this.tabContainer._setPositionalAttributes();
if (!gMultiProcessBrowser) {
let event = new CustomEvent("TabSwitchDone", {
bubbles: true,
cancelable: true
});
this.dispatchEvent(event);
}
if (!aForceUpdate)
TelemetryStopwatch.finish("FX_TAB_SWITCH_UPDATE_MS");
]]>
@ -2760,7 +2768,8 @@
let wasFocused = (document.activeElement == this.mCurrentTab);
aIndex = aIndex < aTab._tPos ? aIndex: aIndex+1;
this.mCurrentTab._selected = false;
this.mCurrentTab._logicallySelected = false;
this.mCurrentTab._visuallySelected = false;
// invalidate caches
this._browsers = null;
@ -2772,9 +2781,11 @@
for (let i = 0; i < this.tabs.length; i++) {
this.tabs[i]._tPos = i;
this.tabs[i]._selected = false;
this.tabs[i]._logicallySelected = false;
this.tabs[i]._visuallySelected = false;
}
this.mCurrentTab._selected = true;
this.mCurrentTab._logicallySelected = true;
this.mCurrentTab._visuallySelected = true;
if (wasFocused)
this.mCurrentTab.focus();
@ -2866,6 +2877,518 @@
</body>
</method>
<!--
The tab switcher is responsible for asynchronously switching
tabs in e10s. It waits until the new tab is ready (i.e., the
layer tree is available) before switching to it. Then it
unloads the layer tree for the old tab.
The tab switcher is a state machine. For each tab, it
maintains state about whether the layer tree for the tab is
available, being loaded, being unloaded, or unavailable. It
also keeps track of the tab currently being displayed, the tab
it's trying to load, and the tab the user has asked to switch
to. The switcher object is created upon tab switch. It is
released when there are no pending tabs to load or unload.
The following general principles have guided the design:
1. We only request one layer tree at a time. If the user
switches to a different tab while waiting, we don't request
the new layer tree until the old tab has loaded or timed out.
2. If loading the layers for a tab times out, we show the
spinner and possibly request the layer tree for another tab if
the user has requested one.
3. We discard layer trees on a delay. This way, if the user is
switching among the same tabs frequently, we don't continually
load the same tabs.
It's important that we always show either the spinner or a tab
whose layers are available. Otherwise the compositor will draw
an entirely black frame, which is very jarring. To ensure this
never happens, we do the following:
1. When switching away from a tab, we assume the old tab might
still be drawn until a MozAfterPaint event occurs. Because
layout and compositing happen asynchronously, we don't have
any other way of knowing when the switch actually takes
place. Therefore, we don't unload the old tab until the next
MozAfterPaint event.
2. Suppose that the user switches from tab A to B and then
back to A. Suppose that we ask for tab A's layers to be
unloaded via message M1 after the first switch and then
request them again via message M2 once the second switch
happens. Both loading and unloading of layers happens
asynchronously, and this can cause problems. It's possible
that the content process publishes one last layer tree before
M1 is received. The parent process doesn't know that this
layer tree was published before M1 and not after M2, so it
will display the tab. However, once M1 arrives, the content
process will destroy the layer tree for A and now we will
display black for it.
To counter this problem, we keep tab A in a separate
"unloading" state until the layer tree is actually dropped in
the compositor thread. While the tab is in the "unloading"
state, we're not allowed to request layers for it. Once the
layers are dropped in the compositor, an event will fire and
we will transition the tab to the "unloaded" state. Then we
are free to request the tab's layers again.
-->
<field name="_switcher">null</field>
<method name="_getSwitcher">
<body><![CDATA[
if (this._switcher) {
return this._switcher;
}
let switcher = {
// How long to wait for a tab's layers to load. After this
// time elapses, we're free to put up the spinner and start
// trying to load a different tab.
TAB_SWITCH_TIMEOUT: 300 /* ms */,
// When the user hasn't switched tabs for this long, we unload
// layers for all tabs that aren't in use.
UNLOAD_DELAY: 300 /* ms */,
// The next three tabs form the principal state variables.
// See the assertions in postActions for their invariants.
// Tab the user requested most recently.
requestedTab: this.selectedTab,
// Tab we're currently trying to load.
loadingTab: null,
// We show this tab in case the requestedTab hasn't loaded yet.
lastVisibleTab: this.selectedTab,
// Auxilliary state variables:
visibleTab: this.selectedTab, // Tab that's on screen.
spinnerTab: null, // Tab showing a spinner.
originalTab: this.selectedTab, // Tab that we started on.
tabbrowser: this, // Reference to gBrowser.
loadTimer: null, // TAB_SWITCH_TIMEOUT timer.
unloadTimer: null, // UNLOAD_DELAY timer.
// Map from tabs to STATE_* (below).
tabState: new Map(),
// Set of tabs that might be visible right now. We maintain
// this set because we can't be sure when a tab is actually
// drawn. A tab is added to this set when we ask to make it
// visible. All tabs but the most recently shown tab are
// removed from the set upon MozAfterPaint.
maybeVisibleTabs: new Set([this.selectedTab]),
STATE_UNLOADED: 0,
STATE_LOADING: 1,
STATE_LOADED: 2,
STATE_UNLOADING: 3,
logging: false,
getTabState: function(tab) {
let state = this.tabState.get(tab);
if (state === undefined) {
return this.STATE_UNLOADED;
}
return state;
},
setTabState: function(tab, state) {
if (state == this.STATE_UNLOADED) {
this.tabState.delete(tab);
} else {
this.tabState.set(tab, state);
}
let browser = tab.linkedBrowser;
let fl = browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
if (state == this.STATE_LOADING) {
// Ask for a MozLayerTreeReady event.
fl.requestNotifyLayerTreeReady();
browser.docShellIsActive = true;
} else if (state == this.STATE_UNLOADING) {
// Ask for MozLayerTreeCleared event.
fl.requestNotifyLayerTreeCleared();
browser.docShellIsActive = false;
}
},
init: function() {
this.log("START");
window.addEventListener("MozAfterPaint", this);
window.addEventListener("MozLayerTreeReady", this);
window.addEventListener("MozLayerTreeCleared", this);
window.addEventListener("TabRemotenessChange", this);
this.setTabState(this.requestedTab, this.STATE_LOADED);
},
destroy: function() {
clearTimeout(this.unloadTimer);
clearTimeout(this.loadTimer);
window.removeEventListener("MozAfterPaint", this);
window.removeEventListener("MozLayerTreeReady", this);
window.removeEventListener("MozLayerTreeCleared", this);
window.removeEventListener("TabRemotenessChange", this);
this.tabbrowser._switcher = null;
},
finish: function() {
this.log("FINISH");
this.assert(this.tabbrowser._switcher);
this.assert(this.tabbrowser._switcher === this);
this.assert(!this.spinnerTab);
this.assert(!this.loadTimer);
this.assert(!this.loadingTab);
this.assert(this.lastVisibleTab === this.requestedTab);
this.assert(this.getTabState(this.requestedTab) == this.STATE_LOADED);
this.destroy();
let toBrowser = this.requestedTab.linkedBrowser;
toBrowser.setAttribute("type", "content-primary");
this.tabbrowser._adjustFocusAfterTabSwitch(this.requestedTab);
let fromBrowser = this.originalTab.linkedBrowser;
// It's possible that the tab we're switching from closed
// before we were able to finalize, in which case, fromBrowser
// doesn't exist.
if (fromBrowser) {
fromBrowser.setAttribute("type", "content-targetable");
}
let event = new CustomEvent("TabSwitchDone", {
bubbles: true,
cancelable: true
});
this.tabbrowser.dispatchEvent(event);
},
// This function is called after all the main state changes to
// make sure we display the right tab.
updateDisplay: function() {
// Figure out which tab we actually want visible right now.
let showTab = null;
if (this.getTabState(this.requestedTab) != this.STATE_LOADED &&
this.lastVisibleTab && this.loadTimer) {
// If we can't show the requestedTab, and lastVisibleTab is
// available, show it.
showTab = this.lastVisibleTab;
} else {
// Show the requested tab. If it's not available, we'll show the spinner.
showTab = this.requestedTab;
}
// Show or hide the spinner as needed.
let needSpinner = this.getTabState(showTab) != this.STATE_LOADED;
if (!needSpinner && this.spinnerTab) {
this.tabbrowser.removeAttribute("pendingpaint");
this.spinnerTab.linkedBrowser.removeAttribute("pendingpaint");
this.spinnerTab = null;
} else if (needSpinner && this.spinnerTab !== showTab) {
if (this.spinnerTab) {
this.spinnerTab.linkedBrowser.removeAttribute("pendingpaint");
}
this.spinnerTab = showTab;
this.tabbrowser.setAttribute("pendingpaint", "true");
this.spinnerTab.linkedBrowser.setAttribute("pendingpaint", "true");
}
// Switch to the tab we've decided to make visible.
if (this.visibleTab !== showTab) {
this.visibleTab = showTab;
this.maybeVisibleTabs.add(showTab);
let tabs = this.tabbrowser.mTabBox.tabs;
let tabPanel = this.tabbrowser.mPanelContainer;
let showPanel = tabs.getRelatedElement(showTab);
let index = Array.indexOf(tabPanel.childNodes, showPanel);
if (index != -1) {
this.log(`Switch to tab ${index} - ${this.tinfo(showTab)}`);
tabPanel.setAttribute("selectedIndex", index);
if (showTab === this.requestedTab) {
this.tabbrowser._adjustFocusAfterTabSwitch(showTab);
}
}
// This doesn't necessarily exist if we're a new window and haven't switched tabs yet
if (this.lastVisibleTab)
this.lastVisibleTab._visuallySelected = false;
this.visibleTab._visuallySelected = true;
}
this.lastVisibleTab = this.visibleTab;
},
assert: function(cond) {
if (!cond) {
dump("Assertion failure\n" + Error().stack);
throw new Error("Assertion failure");
}
},
// We've decided to try to load requestedTab.
loadRequestedTab: function() {
this.assert(!this.loadTimer);
// loadingTab can be non-null here if we timed out loading the current tab.
// In that case we just overwrite it with a different tab; it's had its chance.
this.loadingTab = this.requestedTab;
this.log("Loading tab " + this.tinfo(this.loadingTab));
this.setTabState(this.requestedTab, this.STATE_LOADING);
this.loadTimer = setTimeout(() => this.onLoadTimeout(), this.TAB_SWITCH_TIMEOUT);
},
// This function runs before every event. It fixes up the state
// to account for closed tabs.
preActions: function() {
this.assert(this.tabbrowser._switcher);
this.assert(this.tabbrowser._switcher === this);
for (let [tab, state] of this.tabState) {
if (!tab.linkedBrowser) {
this.tabState.delete(tab);
}
}
if (this.lastVisibleTab && !this.lastVisibleTab.linkedBrowser) {
this.lastVisibleTab = null;
}
if (this.spinnerTab && !this.spinnerTab.linkedBrowser) {
this.spinnerTab = null;
}
if (this.loadingTab && !this.loadingTab.linkedBrowser) {
this.loadingTab = null;
clearTimeout(this.loadTimer);
this.loadTimer = null;
}
},
// This code runs after we've responded to an event or requested a new
// tab. It's expected that we've already updated all the principal
// state variables. This function takes care of updating any auxilliary
// state.
postActions: function() {
// Once we finish loading loadingTab, we null it out. So the state should
// always be LOADING.
this.assert(!this.loadingTab ||
this.getTabState(this.loadingTab) == this.STATE_LOADING);
// We guarantee that loadingTab is non-null iff loadTimer is non-null. So
// the timer is set only when we're loading something.
this.assert(!this.loadTimer || this.loadingTab);
this.assert(!this.loadingTab || this.loadTimer);
// If we're not loading anything, try loading the requested tab.
if (!this.loadTimer && this.getTabState(this.requestedTab) == this.STATE_UNLOADED) {
this.loadRequestedTab();
}
// See how many tabs still have work to do.
let numPending = 0;
for (let [tab, state] of this.tabState) {
if (state == this.STATE_LOADED && tab !== this.requestedTab) {
numPending++;
}
if (state == this.STATE_LOADING || state == this.STATE_UNLOADING) {
numPending++;
}
}
this.updateDisplay();
// It's possible for updateDisplay to trigger one of our own event
// handlers, which might cause finish() to already have been called.
// Check for that before calling finish() again.
if (!this.tabbrowser._switcher) {
return;
}
if (numPending == 0) {
this.finish();
}
this.logState("done");
},
// Fires when we're ready to unload unused tabs.
onUnloadTimeout: function() {
this.logState("onUnloadTimeout");
this.preActions();
let numPending = 0;
// Unload any tabs that can be unloaded.
for (let [tab, state] of this.tabState) {
if (state == this.STATE_LOADED &&
!this.maybeVisibleTabs.has(tab) &&
tab !== this.lastVisibleTab &&
tab !== this.loadingTab &&
tab !== this.requestedTab)
{
this.setTabState(tab, this.STATE_UNLOADING);
}
if (state != this.STATE_UNLOADED && tab !== this.requestedTab) {
numPending++;
}
}
if (numPending) {
// Keep the timer going since there may be more tabs to unload.
this.unloadTimer = setTimeout(() => this.onUnloadTimeout(), this.UNLOAD_DELAY);
}
this.postActions();
},
// Fires when an ongoing load has taken too long.
onLoadTimeout: function() {
this.logState("onLoadTimeout");
this.preActions();
this.loadTimer = null;
this.loadingTab = null;
this.postActions();
},
// Fires when the layers become available for a tab.
onLayersReady: function(browser) {
this.logState("onLayersReady");
let tab = this.tabbrowser.getTabForBrowser(browser);
this.setTabState(tab, this.STATE_LOADED);
if (this.loadingTab === tab) {
clearTimeout(this.loadTimer);
this.loadTimer = null;
this.loadingTab = null;
}
},
// Fires when we paint the screen. Any tab switches we initiated
// previously are done, so there's no need to keep the old layers
// around.
onPaint: function() {
this.maybeVisibleTabs.clear();
},
// Called when we're done clearing the layers for a tab.
onLayersCleared: function(browser) {
this.logState("onLayersCleared");
let tab = this.tabbrowser.getTabForBrowser(browser);
if (tab) {
this.setTabState(tab, this.STATE_UNLOADED);
}
},
// Called when a tab switches from remote to non-remote. In this case
// a MozLayerTreeReady notification that we requested may never fire,
// so we need to simulate it.
onRemotenessChange: function(tab) {
this.logState("onRemotenessChange");
if (!tab.linkedBrowser.isRemoteBrowser) {
if (this.getTabState(tab) == this.STATE_LOADING) {
this.onLayersReady(tab.linkedBrowser);
} else if (this.getTabState(tab) == this.STATE_UNLOADING) {
this.onLayersCleared(tab.linkedBrowser);
}
}
},
// Called when the user asks to switch to a given tab.
requestTab: function(tab) {
if (tab === this.requestedTab) {
return;
}
this.logState("requestTab " + this.tinfo(tab));
this.requestedTab = tab;
this.preActions();
clearTimeout(this.unloadTimer);
this.unloadTimer = setTimeout(() => this.onUnloadTimeout(), this.UNLOAD_DELAY);
this.postActions();
},
handleEvent: function(event) {
this.preActions();
if (event.type == "MozLayerTreeReady") {
this.onLayersReady(event.originalTarget);
} if (event.type == "MozAfterPaint") {
this.onPaint();
} else if (event.type == "MozLayerTreeCleared") {
this.onLayersCleared(event.originalTarget);
} else if (event.type == "TabRemotenessChange") {
this.onRemotenessChange(event.target);
}
this.postActions();
},
tinfo: function(tab) {
if (tab) {
return tab._tPos + "(" + tab.linkedBrowser.currentURI.spec + ")";
} else {
return "null";
}
},
log: function(s) {
if (!this.logging)
return;
dump(s + "\n");
},
logState: function(prefix) {
if (!this.logging)
return;
dump(prefix + " ");
for (let i = 0; i < this.tabbrowser.tabs.length; i++) {
let tab = this.tabbrowser.tabs[i];
let state = this.getTabState(tab);
dump(i + ":");
if (tab === this.lastVisibleTab) dump("V");
if (tab === this.loadingTab) dump("L");
if (tab === this.requestedTab) dump("R");
if (state == this.STATE_LOADED) dump("(+)");
if (state == this.STATE_LOADING) dump("(+?)");
if (state == this.STATE_UNLOADED) dump("(-)");
if (state == this.STATE_UNLOADING) dump("(-?)");
dump(" ");
}
dump("\n");
},
};
this._switcher = switcher;
switcher.init();
return switcher;
]]></body>
</method>
<!-- BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
MAKE SURE TO ADD IT HERE AS WELL. -->
<property name="canGoBack"
@ -3380,6 +3903,10 @@
if (gMultiProcessBrowser) {
messageManager.removeMessageListener("DOMTitleChanged", this);
messageManager.removeMessageListener("contextmenu", this);
if (this._switcher) {
this._switcher.destroy();
}
}
]]>
</destructor>
@ -3404,154 +3931,6 @@
</body>
</method>
<method name="_showBusySpinnerRemoteBrowser">
<parameter name="aBrowser"/>
<body><![CDATA[
aBrowser.setAttribute("pendingpaint", "true");
if (this._contentWaitingCount <= 0) {
// We are not currently spinning
this.setAttribute("pendingpaint", "true");
this._contentWaitingCount = 1;
} else {
this._contentWaitingCount++;
}
]]></body>
</method>
<method name="_hideBusySpinnerRemoteBrowser">
<parameter name="aBrowser"/>
<body><![CDATA[
aBrowser.removeAttribute("pendingpaint");
this._contentWaitingCount--;
if (this._contentWaitingCount <= 0) {
this.removeAttribute("pendingpaint");
}
]]></body>
</method>
<method name="_prepareForTabSwitch">
<parameter name="toTab"/>
<parameter name="fromTab"/>
<body><![CDATA[
const kTabSwitchTimeout = 300;
let toBrowser = this.getBrowserForTab(toTab);
let fromBrowser = fromTab ? this.getBrowserForTab(fromTab)
: null;
// We only want to wait for the MozAfterRemotePaint event if
// the tab we're switching to is a remote tab, and if the tab
// we're switching to isn't the one we've already got. The latter
// case can occur when closing tabs before the currently selected
// one.
let shouldWait = toBrowser.getAttribute("remote") == "true" &&
toBrowser != fromBrowser;
let switchPromise;
if (shouldWait) {
let timeoutId;
let panels = this.mPanelContainer;
// Both the timeout and MozAfterPaint promises use this same
// logic to determine whether they should carry out the tab
// switch, or reject it outright.
let attemptTabSwitch = (aResolve, aReject) => {
if (this.selectedBrowser == toBrowser) {
aResolve();
} else {
// We switched away or closed the browser before we timed
// out. We reject, which will cancel the tab switch.
aReject();
}
};
let timeoutPromise = new Promise((aResolve, aReject) => {
timeoutId = setTimeout(() => {
if (toBrowser.isRemoteBrowser) {
// The browser's remoteness could have changed since we
// setTimeout so only show the spinner if it's still remote.
this._showBusySpinnerRemoteBrowser(toBrowser);
}
attemptTabSwitch(aResolve, aReject);
}, kTabSwitchTimeout);
});
let paintPromise = new Promise((aResolve, aReject) => {
let onRemotePaint = () => {
toBrowser.removeEventListener("MozAfterRemotePaint", onRemotePaint);
this._hideBusySpinnerRemoteBrowser(toBrowser);
clearTimeout(timeoutId);
attemptTabSwitch(aResolve, aReject);
};
toBrowser.addEventListener("MozAfterRemotePaint", onRemotePaint);
toBrowser.QueryInterface(Ci.nsIFrameLoaderOwner)
.frameLoader
.requestNotifyAfterRemotePaint();
// We need to activate the docShell on the tab we're switching
// to - otherwise, we won't initiate a remote paint request and
// therefore we won't get the MozAfterRemotePaint event that we're
// waiting for.
// Note that this happens, as we require, even if the timeout in the
// timeoutPromise triggers before the paintPromise even runs.
toBrowser.docShellIsActive = true;
});
switchPromise = Promise.race([paintPromise, timeoutPromise]);
} else {
// Activate the docShell on the tab we're switching to.
toBrowser.docShellIsActive = true;
// No need to wait - just resolve immediately to do the switch ASAP.
switchPromise = Promise.resolve();
}
return switchPromise;
]]></body>
</method>
<method name="_deactivateContent">
<parameter name="tab"/>
<body><![CDATA[
// It's unlikely, yet possible, that while we were waiting
// to deactivate this tab, that something closed it and wiped
// out the browser. For example, during a tab switch, while waiting
// for the MozAfterRemotePaint event to fire, something closes the
// original tab that the user had selected. If that's the case, then
// there's nothing to deactivate.
let browser = this.getBrowserForTab(tab);
if (browser && this.selectedBrowser != browser) {
browser.docShellIsActive = false;
}
]]></body>
</method>
<method name="_finalizeTabSwitch">
<parameter name="toTab"/>
<parameter name="fromTab"/>
<body><![CDATA[
this._adjustFocusAfterTabSwitch(toTab);
this._deactivateContent(fromTab);
let toBrowser = this.getBrowserForTab(toTab);
toBrowser.setAttribute("type", "content-primary");
let fromBrowser = this.getBrowserForTab(fromTab);
// It's possible that the tab we're switching from closed
// before we were able to finalize, in which case, fromBrowser
// doesn't exist.
if (fromBrowser) {
fromBrowser.setAttribute("type", "content-targetable");
}
]]></body>
</method>
<method name="_cancelTabSwitch">
<parameter name="toTab"/>
<body><![CDATA[
this._deactivateContent(toTab);
]]></body>
</method>
<property name="mContextTab" readonly="true"
onget="return TabContextMenu.contextTab;"/>
<property name="mPrefs" readonly="true"
@ -5042,22 +5421,22 @@
<content context="tabContextMenu" closetabtext="&closeTab.label;">
<xul:stack class="tab-stack" flex="1">
<xul:hbox xbl:inherits="pinned,selected,titlechanged,fadein"
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,titlechanged,fadein"
class="tab-background">
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,titlechanged"
class="tab-background-start"/>
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,titlechanged"
class="tab-background-middle"/>
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,titlechanged"
class="tab-background-end"/>
</xul:hbox>
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
<xul:hbox xbl:inherits="pinned,selected,visuallyselected,titlechanged"
class="tab-content" align="center">
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected"
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected,visuallyselected"
class="tab-throbber"
role="presentation"
layer="true" />
<xul:image xbl:inherits="src=image,fadein,pinned,selected,busy,crashed"
<xul:image xbl:inherits="src=image,fadein,pinned,selected,visuallyselected,busy,crashed"
anonid="tab-icon-image"
class="tab-icon-image"
validate="never"
@ -5067,17 +5446,36 @@
role="presentation"/>
<xul:label flex="1"
anonid="tab-label"
xbl:inherits="value=visibleLabel,crop,accesskey,fadein,pinned,selected"
xbl:inherits="value=visibleLabel,crop,accesskey,fadein,pinned,selected,visuallyselected"
class="tab-text tab-label"
role="presentation"/>
<xul:toolbarbutton anonid="close-button"
xbl:inherits="fadein,pinned,selected"
xbl:inherits="fadein,pinned,selected,visuallyselected"
class="tab-close-button close-icon"/>
</xul:hbox>
</xul:stack>
</content>
<implementation>
<property name="_selected">
<setter>
<![CDATA[
// in e10s we want to only pseudo-select a tab before its rendering is done, so that
// the rest of the system knows that the tab is selected, but we don't want to update its
// visual status to selected until after we receive confirmation that its content has painted.
this._logicallySelected = val;
// If we're non-e10s we should update the visual selection as well at the same time
if (!gMultiProcessBrowser) {
this._visuallySelected = val;
}
return val;
]]>
</setter>
</property>
<property name="label">
<getter>
return this.getAttribute("label");
@ -5514,7 +5912,7 @@
let fromTab = this._selectedPanel ? this.getRelatedElement(this._selectedPanel)
: null;
let switchPromise = gBrowser._prepareForTabSwitch(toTab, fromTab);
gBrowser._getSwitcher().requestTab(toTab);
var panel = this._selectedPanel;
var newPanel = this.childNodes[val];
@ -5525,26 +5923,6 @@
this.dispatchEvent(event);
this._selectedIndex = val;
switchPromise.then(() => {
// If we cannot find the tabpanel that we were trying to switch to, then
// it must have been removed before our Promise could be resolved. In
// that case, we just cancel the tab switch.
var updatedTabIndex = Array.indexOf(this.childNodes, newPanel);
if (updatedTabIndex == -1) {
gBrowser._cancelTabSwitch(toTab);
} else {
this.setAttribute("selectedIndex", updatedTabIndex);
gBrowser._finalizeTabSwitch(toTab, fromTab);
}
}, () => {
// If the promise rejected, that means we don't want to actually
// flip the deck, so we cancel the tab switch.
// We need to nullcheck the method we're about to call because
// the binding might be dead at this point.
if (gBrowser._cancelTabSwitch)
gBrowser._cancelTabSwitch(toTab);
});
}
return val;

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

@ -4,6 +4,9 @@ function test() {
var isLinux = navigator.platform.indexOf("Linux") == 0;
for (let i = 9; i >= 1; i--) {
// Make sure the keystroke goes to chrome.
document.activeElement.blur();
EventUtils.synthesizeKey(i.toString(), { altKey: isLinux, accelKey: !isLinux });
is(gBrowser.tabContainer.selectedIndex, (i == 9 ? gBrowser.tabs.length : i) - 1,

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

@ -32,6 +32,55 @@ function loadURI(tab, url) {
return BrowserTestUtils.browserLoaded(tab.linkedBrowser);
}
// Creates a framescript which caches the current object value from the plugin
// in the page. checkObjectValue below verifies that the framescript is still
// active for the browser and that the cached value matches that from the plugin
// in the page which tells us the plugin hasn't been reinitialized.
function cacheObjectValue(browser) {
let frame_script = function() {
let plugin = content.document.wrappedJSObject.body.firstChild;
let objectValue = plugin.getObjectValue();
addMessageListener("Test:CheckObjectValue", () => {
try {
let plugin = content.document.wrappedJSObject.body.firstChild;
sendAsyncMessage("Test:CheckObjectValue", {
result: plugin.checkObjectValue(objectValue)
});
}
catch (e) {
sendAsyncMessage("Test:CheckObjectValue", {
result: null,
exception: e.toString()
});
}
});
};
browser.messageManager.loadFrameScript("data:,(" + frame_script.toString() + ")();", false)
}
// See the notes for cacheObjectValue above.
function checkObjectValue(browser) {
let mm = browser.messageManager;
return new Promise((resolve, reject) => {
let listener = ({ data }) => {
mm.removeMessageListener("Test:CheckObjectValue", listener);
if (data.result === null) {
ok(false, "checkObjectValue threw an exception: " + data.exception);
reject(data.exception);
}
else {
resolve(data.result);
}
};
mm.addMessageListener("Test:CheckObjectValue", listener);
mm.sendAsyncMessage("Test:CheckObjectValue");
});
}
add_task(function*() {
let embed = '<embed type="application/x-test" allowscriptaccess="always" allowfullscreen="true" wmode="window" width="640" height="480"></embed>'
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED);
@ -57,15 +106,12 @@ add_task(function*() {
is(gBrowser.tabs[2], tabs[3], "tab3");
is(gBrowser.tabs[3], tabs[4], "tab4");
let plugin = tabs[4].linkedBrowser.contentDocument.wrappedJSObject.body.firstChild;
let tab4_plugin_object = plugin.getObjectValue();
cacheObjectValue(tabs[4].linkedBrowser);
swapTabsAndCloseOther(3, 2); // now: 0 1 4
gBrowser.selectedTab = gBrowser.tabs[2];
let doc = gBrowser.tabs[2].linkedBrowser.contentDocument.wrappedJSObject;
plugin = doc.body.firstChild;
ok(plugin && plugin.checkObjectValue(tab4_plugin_object), "same plugin instance");
ok((yield checkObjectValue(gBrowser.tabs[2].linkedBrowser)), "same plugin instance");
is(gBrowser.tabs[1], tabs[1], "tab1");
is(gBrowser.tabs[2], tabs[3], "tab4");
@ -77,9 +123,7 @@ add_task(function*() {
swapTabsAndCloseOther(2, 1); // now: 0 4
is(gBrowser.tabs[1], tabs[1], "tab1");
doc = gBrowser.tabs[1].linkedBrowser.contentDocument.wrappedJSObject;
plugin = doc.body.firstChild;
ok(plugin && plugin.checkObjectValue(tab4_plugin_object), "same plugin instance");
ok((yield checkObjectValue(gBrowser.tabs[1].linkedBrowser)), "same plugin instance");
yield clickTest(gBrowser.tabs[1]);

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

@ -216,14 +216,13 @@ add_task(function*() {
"main-window", "tab1", true,
"tab change when selected tab element was focused");
let paintWaiter;
let switchWaiter;
if (gMultiProcessBrowser) {
paintWaiter = new Promise((resolve, reject) => {
browser2.addEventListener("MozAfterRemotePaint", function paintListener() {
browser2.removeEventListener("MozAfterRemotePaint", paintListener, false);
switchWaiter = new Promise((resolve, reject) => {
gBrowser.addEventListener("TabSwitchDone", function listener() {
gBrowser.removeEventListener("TabSwitchDone", listener);
executeSoon(resolve);
}, false);
browser2.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.requestNotifyAfterRemotePaint();
});
});
}
@ -236,7 +235,7 @@ add_task(function*() {
// Otherwise, the _adjustFocusAfterTabSwitch in tabbrowser gets confused and
// isn't sure what tab is really focused.
if (gMultiProcessBrowser) {
yield paintWaiter;
yield switchWaiter;
}
yield expectFocusShift(function () gBrowser.selectedTab.blur(),

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

@ -25,12 +25,12 @@ add_task(function*() {
is (nbox.clientWidth, nboxWidth, "Opening the toolbox hasn't changed the width of the nbox");
let iframe = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-bottom-iframe");
is (iframe.clientHeight, nboxHeight - 10, "The iframe fits within the available space ");
is (iframe.clientHeight, nboxHeight - 25, "The iframe fits within the available space");
yield toolbox.switchHost(devtools.Toolbox.HostType.SIDE);
iframe = document.getAnonymousElementByAttribute(nbox, "class", "devtools-toolbox-side-iframe");
iframe.style.minWidth = "1px"; // Disable the min width set in css
is (iframe.clientWidth, nboxWidth - 10, "The iframe fits within the available space");
is (iframe.clientWidth, nboxWidth - 25, "The iframe fits within the available space");
yield cleanup(toolbox);
});

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

@ -10,6 +10,12 @@ const {Promise: promise} = require("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
/* A host should always allow this much space for the page to be displayed.
* There is also a min-height on the browser, but we still don't want to set
* frame.height to be larger than that, since it can cause problems with
* resizing the toolbox and panel layout. */
const MIN_PAGE_SIZE = 25;
/**
* A toolbox host represents an object that contains a toolbox (e.g. the
* sidebar or a separate window). Any host object should implement the
@ -57,7 +63,7 @@ BottomHost.prototype = {
this.frame.className = "devtools-toolbox-bottom-iframe";
this.frame.height = Math.min(
Services.prefs.getIntPref(this.heightPref),
this._nbox.clientHeight - 10 // Always show at least some page content
this._nbox.clientHeight - MIN_PAGE_SIZE
);
this._nbox.appendChild(this._splitter);
@ -144,7 +150,7 @@ SidebarHost.prototype = {
this.frame.width = Math.min(
Services.prefs.getIntPref(this.widthPref),
this._sidebar.clientWidth - 10 // Always show at least some page content
this._sidebar.clientWidth - MIN_PAGE_SIZE
);
this._sidebar.appendChild(this._splitter);

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

@ -2328,7 +2328,7 @@ function ElementEditor(aContainer, aNode) {
this.template = this.markup.template.bind(this.markup);
this.doc = this.markup.doc;
this.attrs = {};
this.attrElements = new Map();
this.animationTimers = {};
// The templates will fill the following properties
@ -2408,14 +2408,20 @@ ElementEditor.prototype = {
* Update the state of the editor from the node.
*/
update: function() {
let attrs = this.node.attributes || [];
let attrsToRemove = new Set(this.attrList.querySelectorAll(".attreditor"));
let nodeAttributes = this.node.attributes || [];
// Only loop through the current attributes on the node, anything that's
// been removed will be removed from this DOM because it will be part of
// the attrsToRemove set.
for (let attr of attrs) {
let el = this.attrs[attr.name];
// Keep the data model in sync with attributes on the node.
let currentAttributes = new Set(nodeAttributes.map(a=>a.name));
for (let name of this.attrElements.keys()) {
if (!currentAttributes.has(name)) {
this.removeAttribute(name);
}
}
// Only loop through the current attributes on the node. Missing
// attributes have already been removed at this point.
for (let attr of nodeAttributes) {
let el = this.attrElements.get(attr.name);
let valueChanged = el && el.querySelector(".attr-value").innerHTML !== attr.value;
let isEditing = el && el.querySelector(".editable").inplaceEditor;
let canSimplyShowEditor = el && (!valueChanged || isEditing);
@ -2423,7 +2429,6 @@ ElementEditor.prototype = {
if (canSimplyShowEditor) {
// Element already exists and doesn't need to be recreated.
// Just show it (it's hidden by default due to the template).
attrsToRemove.delete(el);
el.style.removeProperty("display");
} else {
// Create a new editor, because the value of an existing attribute
@ -2439,10 +2444,6 @@ ElementEditor.prototype = {
}
}
}
for (let el of attrsToRemove) {
el.remove();
}
},
_startModifyingAttributes: function() {
@ -2459,6 +2460,18 @@ ElementEditor.prototype = {
".attreditor[data-attr=" + attrName + "] .attr-value");
},
/**
* Remove an attribute from the attrElements object and the DOM
* @param string attrName The name of the attribute to remove
*/
removeAttribute: function(attrName) {
let attr = this.attrElements.get(attrName);
if (attr) {
this.attrElements.delete(attrName);
attr.remove();
}
},
_createAttribute: function(aAttr, aBefore = null) {
// Create the template editor, which will save some variables here.
let data = {
@ -2541,18 +2554,13 @@ ElementEditor.prototype = {
if (aAttr.name == "id") {
before = this.attrList.firstChild;
} else if (aAttr.name == "class") {
let idNode = this.attrs["id"];
let idNode = this.attrElements.get("id");
before = idNode ? idNode.nextSibling : this.attrList.firstChild;
}
this.attrList.insertBefore(attr, before);
// Remove the old version of this attribute from the DOM.
let oldAttr = this.attrs[aAttr.name];
if (oldAttr && oldAttr.parentNode) {
oldAttr.parentNode.removeChild(oldAttr);
}
this.attrs[aAttr.name] = attr;
this.removeAttribute(aAttr.name);
this.attrElements.set(aAttr.name, attr);
let collapsedValue;
if (aAttr.value.match(COLLAPSE_DATA_URL_REGEX)) {

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

@ -140,7 +140,7 @@ function* checkData(index, editor, inspector) {
} else {
let nodeFront = yield getNodeFront("#node14", inspector);
let editor = getContainerForNodeFront(nodeFront, inspector).editor;
let attr = editor.attrs["style"].querySelector(".editable");
let attr = editor.attrElements.get("style").querySelector(".editable");
is(attr.textContent, completion, "Correct value is persisted after pressing Enter");
}
}

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

@ -39,6 +39,32 @@ const TEST_DATA = [
}), "newattr attribute removed");
}
},
{
desc: "Re-adding an attribute",
test: () => {
let node1 = getNode("#node1");
node1.setAttribute("newattr", "newattrval");
},
check: function*(inspector) {
let {editor} = yield getContainerForSelector("#node1", inspector);
ok([...editor.attrList.querySelectorAll(".attreditor")].some(attr => {
return attr.textContent.trim() === "newattr=\"newattrval\"";
}), "newattr attribute found");
}
},
{
desc: "Changing an attribute",
test: () => {
let node1 = getNode("#node1");
node1.setAttribute("newattr", "newattrchanged");
},
check: function*(inspector) {
let {editor} = yield getContainerForSelector("#node1", inspector);
ok([...editor.attrList.querySelectorAll(".attreditor")].some(attr => {
return attr.textContent.trim() === "newattr=\"newattrchanged\"";
}), "newattr attribute found");
}
},
{
desc: "Updating the text-content",
test: () => {

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

@ -123,7 +123,7 @@ function* assertNodeFlashing(nodeFront, inspector) {
function* assertAttributeFlashing(nodeFront, attribute, inspector) {
let container = getContainerForNodeFront(nodeFront, inspector);
ok(container, "Markup container for node found");
ok(container.editor.attrs[attribute], "Attribute exists on editor");
ok(container.editor.attrElements.get(attribute), "Attribute exists on editor");
let attributeElement = container.editor.getAttributeElement(attribute);

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

@ -22,7 +22,7 @@ add_task(function*() {
info("Focus the ID attribute and change its content");
let {editor} = yield getContainerForSelector("#test-div", inspector);
let attr = editor.attrs["id"].querySelector(".editable");
let attr = editor.attrElements.get("id").querySelector(".editable");
let mutated = inspector.once("markupmutation");
setEditableFieldValue(attr,
attr.textContent + ' class="newclass" style="color:green"', inspector);

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

@ -47,7 +47,7 @@ let TEST_DATA = [{
},
validate: (element, container, inspector) => {
let editor = container.editor;
let visibleAttrText = editor.attrs["style"].querySelector(".attr-value").textContent;
let visibleAttrText = editor.attrElements.get("style").querySelector(".attr-value").textContent;
is (visibleAttrText, DATA_URL_INLINE_STYLE_COLLAPSED);
}
}, {
@ -58,7 +58,7 @@ let TEST_DATA = [{
},
validate: (element, container, inspector) => {
let editor = container.editor;
let visibleAttrText = editor.attrs["data-long"].querySelector(".attr-value").textContent;
let visibleAttrText = editor.attrElements.get("data-long").querySelector(".attr-value").textContent;
is (visibleAttrText, LONG_ATTRIBUTE_COLLAPSED)
}
}, {
@ -69,7 +69,7 @@ let TEST_DATA = [{
},
validate: (element, container, inspector) => {
let editor = container.editor;
let visibleAttrText = editor.attrs["src"].querySelector(".attr-value").textContent;
let visibleAttrText = editor.attrElements.get("src").querySelector(".attr-value").textContent;
is (visibleAttrText, DATA_URL_ATTRIBUTE_COLLAPSED);
}
}];

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

@ -36,7 +36,7 @@ function* testCollapsedLongAttribute(inspector) {
});
let {editor} = yield getContainerForSelector("#node24", inspector);
let attr = editor.attrs["data-long"].querySelector(".editable");
let attr = editor.attrElements.get("data-long").querySelector(".editable");
// Check to make sure it has expanded after focus
attr.focus();
@ -48,7 +48,7 @@ function* testCollapsedLongAttribute(inspector) {
setEditableFieldValue(attr, input.value + ' data-short="ABC"', inspector);
yield inspector.once("markupmutation");
let visibleAttrText = editor.attrs["data-long"].querySelector(".attr-value").textContent;
let visibleAttrText = editor.attrElements.get("data-long").querySelector(".attr-value").textContent;
is (visibleAttrText, LONG_ATTRIBUTE_COLLAPSED)
yield assertAttributes("#node24", {
@ -69,7 +69,7 @@ function* testModifyInlineStyleWithQuotes(inspector) {
let onMutated = inspector.once("markupmutation");
let {editor} = yield getContainerForSelector("#node26", inspector);
let attr = editor.attrs["style"].querySelector(".editable");
let attr = editor.attrElements.get("style").querySelector(".editable");
attr.focus();
EventUtils.sendKey("return", inspector.panelWin);
@ -105,7 +105,7 @@ function* testEditingAttributeWithMixedQuotes(inspector) {
let onMutated = inspector.once("markupmutation");
let {editor} = yield getContainerForSelector("#node27", inspector);
let attr = editor.attrs["class"].querySelector(".editable");
let attr = editor.attrElements.get("class").querySelector(".editable");
attr.focus();
EventUtils.sendKey("return", inspector.panelWin);

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

@ -27,7 +27,7 @@ function* testWellformedMixedCase(inspector) {
info("Focusing the viewBox attribute editor");
let {editor} = yield getContainerForSelector("svg", inspector);
let attr = editor.attrs["viewBox"].querySelector(".editable");
let attr = editor.attrElements.get("viewBox").querySelector(".editable");
attr.focus();
EventUtils.sendKey("return", inspector.panelWin);
@ -53,7 +53,7 @@ function* testMalformedMixedCase(inspector) {
info("Focusing the viewBox attribute editor");
let {editor} = yield getContainerForSelector("svg", inspector);
let attr = editor.attrs["viewBox"].querySelector(".editable");
let attr = editor.attrElements.get("viewBox").querySelector(".editable");
attr.focus();
EventUtils.sendKey("return", inspector.panelWin);

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

@ -133,7 +133,7 @@ function* runEditAttributesTest(test, inspector) {
info("Listening for the markupmutation event");
let nodeMutated = inspector.once("markupmutation");
let attr = container.editor.attrs[test.name].querySelector(".editable");
let attr = container.editor.attrElements.get(test.name).querySelector(".editable");
setEditableFieldValue(attr, test.value, inspector);
yield nodeMutated;

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

@ -57,7 +57,6 @@ skip-if = e10s # Bug 1091596
[browser_net_cyrillic-02.js]
[browser_net_details-no-duplicated-content.js]
[browser_net_filter-01.js]
skip-if = e10s # Bug 1091603
[browser_net_filter-02.js]
[browser_net_filter-03.js]
[browser_net_filter-04.js]

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

@ -297,8 +297,10 @@ PerformanceFront.prototype = {
return profilerStatus.currentTime;
}
// Extend the profiler options so that protocol.js doesn't modify the original.
let profilerOptions = extend({}, this._customProfilerOptions);
// If this._customProfilerOptions is defined, use those to pass in
// to the profiler actor. The profiler actor handles all the defaults
// now, so this should only be used for tests.
let profilerOptions = this._customProfilerOptions || {};
yield this._request("profiler", "startProfiler", profilerOptions);
this.emit("profiler-activated");
@ -400,19 +402,6 @@ PerformanceFront.prototype = {
deferred.resolve();
}),
/**
* Overrides the options sent to the built-in profiler module when activating,
* such as the maximum entries count, the sampling interval etc.
*
* Used in tests and for older backend implementations.
*/
_customProfilerOptions: {
entries: 1000000,
interval: 1,
features: ["js"],
threadFilters: ["GeckoMain"]
},
/**
* Returns an object indicating if mock actors are being used or not.
*/

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

@ -11,8 +11,8 @@
*/
/* Lightweight theme on tabs */
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
background-attachment: scroll, fixed;
background-color: transparent;
background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
@ -20,7 +20,7 @@
background-repeat: repeat-x, no-repeat;
}
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-attachment: scroll, scroll, fixed;
background-color: transparent;
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),

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

@ -1841,15 +1841,15 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
/* Tab close button */
.tab-close-button:not([selected]):not(:hover) {
.tab-close-button:not([visuallyselected]):not(:hover) {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 64, 16, 48);
}
#TabsToolbar[brighttext] .tab-close-button:not([selected]):not(:hover) {
#TabsToolbar[brighttext] .tab-close-button:not([visuallyselected]):not(:hover) {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 80, 16, 64);
}
.tab-close-button:not([selected]):not(:hover):-moz-lwtheme-darktext {
.tab-close-button:not([visuallyselected]):not(:hover):-moz-lwtheme-darktext {
background-image: -moz-image-rect(url("chrome://global/skin/icons/close.svg"), 0, 96, 16, 80);
}
@ -1924,7 +1924,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
}
.alltabs-item[selected="true"] {
.alltabs-item[visuallyselected="true"] {
font-weight: bold;
}

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

@ -10,8 +10,8 @@
*/
/* Lightweight theme on tabs */
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
background-attachment: scroll, fixed;
background-color: transparent;
background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
@ -19,7 +19,7 @@
background-repeat: repeat-x, no-repeat;
}
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-attachment: scroll, scroll, fixed;
background-color: transparent;
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
@ -30,7 +30,7 @@
}
@media (min-resolution: 2dppx) {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
@fgTabTextureLWT@;/*,
lwtHeader;*/

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

@ -3045,26 +3045,26 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
}
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([visuallyselected=true]),
.tabs-newtab-button:hover {
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png),
url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png),
url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png);
}
.tab-background-middle[selected=true] {
.tab-background-middle[visuallyselected=true] {
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
@fgTabTexture@,
none;
}
.tab-background-start[selected=true]:-moz-locale-dir(ltr)::after,
.tab-background-end[selected=true]:-moz-locale-dir(rtl)::after {
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr)::after,
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-start@2x.png);
}
.tab-background-end[selected=true]:-moz-locale-dir(ltr)::after,
.tab-background-start[selected=true]:-moz-locale-dir(rtl)::after {
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr)::after,
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-end@2x.png);
}
@ -3082,13 +3082,13 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
/* Background tab separators */
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[beforeselected]:not([last-visible-tab])::after,
.tabbrowser-tab:not([selected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([selected]):not([beforehovered]):not(:hover)::after {
.tabbrowser-tab:not([visuallyselected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-separator@2x.png);
}
}
.tabbrowser-tab:not(:hover) > .tab-stack > .tab-content > .tab-icon-image:not([selected="true"]) {
.tabbrowser-tab:not(:hover) > .tab-stack > .tab-content > .tab-icon-image:not([visuallyselected="true"]) {
opacity: .9;
}
@ -3100,7 +3100,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
opacity: 0.9999;
}
.tab-label:not([selected="true"]) {
.tab-label:not([visuallyselected="true"]) {
opacity: .7;
}
@ -3110,12 +3110,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
border: none;
}
.tabbrowser-tab[selected=true]:not(:-moz-lwtheme) {
.tabbrowser-tab[visuallyselected=true]:not(:-moz-lwtheme) {
/* overriding tabbox.css */
color: inherit;
}
.tabbrowser-tab[selected=true] {
.tabbrowser-tab[visuallyselected=true] {
/* overriding tabbox.css */
text-shadow: inherit;
}
@ -3165,7 +3165,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
* of the window (e.g. no menubar, tabs in titlebar, etc.) to make it easier to drag the window by
* the titlebar. We don't need this in fullscreen since window dragging is not an issue there.
*/
#main-window[tabsintitlebar]:not([inFullscreen]) .tab-background-middle:not([selected=true]) {
#main-window[tabsintitlebar]:not([inFullscreen]) .tab-background-middle:not([visuallyselected=true]) {
clip-path: url(chrome://browser/content/browser.xul#tab-hover-clip-path);
}
@ -3201,12 +3201,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
cursor: default;
}
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([selected=true]):not(:hover) {
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([visuallyselected=true]):not(:hover) {
-moz-image-region: rect(0, 64px, 16px, 48px);
}
@media (min-resolution: 2dppx) {
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([selected=true]):not(:hover) {
#TabsToolbar[brighttext] .tab-close-button.close-icon:not([visuallyselected=true]):not(:hover) {
-moz-image-region: rect(0, 128px, 32px, 96px);
}
}

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

@ -85,11 +85,11 @@
/* Tab styling - make sure to use an inverted icon for the selected tab
(brighttext only covers the unselected tabs) */
.tab-close-button[selected=true]:not(:hover) {
.tab-close-button[visuallyselected=true]:not(:hover) {
-moz-image-region: rect(0, 64px, 16px, 48px);
}
@media (min-resolution: 2dppx) {
.tab-close-button[selected=true]:not(:hover) {
.tab-close-button[visuallyselected=true]:not(:hover) {
-moz-image-region: rect(0, 128px, 32px, 96px);
}
}

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

@ -141,17 +141,17 @@
-moz-padding-start: 0;
}
.tab-background-start[selected=true]::after,
.tab-background-start[selected=true]::before,
.tab-background-start[visuallyselected=true]::after,
.tab-background-start[visuallyselected=true]::before,
.tab-background-start,
.tab-background-end,
.tab-background-end[selected=true]::after,
.tab-background-end[selected=true]::before {
.tab-background-end[visuallyselected=true]::after,
.tab-background-end[visuallyselected=true]::before {
width: 0;
}
.tab-background-start[selected=true]::after,
.tab-background-end[selected=true]::after {
.tab-background-start[visuallyselected=true]::after,
.tab-background-end[visuallyselected=true]::after {
-moz-margin-start: 0;
}
/* End override @tabCurveHalfWidth@ and @tabCurveWidth@ */
@ -270,8 +270,8 @@ searchbar:not([oneoffui]) .search-go-button {
/* Make the tab splitter 1px wide with a solid background. */
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[beforeselected]:not([last-visible-tab])::after,
.tabbrowser-tab:not([selected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([selected]):not([beforehovered]):not(:hover)::after {
.tabbrowser-tab:not([visuallyselected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
background: var(--tab-separator-color);
width: 1px;
-moz-margin-start: 0;
@ -282,7 +282,7 @@ searchbar:not([oneoffui]) .search-go-button {
due to the ::after element causing the width of the tab to extend, which
causes an overflow and makes it disappear, which removes the overflow and
causes it to reappear, etc, etc. */
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([selected]):not([beforehovered]):not(:hover)::after {
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
-moz-margin-start: -1px;
-moz-margin-end: 0;
}
@ -304,7 +304,7 @@ searchbar:not([oneoffui]) .search-go-button {
pointer-events: auto;
}
.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) > .tab-stack > .tab-content {
.tabbrowser-tab[pinned][titlechanged]:not([visuallyselected="true"]) > .tab-stack > .tab-content {
background-image: var(--pinned-tab-glow);
background-position: center;
background-size: 100%;
@ -316,7 +316,7 @@ searchbar:not([oneoffui]) .search-go-button {
background-color: var(--tab-hover-background-color);
}
.tabbrowser-tab[selected] {
.tabbrowser-tab[visuallyselected] {
color: var(--tab-selection-color) !important; /* Override color: inherit */
background-color: var(--tab-selection-background-color);
box-shadow: var(--tab-selection-box-shadow);

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

@ -47,7 +47,7 @@
}
/* The selected tab should appear above adjacent tabs, .tabs-newtab-button and the highlight of #nav-bar */
.tabbrowser-tab[selected=true] {
.tabbrowser-tab[visuallyselected=true] {
position: relative;
z-index: 2;
}
@ -167,17 +167,17 @@
transition: opacity 150ms ease;
}
.tab-background-start[selected=true]::after,
.tab-background-start[selected=true]::before,
.tab-background-start[visuallyselected=true]::after,
.tab-background-start[visuallyselected=true]::before,
.tab-background-start,
.tab-background-end,
.tab-background-end[selected=true]::after,
.tab-background-end[selected=true]::before {
.tab-background-end[visuallyselected=true]::after,
.tab-background-end[visuallyselected=true]::before {
min-height: var(--tab-min-height);
width: @tabCurveWidth@;
}
.tabbrowser-tab:not([selected=true]),
.tabbrowser-tab:not([visuallyselected=true]),
.tabbrowser-tab:-moz-lwtheme {
color: inherit;
}
@ -193,8 +193,8 @@
*/
.tab-background-start[selected=true]::after,
.tab-background-end[selected=true]::after {
.tab-background-start[visuallyselected=true]::after,
.tab-background-end[visuallyselected=true]::after {
/* position ::after on top of its parent */
-moz-margin-start: -@tabCurveWidth@;
background-size: 100% 100%;
@ -203,47 +203,47 @@
position: relative;
}
.tab-background-start[selected=true]::before,
.tab-background-end[selected=true]::before {
.tab-background-start[visuallyselected=true]::before,
.tab-background-end[visuallyselected=true]::before {
/* all ::before pseudo elements */
content: "";
display: -moz-box;
}
.tab-background-start[selected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
.tab-background-end[selected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
background-image: url(chrome://browser/skin/tabbrowser/tab-selected-start.svg);
background-size: 100% 100%;
}
.tab-background-end[selected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
.tab-background-start[selected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr):not(:-moz-lwtheme)::before,
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl):not(:-moz-lwtheme)::before {
background-image: url(chrome://browser/skin/tabbrowser/tab-selected-end.svg);
background-size: 100% 100%;
}
/* For lightweight themes, clip the header image on start, middle, and end. */
.tab-background-start[selected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
.tab-background-end[selected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
clip-path: url(chrome://browser/content/browser.xul#tab-curve-clip-path-start);
}
.tab-background-end[selected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
.tab-background-start[selected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr):-moz-lwtheme::before,
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl):-moz-lwtheme::before {
clip-path: url(chrome://browser/content/browser.xul#tab-curve-clip-path-end);
}
.tab-background-start[selected=true]:-moz-locale-dir(ltr)::after,
.tab-background-end[selected=true]:-moz-locale-dir(rtl)::after {
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr)::after,
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-start.png);
}
.tab-background-end[selected=true]:-moz-locale-dir(ltr)::after,
.tab-background-start[selected=true]:-moz-locale-dir(rtl)::after {
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr)::after,
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-end.png);
}
.tab-background-middle[selected=true] {
.tab-background-middle[visuallyselected=true] {
background-clip: padding-box, padding-box, content-box;
background-color: @fgTabBackgroundColor@;
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
@ -258,7 +258,7 @@
/* Selected tab lightweight theme styles.
See browser-lightweightTheme.css for information about run-time changes to LWT styles. */
.tab-background-middle[selected=true]:-moz-lwtheme {
.tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-color: transparent;
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
@fgTabTextureLWT@;/*,
@ -268,21 +268,21 @@
}
/* These LWT styles are normally overridden by browser-lightweightTheme.css */
.tab-background-start[selected=true]:-moz-lwtheme::before,
.tab-background-end[selected=true]:-moz-lwtheme::before {
.tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
.tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
background-image: @fgTabTextureLWT@;
}
.tab-background-start[selected=true]:-moz-lwtheme::before,
.tab-background-end[selected=true]:-moz-lwtheme::before,
.tab-background-middle[selected=true]:-moz-lwtheme {
.tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
.tab-background-end[visuallyselected=true]:-moz-lwtheme::before,
.tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-color: transparent;
}
/* End selected tab */
/* new tab button border and gradient on hover */
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([visuallyselected=true]),
.tabs-newtab-button:hover {
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start.png),
url(chrome://browser/skin/tabbrowser/tab-background-middle.png),
@ -311,7 +311,7 @@
position: absolute;
}
.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) > .tab-stack > .tab-content {
.tabbrowser-tab[pinned][titlechanged]:not([visuallyselected="true"]) > .tab-stack > .tab-content {
background-image: radial-gradient(farthest-corner at center bottom, rgb(255,255,255) 3%, rgba(186,221,251,0.75) 20%, rgba(127,179,255,0.25) 40%, transparent 70%);
background-position: center bottom var(--tab-toolbar-navbar-overlap);
background-repeat: no-repeat;
@ -321,8 +321,8 @@
/* Background tab separators (3px wide).
Also show separators beside the selected tab when dragging it. */
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[beforeselected]:not([last-visible-tab])::after,
.tabbrowser-tab:not([selected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([selected]):not([beforehovered]):not(:hover)::after {
.tabbrowser-tab:not([visuallyselected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
-moz-margin-start: -1.5px;
-moz-margin-end: -1.5px;
background-image: url(chrome://browser/skin/tabbrowser/tab-separator.png);

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

@ -83,7 +83,7 @@
background-color: @customToolbarColor@;
}
.tab-background-middle[selected=true]:not(:-moz-lwtheme) {
.tab-background-middle[visuallyselected=true]:not(:-moz-lwtheme) {
background-color: @customToolbarColor@;
}

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

@ -11,8 +11,8 @@
*/
/* Lightweight theme on tabs */
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[selected=true]:-moz-lwtheme::before,
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[selected=true]:-moz-lwtheme::before {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-start[visuallyselected=true]:-moz-lwtheme::before,
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-end[visuallyselected=true]:-moz-lwtheme::before {
background-attachment: scroll, fixed;
background-color: transparent;
background-image: @fgTabTextureLWT@;/*, lwtHeader;*/
@ -20,7 +20,7 @@
background-repeat: repeat-x, no-repeat;
}
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-attachment: scroll, scroll, fixed;
background-color: transparent;
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle.png),
@ -31,7 +31,7 @@
}
@media (min-resolution: 1.25dppx) {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[selected=true]:-moz-lwtheme {
#tabbrowser-tabs:not([movingtab]) > .tabbrowser-tab > .tab-stack > .tab-background > .tab-background-middle[visuallyselected=true]:-moz-lwtheme {
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
@fgTabTextureLWT@;/*,
lwtHeader;*/

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

@ -1828,26 +1828,26 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png);
}
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([selected=true]),
.tabbrowser-tab:hover > .tab-stack > .tab-background:not([visuallyselected=true]),
.tabs-newtab-button:hover {
background-image: url(chrome://browser/skin/tabbrowser/tab-background-start@2x.png),
url(chrome://browser/skin/tabbrowser/tab-background-middle@2x.png),
url(chrome://browser/skin/tabbrowser/tab-background-end@2x.png);
}
.tab-background-middle[selected=true] {
.tab-background-middle[visuallyselected=true] {
background-image: url(chrome://browser/skin/tabbrowser/tab-active-middle@2x.png),
@fgTabTexture@,
none;
}
.tab-background-start[selected=true]:-moz-locale-dir(ltr)::after,
.tab-background-end[selected=true]:-moz-locale-dir(rtl)::after {
.tab-background-start[visuallyselected=true]:-moz-locale-dir(ltr)::after,
.tab-background-end[visuallyselected=true]:-moz-locale-dir(rtl)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-start@2x.png);
}
.tab-background-end[selected=true]:-moz-locale-dir(ltr)::after,
.tab-background-start[selected=true]:-moz-locale-dir(rtl)::after {
.tab-background-end[visuallyselected=true]:-moz-locale-dir(ltr)::after,
.tab-background-start[visuallyselected=true]:-moz-locale-dir(rtl)::after {
background-image: url(chrome://browser/skin/tabbrowser/tab-stroke-end@2x.png);
}
}
@ -1856,14 +1856,14 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
/* Use lighter colors of buttons and text in the titlebar on luna-blue */
@media (-moz-windows-theme: luna-blue) {
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[beforeselected]:not([last-visible-tab])::after,
.tabbrowser-tab:not([selected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([selected]):not([beforehovered]):not(:hover)::after {
.tabbrowser-tab:not([visuallyselected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
background-image: url("chrome://browser/skin/tabbrowser/tab-separator-luna-blue.png");
}
}
%endif
#TabsToolbar[brighttext] .tab-close-button:not(:hover):not([selected="true"]) {
#TabsToolbar[brighttext] .tab-close-button:not(:hover):not([visuallyselected="true"]) {
-moz-image-region: rect(0, 64px, 16px, 48px) !important;
}
@ -1878,7 +1878,7 @@ toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
* of the window (e.g. no menubar, tabs in titlebar, etc.) to make it easier to drag the window by
* the titlebar. We don't need this in fullscreen since window dragging is not an issue there.
*/
#main-window[tabsintitlebar][sizemode=normal] #toolbar-menubar[autohide="true"][inactive] + #TabsToolbar .tab-background-middle:not([selected=true]) {
#main-window[tabsintitlebar][sizemode=normal] #toolbar-menubar[autohide="true"][inactive] + #TabsToolbar .tab-background-middle:not([visuallyselected=true]) {
clip-path: url(chrome://browser/content/browser.xul#tab-hover-clip-path);
}

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

@ -158,6 +158,6 @@
/* Tab styling - make sure to use an inverted icon for the selected tab
(brighttext only covers the unselected tabs) */
.tab-close-button[selected=true]:not(:hover) {
.tab-close-button[visuallyselected=true]:not(:hover) {
-moz-image-region: rect(0, 64px, 16px, 48px);
}

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

@ -64,17 +64,25 @@ AC_ARG_WITH(nspr-exec-prefix,
if test -z "$no_nspr"; then
nspr_config_major_version=`echo $NSPR_VERSION_STRING | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
nspr_config_minor_version=`echo $NSPR_VERSION_STRING | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
nspr_config_micro_version=`echo $NSPR_VERSION_STRING | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
if test -z "$nspr_config_micro_version"; then
nspr_config_micro_version="0"
fi
min_nspr_major_version=`echo $min_nspr_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
min_nspr_minor_version=`echo $min_nspr_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
min_nspr_micro_version=`echo $min_nspr_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
if test -z "$min_nspr_micro_version"; then
min_nspr_micro_version="0"
fi
if test "$nspr_config_major_version" -ne "$min_nspr_major_version"; then
no_nspr="yes"
elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&

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

@ -45,17 +45,25 @@ AC_ARG_WITH(nss-exec-prefix,
NSS_LIBS=`$NSS_CONFIG $nss_config_args --libs`
nss_config_major_version=`$NSS_CONFIG $nss_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
nss_config_minor_version=`$NSS_CONFIG $nss_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
nss_config_micro_version=`$NSS_CONFIG $nss_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
if test -z "$nss_config_micro_version"; then
nss_config_micro_version="0"
fi
min_nss_major_version=`echo $min_nss_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
min_nss_minor_version=`echo $min_nss_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
min_nss_micro_version=`echo $min_nss_version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
if test -z "$min_nss_micro_version"; then
min_nss_micro_version="0"
fi
if test "$nss_config_major_version" -lt "$min_nss_major_version"; then
no_nss="yes"
elif test "$nss_config_major_version" -eq "$min_nss_major_version" &&

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

@ -33,9 +33,9 @@ public:
// Check whether two markers should be considered the same,
// for the purpose of pairing start and end markers. Normally
// this definition suffices.
virtual bool Equals(const TimelineMarker* aOther)
virtual bool Equals(const TimelineMarker& aOther)
{
return strcmp(mName, aOther->mName) == 0;
return strcmp(mName, aOther.mName) == 0;
}
// Add details specific to this marker type to aMarker. The

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

@ -2977,10 +2977,10 @@ nsDocShell::PopProfileTimelineMarkers(
// If we see an unpaired START, we keep it around for the next call
// to PopProfileTimelineMarkers. We store the kept START objects in
// this array.
nsTArray<TimelineMarker*> keptMarkers;
nsTArray<UniquePtr<TimelineMarker>> keptMarkers;
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
TimelineMarker* startPayload = mProfileTimelineMarkers[i];
UniquePtr<TimelineMarker>& startPayload = mProfileTimelineMarkers[i];
const char* startMarkerName = startPayload->GetName();
bool hasSeenPaintedLayer = false;
@ -3002,7 +3002,7 @@ nsDocShell::PopProfileTimelineMarkers(
// enough for the amount of markers to always be small enough that the
// nested for loop isn't going to be a performance problem.
for (uint32_t j = i + 1; j < mProfileTimelineMarkers.Length(); ++j) {
TimelineMarker* endPayload = mProfileTimelineMarkers[j];
UniquePtr<TimelineMarker>& endPayload = mProfileTimelineMarkers[j];
const char* endMarkerName = endPayload->GetName();
// Look for Layer markers to stream out paint markers.
@ -3011,7 +3011,7 @@ nsDocShell::PopProfileTimelineMarkers(
endPayload->AddLayerRectangles(layerRectangles);
}
if (!startPayload->Equals(endPayload)) {
if (!startPayload->Equals(*endPayload)) {
continue;
}
@ -3048,14 +3048,13 @@ nsDocShell::PopProfileTimelineMarkers(
// If we did not see the corresponding END, keep the START.
if (!hasSeenEnd) {
keptMarkers.AppendElement(mProfileTimelineMarkers[i]);
keptMarkers.AppendElement(Move(mProfileTimelineMarkers[i]));
mProfileTimelineMarkers.RemoveElementAt(i);
--i;
}
}
}
ClearProfileTimelineMarkers();
mProfileTimelineMarkers.SwapElements(keptMarkers);
if (!ToJSValue(aCx, profileTimelineMarkers, aProfileTimelineMarkers)) {
@ -3086,10 +3085,10 @@ nsDocShell::AddProfileTimelineMarker(const char* aName,
}
void
nsDocShell::AddProfileTimelineMarker(UniquePtr<TimelineMarker>& aMarker)
nsDocShell::AddProfileTimelineMarker(UniquePtr<TimelineMarker>&& aMarker)
{
if (mProfileTimelineRecording) {
mProfileTimelineMarkers.AppendElement(aMarker.release());
mProfileTimelineMarkers.AppendElement(Move(aMarker));
}
}
@ -3125,9 +3124,6 @@ nsDocShell::GetWindowDraggingAllowed(bool* aValue)
void
nsDocShell::ClearProfileTimelineMarkers()
{
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
delete mProfileTimelineMarkers[i];
}
mProfileTimelineMarkers.Clear();
}

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

@ -272,7 +272,7 @@ public:
// See nsIDocShell::recordProfileTimelineMarkers
void AddProfileTimelineMarker(const char* aName,
TracingMetadata aMetaData);
void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>& aMarker);
void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>&& aMarker);
// Global counter for how many docShells are currently recording profile
// timeline markers
@ -984,7 +984,7 @@ private:
// True if recording profiles.
bool mProfileTimelineRecording;
nsTArray<TimelineMarker*> mProfileTimelineMarkers;
nsTArray<mozilla::UniquePtr<TimelineMarker>> mProfileTimelineMarkers;
// Get rid of all the timeline markers accumulated so far
void ClearProfileTimelineMarkers();

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

@ -8,6 +8,8 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
let { Promise } = Cu.import('resource://gre/modules/Promise.jsm', {});
Cu.import("resource://gre/modules/Timer.jsm");
// Functions that look like mochitest functions but forward to the
// browser process.
@ -81,8 +83,9 @@ this.timelineContentTest = function(tests) {
function timelineWaitForMarkers(docshell, searchFor) {
if (typeof(searchFor) == "string") {
let searchForString = searchFor;
let f = function (markers) {
return markers.some(m => m.name == searchFor);
return markers.some(m => m.name == searchForString);
};
searchFor = f;
}
@ -92,14 +95,15 @@ function timelineWaitForMarkers(docshell, searchFor) {
let maxWaitIterationCount = 10; // Wait for 2sec maximum
let markers = [];
let interval = content.setInterval(() => {
setTimeout(function timeoutHandler() {
let newMarkers = docshell.popProfileTimelineMarkers();
markers = [...markers, ...newMarkers];
if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) {
content.clearInterval(interval);
resolve(markers);
} else {
setTimeout(timeoutHandler, 200);
waitIterationCount++;
}
waitIterationCount++;
}, 200);
});
}

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

@ -39,9 +39,16 @@ function makeTimelineTest(frameScriptName, url) {
/* Open a URL for a timeline test. */
function timelineTestOpenUrl(url) {
return new Promise(function(resolve, reject) {
window.focus();
window.focus();
let tabSwitchPromise = new Promise((resolve, reject) => {
window.gBrowser.addEventListener("TabSwitchDone", function listener() {
window.gBrowser.removeEventListener("TabSwitchDone", listener);
resolve();
});
});
let loadPromise = new Promise(function(resolve, reject) {
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
let linkedBrowser = tab.linkedBrowser;
@ -50,4 +57,6 @@ function timelineTestOpenUrl(url) {
resolve(tab);
}, true);
});
return Promise.all([tabSwitchPromise, loadPromise]).then(([_, tab]) => tab);
}

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

@ -934,13 +934,13 @@ public:
}
}
virtual bool Equals(const TimelineMarker* aOther) override
virtual bool Equals(const TimelineMarker& aOther) override
{
if (!TimelineMarker::Equals(aOther)) {
return false;
}
// Console markers must have matching causes as well.
return GetCause() == aOther->GetCause();
return GetCause() == aOther.GetCause();
}
virtual void AddDetails(mozilla::dom::ProfileTimelineMarker& aMarker) override
@ -1057,7 +1057,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
MakeUnique<ConsoleTimelineMarker>(docShell,
aMethodName == MethodTime ? TRACING_INTERVAL_START : TRACING_INTERVAL_END,
key);
docShell->AddProfileTimelineMarker(marker);
docShell->AddProfileTimelineMarker(Move(marker));
}
}
}

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

@ -312,7 +312,6 @@ AutoJSAPI::~AutoJSAPI()
{
if (mOwnErrorReporting) {
MOZ_ASSERT(NS_IsMainThread(), "See corresponding assertion in TakeOwnershipOfErrorReporting()");
JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(mOldAutoJSAPIOwnsErrorReporting);
if (HasException()) {
@ -342,6 +341,13 @@ AutoJSAPI::~AutoJSAPI()
NS_WARNING("OOMed while acquiring uncaught exception from JSAPI");
}
}
// We need to do this _after_ processing the existing exception, because the
// JS engine can throw while doing that, and uses this bit to determine what
// to do in that case: squelch the exception if the bit is set, otherwise
// call the error reporter. Calling WarningOnlyErrorReporter with a
// non-warning will assert, so we need to make sure we do the former.
JS::ContextOptionsRef(cx()).setAutoJSAPIOwnsErrorReporting(mOldAutoJSAPIOwnsErrorReporting);
}
if (mOldErrorReporter.isSome()) {

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

@ -2779,6 +2779,10 @@ nsFrameLoader::RequestNotifyLayerTreeReady()
return mRemoteBrowser->RequestNotifyLayerTreeReady() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}
if (!mOwnerContent) {
return NS_ERROR_NOT_AVAILABLE;
}
nsRefPtr<AsyncEventDispatcher> event =
new AsyncEventDispatcher(mOwnerContent,
NS_LITERAL_STRING("MozLayerTreeReady"),
@ -2795,6 +2799,10 @@ nsFrameLoader::RequestNotifyLayerTreeCleared()
return mRemoteBrowser->RequestNotifyLayerTreeCleared() ? NS_OK : NS_ERROR_NOT_AVAILABLE;
}
if (!mOwnerContent) {
return NS_ERROR_NOT_AVAILABLE;
}
nsRefPtr<AsyncEventDispatcher> event =
new AsyncEventDispatcher(mOwnerContent,
NS_LITERAL_STRING("MozLayerTreeCleared"),

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

@ -1239,6 +1239,7 @@ GK_ATOM(viewport_minimum_scale, "viewport-minimum-scale")
GK_ATOM(viewport_user_scalable, "viewport-user-scalable")
GK_ATOM(viewport_width, "viewport-width")
GK_ATOM(visibility, "visibility")
GK_ATOM(visuallyselected, "visuallyselected")
GK_ATOM(vlink, "vlink")
GK_ATOM(vspace, "vspace")
GK_ATOM(wbr, "wbr")

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

@ -643,9 +643,8 @@ public:
JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp) const override;
virtual bool set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp,
JS::Handle<jsid> id, JS::Handle<JS::Value> v,
JS::Handle<JS::Value> receiver,
JS::ObjectOpResult &result) const override;
// SpiderMonkey extensions
@ -909,9 +908,9 @@ nsOuterWindowProxy::get(JSContext *cx, JS::Handle<JSObject*> proxy,
bool
nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp,
JS::Handle<JS::Value> v,
JS::Handle<JS::Value> receiver,
JS::ObjectOpResult &result) const
{
int32_t index = GetArrayIndexFromId(cx, id);
@ -921,7 +920,7 @@ nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
return result.failReadOnly();
}
return js::Wrapper::set(cx, proxy, receiver, id, vp, result);
return js::Wrapper::set(cx, proxy, id, v, receiver, result);
}
bool

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

@ -9807,7 +9807,7 @@ class CGProxySpecialOperation(CGPerSignatureCall):
false.
"""
def __init__(self, descriptor, operation, checkFound=True,
argumentMutableValue=None, resultVar=None, foundVar=None):
argumentHandleValue=None, resultVar=None, foundVar=None):
self.checkFound = checkFound
self.foundVar = foundVar or "found"
@ -9832,12 +9832,12 @@ class CGProxySpecialOperation(CGPerSignatureCall):
treatNullAs=argument.treatNullAs,
sourceDescription=("value being assigned to %s setter" %
descriptor.interface.identifier.name))
if argumentMutableValue is None:
argumentMutableValue = "desc.value()"
if argumentHandleValue is None:
argumentHandleValue = "desc.value()"
templateValues = {
"declName": argument.identifier.name,
"holderName": argument.identifier.name + "_holder",
"val": argumentMutableValue,
"val": argumentHandleValue,
"obj": "obj",
"passedToJSImpl": "false"
}
@ -9882,10 +9882,10 @@ class CGProxyIndexedOperation(CGProxySpecialOperation):
foundVar: See the docstring for CGProxySpecialOperation.
"""
def __init__(self, descriptor, name, doUnwrap=True, checkFound=True,
argumentMutableValue=None, resultVar=None, foundVar=None):
argumentHandleValue=None, resultVar=None, foundVar=None):
self.doUnwrap = doUnwrap
CGProxySpecialOperation.__init__(self, descriptor, name, checkFound,
argumentMutableValue=argumentMutableValue,
argumentHandleValue=argumentHandleValue,
resultVar=resultVar,
foundVar=foundVar)
@ -9943,9 +9943,9 @@ class CGProxyIndexedSetter(CGProxyIndexedOperation):
"""
Class to generate a call to an indexed setter.
"""
def __init__(self, descriptor, argumentMutableValue=None):
def __init__(self, descriptor, argumentHandleValue=None):
CGProxyIndexedOperation.__init__(self, descriptor, 'IndexedSetter',
argumentMutableValue=argumentMutableValue)
argumentHandleValue=argumentHandleValue)
class CGProxyIndexedDeleter(CGProxyIndexedOperation):
@ -9973,10 +9973,10 @@ class CGProxyNamedOperation(CGProxySpecialOperation):
foundVar: See the docstring for CGProxySpecialOperation.
"""
def __init__(self, descriptor, name, value=None, argumentMutableValue=None,
def __init__(self, descriptor, name, value=None, argumentHandleValue=None,
resultVar=None, foundVar=None):
CGProxySpecialOperation.__init__(self, descriptor, name,
argumentMutableValue=argumentMutableValue,
argumentHandleValue=argumentHandleValue,
resultVar=resultVar,
foundVar=foundVar)
self.value = value
@ -10074,9 +10074,9 @@ class CGProxyNamedSetter(CGProxyNamedOperation):
"""
Class to generate a call to a named setter.
"""
def __init__(self, descriptor, argumentMutableValue=None):
def __init__(self, descriptor, argumentHandleValue=None):
CGProxyNamedOperation.__init__(self, descriptor, 'NamedSetter',
argumentMutableValue=argumentMutableValue)
argumentHandleValue=argumentHandleValue)
class CGProxyNamedDeleter(CGProxyNamedOperation):
@ -10693,7 +10693,7 @@ class CGDOMJSProxyHandler_setCustom(ClassMethod):
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::MutableHandle<JS::Value>', 'vp'),
Argument('JS::Handle<JS::Value>', 'v'),
Argument('bool*', 'done')]
ClassMethod.__init__(self, "setCustom", "bool", args, virtual=True, override=True, const=True)
self.descriptor = descriptor
@ -10718,7 +10718,7 @@ class CGDOMJSProxyHandler_setCustom(ClassMethod):
raise ValueError("In interface " + self.descriptor.name + ": " +
"Can't cope with [OverrideBuiltins] and unforgeable members")
callSetter = CGProxyNamedSetter(self.descriptor, argumentMutableValue="vp")
callSetter = CGProxyNamedSetter(self.descriptor, argumentHandleValue="v")
return (assertion +
callSetter.define() +
"*done = true;\n"
@ -10743,7 +10743,7 @@ class CGDOMJSProxyHandler_setCustom(ClassMethod):
""",
callSetter=CGProxyIndexedSetter(self.descriptor,
argumentMutableValue="vp").define())
argumentHandleValue="v").define())
else:
setIndexed = ""

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

@ -219,13 +219,14 @@ DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::
}
bool
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> receiver,
Handle<jsid> id, MutableHandle<JS::Value> vp, ObjectOpResult &result) const
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<jsid> id,
Handle<JS::Value> v, Handle<JS::Value> receiver,
ObjectOpResult &result) const
{
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
bool done;
if (!setCustom(cx, proxy, id, vp, &done)) {
if (!setCustom(cx, proxy, id, v, &done)) {
return false;
}
if (done) {
@ -252,7 +253,7 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> r
}
}
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, desc, result);
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, desc, result);
}
bool
@ -350,7 +351,7 @@ IdToInt32(JSContext* cx, JS::Handle<jsid> id)
bool
DOMProxyHandler::setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp, bool *done) const
JS::Handle<JS::Value> v, bool *done) const
{
*done = false;
return true;

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

@ -122,8 +122,8 @@ public:
const override;
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
bool* bp) const override;
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver, JS::ObjectOpResult &result)
const override;
/*
@ -132,7 +132,7 @@ public:
* *done to false.
*/
virtual bool setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp, bool *done) const;
JS::Handle<JS::Value> v, bool *done) const;
static JSObject* GetExpandoObject(JSObject* obj);

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

@ -1094,7 +1094,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<EventTimelineMarker>(ds, TRACING_INTERVAL_START,
phase, typeStr);
ds->AddProfileTimelineMarker(marker);
ds->AddProfileTimelineMarker(Move(marker));
}
}

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

@ -28,6 +28,7 @@
#include "mozilla/dom/Response.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/Telemetry.h"
#include "InternalRequest.h"
#include "InternalResponse.h"
@ -231,6 +232,8 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
return nullptr;
}
Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1);
nsRefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p);
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
nsRefPtr<FetchDriver> fetch =
@ -244,6 +247,8 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 0);
if (worker->IsServiceWorker()) {
r->SetSkipServiceWorker();
}

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

@ -60,6 +60,9 @@ FetchDriver::Fetch(FetchDriverObserver* aObserver)
workers::AssertIsOnMainThread();
mObserver = aObserver;
Telemetry::Accumulate(Telemetry::SERVICE_WORKER_REQUEST_PASSTHROUGH,
mRequest->WasCreatedByFetchEvent());
return Fetch(false /* CORS flag */);
}

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

@ -41,6 +41,7 @@ InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult
copy->mMode = mMode;
copy->mCredentialsMode = mCredentialsMode;
copy->mCacheMode = mCacheMode;
copy->mCreatedByFetchEvent = mCreatedByFetchEvent;
return copy.forget();
}
@ -87,6 +88,7 @@ InternalRequest::InternalRequest(const InternalRequest& aOther)
, mSynchronous(aOther.mSynchronous)
, mUnsafeRequest(aOther.mUnsafeRequest)
, mUseURLCredentials(aOther.mUseURLCredentials)
, mCreatedByFetchEvent(aOther.mCreatedByFetchEvent)
{
// NOTE: does not copy body stream... use the fallible Clone() for that
}

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

@ -283,6 +283,24 @@ public:
already_AddRefed<InternalRequest>
GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const;
bool
WasCreatedByFetchEvent() const
{
return mCreatedByFetchEvent;
}
void
SetCreatedByFetchEvent()
{
mCreatedByFetchEvent = true;
}
void
ClearCreatedByFetchEvent()
{
mCreatedByFetchEvent = false;
}
private:
// Does not copy mBodyStream. Use fallible Clone() for complete copy.
explicit InternalRequest(const InternalRequest& aOther);
@ -317,6 +335,10 @@ private:
bool mSynchronous;
bool mUnsafeRequest;
bool mUseURLCredentials;
// This is only set when a Request object is created by a fetch event. We
// use it to check if Service Workers are simply fetching intercepted Request
// objects without modifying them.
bool mCreatedByFetchEvent = false;
};
} // namespace dom

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

@ -147,16 +147,19 @@ Request::Constructor(const GlobalObject& aGlobal,
: fallbackCredentials;
if (mode != RequestMode::EndGuard_) {
request->ClearCreatedByFetchEvent();
request->SetMode(mode);
}
if (credentials != RequestCredentials::EndGuard_) {
request->ClearCreatedByFetchEvent();
request->SetCredentialsMode(credentials);
}
RequestCache cache = aInit.mCache.WasPassed() ?
aInit.mCache.Value() : fallbackCache;
if (cache != RequestCache::EndGuard_) {
request->ClearCreatedByFetchEvent();
request->SetCacheMode(cache);
}
@ -185,8 +188,10 @@ Request::Constructor(const GlobalObject& aGlobal,
upperCaseMethod.EqualsLiteral("POST") ||
upperCaseMethod.EqualsLiteral("PUT") ||
upperCaseMethod.EqualsLiteral("OPTIONS")) {
request->ClearCreatedByFetchEvent();
request->SetMethod(upperCaseMethod);
} else {
request->ClearCreatedByFetchEvent();
request->SetMethod(method);
}
}
@ -199,6 +204,7 @@ Request::Constructor(const GlobalObject& aGlobal,
if (aRv.Failed()) {
return nullptr;
}
request->ClearCreatedByFetchEvent();
headers = h->GetInternalHeaders();
} else {
headers = new InternalHeaders(*requestHeaders);
@ -244,6 +250,7 @@ Request::Constructor(const GlobalObject& aGlobal,
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
request->ClearCreatedByFetchEvent();
request->SetBody(stream);
if (!contentType.IsVoid() &&

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

@ -612,8 +612,7 @@ parent:
* This call connects the content process to a plugin process. While this
* call runs, a new PluginModuleParent will be created in the ContentChild
* via bridging. The corresponding PluginModuleChild will live in the plugin
* process. We use intr semantics here to ensure that the PluginModuleParent
* allocation message is dispatched before LoadPlugin returns.
* process.
*/
sync LoadPlugin(uint32_t pluginId) returns (nsresult rv);

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

@ -277,6 +277,7 @@ TabParent::TabParent(nsIContentParent* aManager,
, mInitedByParent(false)
, mTabId(aTabId)
, mCreatingWindow(false)
, mNeedLayerTreeReadyNotification(false)
{
MOZ_ASSERT(aManager);
}
@ -2389,6 +2390,12 @@ TabParent::RecvGetRenderFrameInfo(PRenderFrameParent* aRenderFrame,
RenderFrameParent* renderFrame = static_cast<RenderFrameParent*>(aRenderFrame);
renderFrame->GetTextureFactoryIdentifier(aTextureFactoryIdentifier);
*aLayersId = renderFrame->GetLayersId();
if (mNeedLayerTreeReadyNotification) {
RequestNotifyLayerTreeReady();
mNeedLayerTreeReadyNotification = false;
}
return true;
}
@ -2691,11 +2698,11 @@ TabParent::RequestNotifyLayerTreeReady()
{
RenderFrameParent* frame = GetRenderFrame();
if (!frame) {
return false;
mNeedLayerTreeReadyNotification = true;
} else {
CompositorParent::RequestNotifyLayerTreeReady(frame->GetLayersId(),
new LayerTreeUpdateObserver());
}
CompositorParent::RequestNotifyLayerTreeReady(frame->GetLayersId(),
new LayerTreeUpdateObserver());
return true;
}

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

@ -520,6 +520,11 @@ private:
// CreateWindow response. Then TabChild loads them immediately.
nsTArray<FrameScriptInfo> mDelayedFrameScripts;
// If the user called RequestNotifyLayerTreeReady and the RenderFrameParent
// wasn't ready yet, we set this flag and call RequestNotifyLayerTreeReady
// again once the RenderFrameParent arrives.
bool mNeedLayerTreeReadyNotification;
private:
// This is used when APZ needs to find the TabParent associated with a layer
// to dispatch events.

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

@ -1820,7 +1820,7 @@ _popupcontextmenu(NPP instance, NPMenu* menu)
if (success) {
return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
screenX, screenY,
PluginModuleChild::GetChrome(),
InstCast(instance)->Manager(),
ProcessBrowserEvents);
} else {
NS_WARNING("Convertpoint failed, could not created contextmenu.");

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

@ -17,8 +17,8 @@ interface FetchEvent : Event {
readonly attribute Client? client; // The window issuing the request.
readonly attribute boolean isReload;
[Throws] void respondWith(Promise<Response> r);
[Throws] void respondWith(Response r);
[Throws]
void respondWith((Response or Promise<Response>) r);
};
dictionary FetchEventInit : EventInit {

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

@ -282,37 +282,32 @@ RespondWithHandler::CancelRequest()
} // anonymous namespace
void
FetchEvent::RespondWith(Promise& aPromise, ErrorResult& aRv)
FetchEvent::RespondWith(const ResponseOrPromise& aArg, ErrorResult& aRv)
{
if (mWaitToRespond) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsRefPtr<Promise> promise;
if (aArg.IsResponse()) {
nsRefPtr<Response> res = &aArg.GetAsResponse();
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
promise = Promise::Create(worker->GlobalScope(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
promise->MaybeResolve(res);
} else if (aArg.IsPromise()) {
promise = &aArg.GetAsPromise();
}
mWaitToRespond = true;
nsRefPtr<RespondWithHandler> handler =
new RespondWithHandler(mChannel, mServiceWorker, mRequest->Mode());
aPromise.AppendNativeHandler(handler);
}
void
FetchEvent::RespondWith(Response& aResponse, ErrorResult& aRv)
{
if (mWaitToRespond) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
nsRefPtr<Promise> promise = Promise::Create(worker->GlobalScope(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
promise->MaybeResolve(&aResponse);
RespondWith(*promise, aRv);
promise->AppendNativeHandler(handler);
}
already_AddRefed<ServiceWorkerClient>

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

@ -19,6 +19,7 @@ class nsIInterceptedChannel;
namespace mozilla {
namespace dom {
class Request;
class ResponseOrPromise;
} // namespace dom
} // namespace mozilla
@ -82,10 +83,7 @@ public:
}
void
RespondWith(Promise& aPromise, ErrorResult& aRv);
void
RespondWith(Response& aResponse, ErrorResult& aRv);
RespondWith(const ResponseOrPromise& aArg, ErrorResult& aRv);
already_AddRefed<Promise>
ForwardTo(const nsAString& aUrl);

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

@ -2302,6 +2302,10 @@ private:
if (NS_WARN_IF(rv.Failed())) {
return false;
}
// For Telemetry, note that this Request object was created by a Fetch event.
nsRefPtr<InternalRequest> internalReq = request->GetInternalRequest();
MOZ_ASSERT(internalReq);
internalReq->SetCreatedByFetchEvent();
RootedDictionary<FetchEventInit> init(aCx);
init.mRequest.Construct();

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

@ -849,9 +849,8 @@ LayerTransactionParent::RecvClearCachedResources()
// context, it's just a subtree root. We need to scope the clear
// of resources to exactly that subtree, so we specify it here.
mLayerManager->ClearCachedResources(mRoot);
mShadowLayersManager->NotifyClearCachedResources(this);
}
mShadowLayersManager->NotifyClearCachedResources(this);
return true;
}

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

@ -29,9 +29,7 @@ namespace layers {
* the main thread and the compositor thread context. It's primary
* purpose is to manage the PLayerTransaction sub protocol.
*/
// This should really be 'sync', but we're using 'rpc' as a workaround
// for Bug 716631.
intr protocol PCompositor
sync protocol PCompositor
{
// A Compositor manages a single Layer Manager (PLayerTransaction)
manages PLayerTransaction;

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

@ -23,7 +23,7 @@ namespace layers {
* frames directly to the compositor thread/process without relying on the main thread
* which might be too busy dealing with content script.
*/
intr protocol PImageBridge
sync protocol PImageBridge
{
manages PCompositable;
manages PTexture;

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

@ -4,10 +4,9 @@
<script id="script">
var i=0;
function doe() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var navigator1 = top.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation);
var docShell = navigator1.QueryInterface(Components.interfaces.nsIDocShell);
var docviewer = docShell.contentViewer;
var navigator1 = SpecialPowers.wrap(top).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(SpecialPowers.Ci.nsIWebNavigation);
var docShell = navigator1.QueryInterface(SpecialPowers.Ci.nsIDocShell);
var docviewer = docShell.contentViewer.QueryInterface(SpecialPowers.Ci.nsIMarkupDocumentViewer);
docviewer.textZoom=i;
i=i+0.2;
if (i>10)

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

@ -12,10 +12,9 @@ if (document.getElementById('content')) {
var docviewer;
function do_onload() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var navigator = parent.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebNavigation);
var docShell = navigator.QueryInterface(Components.interfaces.nsIDocShell);
docviewer = docShell.contentViewer;
var navigator1 = SpecialPowers.wrap(parent).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).getInterface(SpecialPowers.Ci.nsIWebNavigation);
var docShell = navigator1.QueryInterface(SpecialPowers.Ci.nsIDocShell);
docviewer = docShell.contentViewer.QueryInterface(SpecialPowers.Ci.nsIMarkupDocumentViewer);
setTimeout(doe,500, 0.2);
}

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

@ -71,10 +71,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
ReturnStatus *rs, JSVariant *result) {
return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
}
bool RecvSet(const uint64_t &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result) {
return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, value, rs, result);
bool RecvSet(const uint64_t &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs) {
return Answer::RecvSet(ObjectId::deserialize(objId), id, value, receiverVar, rs);
}
bool RecvIsExtensible(const uint64_t &objId, ReturnStatus *rs,
@ -161,10 +160,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
ReturnStatus *rs, JSVariant *result) {
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
}
bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result) {
return Base::SendSet(objId.serialize(), receiverVar, id, value, rs, result);
bool SendSet(const ObjectId &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs) {
return Base::SendSet(objId.serialize(), id, value, receiverVar, rs);
}
bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,

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

@ -33,7 +33,7 @@ both:
prio(high) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
prio(high) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, JSVariant value) returns (ReturnStatus rs, JSVariant result);
prio(high) sync Set(uint64_t objId, JSIDVariant id, JSVariant value, JSVariant receiver) returns (ReturnStatus rs);
prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);

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

@ -308,26 +308,17 @@ WrapperAnswer::RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
}
bool
WrapperAnswer::RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &idVar, const JSVariant &value, ReturnStatus *rs,
JSVariant *resultValue)
WrapperAnswer::RecvSet(const ObjectId &objId, const JSIDVariant &idVar, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs)
{
// We may run scripted setters.
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
JSContext *cx = aes.cx();
// The outparam will be written to the buffer, so it must be set even if
// the parent won't read it.
*resultValue = UndefinedVariant();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj)
return fail(cx, rs);
RootedObject receiver(cx, fromObjectVariant(cx, receiverVar));
if (!receiver)
return fail(cx, rs);
LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar), InVariant(value));
RootedId id(cx);
@ -338,12 +329,12 @@ WrapperAnswer::RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
if (!fromVariant(cx, value, &val))
return fail(cx, rs);
ObjectOpResult result;
RootedValue receiverVal(cx, ObjectValue(*receiver));
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiverVal, result))
RootedValue receiver(cx);
if (!fromVariant(cx, receiverVar, &receiver))
return fail(cx, rs);
if (!toVariant(cx, val, resultValue))
ObjectOpResult result;
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiver, result))
return fail(cx, rs);
return ok(rs, result);

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

@ -37,9 +37,8 @@ class WrapperAnswer : public virtual JavaScriptShared
bool RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result);
bool RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result);
bool RecvSet(const ObjectId &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs);
bool RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result);

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

@ -110,9 +110,8 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const override;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp,
JS::ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result) const override;
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const override;
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const override;
@ -517,41 +516,37 @@ WrapperOwner::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
}
bool
CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result) const
CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result) const
{
FORWARD(set, (cx, proxy, receiver, id, vp, result));
FORWARD(set, (cx, proxy, id, v, receiver, result));
}
bool
WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result)
WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result)
{
ObjectId objId = idOf(proxy);
ObjectVariant receiverVar;
if (!toObjectVariant(cx, receiver, &receiverVar))
return false;
JSIDVariant idVar;
if (!toJSIDVariant(cx, id, &idVar))
return false;
JSVariant val;
if (!toVariant(cx, vp, &val))
if (!toVariant(cx, v, &val))
return false;
JSVariant receiverVar;
if (!toVariant(cx, receiver, &receiverVar))
return false;
ReturnStatus status;
JSVariant resultValue;
if (!SendSet(objId, receiverVar, idVar, val, &status, &resultValue))
if (!SendSet(objId, idVar, val, receiverVar, &status))
return ipcfail(cx);
LOG_STACK();
if (!ok(cx, status, result))
return false;
return fromVariant(cx, resultValue, vp);
return ok(cx, status, result);
}
bool

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

@ -42,8 +42,8 @@ class WrapperOwner : public virtual JavaScriptShared
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp);
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result);
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result);
bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
bool construct);
@ -128,9 +128,8 @@ class WrapperOwner : public virtual JavaScriptShared
virtual bool SendGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result) = 0;
virtual bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const JSVariant &value,
ReturnStatus *rs, JSVariant *result) = 0;
virtual bool SendSet(const ObjectId &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs) = 0;
virtual bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result) = 0;

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

@ -342,8 +342,8 @@ typedef bool
(* GetPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp);
typedef bool
(* SetPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
(* SetPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result);
typedef bool
(* GetOwnPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);

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

@ -295,8 +295,8 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const;
virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const;
virtual bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const;
/*
* [[Call]] and [[Construct]] are standard internal methods but according
@ -395,9 +395,8 @@ class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
bool *bp) const override;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp,
ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const override;
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const override;
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const override;

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

@ -4443,20 +4443,13 @@ FoldMaskedArrayIndex(FunctionCompiler &f, ParseNode **indexExpr, int32_t *mask,
uint32_t mask2;
if (IsLiteralOrConstInt(f, maskNode, &mask2)) {
// Flag the access to skip the bounds check if the mask ensures that an 'out of
// bounds' access can not occur based on the current heap length constraint.
if (mask2 == 0) {
// Flag the access to skip the bounds check if the mask ensures that an
// 'out of bounds' access can not occur based on the current heap length
// constraint. The unsigned maximum of a masked index is the mask
// itself, so check that the mask is not negative and compare the mask
// to the known minimum heap length.
if (int32_t(mask2) >= 0 && mask2 < f.m().minHeapLength())
*needsBoundsCheck = NO_BOUNDS_CHECK;
} else {
uint32_t minHeap = f.m().minHeapLength();
uint32_t minHeapZeroes = CountLeadingZeroes32(minHeap - 1);
uint32_t maskZeroes = CountLeadingZeroes32(mask2);
if ((minHeapZeroes < maskZeroes) ||
(IsPowerOfTwo(minHeap) && minHeapZeroes == maskZeroes))
{
*needsBoundsCheck = NO_BOUNDS_CHECK;
}
}
*mask &= mask2;
*indexExpr = indexNode;
return true;

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

@ -1904,8 +1904,8 @@ TypedObject::obj_getArrayElement(JSContext *cx,
}
bool
TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
{
Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
@ -1919,7 +1919,7 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject recei
case type::Array: {
if (JSID_IS_ATOM(id, cx->names().length)) {
if (obj == receiver) {
if (receiver.isObject() && obj == &receiver.toObject()) {
JS_ReportErrorNumber(cx, GetErrorMessage,
nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
return false;
@ -1929,8 +1929,8 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject recei
uint32_t index;
if (IdIsIndex(id, &index)) {
if (obj != receiver)
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
if (!receiver.isObject() || obj != &receiver.toObject())
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
if (index >= uint32_t(typedObj->length())) {
JS_ReportErrorNumber(cx, GetErrorMessage,
@ -1941,7 +1941,7 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject recei
Rooted<TypeDescr*> elementType(cx);
elementType = &typedObj->typeDescr().as<ArrayTypeDescr>().elementType();
size_t offset = elementType->size() * index;
if (!ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), vp))
if (!ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), v))
return false;
return result.succeed();
}
@ -1955,19 +1955,19 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject recei
if (!descr->fieldIndex(id, &fieldIndex))
break;
if (obj != receiver)
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
if (!receiver.isObject() || obj != &receiver.toObject())
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
size_t offset = descr->fieldOffset(fieldIndex);
Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
RootedAtom fieldName(cx, &descr->fieldName(fieldIndex));
if (!ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, vp))
if (!ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, v))
return false;
return result.succeed();
}
}
return SetPropertyOnProto(cx, obj, receiver, id, vp, result);
return SetPropertyOnProto(cx, obj, id, v, receiver, result);
}
bool

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

@ -540,8 +540,8 @@ class TypedObject : public JSObject
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
static bool obj_getOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);

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

@ -154,13 +154,35 @@ function GetIterator(obj, method) {
return iterator;
}
// ES6 draft 20150317 7.3.20.
function SpeciesConstructor(obj, defaultConstructor) {
var C = obj.constructor;
if (C === undefined) {
// Step 1.
assert(IsObject(obj), "not passed an object");
// Steps 2-3.
var ctor = obj.constructor;
// Step 4.
if (ctor === undefined)
return defaultConstructor;
}
if (!IsConstructor(C)) {
ThrowError(JSMSG_NOT_CONSTRUCTOR, DecompileArg(1, C));
}
return C;
// Step 5.
if (!IsObject(ctor))
ThrowError(JSMSG_NOT_NONNULL_OBJECT, "object's 'constructor' property");
// Steps 6-7. We don't yet implement @@species and Symbol.species, so we
// don't implement this correctly right now. Somebody fix this!
var s = /* ctor[Symbol.species] */ undefined;
// Step 8.
if (s === undefined || s === null)
return defaultConstructor;
// Step 9.
if (IsConstructor(s))
return s;
// Step 10.
ThrowError(JSMSG_NOT_CONSTRUCTOR,
"@@species property of object's constructor");
}

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

@ -113,21 +113,39 @@ enum class AllocKind {
static_assert(uint8_t(AllocKind::OBJECT0) == 0, "Please check AllocKind iterations and comparisons"
" of the form |kind <= AllocKind::OBJECT_LAST| to ensure their range is still valid!");
// Returns a sequence for use in a range-based for loop,
// to iterate over all alloc kinds.
inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT))
AllAllocKinds()
{
return mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT);
}
// Returns a sequence for use in a range-based for loop,
// to iterate over all object alloc kinds.
inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::OBJECT0, AllocKind::OBJECT_LIMIT))
ObjectAllocKinds()
{
return mozilla::MakeEnumeratedRange<int>(AllocKind::OBJECT0, AllocKind::OBJECT_LIMIT);
}
// Returns a sequence for use in a range-based for loop,
// to iterate over alloc kinds from |first| to |limit|, exclusive.
inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT))
SomeAllocKinds(AllocKind first = AllocKind::FIRST, AllocKind limit = AllocKind::LIMIT)
{
MOZ_ASSERT(limit <= AllocKind::LIMIT);
MOZ_ASSERT(first <= limit);
return mozilla::MakeEnumeratedRange<int>(first, limit);
}
// AllAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
// with each index corresponding to a particular alloc kind.
template<typename ValueType> using AllAllocKindArray =
mozilla::EnumeratedArray<AllocKind, AllocKind::LIMIT, ValueType>;
// ObjectAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
// with each index corresponding to a particular object alloc kind.
template<typename ValueType> using ObjectAllocKindArray =
mozilla::EnumeratedArray<AllocKind, AllocKind::OBJECT_LIMIT, ValueType>;

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

@ -0,0 +1,10 @@
setJitCompilerOption("ion.warmup.trigger", 30);
function bar(i) {
if (i >= 40)
return;
if ("aaa,bbb,ccc".split(",")[0].length != 3)
throw "???";
bar(i + 1);
}
bar(0);

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

@ -8366,7 +8366,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
RootedValue v(cx, rhs);
if (!PutProperty(cx, obj, id, &v, op == JSOP_STRICTSETPROP))
if (!PutProperty(cx, obj, id, v, op == JSOP_STRICTSETPROP))
return false;
}

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

@ -1567,9 +1567,6 @@ EmitCallProxyGet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
masm.Push(object);
masm.movePtr(StackPointer, argProxyReg);
// Unused space, to keep the same stack layout as Proxy::set frames.
PushObjectOpResult(masm);
masm.loadJSContext(argJSContextReg);
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
@ -2220,6 +2217,15 @@ EmitObjectOpResultCheck(MacroAssembler &masm, Label *failure, bool strict,
masm.bind(&noStrictError);
}
static bool
ProxySetProperty(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v, bool strict)
{
RootedValue receiver(cx, ObjectValue(*proxy));
ObjectOpResult result;
return Proxy::set(cx, proxy, id, v, receiver, result)
&& result.checkStrictErrorOrWarning(cx, proxy, id, strict);
}
static bool
EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
HandleId propId, RegisterSet liveRegs, Register object,
@ -2237,22 +2243,25 @@ EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
RegisterSet regSet(RegisterSet::All());
regSet.take(AnyRegister(object));
// Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
// MutableHandleValue vp, ObjectOpResult &result)
// ProxySetProperty(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
// bool strict);
Register argJSContextReg = regSet.takeGeneral();
Register argProxyReg = regSet.takeGeneral();
Register argIdReg = regSet.takeGeneral();
Register argVpReg = regSet.takeGeneral();
Register argResultReg = regSet.takeGeneral();
Register argValueReg = regSet.takeGeneral();
Register argStrictReg = regSet.takeGeneral();
Register scratch = regSet.takeGeneral();
// Push stubCode for marking.
attacher.pushStubCodePointer(masm);
// Push args on stack first so we can take pointers to make handles.
// Push args on stack so we can take pointers to make handles.
// Push value before touching any other registers (see WARNING above).
masm.Push(value);
masm.movePtr(StackPointer, argVpReg);
masm.movePtr(StackPointer, argValueReg);
masm.move32(Imm32(strict), argStrictReg);
masm.Push(propId, scratch);
masm.movePtr(StackPointer, argIdReg);
@ -2263,10 +2272,6 @@ EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
masm.Push(object);
masm.movePtr(StackPointer, argProxyReg);
// Allocate result out-param.
PushObjectOpResult(masm);
masm.movePtr(StackPointer, argResultReg);
masm.loadJSContext(argJSContextReg);
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
@ -2274,24 +2279,17 @@ EmitCallProxySet(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
masm.enterFakeExitFrame(IonOOLProxyExitFrameLayout::Token());
// Make the call.
masm.setupUnalignedABICall(6, scratch);
masm.setupUnalignedABICall(5, scratch);
masm.passABIArg(argJSContextReg);
masm.passABIArg(argProxyReg);
masm.passABIArg(argProxyReg);
masm.passABIArg(argIdReg);
masm.passABIArg(argVpReg);
masm.passABIArg(argResultReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, Proxy::set));
masm.passABIArg(argValueReg);
masm.passABIArg(argStrictReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ProxySetProperty));
// Test for error.
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
// Test for strict failure. We emit the check even in non-strict mode in
// order to pick up the warning if extraWarnings is enabled.
EmitObjectOpResultCheck<IonOOLProxyExitFrameLayout>(masm, masm.exceptionLabel(), strict,
scratch, argJSContextReg, argProxyReg,
argIdReg, argVpReg, argResultReg);
// masm.leaveExitFrame & pop locals
masm.adjustStack(IonOOLProxyExitFrameLayout::Size());
@ -2508,8 +2506,9 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
SetterOp target = shape->setterOp();
MOZ_ASSERT(target);
// JSSetterOp: bool fn(JSContext *cx, HandleObject obj,
// HandleId id, MutableHandleValue vp, ObjectOpResult &result);
// HandleId id, HandleValue value, ObjectOpResult &result);
// First, allocate an ObjectOpResult on the stack. We push this before
// the stubCode pointer in order to match the layout of
@ -2530,11 +2529,11 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
// OK, now we can grab our remaining registers and grab the pointer to
// what we just pushed into one of them.
Register argJSContextReg = regSet.takeGeneral();
Register argVpReg = regSet.takeGeneral();
Register argValueReg = regSet.takeGeneral();
// We can just reuse the "object" register for argObjReg
Register argObjReg = object;
Register argIdReg = regSet.takeGeneral();
masm.movePtr(StackPointer, argVpReg);
masm.movePtr(StackPointer, argValueReg);
// push canonical jsid from shape instead of propertyname.
masm.Push(shape->propid(), argIdReg);
@ -2554,18 +2553,20 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
masm.passABIArg(argJSContextReg);
masm.passABIArg(argObjReg);
masm.passABIArg(argIdReg);
masm.passABIArg(argVpReg);
masm.passABIArg(argValueReg);
masm.passABIArg(argResultReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target));
// Test for error.
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
// Test for failure.
// Test for strict failure. We emit the check even in non-strict mode
// in order to pick up the warning if extraWarnings is enabled.
EmitObjectOpResultCheck<IonOOLSetterOpExitFrameLayout>(masm, masm.exceptionLabel(),
strict, scratchReg,
argJSContextReg, argObjReg,
argIdReg, argVpReg, argResultReg);
argIdReg, argValueReg,
argResultReg);
// masm.leaveExitFrame & pop locals.
masm.adjustStack(IonOOLSetterOpExitFrameLayout::Size());

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

@ -699,17 +699,14 @@ class IonOOLSetterOpExitFrameLayout : public IonOOLPropertyOpExitFrameLayout
// Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
// MutableHandleValue vp)
// Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
// MutableHandleValue vp, ObjectOpResult &result)
// ProxySetProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandleValue vp,
// bool strict)
class IonOOLProxyExitFrameLayout
{
protected: // only to silence a clang warning about unused private fields
ExitFooterFrame footer_;
ExitFrameLayout exit_;
// result out-parameter (unused for Proxy::get)
JS::ObjectOpResult result_;
// The proxy object.
JSObject *proxy_;
@ -734,22 +731,10 @@ class IonOOLProxyExitFrameLayout
return sizeof(IonOOLProxyExitFrameLayout);
}
static size_t offsetOfObject() {
return offsetof(IonOOLProxyExitFrameLayout, proxy_);
}
static size_t offsetOfResult() {
return offsetof(IonOOLProxyExitFrameLayout, vp0_);
}
static size_t offsetOfId() {
return offsetof(IonOOLProxyExitFrameLayout, id_);
}
static size_t offsetOfObjectOpResult() {
return offsetof(IonOOLProxyExitFrameLayout, result_);
}
inline JitCode **stubCode() {
return &stubCode_;
}

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

@ -1542,9 +1542,14 @@ IonBuilder::inlineConstantStringSplit(CallInfo &callInfo)
if (templateObject->getDenseInitializedLength() != initLength)
return InliningStatus_NotInlined;
JSContext *cx = GetJitContext()->cx;
Vector<MConstant *, 0, SystemAllocPolicy> arrayValues;
for (uint32_t i = 0; i < initLength; i++) {
MConstant *value = MConstant::New(alloc(), templateObject->getDenseElement(i), constraints());
JSAtom *str = js::AtomizeString(cx, templateObject->getDenseElement(i).toString());
if (!str)
return InliningStatus_Error;
MConstant *value = MConstant::New(alloc(), StringValue(str), constraints());
if (!TypeSetIncludes(key.maybeTypes(), value->type(), value->resultTypeSet()))
return InliningStatus_NotInlined;

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

@ -710,6 +710,8 @@ MConstant::MConstant(const js::Value &vp, CompilerConstraintList *constraints)
setResultTypeSet(MakeUnknownTypeSet());
}
MOZ_ASSERT_IF(vp.isString(), vp.toString()->isAtom());
setMovable();
}

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

@ -1153,7 +1153,8 @@ class MQuaternaryInstruction : public MAryInstruction<4>
}
};
class MVariadicInstruction : public MInstruction
template <class T>
class MVariadicT : public T
{
FixedList<MUse> operands_;
@ -1190,6 +1191,8 @@ class MVariadicInstruction : public MInstruction
}
};
typedef MVariadicT<MInstruction> MVariadicInstruction;
// Generates an LSnapshot without further effect.
class MStart : public MNullaryInstruction
{

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

@ -434,7 +434,6 @@ bool
SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
bool strict, jsbytecode *pc)
{
RootedValue v(cx, value);
RootedId id(cx, NameToId(name));
JSOp op = JSOp(*pc);
@ -448,21 +447,21 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
return true;
}
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult result;
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
if (!NativeSetProperty(
cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
cx, obj.as<NativeObject>(), id, value, receiver,
(op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
? Unqualified
: Qualified,
&v,
result))
{
return false;
}
} else {
if (!SetProperty(cx, obj, obj, id, &v, result))
if (!SetProperty(cx, obj, id, value, receiver, result))
return false;
}
return result.checkStrictErrorOrWarning(cx, obj, id, strict);

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

@ -2020,44 +2020,15 @@ CodeGeneratorMIPS::visitAsmJSPassStackArg(LAsmJSPassStackArg *ins)
}
void
CodeGeneratorMIPS::visitUDiv(LUDiv *ins)
{
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register output = ToRegister(ins->output());
Label done;
if (ins->mir()->canBeDivideByZero()) {
if (ins->mir()->isTruncated()) {
Label notzero;
masm.ma_b(rhs, rhs, &notzero, Assembler::NonZero, ShortJump);
masm.move32(Imm32(0), output);
masm.ma_b(&done, ShortJump);
masm.bind(&notzero);
} else {
MOZ_ASSERT(ins->mir()->fallible());
bailoutCmp32(Assembler::Equal, rhs, Imm32(0), ins->snapshot());
}
}
masm.as_divu(lhs, rhs);
masm.as_mflo(output);
if (!ins->mir()->isTruncated())
bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());
masm.bind(&done);
}
void
CodeGeneratorMIPS::visitUMod(LUMod *ins)
CodeGeneratorMIPS::visitUDivOrMod(LUDivOrMod *ins)
{
Register lhs = ToRegister(ins->lhs());
Register rhs = ToRegister(ins->rhs());
Register output = ToRegister(ins->output());
Label done;
if (ins->mir()->canBeDivideByZero()) {
// Prevent divide by zero.
if (ins->canBeDivideByZero()) {
if (ins->mir()->isTruncated()) {
// Infinity|0 == 0
Label notzero;
@ -2066,7 +2037,6 @@ CodeGeneratorMIPS::visitUMod(LUMod *ins)
masm.ma_b(&done, ShortJump);
masm.bind(&notzero);
} else {
MOZ_ASSERT(ins->mir()->fallible());
bailoutCmp32(Assembler::Equal, rhs, Imm32(0), ins->snapshot());
}
}
@ -2074,6 +2044,14 @@ CodeGeneratorMIPS::visitUMod(LUMod *ins)
masm.as_divu(lhs, rhs);
masm.as_mfhi(output);
// If the remainder is > 0, bailout since this must be a double.
if (ins->mir()->isDiv()) {
if (!ins->mir()->toDiv()->canTruncateRemainder())
bailoutCmp32(Assembler::NonZero, output, output, ins->snapshot());
// Get quotient
masm.as_mflo(output);
}
if (!ins->mir()->isTruncated())
bailoutCmp32(Assembler::LessThan, output, Imm32(0), ins->snapshot());

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

@ -273,8 +273,7 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
protected:
void visitEffectiveAddress(LEffectiveAddress *ins);
void visitUDiv(LUDiv *ins);
void visitUMod(LUMod *ins);
void visitUDivOrMod(LUDivOrMod *ins);
public:
// Unimplemented SIMD instructions

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

@ -355,23 +355,20 @@ class LMulI : public LBinaryMath<0>
}
};
class LUDiv : public LBinaryMath<0>
class LUDivOrMod : public LBinaryMath<0>
{
public:
LIR_HEADER(UDiv);
LIR_HEADER(UDivOrMod);
MDiv *mir() {
return mir_->toDiv();
MBinaryArithInstruction *mir() const {
MOZ_ASSERT(mir_->isDiv() || mir_->isMod());
return static_cast<MBinaryArithInstruction *>(mir_);
}
};
class LUMod : public LBinaryMath<0>
{
public:
LIR_HEADER(UMod);
MMod *mir() {
return mir_->toMod();
bool canBeDivideByZero() const {
if (mir_->isMod())
return mir_->toMod()->canBeDivideByZero();
return mir_->toDiv()->canBeDivideByZero();
}
};

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

@ -20,8 +20,7 @@
_(PowHalfD) \
_(AsmJSUInt32ToDouble) \
_(AsmJSUInt32ToFloat32) \
_(UDiv) \
_(UMod) \
_(UDivOrMod) \
_(AsmJSLoadFuncPtr)
#endif // jit_mips_LOpcodes_mips_h__

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

@ -419,7 +419,7 @@ LIRGeneratorMIPS::lowerUDiv(MDiv *div)
MDefinition *lhs = div->getOperand(0);
MDefinition *rhs = div->getOperand(1);
LUDiv *lir = new(alloc()) LUDiv;
LUDivOrMod *lir = new(alloc()) LUDivOrMod;
lir->setOperand(0, useRegister(lhs));
lir->setOperand(1, useRegister(rhs));
if (div->fallible())
@ -434,7 +434,7 @@ LIRGeneratorMIPS::lowerUMod(MMod *mod)
MDefinition *lhs = mod->getOperand(0);
MDefinition *rhs = mod->getOperand(1);
LUMod *lir = new(alloc()) LUMod;
LUDivOrMod *lir = new(alloc()) LUDivOrMod;
lir->setOperand(0, useRegister(lhs));
lir->setOperand(1, useRegister(rhs));
if (mod->fallible())

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

@ -234,6 +234,15 @@ class MacroAssemblerMIPS : public Assembler
ma_li(ScratchRegister, imm);
ma_b(lhs, ScratchRegister, l, c, jumpKind);
}
void ma_b(Register lhs, ImmWord imm, Label *l, Condition c, JumpKind jumpKind = LongJump)
{
ma_b(lhs, Imm32(uint32_t(imm.value)), l, c, jumpKind);
}
void ma_b(Address addr, ImmWord imm, Label *l, Condition c, JumpKind jumpKind = LongJump)
{
ma_b(addr, Imm32(uint32_t(imm.value)), l, c, jumpKind);
}
void ma_b(Register lhs, Address addr, Label *l, Condition c, JumpKind jumpKind = LongJump);
void ma_b(Address addr, Imm32 imm, Label *l, Condition c, JumpKind jumpKind = LongJump);
void ma_b(Address addr, ImmGCPtr imm, Label *l, Condition c, JumpKind jumpKind = LongJump);

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

@ -82,6 +82,7 @@ MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}")
MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 1, JSEXN_TYPEERR, "{0} is not a non-null object")
MSG_DEF(JSMSG_SET_NON_OBJECT_RECEIVER, 1, JSEXN_TYPEERR, "can't assign to properties of {0}: not an object")
MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified")
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0} is not extensible")
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property {0}")

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

@ -27,13 +27,13 @@ class CustomProxyHandler : public DirectProxyHandler {
return impl(cx, proxy, id, desc, true);
}
bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const override
bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver,
ObjectOpResult &result) const override
{
Rooted<JSPropertyDescriptor> desc(cx);
if (!DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, &desc))
return false;
return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, desc, result);
return SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, desc, result);
}
private:

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