Merge mozilla-central to autoland

This commit is contained in:
Dorel Luca 2018-08-21 19:03:25 +03:00
commit b704584332
77 changed files with 485 additions and 241 deletions

View File

@ -21,7 +21,7 @@
<?xml-stylesheet href="chrome://browser/skin/customizableui/panelUI.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/downloads/downloads.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/searchbar.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/compacttheme.css" type="text/css" alternate="yes" title="Light/Dark"?>

View File

@ -6,7 +6,7 @@
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<!DOCTYPE dialog [

View File

@ -5,7 +5,8 @@
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/sidebar.css"?>
<!DOCTYPE page [
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">

View File

@ -5,7 +5,8 @@
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/sidebar.css"?>
<!DOCTYPE page [
<!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">

View File

@ -7,7 +7,7 @@
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/organizer.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css"?>

View File

@ -9,7 +9,7 @@
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="510634: Wrong icons on bookmarks sidebar"

View File

@ -10,7 +10,7 @@
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="1163447: selectItems in Places no longer selects items within Toolbar or Sidebar folders"

View File

@ -10,7 +10,7 @@
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="549192: History view not updated after deleting entry"

View File

@ -10,7 +10,7 @@
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="549491: 'The root node is never visible' exception when details of the root node are modified "

View File

@ -10,7 +10,7 @@
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="549192: History view not updated after deleting entry"

View File

@ -9,7 +9,7 @@
type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="435322: Places tree view's formatting"

View File

@ -7,7 +7,7 @@
<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
<?xml-stylesheet href="chrome://browser/skin/places/tree-icons.css"?>
<dialog id="selectBookmarkDialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"

View File

@ -32,7 +32,7 @@ browser.jar:
skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png)
skin/classic/browser/places/editBookmark.css (places/editBookmark.css)
skin/classic/browser/places/livemark-item.png (places/livemark-item.png)
* skin/classic/browser/places/places.css (places/places.css)
* skin/classic/browser/places/sidebar.css (places/sidebar.css)
skin/classic/browser/places/organizer.css (places/organizer.css)
skin/classic/browser/places/organizer.xml (places/organizer.xml)
skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png)

View File

@ -4,7 +4,7 @@
/* Sidebars */
%include ../../shared/places/places.inc.css
%include ../../shared/places/sidebar.inc.css
#sidebar-search-container {
padding: 8px;
@ -48,7 +48,3 @@
.sidebar-placesTreechildren::-moz-tree-cell(separator) {
cursor: default;
}
/* Trees */
%include ../../shared/places/tree-icons.inc.css

View File

@ -34,7 +34,7 @@ browser.jar:
skin/classic/browser/notification-icons/geo-blocked.svg (notification-icons/geo-blocked.svg)
skin/classic/browser/notification-icons/geo.svg (notification-icons/geo.svg)
skin/classic/browser/places/allBookmarks.png (places/allBookmarks.png)
* skin/classic/browser/places/places.css (places/places.css)
* skin/classic/browser/places/sidebar.css (places/sidebar.css)
skin/classic/browser/places/organizer.css (places/organizer.css)
skin/classic/browser/places/toolbar.png (places/toolbar.png)
skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png)

View File

@ -4,7 +4,7 @@
/* Sidebars */
%include ../../shared/places/places.inc.css
%include ../../shared/places/sidebar.inc.css
.sidebar-placesTree {
margin: 0;
@ -66,7 +66,3 @@
#viewButton:focus {
box-shadow: var(--focus-ring-box-shadow);
}
/* Trees */
%include ../../shared/places/tree-icons.inc.css

View File

@ -239,6 +239,7 @@
skin/classic/browser/places/history.svg (../shared/places/history.svg)
skin/classic/browser/places/tag.svg (../shared/places/tag.svg)
skin/classic/browser/places/unfiledBookmarks.svg (../shared/places/unfiledBookmarks.svg)
skin/classic/browser/places/tree-icons.css (../shared/places/tree-icons.css)
skin/classic/browser/privatebrowsing/aboutPrivateBrowsing.css (../shared/privatebrowsing/aboutPrivateBrowsing.css)
skin/classic/browser/privatebrowsing/favicon.svg (../shared/privatebrowsing/favicon.svg)
skin/classic/browser/privatebrowsing/private-browsing.svg (../shared/privatebrowsing/private-browsing.svg)

View File

@ -98,11 +98,6 @@ treechildren::-moz-tree-cell-text(title, separator, selected, focus) {
color: HighlightText;
}
treechildren::-moz-tree-twisty(title, separator) {
-moz-appearance: none;
padding: 0;
}
treechildren::-moz-tree-image(cutting) {
opacity: 0.5;
}

View File

@ -27,7 +27,7 @@ browser.jar:
skin/classic/browser/notification-icons/geo-blocked.svg (notification-icons/geo-blocked.svg)
skin/classic/browser/notification-icons/geo-detailed.svg (notification-icons/geo-detailed.svg)
skin/classic/browser/notification-icons/geo.svg (notification-icons/geo.svg)
* skin/classic/browser/places/places.css (places/places.css)
* skin/classic/browser/places/sidebar.css (places/sidebar.css)
* skin/classic/browser/places/organizer.css (places/organizer.css)
skin/classic/browser/places/toolbarDropMarker.png (places/toolbarDropMarker.png)
skin/classic/browser/places/editBookmark.css (places/editBookmark.css)

View File

@ -4,7 +4,7 @@
/* Sidebars */
%include ../../shared/places/places.inc.css
%include ../../shared/places/sidebar.inc.css
.sidebar-placesTree {
-moz-appearance: none;
@ -44,12 +44,6 @@
}
}
/* Trees */
%include ../../shared/places/tree-icons.inc.css
/* Browser Sidebars */
/* Default button vert. margins are 1px/2px, and this can cause misalignment */
#viewButton {
margin: 0;

View File

@ -134,7 +134,7 @@ IndexedDBHelper.prototype = {
* be invoked with the transaction and the `store' object store.
* @param successCb
* Success callback to call on a successful transaction commit.
* The result is stored in txn.result.
* The result is stored in txn.result (in the callback function).
* @param failureCb
* Error callback to call when an error is encountered.
*/
@ -162,6 +162,14 @@ IndexedDBHelper.prototype = {
txn.oncomplete = function () {
if (DEBUG) debug("Transaction complete. Returning to callback.");
/*
* txn.result property is not part of the transaction object returned
* by this._db.transaction method called above.
* The property is expected to be set in the callback function.
* However, it can happen that the property is not set for some reason,
* so we have to check if the property exists before calling the
* success callback.
*/
if (successCb) {
if ("result" in txn) {
successCb(txn.result);
@ -173,6 +181,12 @@ IndexedDBHelper.prototype = {
txn.onabort = function () {
if (DEBUG) debug("Caught error on transaction");
/*
* txn.error property is part of the transaction object returned by
* this._db.transaction method called above.
* The attribute is defined in IDBTranscation WebIDL interface.
* It may be null.
*/
if (failureCb) {
failureCb(getErrorName(txn.error));
}

View File

@ -35,6 +35,7 @@
#define PREF_VOLUME_SCALE "media.volume_scale"
#define PREF_CUBEB_BACKEND "media.cubeb.backend"
#define PREF_CUBEB_OUTPUT_DEVICE "media.cubeb.output_device"
#define PREF_CUBEB_LATENCY_PLAYBACK "media.cubeb_latency_playback_ms"
#define PREF_CUBEB_LATENCY_MSG "media.cubeb_latency_msg_frames"
// Allows to get something non-default for the preferred sample-rate, to allow
@ -142,6 +143,7 @@ size_t sAudioIPCStackSize;
#endif
StaticAutoPtr<char> sBrandName;
StaticAutoPtr<char> sCubebBackendName;
StaticAutoPtr<char> sCubebOutputDeviceName;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
@ -188,6 +190,19 @@ static const uint32_t CUBEB_NORMAL_LATENCY_FRAMES = 1024;
namespace CubebUtils {
cubeb* GetCubebContextUnlocked();
void GetPrefAndSetString(const char* aPref, StaticAutoPtr<char>& aStorage)
{
nsAutoCString value;
Preferences::GetCString(aPref, value);
if (value.IsEmpty()) {
aStorage = nullptr;
} else {
aStorage = new char[value.Length() + 1];
PodCopy(aStorage.get(), value.get(), value.Length());
aStorage[value.Length()] = 0;
}
}
void PrefChanged(const char* aPref, void* aClosure)
{
if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) {
@ -235,15 +250,10 @@ void PrefChanged(const char* aPref, void* aClosure)
}
} else if (strcmp(aPref, PREF_CUBEB_BACKEND) == 0) {
StaticMutexAutoLock lock(sMutex);
nsAutoCString value;
Preferences::GetCString(aPref, value);
if (value.IsEmpty()) {
sCubebBackendName = nullptr;
} else {
sCubebBackendName = new char[value.Length() + 1];
PodCopy(sCubebBackendName.get(), value.get(), value.Length());
sCubebBackendName[value.Length()] = 0;
}
GetPrefAndSetString(aPref, sCubebBackendName);
} else if (strcmp(aPref, PREF_CUBEB_OUTPUT_DEVICE) == 0) {
StaticMutexAutoLock lock(sMutex);
GetPrefAndSetString(aPref, sCubebOutputDeviceName);
} else if (strcmp(aPref, PREF_CUBEB_FORCE_NULL_CONTEXT) == 0) {
StaticMutexAutoLock lock(sMutex);
sCubebForceNullContext = Preferences::GetBool(aPref, false);
@ -538,15 +548,11 @@ uint32_t GetCubebMSGLatencyInFrames(cubeb_stream_params * params)
}
static const char* gInitCallbackPrefs[] = {
PREF_VOLUME_SCALE,
PREF_CUBEB_LATENCY_PLAYBACK,
PREF_CUBEB_LATENCY_MSG,
PREF_CUBEB_BACKEND,
PREF_CUBEB_FORCE_NULL_CONTEXT,
PREF_CUBEB_SANDBOX,
PREF_AUDIOIPC_POOL_SIZE,
PREF_AUDIOIPC_STACK_SIZE,
nullptr,
PREF_VOLUME_SCALE, PREF_CUBEB_OUTPUT_DEVICE,
PREF_CUBEB_LATENCY_PLAYBACK, PREF_CUBEB_LATENCY_MSG,
PREF_CUBEB_BACKEND, PREF_CUBEB_FORCE_NULL_CONTEXT,
PREF_CUBEB_SANDBOX, PREF_AUDIOIPC_POOL_SIZE,
PREF_AUDIOIPC_STACK_SIZE, nullptr,
};
static const char* gCallbackPrefs[] = {
PREF_CUBEB_FORCE_SAMPLE_RATE,
@ -627,6 +633,12 @@ void GetCurrentBackend(nsAString& aBackend)
aBackend.AssignLiteral("unknown");
}
char* GetForcedOutputDevice()
{
StaticMutexAutoLock lock(sMutex);
return sCubebOutputDeviceName;
}
uint16_t ConvertCubebType(cubeb_device_type aType)
{
uint16_t map[] = {

View File

@ -49,6 +49,7 @@ void GetCurrentBackend(nsAString& aBackend);
void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,
Side aSide);
cubeb_stream_prefs GetDefaultStreamPrefs();
char* GetForcedOutputDevice();
#ifdef MOZ_WIDGET_ANDROID
uint32_t AndroidGetAudioOutputSampleRate();

View File

@ -659,6 +659,22 @@ AudioCallbackDriver::Init()
return true;
}
CubebUtils::AudioDeviceID forcedOutputDeviceId = nullptr;
char* forcedOutputDeviceName = CubebUtils::GetForcedOutputDevice();
if (forcedOutputDeviceName) {
nsTArray<RefPtr<AudioDeviceInfo>> deviceInfos;
GetDeviceCollection(deviceInfos, CubebUtils::Output);
for (const auto& device : deviceInfos) {
const nsString& name = device->Name();
if (name.Equals(NS_ConvertUTF8toUTF16(forcedOutputDeviceName))) {
if (device->DeviceID()) {
forcedOutputDeviceId = device->DeviceID();
}
}
}
}
mBuffer = AudioCallbackBufferWrapper<AudioDataValue>(mOutputChannels);
mScratchBuffer = SpillBuffer<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 2>(mOutputChannels);
@ -690,7 +706,7 @@ AudioCallbackDriver::Init()
"AudioCallbackDriver",
input_id,
inputWanted ? &input : nullptr,
output_id,
forcedOutputDeviceId ? forcedOutputDeviceId : output_id,
&output,
latency_frames,
DataCallback_s,

View File

@ -681,7 +681,7 @@ MediaStreamGraphImpl::PlayAudio(MediaStream* aStream)
float volume = 0.0f;
for (uint32_t i = 0; i < aStream->mAudioOutputs.Length(); ++i) {
volume += aStream->mAudioOutputs[i].mVolume;
volume += aStream->mAudioOutputs[i].mVolume * mGlobalVolume;
}
StreamTime ticksWritten = 0;
@ -3711,6 +3711,7 @@ MediaStreamGraphImpl::MediaStreamGraphImpl(GraphDriverType aDriverRequested,
, mAbstractMainThread(aMainThread)
, mSelfRef(this)
, mOutputChannels(std::min<uint32_t>(8, CubebUtils::MaxNumberOfChannels()))
, mGlobalVolume(CubebUtils::GetVolumeScale())
#ifdef DEBUG
, mCanRunMessagesSynchronously(false)
#endif

View File

@ -922,6 +922,12 @@ private:
*/
const uint32_t mOutputChannels;
/**
* Global volume scale. Used when running tests so that the output is not too
* loud.
*/
const float mGlobalVolume;
#ifdef DEBUG
/**
* Used to assert when AppendMessage() runs ControlMessages synchronously.

View File

@ -426,12 +426,6 @@ function setupEnvironment() {
]
};
if (!WANT_FAKE_AUDIO) {
defaultMochitestPrefs.set.push(
["media.volume_scale", "1"],
);
}
const isAndroid = !!navigator.userAgent.includes("Android");
if (isAndroid) {

View File

@ -4200,10 +4200,8 @@ EditorBase::EndUpdateViewBatch()
return;
}
DebugOnly<nsresult> rv =
htmlEditor->CheckSelectionStateForAnonymousButtons(selection);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"CheckSelectionStateForAnonymousButtons() failed");
DebugOnly<nsresult> rv = htmlEditor->RefereshEditingUI(*selection);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RefereshEditingUI() failed");
}
TextComposition*

View File

@ -418,7 +418,11 @@ HTMLEditor::EndMoving()
if (!selection) {
return NS_ERROR_NOT_INITIALIZED;
}
return CheckSelectionStateForAnonymousButtons(selection);
nsresult rv = RefereshEditingUI(*selection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
HTMLEditor::SetFinalPosition(int32_t aX,

View File

@ -282,21 +282,75 @@ HTMLEditor::DeleteRefToAnonymousNode(ManualNACPtr aContent,
// The ManualNACPtr destructor will invoke UnbindFromTree.
}
// The following method is mostly called by a selection listener. When a
// selection change is notified, the method is called to check if resizing
// handles, a grabber and/or inline table editing UI need to be displayed
// or refreshed
void
HTMLEditor::HideAnonymousEditingUIs()
{
if (mAbsolutelyPositionedObject) {
HideGrabber();
NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
}
if (mInlineEditedCell) {
HideInlineTableEditingUI();
NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUI failed");
}
if (mResizedObject) {
DebugOnly<nsresult> rv = HideResizers();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HideResizers() failed");
NS_ASSERTION(!mResizedObject, "HideResizers failed");
}
}
void
HTMLEditor::HideAnonymousEditingUIsIfUnnecessary()
{
// XXX Perhaps, this is wrong approach to hide multiple UIs because
// hiding one UI may causes overwriting existing UI with newly
// created one. In such case, we will leak ovewritten UI.
if (!IsAbsolutePositionEditorEnabled() && mAbsolutelyPositionedObject) {
// XXX If we're moving something, we need to cancel or commit the
// operation now.
HideGrabber();
NS_ASSERTION(!mAbsolutelyPositionedObject, "HideGrabber failed");
}
if (!IsInlineTableEditorEnabled() && mInlineEditedCell) {
// XXX If we're resizing a table element, we need to cancel or commit the
// operation now.
HideInlineTableEditingUI();
NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUI failed");
}
if (!IsObjectResizerEnabled() && mResizedObject) {
// XXX If we're resizing something, we need to cancel or commit the
// operation now.
DebugOnly<nsresult> rv = HideResizers();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "HideResizers() failed");
NS_ASSERTION(!mResizedObject, "HideResizers failed");
}
}
NS_IMETHODIMP
HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
{
if (NS_WARN_IF(!aSelection)) {
return NS_ERROR_INVALID_ARG;
}
nsresult rv = RefereshEditingUI(*aSelection);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
HTMLEditor::RefereshEditingUI(Selection& aSelection)
{
// First, we need to remove unnecessary editing UI now since some of them
// may be disabled while them are visible.
HideAnonymousEditingUIsIfUnnecessary();
// early way out if all contextual UI extensions are disabled
if (NS_WARN_IF(!IsObjectResizerEnabled() &&
!IsAbsolutePositionEditorEnabled() &&
!IsInlineTableEditorEnabled())) {
if (!IsObjectResizerEnabled() &&
!IsAbsolutePositionEditorEnabled() &&
!IsInlineTableEditorEnabled()) {
return NS_OK;
}
@ -306,7 +360,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
}
// let's get the containing element of the selection
RefPtr<Element> focusElement = GetSelectionContainerElement(*aSelection);
RefPtr<Element> focusElement = GetSelectionContainerElement(aSelection);
if (NS_WARN_IF(!focusElement)) {
return NS_OK;
}
@ -331,7 +385,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
// Resizing or Inline Table Editing is enabled, we need to check if the
// selection is contained in a table cell
cellElement =
GetElementOrParentByTagNameAtSelection(*aSelection, *nsGkAtoms::td);
GetElementOrParentByTagNameAtSelection(aSelection, *nsGkAtoms::td);
}
if (IsObjectResizerEnabled() && cellElement) {
@ -342,6 +396,9 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
if (nsGkAtoms::img != focusTagAtom) {
// the element container of the selection is not an image, so we'll show
// the resizers around the table
// XXX There may be a bug. cellElement may be not in <table> in invalid
// tree. So, perhaps, GetEnclosingTable() returns nullptr, we should
// not set focusTagAtom to nsGkAtoms::table.
focusElement = GetEnclosingTable(cellElement);
focusTagAtom = nsGkAtoms::table;
}
@ -369,15 +426,21 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
if (IsObjectResizerEnabled() && mResizedObject &&
mResizedObject != focusElement) {
// Perhaps, even if HideResizers() failed, we should try to hide inline
// table editing UI. However, it returns error only when we cannot do
// anything. So, it's okay for now.
nsresult rv = HideResizers();
NS_ENSURE_SUCCESS(rv, rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
NS_ASSERTION(!mResizedObject, "HideResizers failed");
}
if (mIsInlineTableEditingEnabled && mInlineEditedCell &&
if (IsInlineTableEditorEnabled() && mInlineEditedCell &&
mInlineEditedCell != cellElement) {
nsresult rv = HideInlineTableEditingUI();
NS_ENSURE_SUCCESS(rv, rv);
// XXX HideInlineTableEditingUI() won't return error. Should be change it
// void later.
HideInlineTableEditingUI();
NS_ASSERTION(!mInlineEditedCell, "HideInlineTableEditingUI failed");
}
@ -417,7 +480,7 @@ HTMLEditor::CheckSelectionStateForAnonymousButtons(Selection* aSelection)
}
}
if (mIsInlineTableEditingEnabled && cellElement &&
if (IsInlineTableEditorEnabled() && cellElement &&
IsModifiableNode(*cellElement) && cellElement != hostContent) {
if (mInlineEditedCell) {
nsresult rv = RefreshInlineTableEditingUI();

View File

@ -258,20 +258,6 @@ HTMLEditor::~HTMLEditor()
}
}
void
HTMLEditor::HideAnonymousEditingUIs()
{
if (mAbsolutelyPositionedObject) {
HideGrabber();
}
if (mInlineEditedCell) {
HideInlineTableEditingUI();
}
if (mResizedObject) {
HideResizers();
}
}
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLEditor)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLEditor, TextEditor)
@ -434,9 +420,9 @@ HTMLEditor::NotifySelectionChanged(nsIDocument* aDocument,
typeInState->OnSelectionChange(*aSelection);
// We used a class which derived from nsISelectionListener to call
// HTMLEditor::CheckSelectionStateForAnonymousButtons(). The lifetime of
// the class was exactly same as mTypeInState. So, call it only when
// mTypeInState is not nullptr.
// HTMLEditor::RefereshEditingUI(). The lifetime of the class was
// exactly same as mTypeInState. So, call it only when mTypeInState
// is not nullptr.
if ((aReason & (nsISelectionListener::MOUSEDOWN_REASON |
nsISelectionListener::KEYPRESS_REASON |
nsISelectionListener::SELECTALL_REASON)) && aSelection) {
@ -445,7 +431,8 @@ HTMLEditor::NotifySelectionChanged(nsIDocument* aDocument,
// FYI: This is an XPCOM method. So, the caller, Selection, guarantees
// the lifetime of this instance. So, don't need to grab this with
// local variable.
CheckSelectionStateForAnonymousButtons(aSelection);
DebugOnly<nsresult> rv = RefereshEditingUI(*aSelection);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RefereshEditingUI() failed");
}
}

View File

@ -227,7 +227,15 @@ public:
*/
void EnableObjectResizer(bool aEnable)
{
if (mIsObjectResizingEnabled == aEnable) {
return;
}
mIsObjectResizingEnabled = aEnable;
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return;
}
RefereshEditingUI(*selection);
}
bool IsObjectResizerEnabled() const
{
@ -240,7 +248,15 @@ public:
*/
void EnableInlineTableEditor(bool aEnable)
{
if (mIsInlineTableEditingEnabled == aEnable) {
return;
}
mIsInlineTableEditingEnabled = aEnable;
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return;
}
RefereshEditingUI(*selection);
}
bool IsInlineTableEditorEnabled() const
{
@ -254,7 +270,15 @@ public:
*/
void EnableAbsolutePositionEditor(bool aEnable)
{
if (mIsAbsolutelyPositioningEnabled == aEnable) {
return;
}
mIsAbsolutelyPositioningEnabled = aEnable;
RefPtr<Selection> selection = GetSelection();
if (NS_WARN_IF(!selection)) {
return;
}
RefereshEditingUI(*selection);
}
bool IsAbsolutePositionEditorEnabled() const
{
@ -1510,6 +1534,13 @@ protected: // Shouldn't be used by friend classes
void DeleteRefToAnonymousNode(ManualNACPtr aContent,
nsIPresShell* aShell);
/**
* RefereshEditingUI() may refresh editing UIs for current Selection, focus,
* etc. If this shows or hides some UIs, it causes reflow. So, this is
* not safe method.
*/
nsresult RefereshEditingUI(Selection& aSelection);
nsresult ShowResizersInner(Element& aResizedElement);
/**
@ -1570,8 +1601,19 @@ protected: // Shouldn't be used by friend classes
void SetFinalSize(int32_t aX, int32_t aY);
void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
bool aPreserveRatio);
/**
* HideAnonymousEditingUIs() forcibly hides all editing UIs (resizers,
* inline-table-editing UI, absolute positioning UI).
*/
void HideAnonymousEditingUIs();
/**
* HideAnonymousEditingUIsIfUnnecessary() hides all editing UIs if some of
* visible UIs are now unnecessary.
*/
void HideAnonymousEditingUIsIfUnnecessary();
/**
* sets the z-index of an element.
* @param aElement [IN] the element
@ -1612,7 +1654,7 @@ protected: // Shouldn't be used by friend classes
/**
* Hide all inline table editing UI
*/
nsresult HideInlineTableEditingUI();
void HideInlineTableEditingUI();
/**
* IsEmptyTextNode() returns true if aNode is a text node and does not have

View File

@ -94,7 +94,7 @@ HTMLEditor::ShowInlineTableEditingUI(Element* aCell)
return RefreshInlineTableEditingUI();
}
nsresult
void
HTMLEditor::HideInlineTableEditingUI()
{
mInlineEditedCell = nullptr;
@ -112,14 +112,23 @@ HTMLEditor::HideInlineTableEditingUI()
// are no document observers to notify, but we still want to
// UnbindFromTree.
DeleteRefToAnonymousNode(std::move(mAddColumnBeforeButton), ps);
DeleteRefToAnonymousNode(std::move(mRemoveColumnButton), ps);
DeleteRefToAnonymousNode(std::move(mAddColumnAfterButton), ps);
DeleteRefToAnonymousNode(std::move(mAddRowBeforeButton), ps);
DeleteRefToAnonymousNode(std::move(mRemoveRowButton), ps);
DeleteRefToAnonymousNode(std::move(mAddRowAfterButton), ps);
// Calling DeleteRefToAnonymousNode() may cause showing the UI again.
// Therefore, we should forget all anonymous contents first.
// Otherwise, we could leak the old content because of overwritten by
// ShowInlineTableEditingUI().
ManualNACPtr addColumnBeforeButton(std::move(mAddColumnBeforeButton));
ManualNACPtr removeColumnButton(std::move(mRemoveColumnButton));
ManualNACPtr addColumnAfterButton(std::move(mAddColumnAfterButton));
ManualNACPtr addRowBeforeButton(std::move(mAddRowBeforeButton));
ManualNACPtr removeRowButton(std::move(mRemoveRowButton));
ManualNACPtr addRowAfterButton(std::move(mAddRowAfterButton));
return NS_OK;
DeleteRefToAnonymousNode(std::move(addColumnBeforeButton), ps);
DeleteRefToAnonymousNode(std::move(removeColumnButton), ps);
DeleteRefToAnonymousNode(std::move(addColumnAfterButton), ps);
DeleteRefToAnonymousNode(std::move(addRowBeforeButton), ps);
DeleteRefToAnonymousNode(std::move(removeRowButton), ps);
DeleteRefToAnonymousNode(std::move(addRowAfterButton), ps);
}
nsresult

View File

@ -78,6 +78,16 @@ SimpleTest.waitForFocus(async function() {
is(target.hasAttribute("_moz_abspos"), kTest.movable,
kDescription + (kTest.movable ? "While enableAbsolutePositionEditing is enabled, positioner should appear" :
"Even while enableAbsolutePositionEditing is enabled, positioner shouldn't appear"));
document.execCommand("enableAbsolutePositionEditing", false, false);
ok(!target.hasAttribute("_moz_abspos"),
kDescription + "When enableAbsolutePositionEditing is disabled even while positioner is visible, positioner should disappear");
document.execCommand("enableAbsolutePositionEditing", false, true);
is(target.hasAttribute("_moz_abspos"), kTest.movable,
kDescription + (kTest.movable ?
"When enableAbsolutePositionEditing is enabled when absolute positioned element is selected, positioner should appear" :
"Even if enableAbsolutePositionEditing is enabled when static positioned element is selected, positioner shouldn't appear"));
}
}

View File

@ -89,6 +89,15 @@ SimpleTest.waitForFocus(async function() {
is(target.hasAttribute("_moz_resizing"), kResizable,
kDescription + (kResizable ? "While enableObjectResizing is enabled, resizers should appear" :
"Even while enableObjectResizing is enabled, resizers shouldn't appear"));
document.execCommand("enableObjectResizing", false, false);
ok(!target.hasAttribute("_moz_resizing"),
kDescription + "enableObjectResizing is disabled even while resizers are visible, resizers should disappear");
document.execCommand("enableObjectResizing", false, true);
is(target.hasAttribute("_moz_resizing"), kResizable,
kDescription + (kResizable ? "enableObjectResizing is enabled when resizable object is selected, resizers should appear" :
"Even if enableObjectResizing is enabled when non-resizable object is selected, resizers shouldn't appear"));
}
}

View File

@ -399,9 +399,14 @@ interface nsIHTMLEditor : nsISupports
attribute boolean isCSSEnabled;
/**
* Checks if the anonymous nodes created by the HTML editor have to be
* refreshed or hidden depending on a possible new state of the selection
* @param aSelection [IN] a selection
* checkSelectionStateForAnonymousButtons() may refresh editing UI such as
* resizers, inline-table-editing UI, absolute positioning UI for current
* Selection and focus state. When this method shows or hides UI, the
* editor (and/or its document/window) could be broken by mutation observers.
* FYI: Current user in script is only BlueGriffon.
*
* @param aSelection Selection instance for the normal selection of the
* document.
*/
void checkSelectionStateForAnonymousButtons(in Selection aSelection);

View File

@ -773,8 +773,15 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
// If id namespaces do not match, it means the command is obsolete, probably
// because the tab just moved to a new window.
// In that case do not send the commands to webrender.
bool validTransaction = aIdNamespace == mIdNamespace;
wr::TransactionBuilder txn;
wr::AutoTransactionSender sender(mApi, &txn);
Maybe<wr::AutoTransactionSender> sender;
if (validTransaction) {
sender.emplace(mApi, &txn);
}
ProcessWebRenderParentCommands(aCommands, txn);
@ -795,10 +802,7 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
wr::Vec<uint8_t> dlData(std::move(dl));
// If id namespaces do not match, it means the command is obsolete, probably
// because the tab just moved to a new window.
// In that case do not send the commands to webrender.
if (mIdNamespace == aIdNamespace) {
if (validTransaction) {
if (IsRootWebRenderBridgeParent()) {
LayoutDeviceIntSize widgetSize = mWidget->GetClientSize();
LayoutDeviceIntRect docRect(LayoutDeviceIntPoint(), widgetSize);
@ -817,7 +821,7 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
HoldPendingTransactionId(wrEpoch, aTransactionId, aRefreshStartTime, aTxnStartTime, aFwdTime);
if (mIdNamespace != aIdNamespace) {
if (!validTransaction) {
// Pretend we composited since someone is wating for this event,
// though DisplayList was not pushed to webrender.
if (CompositorBridgeParent* cbp = GetRootCompositorBridgeParent()) {

View File

@ -11,6 +11,7 @@
typedef uint32_t HashNumber;
#include "jsapi.h"
#include "jsfriendapi.h"
#include "js/Conversions.h"
#include "js/Initialization.h"

View File

@ -5333,6 +5333,15 @@ BaselineCompile(JSContext* cx, unsigned argc, Value* vp)
const char* returnedStr = nullptr;
do {
#ifdef JS_MORE_DETERMINISTIC
// In order to check for differential behaviour, baselineCompile should have
// the same output whether --no-baseline is used or not.
if (fuzzingSafe) {
returnedStr = "skipped (fuzzing-safe)";
break;
}
#endif
AutoRealm ar(cx, script);
if (script->hasBaselineScript()) {
if (forceDebug && !script->baselineScript()->hasDebugInstrumentation()) {
@ -6056,7 +6065,8 @@ gc::ZealModeHelpText),
" that extra boilerplate is needed afterwards to cause the VM to start\n"
" running the jitcode rather than staying in the interpreter:\n"
" baselineCompile(); for (var i=0; i<1; i++) {} ...\n"
" The interpreter will enter the new jitcode at the loop header.\n"),
" The interpreter will enter the new jitcode at the loop header unless\n"
" baselineCompile returned a string or threw an error.\n"),
JS_FS_HELP_END
};

View File

@ -0,0 +1,32 @@
// Debugger and debuggees must be in different compartments.
load(libdir + "asserts.js");
function testConstructor() {
var g = newGlobal({sameCompartmentAs: this});
assertTypeErrorMessage(() => new Debugger(g),
"Debugger: argument must be an object from a different compartment");
}
testConstructor();
function testAddDebuggee() {
var g = newGlobal({sameCompartmentAs: this});
var dbg = new Debugger();
assertTypeErrorMessage(() => dbg.addDebuggee(this),
"debugger and debuggee must be in different compartments");
}
testAddDebuggee();
function testAddAllGlobalsAsDebuggees() {
var g1 = newGlobal({sameCompartmentAs: this});
var g2 = newGlobal();
var g3 = newGlobal({sameCompartmentAs: g2});
var g4 = newGlobal({sameZoneAs: this});
var dbg = new Debugger();
dbg.addAllGlobalsAsDebuggees();
assertEq(dbg.hasDebuggee(g1), false);
assertEq(dbg.hasDebuggee(g2), true);
assertEq(dbg.hasDebuggee(g3), true);
assertEq(dbg.hasDebuggee(g4), true);
}
testAddAllGlobalsAsDebuggees();

View File

@ -0,0 +1,6 @@
function f(a) {
return a.toString();
}
var g = newGlobal({sameCompartmentAs: this});
g.evaluate("function Obj() {}");
f(f(new g.Obj()));

View File

@ -1,9 +1,10 @@
// |jit-test| test-also=--fuzzing-safe
// Check that the help text for baselineCompile() is accurate.
if (typeof inJit == "function" && typeof baselineCompile == "function") {
if (!inJit()) {
baselineCompile(); // compile the current script
var res = baselineCompile(); // compile the current script
assertEq(inJit(), false,
"We have compiled this script to baseline jitcode, but shouldn't " +
@ -13,7 +14,7 @@ if (typeof inJit == "function" && typeof baselineCompile == "function") {
for (var i=0; i<1; i++) {} // exact boilerplate suggested by the help text
assertEq(inJit(), true,
assertEq(typeof res != "string" ? inJit() : true, true,
"help text in TestingFunctions.cpp claims the above loop causes " +
"the interpreter to start running the new baseline jitcode");
}

View File

@ -4563,7 +4563,7 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative* call)
MOZ_ASSERT(obj == argObj);
// Push a Value containing the callee object: natives are allowed to access their callee before
// setitng the return value. After this the StackPointer points to &vp[0].
// setting the return value. After this the StackPointer points to &vp[0].
masm.Push(ObjectValue(*target->rawJSFunction()));
// Now compute the argv value. Since StackPointer is pointing to &vp[0] and

View File

@ -2087,6 +2087,7 @@ IonCompile(JSContext* cx, JSScript* script,
const MIRGenerator::ObjectGroupVector& groups = builder->abortedPreliminaryGroups();
for (size_t i = 0; i < groups.length(); i++) {
ObjectGroup* group = groups[i];
AutoRealm ar(cx, group);
AutoSweepObjectGroup sweep(group);
if (auto* newScript = group->newScript(sweep)) {
if (!newScript->maybeAnalyze(cx, group, nullptr, /* force = */ true))

View File

@ -93,7 +93,7 @@ JSJitFrameIter::callee() const
JSFunction*
JSJitFrameIter::maybeCallee() const
{
if (isScripted() && (isFunctionFrame()))
if (isScripted() && isFunctionFrame())
return callee();
return nullptr;
}

View File

@ -190,6 +190,7 @@ class OsiIndex
// [ frame size | has cached saved frame bit | frame header size | frame type ]
// < highest - - - - - - - - - - - - - - lowest >
static const uintptr_t FRAMETYPE_BITS = 4;
static const uintptr_t FRAMETYPE_MASK = (1 << FRAMETYPE_BITS) - 1;
static const uintptr_t FRAME_HEADER_SIZE_SHIFT = FRAMETYPE_BITS;
static const uintptr_t FRAME_HEADER_SIZE_BITS = 3;
static const uintptr_t FRAME_HEADER_SIZE_MASK = (1 << FRAME_HEADER_SIZE_BITS) - 1;
@ -342,8 +343,6 @@ class CommonFrameLayout
uint8_t* returnAddress_;
uintptr_t descriptor_;
static const uintptr_t FrameTypeMask = (1 << FRAMETYPE_BITS) - 1;
public:
static size_t offsetOfDescriptor() {
return offsetof(CommonFrameLayout, descriptor_);
@ -355,10 +354,10 @@ class CommonFrameLayout
return offsetof(CommonFrameLayout, returnAddress_);
}
FrameType prevType() const {
return FrameType(descriptor_ & FrameTypeMask);
return FrameType(descriptor_ & FRAMETYPE_MASK);
}
void changePrevType(FrameType type) {
descriptor_ &= ~FrameTypeMask;
descriptor_ &= ~FRAMETYPE_MASK;
descriptor_ |= type;
}
size_t prevFrameLocalSize() const {

View File

@ -658,6 +658,8 @@ class LSafepoint;
class LInstruction;
class LElementVisitor;
constexpr size_t MaxNumLInstructionOperands = 63;
// The common base class for LPhi and LInstruction.
class LNode
{
@ -672,9 +674,12 @@ class LNode
// Bitfields below are all uint32_t to make sure MSVC packs them correctly.
uint32_t op_ : 10;
uint32_t isCall_ : 1;
// LPhi::numOperands() may not fit in this bitfield, so we only use this
// field for LInstruction.
uint32_t nonPhiNumOperands_ : 6;
static_assert((1 << 6) - 1 == MaxNumLInstructionOperands, "packing constraints");
// For LInstruction, the first operand is stored at offset
// sizeof(LInstruction) + nonPhiOperandsOffset_ * sizeof(uintptr_t).
uint32_t nonPhiOperandsOffset_ : 5;

View File

@ -2656,7 +2656,7 @@ IonBuilder::inlineGuardToClass(CallInfo& callInfo, const Class* clasp)
{
return InliningStatus_NotInlined;
}
TemporaryTypeSet* types = callInfo.getArg(0)->resultTypeSet();
const Class* knownClass = types ? types->getKnownClass(constraints()) : nullptr;

View File

@ -239,8 +239,8 @@ class MUse : public TempObject, public InlineListNode<MUse>
#ifdef DEBUG
// Return the operand index of this MUse in its consumer. This is DEBUG-only
// as normal code should instead to call indexOf on the casted consumer
// directly, to allow it to be devirtualized and inlined.
// as normal code should instead call indexOf on the cast consumer directly,
// to allow it to be devirtualized and inlined.
size_t index() const;
#endif
};

View File

@ -828,7 +828,6 @@ LIRGeneratorShared::useBoxOrTyped(MDefinition* mir)
if (mir->type() == MIRType::Value)
return useBox(mir);
#if defined(JS_NUNBOX32)
return LBoxAllocation(useRegister(mir), LAllocation());
#else

View File

@ -301,9 +301,6 @@ CodeGenerator::visitWasmStackArg(LWasmStackArg* ins)
case MIRType::Float32:
masm.storeFloat32(ToFloatRegister(ins->arg()), dst);
return;
case MIRType::Int32x4:
case MIRType::Bool32x4:
case MIRType::Float32x4:
default:
break;
}

View File

@ -335,7 +335,7 @@ MacroAssembler::flexibleDivMod32(Register rhs, Register lhsOutput, Register remO
MOZ_ASSERT(lhsOutput != remOutput);
// Choose a register that is not edx, or eax to hold the rhs;
// ebx is chosen arbitrarily, and will be preserved if necessary.
// ebx is chosen arbitrarily, and will be preserved if necessary.
Register regForRhs = (rhs == eax || rhs == edx) ? ebx : rhs;
// Add registers we will be clobbering as live, but

View File

@ -461,6 +461,7 @@ MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 2, JSEXN_TYPEERR, "{0} does not refer to
MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null")
MSG_DEF(JSMSG_DEBUG_BAD_YIELD, 0, JSEXN_TYPEERR, "generator yielded invalid value")
MSG_DEF(JSMSG_DEBUG_CANT_DEBUG_GLOBAL, 0, JSEXN_TYPEERR, "passing non-debuggable global to addDebuggee")
MSG_DEF(JSMSG_DEBUG_SAME_COMPARTMENT, 0, JSEXN_TYPEERR, "debugger and debuggee must be in different compartments")
MSG_DEF(JSMSG_DEBUG_CCW_REQUIRED, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment")
MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
MSG_DEF(JSMSG_DEBUG_LOOP, 0, JSEXN_TYPEERR, "cannot debug an object in same compartment as debugger or a compartment that is already debugging the debugger")

View File

@ -3723,9 +3723,11 @@ Debugger::addDebuggee(JSContext* cx, unsigned argc, Value* vp)
Debugger::addAllGlobalsAsDebuggees(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGGER(cx, argc, vp, "addAllGlobalsAsDebuggees", args, dbg);
for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
for (RealmsInZoneIter r(zone); !r.done(); r.next()) {
if (r == dbg->object->realm() || r->creationOptions().invisibleToDebugger())
for (CompartmentsIter comp(cx->runtime()); !comp.done(); comp.next()) {
if (comp == dbg->object->compartment())
continue;
for (RealmsInCompartmentIter r(comp); !r.done(); r.next()) {
if (r->creationOptions().invisibleToDebugger())
continue;
r->compartment()->gcState.scheduledForDestruction = false;
GlobalObject* global = r->maybeGlobal();
@ -3921,7 +3923,7 @@ Debugger::construct(JSContext* cx, unsigned argc, Value* vp)
// Add the initial debuggees, if any.
for (unsigned i = 0; i < args.length(); i++) {
JSObject& wrappedObj = args[i].toObject().as<ProxyObject>().private_().toObject();
Rooted<GlobalObject*> debuggee(cx, &wrappedObj.deprecatedGlobal());
Rooted<GlobalObject*> debuggee(cx, &wrappedObj.nonCCWGlobal());
if (!debugger->addDebuggeeGlobal(cx, debuggee))
return false;
}
@ -3946,6 +3948,12 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> global)
return false;
}
// Debugger and debuggee must be in different compartments.
if (debuggeeRealm->compartment() == object->compartment()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_SAME_COMPARTMENT);
return false;
}
// Check for cycles. If global's realm is reachable from this Debugger
// object's realm by following debuggee-to-debugger links, then adding
// global would create a cycle. (Typically nobody is debugging the

View File

@ -648,7 +648,7 @@ LazyStubTier::createMany(HasGcTypes gcTypesEnabled, const Uint32Vector& funcExpo
const FuncExport& fe = funcExports[funcExportIndex];
numExpectedRanges += fe.funcType().temporarilyUnsupportedAnyRef() ? 1 : 2;
void* calleePtr = moduleSegmentBase +
moduleRanges[fe.interpCodeRangeIndex()].funcNormalEntry();
moduleRanges[fe.funcCodeRangeIndex()].funcNormalEntry();
Maybe<ImmPtr> callee;
callee.emplace(calleePtr, ImmPtr::NoCheckToken());
if (!GenerateEntryStubs(masm, funcExportIndex, fe, callee, /* asmjs */ false,
@ -803,7 +803,7 @@ LazyStubTier::lookupInterpEntry(uint32_t funcIndex) const
&match));
const LazyFuncExport& fe = exports_[match];
const LazyStubSegment& stub = *stubSegments_[fe.lazyStubSegmentIndex];
return stub.base() + stub.codeRanges()[fe.interpCodeRangeIndex].begin();
return stub.base() + stub.codeRanges()[fe.funcCodeRangeIndex].begin();
}
void

View File

@ -190,7 +190,7 @@ class FuncExport
FuncType funcType_;
MOZ_INIT_OUTSIDE_CTOR struct CacheablePod {
uint32_t funcIndex_;
uint32_t interpCodeRangeIndex_;
uint32_t funcCodeRangeIndex_;
uint32_t eagerInterpEntryOffset_; // Machine code offset
bool hasEagerStubs_;
} pod;
@ -201,7 +201,7 @@ class FuncExport
: funcType_(std::move(funcType))
{
pod.funcIndex_ = funcIndex;
pod.interpCodeRangeIndex_ = UINT32_MAX;
pod.funcCodeRangeIndex_ = UINT32_MAX;
pod.eagerInterpEntryOffset_ = UINT32_MAX;
pod.hasEagerStubs_ = hasEagerStubs;
}
@ -210,9 +210,9 @@ class FuncExport
MOZ_ASSERT(hasEagerStubs());
pod.eagerInterpEntryOffset_ = entryOffset;
}
void initInterpCodeRangeIndex(uint32_t codeRangeIndex) {
MOZ_ASSERT(pod.interpCodeRangeIndex_ == UINT32_MAX);
pod.interpCodeRangeIndex_ = codeRangeIndex;
void initFuncCodeRangeIndex(uint32_t codeRangeIndex) {
MOZ_ASSERT(pod.funcCodeRangeIndex_ == UINT32_MAX);
pod.funcCodeRangeIndex_ = codeRangeIndex;
}
bool hasEagerStubs() const {
@ -224,9 +224,9 @@ class FuncExport
uint32_t funcIndex() const {
return pod.funcIndex_;
}
uint32_t interpCodeRangeIndex() const {
MOZ_ASSERT(pod.interpCodeRangeIndex_ != UINT32_MAX);
return pod.interpCodeRangeIndex_;
uint32_t funcCodeRangeIndex() const {
MOZ_ASSERT(pod.funcCodeRangeIndex_ != UINT32_MAX);
return pod.funcCodeRangeIndex_;
}
uint32_t eagerInterpEntryOffset() const {
MOZ_ASSERT(pod.eagerInterpEntryOffset_ != UINT32_MAX);
@ -532,11 +532,11 @@ struct LazyFuncExport
{
size_t funcIndex;
size_t lazyStubSegmentIndex;
size_t interpCodeRangeIndex;
LazyFuncExport(size_t funcIndex, size_t lazyStubSegmentIndex, size_t interpCodeRangeIndex)
size_t funcCodeRangeIndex;
LazyFuncExport(size_t funcIndex, size_t lazyStubSegmentIndex, size_t funcCodeRangeIndex)
: funcIndex(funcIndex),
lazyStubSegmentIndex(lazyStubSegmentIndex),
interpCodeRangeIndex(interpCodeRangeIndex)
funcCodeRangeIndex(funcCodeRangeIndex)
{}
};

View File

@ -862,7 +862,7 @@ ModuleGenerator::finishMetadata(const ShareableBytes& bytecode)
// now that every function has a code range.
for (FuncExport& fe : metadataTier_->funcExports)
fe.initInterpCodeRangeIndex(funcToCodeRange_[fe.funcIndex()]);
fe.initFuncCodeRangeIndex(funcToCodeRange_[fe.funcIndex()]);
for (ElemSegment& elems : env_->elemSegments) {
Uint32Vector& codeRangeIndices = elems.elemCodeRangeIndices(tier());

View File

@ -118,7 +118,7 @@ class Instance
#endif
// This method returns a pointer to the GC object that owns this Instance.
// Instances may be reached via weak edges (e.g., Compartment::instances_)
// Instances may be reached via weak edges (e.g., Realm::instances_)
// so this perform a read-barrier on the returned object unless the barrier
// is explicitly waived.

View File

@ -1384,7 +1384,7 @@ WasmInstanceObject::getExportedFunctionCodeRange(HandleFunction fun, Tier tier)
uint32_t funcIndex = ExportedFunctionToFuncIndex(fun);
MOZ_ASSERT(exports().lookup(funcIndex)->value() == fun);
const FuncExport& funcExport = instance().metadata(tier).lookupFuncExport(funcIndex);
return instance().metadata(tier).codeRanges[funcExport.interpCodeRangeIndex()];
return instance().metadata(tier).codeRanges[funcExport.funcCodeRangeIndex()];
}
/* static */ WasmInstanceScope*
@ -2051,7 +2051,7 @@ WasmTableObject::setImpl(JSContext* cx, const CallArgs& args)
Tier tier = instance.code().bestTier();
const MetadataTier& metadata = instance.metadata(tier);
const FuncExport& funcExport = metadata.lookupFuncExport(funcIndex);
const CodeRange& codeRange = metadata.codeRanges[funcExport.interpCodeRangeIndex()];
const CodeRange& codeRange = metadata.codeRanges[funcExport.funcCodeRangeIndex()];
void* code = instance.codeBase(tier) + codeRange.funcTableEntry();
table.set(index, code, instance);
} else {

View File

@ -229,23 +229,26 @@ wasm::UnregisterCodeSegment(const CodeSegment* cs)
}
const CodeSegment*
wasm::LookupCodeSegment(const void* pc, const CodeRange** cr /*= nullptr */)
wasm::LookupCodeSegment(const void* pc, const CodeRange** codeRange /*= nullptr */)
{
if (const CodeSegment* found = processCodeSegmentMap.lookup(pc)) {
if (cr) {
*cr = found->isModule()
? found->asModule()->lookupRange(pc)
: found->asLazyStub()->lookupRange(pc);
if (codeRange) {
*codeRange = found->isModule()
? found->asModule()->lookupRange(pc)
: found->asLazyStub()->lookupRange(pc);
}
return found;
}
if (codeRange)
*codeRange = nullptr;
return nullptr;
}
const Code*
wasm::LookupCode(const void* pc, const CodeRange** cr /* = nullptr */)
wasm::LookupCode(const void* pc, const CodeRange** codeRange /* = nullptr */)
{
const CodeSegment* found = LookupCodeSegment(pc, cr);
const CodeSegment* found = LookupCodeSegment(pc, codeRange);
MOZ_ASSERT_IF(!found && codeRange, !*codeRange);
return found ? &found->code() : nullptr;
}

View File

@ -1853,6 +1853,18 @@ public:
return true;
}
/**
* The mCallee holds a strong ref to us since the refresh driver doesn't.
* Our dtor and mCallee's Destroy() method both call RemoveObserver() -
* whichever comes first removes us from the refresh driver.
*/
void RemoveObserver() {
if (mCallee) {
RefreshDriver(mCallee)->RemoveRefreshObserver(this, FlushType::Style);
mCallee = nullptr;
}
}
private:
// Private destructor, to discourage deletion outside of Release():
~AsyncSmoothMSDScroll() {
@ -1865,17 +1877,6 @@ private:
return aCallee->mOuter->PresContext()->RefreshDriver();
}
/*
* The refresh driver doesn't hold a reference to its observers,
* so releasing this object can (and is) used to remove the observer on DTOR.
* Currently, this object is released once the scrolling ends.
*/
void RemoveObserver() {
if (mCallee) {
RefreshDriver(mCallee)->RemoveRefreshObserver(this, FlushType::Style);
}
}
mozilla::layers::AxisPhysicsMSDModel mXAxisModel, mYAxisModel;
nsRect mRange;
mozilla::TimeStamp mLastRefreshTime;
@ -1974,17 +1975,10 @@ public:
ScrollFrameHelper::AsyncScrollCallback(mCallee, aTime);
}
private:
ScrollFrameHelper *mCallee;
nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) {
return aCallee->mOuter->PresContext()->RefreshDriver();
}
/*
* The refresh driver doesn't hold a reference to its observers,
* so releasing this object can (and is) used to remove the observer on DTOR.
* Currently, this object is released once the scrolling ends.
/**
* The mCallee holds a strong ref to us since the refresh driver doesn't.
* Our dtor and mCallee's Destroy() method both call RemoveObserver() -
* whichever comes first removes us from the refresh driver.
*/
void RemoveObserver() {
if (mCallee) {
@ -1992,8 +1986,15 @@ private:
if (nsIPresShell* shell = mCallee->mOuter->PresShell()) {
shell->SuppressDisplayport(false);
}
mCallee = nullptr;
}
}
private:
ScrollFrameHelper *mCallee;
nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) {
return aCallee->mOuter->PresContext()->RefreshDriver();
}
};
/*
@ -4891,6 +4892,12 @@ ScrollFrameHelper::Destroy(PostDestroyData& aPostDestroyData)
mScrollActivityTimer->Cancel();
mScrollActivityTimer = nullptr;
}
if (mAsyncScroll) {
mAsyncScroll->RemoveObserver();
}
if (mAsyncSmoothMSDScroll) {
mAsyncSmoothMSDScroll->RemoveObserver();
}
}
/**

View File

@ -71,6 +71,7 @@
#include "nsQuickSort.h"
#include "nsReadableUtils.h"
#include "nsRefPtrHashtable.h"
#include "nsRelativeFilePref.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
@ -2309,21 +2310,6 @@ private:
nsCOMPtr<nsISupportsString> mUnicodeString;
};
class nsRelativeFilePref final : public nsIRelativeFilePref
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIRELATIVEFILEPREF
nsRelativeFilePref();
private:
virtual ~nsRelativeFilePref();
nsCOMPtr<nsIFile> mFile;
nsCString mRelativeToKey;
};
//----------------------------------------------------------------------------
// nsPrefBranch
//----------------------------------------------------------------------------

View File

@ -26,6 +26,7 @@ XPIDL_MODULE = 'pref'
EXPORTS.mozilla += [
'init/StaticPrefList.h',
'nsRelativeFilePref.h',
'Preferences.h',
'StaticPrefs.h',
]

View File

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_nsRelativeFilePref_h
#define mozilla_nsRelativeFilePref_h
#include "nsCOMPtr.h"
#include "nsIFile.h"
#include "nsString.h"
// Note: This class is in its own file because it is needed by Mailnews.
namespace mozilla {
class nsRelativeFilePref final : public nsIRelativeFilePref
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIRELATIVEFILEPREF
nsRelativeFilePref();
private:
virtual ~nsRelativeFilePref();
nsCOMPtr<nsIFile> mFile;
nsCString mRelativeToKey;
};
} // namespace mozilla
#endif // mozilla_nsRelativeFilePref_h

View File

@ -554,7 +554,7 @@ impl WebDriverHandler<GeckoExtensionRoute> for MarionetteHandler {
},
_ => {
return Err(WebDriverError::new(
ErrorStatus::SessionNotCreated,
ErrorStatus::InvalidSessionId,
"Tried to run command without establishing a connection"));
}
}

View File

@ -740,9 +740,8 @@ class Marionette(object):
:returns: Full response from the server, or if `key` is given,
the value of said key in the response.
"""
if not self.session_id and name != "WebDriver:NewSession":
raise errors.MarionetteException("Please start a session")
raise errors.InvalidSessionIdException("Please start a session")
try:
msg = self.client.request(name, params)
@ -1277,7 +1276,10 @@ class Marionette(object):
"""
try:
if send_request:
self._send_message("WebDriver:DeleteSession")
try:
self._send_message("WebDriver:DeleteSession")
except errors.InvalidSessionIdException:
pass
finally:
self.process_id = None
self.profile = None

View File

@ -10,7 +10,7 @@ import shutil
from marionette_driver import Wait
from marionette_driver.errors import (
MarionetteException,
InvalidSessionIdException,
NoSuchWindowException,
TimeoutException
)
@ -106,8 +106,8 @@ class TestCrash(BaseCrashTestCase):
self.assertEqual(self.marionette.crashed, 1)
self.assertIsNone(self.marionette.session)
self.assertRaisesRegexp(MarionetteException, 'Please start a session',
self.marionette.get_url)
with self.assertRaisesRegexp(InvalidSessionIdException, 'Please start a session'):
self.marionette.get_url()
self.marionette.start_session()
self.assertNotEqual(self.marionette.process_id, self.pid)
@ -134,8 +134,8 @@ class TestCrash(BaseCrashTestCase):
self.assertEqual(self.marionette.crashed, 1)
self.assertIsNone(self.marionette.session)
self.assertRaisesRegexp(MarionetteException, 'Please start a session',
self.marionette.get_url)
with self.assertRaisesRegexp(InvalidSessionIdException, 'Please start a session'):
self.marionette.get_url()
self.marionette.start_session()
self.assertNotEqual(self.marionette.process_id, self.pid)

View File

@ -140,7 +140,7 @@ class TestQuitRestart(MarionetteTestCase):
self.marionette.quit(clean=True)
self.assertEqual(self.marionette.session, None)
with self.assertRaisesRegexp(errors.MarionetteException, "Please start a session"):
with self.assertRaisesRegexp(errors.InvalidSessionIdException, "Please start a session"):
self.marionette.get_url()
self.marionette.start_session()
@ -153,7 +153,7 @@ class TestQuitRestart(MarionetteTestCase):
self.marionette.quit()
self.assertEqual(self.marionette.session, None)
with self.assertRaisesRegexp(errors.MarionetteException, "Please start a session"):
with self.assertRaisesRegexp(errors.InvalidSessionIdException, "Please start a session"):
self.marionette.get_url()
self.marionette.start_session()
@ -245,7 +245,7 @@ class TestQuitRestart(MarionetteTestCase):
self.marionette.quit(in_app=True)
self.assertEqual(self.marionette.session, None)
with self.assertRaisesRegexp(errors.MarionetteException, "Please start a session"):
with self.assertRaisesRegexp(errors.InvalidSessionIdException, "Please start a session"):
self.marionette.get_url()
self.marionette.start_session()
@ -257,7 +257,7 @@ class TestQuitRestart(MarionetteTestCase):
def test_in_app_quit_with_callback(self):
self.marionette.quit(in_app=True, callback=self.shutdown)
self.assertEqual(self.marionette.session, None)
with self.assertRaisesRegexp(errors.MarionetteException, "Please start a session"):
with self.assertRaisesRegexp(errors.InvalidSessionIdException, "Please start a session"):
self.marionette.get_url()
self.marionette.start_session()

View File

@ -47,7 +47,7 @@ class TestSession(MarionetteTestCase):
self.marionette._send_message("WebDriver:NewSession", {})
def test_no_session(self):
with self.assertRaisesRegexp(errors.MarionetteException, "Please start a session"):
with self.assertRaises(errors.InvalidSessionIdException):
self.marionette.get_url()
self.marionette.start_session()

View File

@ -290,8 +290,9 @@ class TCPConnection {
throw new UnknownCommandError(cmd.name);
}
if (!["newSession", "WebDriver:NewSession"].includes(cmd.name)) {
assert.session(this.driver);
if (cmd.name != "WebDriver:NewSession") {
assert.session(this.driver,
"Tried to run command without establishing a connection");
}
let rv = await fn.bind(this.driver)(cmd);

View File

@ -759,7 +759,6 @@ def findTestMediaDevices(log):
info['video'] = name
pactl = spawn.find_executable("pactl")
pacmd = spawn.find_executable("pacmd")
# Use pactl to see if the PulseAudio module-null-sink module is loaded.
def null_sink_loaded():
@ -776,9 +775,6 @@ def findTestMediaDevices(log):
log.error('Couldn\'t load module-null-sink')
return None
# Whether it was loaded or not make it the default output
subprocess.check_call([pacmd, 'set-default-sink', 'null'])
# Hardcode the name since it's always the same.
info['audio'] = 'Monitor of Null Output'
return info
@ -1930,6 +1926,8 @@ toolbar#nav-bar {
if options.useTestMediaDevices:
prefs['media.audio_loopback_dev'] = self.mediaDevices['audio']
prefs['media.video_loopback_dev'] = self.mediaDevices['video']
prefs['media.cubeb.output_device'] = "Null Output"
prefs['media.volume_scale'] = "1.0"
# Disable web replay rewinding by default if recordings are being saved.
if options.recordingPath:

View File

@ -1,3 +0,0 @@
[modifier_click.py]
disabled:
if os == "linux": https://bugzilla.mozilla.org/show_bug.cgi?id=1447844

View File

@ -1,3 +0,0 @@
[mouse_pause_dblclick.py]
disabled:
if os == "linux": https://bugzilla.mozilla.org/show_bug.cgi?id=1447449

View File

@ -1,4 +0,0 @@
[delete.py]
[test_dismissed_beforeunload_prompt]
expected: FAIL

View File

@ -404,6 +404,13 @@ class Session(object):
self.end()
def start(self):
"""Start a new WebDriver session.
:return: Dictionary with `capabilities` and `sessionId`.
:raises error.WebDriverException: If the remote end returns
an error.
"""
if self.session_id is not None:
return
@ -422,13 +429,13 @@ class Session(object):
return value
def end(self):
"""Tries to close the active session."""
"""Try to close the active session."""
if self.session_id is None:
return
try:
self.send_command("DELETE", "session/%s" % self.session_id)
except error.SessionNotCreatedException:
except error.InvalidSessionIdException:
pass
finally:
self.session_id = None
@ -446,10 +453,10 @@ class Session(object):
the `value` field returned after parsing the response
body as JSON.
:raises ValueError: If the response body does not contain a
`value` key.
:raises error.WebDriverException: If the remote end returns
an error.
:raises ValueError: If the response body does not contain a
`value` key.
"""
response = self.transport.send(
method, url, body,
@ -459,7 +466,7 @@ class Session(object):
if response.status != 200:
err = error.from_response(response)
if isinstance(err, error.SessionNotCreatedException):
if isinstance(err, error.InvalidSessionIdException):
# The driver could have already been deleted the session.
self.session_id = None
@ -495,14 +502,9 @@ class Session(object):
:return: `None` if the HTTP response body was empty, otherwise
the result of parsing the body as JSON.
:raises error.SessionNotCreatedException: If there is no active
session.
:raises error.WebDriverException: If the remote end returns
an error.
"""
if self.session_id is None:
raise error.SessionNotCreatedException()
url = urlparse.urljoin("session/%s/" % self.session_id, uri)
return self.send_command(method, url, body)

View File

@ -13,6 +13,7 @@ def test_null_response_value(session):
response = delete_session(session)
value = assert_success(response)
assert value is None
# Need an explicit call to session.end() to notify the test harness
# that a new session needs to be created for subsequent tests.
session.end()