Backed out 2 changesets (bug 1495153) for causing perma failures on dynamic-max-width.html
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Sun, 07 Oct 2018 05:14:44 +0300
changeset 495662 90853a59691e
parent 495661 9f2c6ae03c6d
child 495663 b83d37998028
child 495670 4740b2dbe785
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1495153
milestone64.0a1
backs out6d95f0e0cc76
6800eb348ebe
first release with
nightly linux32
90853a59691e / 64.0a1 / 20181007100131 / files
nightly linux64
90853a59691e / 64.0a1 / 20181007100131 / files
nightly mac
90853a59691e / 64.0a1 / 20181007100131 / files
nightly win32
90853a59691e / 64.0a1 / 20181007100131 / files
nightly win64
90853a59691e / 64.0a1 / 20181007100131 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 2 changesets (bug 1495153) for causing perma failures on dynamic-max-width.html Backed out changeset 6d95f0e0cc76 (bug 1495153) Backed out changeset 6800eb348ebe (bug 1495153)
layout/forms/nsFileControlFrame.cpp
layout/forms/nsFileControlFrame.h
layout/generic/nsTextFrame.cpp
layout/generic/nsTextFrame.h
layout/reftests/forms/input/file/dynamic-max-width-ref.html
layout/reftests/forms/input/file/dynamic-max-width.html
layout/reftests/forms/input/file/reftest.list
layout/style/res/forms.css
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -22,17 +22,16 @@
 #include "mozilla/dom/MutationEventBinding.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPrefs.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "mozilla/EventStates.h"
 #include "nsTextNode.h"
-#include "nsTextFrame.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsIFrame*
 NS_NewFileControlFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
 {
   return new (aPresShell) nsFileControlFrame(aStyle);
@@ -52,154 +51,16 @@ nsFileControlFrame::Init(nsIContent*    
                          nsContainerFrame* aParent,
                          nsIFrame*         aPrevInFlow)
 {
   nsBlockFrame::Init(aContent, aParent, aPrevInFlow);
 
   mMouseListener = new DnDListener(this);
 }
 
-bool
-nsFileControlFrame::CropTextToWidth(gfxContext&     aRenderingContext,
-                                    const nsIFrame* aFrame,
-                                    nscoord         aWidth,
-                                    nsString&       aText)
-{
-  if (aText.IsEmpty()) {
-    return false;
-  }
-
-  RefPtr<nsFontMetrics> fm =
-    nsLayoutUtils::GetFontMetricsForFrame(aFrame, 1.0f);
-
-  // see if the text will completely fit in the width given
-  nscoord textWidth =
-    nsLayoutUtils::AppUnitWidthOfStringBidi(aText, aFrame, *fm,
-                                            aRenderingContext);
-  if (textWidth <= aWidth) {
-    return false;
-  }
-
-  DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
-  const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
-
-  // see if the width is even smaller than the ellipsis
-  fm->SetTextRunRTL(false);
-  textWidth = nsLayoutUtils::AppUnitWidthOfString(kEllipsis, *fm, drawTarget);
-  if (textWidth >= aWidth) {
-    aText = kEllipsis;
-    return true;
-  }
-
-  // determine how much of the string will fit in the max width
-  nscoord totalWidth = textWidth;
-  using mozilla::unicode::ClusterIterator;
-  using mozilla::unicode::ClusterReverseIterator;
-  ClusterIterator leftIter(aText.Data(), aText.Length());
-  ClusterReverseIterator rightIter(aText.Data(), aText.Length());
-  const char16_t* leftPos = leftIter;
-  const char16_t* rightPos = rightIter;
-  const char16_t* pos;
-  ptrdiff_t length;
-  nsAutoString leftString, rightString;
-
-  while (leftPos < rightPos) {
-    leftIter.Next();
-    pos = leftIter;
-    length = pos - leftPos;
-    textWidth = nsLayoutUtils::AppUnitWidthOfString(leftPos, length,
-                                                    *fm, drawTarget);
-    if (totalWidth + textWidth > aWidth) {
-      break;
-    }
-
-    leftString.Append(leftPos, length);
-    leftPos = pos;
-    totalWidth += textWidth;
-
-    if (leftPos >= rightPos) {
-      break;
-    }
-
-    rightIter.Next();
-    pos = rightIter;
-    length = rightPos - pos;
-    textWidth = nsLayoutUtils::AppUnitWidthOfString(pos, length,
-                                                    *fm, drawTarget);
-    if (totalWidth + textWidth > aWidth) {
-      break;
-    }
-
-    rightString.Insert(pos, 0, length);
-    rightPos = pos;
-    totalWidth += textWidth;
-  }
-
-  aText = leftString + kEllipsis + rightString;
-  return true;
-}
-
-void
-nsFileControlFrame::Reflow(nsPresContext*     aPresContext,
-                           ReflowOutput&      aMetrics,
-                           const ReflowInput& aReflowInput,
-                           nsReflowStatus&    aStatus)
-{
-  // Restore the uncropped filename.
-  nsAutoString filename;
-  HTMLInputElement::FromNode(mContent)->GetDisplayFileName(filename);
-
-  bool done = false;
-  while (true) {
-    UpdateDisplayedValue(filename, false);  // update the text node
-    AddStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
-    LinesBegin()->MarkDirty();
-    nsBlockFrame::Reflow(aPresContext, aMetrics, aReflowInput, aStatus);
-    if (done) {
-      break;
-    }
-    nscoord lineISize = LinesBegin()->ISize();
-    const auto cbWM = aMetrics.GetWritingMode();
-    const auto wm = GetWritingMode();
-    nscoord iSize = wm.IsOrthogonalTo(cbWM) ? aMetrics.BSize(cbWM)
-                                            : aMetrics.ISize(cbWM);
-    auto bp = GetLogicalUsedBorderAndPadding(wm);
-    nscoord contentISize = iSize - bp.IStartEnd(wm);
-    if (lineISize > contentISize) {
-      // The filename overflows - crop it and reflow again (once).
-      // NOTE: the label frame might have bidi-continuations
-      auto* labelFrame = mTextContent->GetPrimaryFrame();
-      nscoord labelBP =
-        labelFrame->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
-      auto* lastLabelCont = labelFrame->LastContinuation();
-      if (lastLabelCont != labelFrame) {
-        labelBP +=
-          lastLabelCont->GetLogicalUsedBorderAndPadding(wm).IStartEnd(wm);
-      }
-      auto* buttonFrame = mBrowseFilesOrDirs->GetPrimaryFrame();
-      nscoord availableISizeForLabel = contentISize - buttonFrame->ISize(wm) -
-        buttonFrame->GetLogicalUsedMargin(wm).IStartEnd(wm);
-      if (CropTextToWidth(*aReflowInput.mRenderingContext,
-                          labelFrame,
-                          availableISizeForLabel - labelBP,
-                          filename)) {
-        nsBlockFrame::DidReflow(aPresContext, &aReflowInput);
-        aStatus.Reset();
-        labelFrame->AddStateBits(NS_FRAME_IS_DIRTY |
-                                 NS_BLOCK_NEEDS_BIDI_RESOLUTION);
-        mMinWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
-        mPrefWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
-        done = true;
-        continue;
-      }
-    }
-    break;
-  }
-}
-
 void
 nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
 {
   NS_ENSURE_TRUE_VOID(mContent);
 
   // Remove the events.
   if (mContent) {
     mContent->RemoveSystemEventListener(NS_LITERAL_STRING("drop"),
@@ -275,29 +136,35 @@ nsFileControlFrame::CreateAnonymousConte
   fileContent->GetAccessKey(accessKey);
 
   mBrowseFilesOrDirs = MakeAnonButton(doc, "Browse", fileContent, accessKey);
   if (!mBrowseFilesOrDirs || !aElements.AppendElement(mBrowseFilesOrDirs)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Create and setup the text showing the selected files.
-  mTextContent = doc->CreateHTMLElement(nsGkAtoms::label);
+  RefPtr<NodeInfo> nodeInfo;
+  nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::label, nullptr,
+                                                 kNameSpaceID_XUL,
+                                                 nsINode::ELEMENT_NODE);
+  NS_TrustedNewXULElement(getter_AddRefs(mTextContent), nodeInfo.forget());
   // NOTE: SetIsNativeAnonymousRoot() has to be called before setting any
   // attribute.
   mTextContent->SetIsNativeAnonymousRoot();
-  RefPtr<nsTextNode> text = new nsTextNode(doc->NodeInfoManager());
-  mTextContent->AppendChildTo(text, false);
+  mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::crop,
+                        NS_LITERAL_STRING("center"), false);
 
   // Update the displayed text to reflect the current element's value.
   nsAutoString value;
   HTMLInputElement::FromNode(mContent)->GetDisplayFileName(value);
   UpdateDisplayedValue(value, false);
 
-  aElements.AppendElement(mTextContent);
+  if (!aElements.AppendElement(mTextContent)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   // We should be able to interact with the element by doing drag and drop.
   mContent->AddSystemEventListener(NS_LITERAL_STRING("drop"),
                                    mMouseListener, false);
   mContent->AddSystemEventListener(NS_LITERAL_STRING("dragover"),
                                    mMouseListener, false);
 
   SyncDisabledState();
@@ -544,43 +411,26 @@ nsFileControlFrame::DnDListener::CanDrop
   uint32_t listLength = 0;
   if (fileList) {
     listLength = fileList->Length();
   }
   return listLength <= 1 || aSupportsMultiple;
 }
 
 nscoord
-nsFileControlFrame::GetMinISize(gfxContext* aRenderingContext)
+nsFileControlFrame::GetMinISize(gfxContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_INLINE_SIZE(this, result);
 
   // Our min inline size is our pref inline size
   result = GetPrefISize(aRenderingContext);
   return result;
 }
 
-nscoord
-nsFileControlFrame::GetPrefISize(gfxContext* aRenderingContext)
-{
-  nscoord result;
-  DISPLAY_MIN_INLINE_SIZE(this, result);
-
-  // Make sure we measure with the uncropped filename.
-  if (mPrefWidth == NS_INTRINSIC_WIDTH_UNKNOWN) {
-    nsAutoString filename;
-    HTMLInputElement::FromNode(mContent)->GetDisplayFileName(filename);
-    UpdateDisplayedValue(filename, false);
-  }
-
-  result = nsBlockFrame::GetPrefISize(aRenderingContext);
-  return result;
-}
-
 void
 nsFileControlFrame::SyncDisabledState()
 {
   EventStates eventStates = mContent->AsElement()->State();
   if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
     mBrowseFilesOrDirs->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
                                 EmptyString(), true);
   } else {
@@ -620,26 +470,17 @@ nsFileControlFrame::GetFrameName(nsAStri
 {
   return MakeFrameName(NS_LITERAL_STRING("FileControl"), aResult);
 }
 #endif
 
 void
 nsFileControlFrame::UpdateDisplayedValue(const nsAString& aValue, bool aNotify)
 {
-  auto* text = Text::FromNode(mTextContent->GetFirstChild());
-  uint32_t oldLength = aNotify ? 0 : text->TextLength();
-  text->SetText(aValue, aNotify);
-  if (!aNotify) {
-    // We can't notify during Reflow so we need to tell the text frame
-    // about the text content change we just did.
-    if (auto* textFrame = static_cast<nsTextFrame*>(text->GetPrimaryFrame())) {
-      textFrame->NotifyNativeAnonymousTextnodeChange(oldLength);
-    }
-  }
+  mTextContent->SetAttr(kNameSpaceID_None, nsGkAtoms::value, aValue, aNotify);
 }
 
 nsresult
 nsFileControlFrame::SetFormProperty(nsAtom* aName,
                                     const nsAString& aValue)
 {
   if (nsGkAtoms::value == aName) {
     UpdateDisplayedValue(aValue, true);
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -22,49 +22,43 @@ class DataTransfer;
 } // namespace dom
 } // namespace mozilla
 
 class nsFileControlFrame final : public nsBlockFrame,
                                  public nsIFormControlFrame,
                                  public nsIAnonymousContentCreator
 {
 public:
-  NS_DECL_QUERYFRAME
-  NS_DECL_FRAMEARENA_HELPERS(nsFileControlFrame)
-
   explicit nsFileControlFrame(ComputedStyle* aStyle);
 
   virtual void Init(nsIContent*       aContent,
                     nsContainerFrame* aParent,
                     nsIFrame*         aPrevInFlow) override;
 
-  void Reflow(nsPresContext*     aPresContext,
-              ReflowOutput&      aDesiredSize,
-              const ReflowInput& aReflowInput,
-              nsReflowStatus&    aStatus) override;
-
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
+  NS_DECL_QUERYFRAME
+  NS_DECL_FRAMEARENA_HELPERS(nsFileControlFrame)
+
   // nsIFormControlFrame
   virtual nsresult SetFormProperty(nsAtom* aName, const nsAString& aValue) override;
   virtual void SetFocus(bool aOn, bool aRepaint) override;
 
-  nscoord GetMinISize(gfxContext* aRenderingContext) override;
-  nscoord GetPrefISize(gfxContext* aRenderingContext) override;
+  virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
-  nsresult AttributeChanged(int32_t aNameSpaceID,
-                            nsAtom* aAttribute,
-                            int32_t aModType) override;
+  virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
+                                    nsAtom*        aAttribute,
+                                    int32_t         aModType) override;
   virtual void ContentStatesChanged(mozilla::EventStates aStates) override;
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                         uint32_t aFilter) override;
 
 #ifdef ACCESSIBILITY
@@ -153,25 +147,16 @@ protected:
   /**
    * Drag and drop mouse listener.
    * This makes sure we don't get used after destruction.
    */
   RefPtr<DnDListener> mMouseListener;
 
 protected:
   /**
-   * Crop aText to fit inside aWidth using the styles of aFrame.
-   * @return true if aText was modified
-   */
-  static bool CropTextToWidth(gfxContext&     aRenderingContext,
-                              const nsIFrame* aFrame,
-                              nscoord         aWidth,
-                              nsString&       aText);
-
-  /**
    * Sync the disabled state of the content with anonymous children.
    */
   void SyncDisabledState();
 
   /**
    * Updates the displayed value by using aValue.
    */
   void UpdateDisplayedValue(const nsAString& aValue, bool aNotify);
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4791,38 +4791,16 @@ nsTextFrame::DisconnectTextRuns()
   MOZ_ASSERT(!IsInTextRunUserData(),
              "Textrun mentions this frame in its user data so we can't just disconnect");
   mTextRun = nullptr;
   if ((GetStateBits() & TEXT_HAS_FONT_INFLATION)) {
     DeleteProperty(UninflatedTextRunProperty());
   }
 }
 
-void
-nsTextFrame::NotifyNativeAnonymousTextnodeChange(uint32_t aOldLength)
-{
-  MOZ_ASSERT(mContent->IsInNativeAnonymousSubtree());
-
-  MarkIntrinsicISizesDirty();
-
-  // This is to avoid making a new Reflow request in CharacterDataChanged:
-  for (nsTextFrame* f = this; f; f = f->GetNextContinuation()) {
-    f->AddStateBits(NS_FRAME_IS_DIRTY);
-    f->mReflowRequestedForCharDataChange = true;
-  }
-
-  // Pretend that all the text changed.
-  CharacterDataChangeInfo info;
-  info.mAppend = false;
-  info.mChangeStart = 0;
-  info.mChangeEnd = aOldLength;
-  info.mReplaceLength = mContent->TextLength();
-  CharacterDataChanged(info);
-}
-
 nsresult
 nsTextFrame::CharacterDataChanged(const CharacterDataChangeInfo& aInfo)
 {
   if (mContent->HasFlag(NS_HAS_NEWLINE_PROPERTY)) {
     mContent->DeleteProperty(nsGkAtoms::newline);
     mContent->UnsetFlags(NS_HAS_NEWLINE_PROPERTY);
   }
   if (mContent->HasFlag(NS_HAS_FLOWLENGTH_PROPERTY)) {
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -663,23 +663,16 @@ public:
 
   void AssignJustificationGaps(const mozilla::JustificationAssignment& aAssign);
   mozilla::JustificationAssignment GetJustificationAssignment() const;
 
   uint32_t CountGraphemeClusters() const;
 
   bool HasAnyNoncollapsedCharacters() override;
 
-  /**
-   * Call this after you have manually changed the text node contents without
-   * notifying that change.  This behaves as if all the text contents changed.
-   * (You should only use this for native anonymous content.)
-   */
-  void NotifyNativeAnonymousTextnodeChange(uint32_t aOldLength);
-
 protected:
   virtual ~nsTextFrame();
 
   RefPtr<gfxTextRun> mTextRun;
   nsTextFrame* mNextContinuation;
   // The key invariant here is that mContentOffset never decreases along
   // a next-continuation chain. And of course mContentOffset is always <= the
   // the text node's content length, and the mContentOffset for the first frame
deleted file mode 100644
--- a/layout/reftests/forms/input/file/dynamic-max-width-ref.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE HTML>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html><head>
-  <meta charset="utf-8">
-  <title>Reference for dynamic-max-width.html</title>
-</head>
-<body>
-
-<input type=file dir=rtl>
-
-<br>
-
-<input type=file>
-
-
-</body>
-</html>
deleted file mode 100644
--- a/layout/reftests/forms/input/file/dynamic-max-width.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE HTML>
-<!--
-     Any copyright is dedicated to the Public Domain.
-     http://creativecommons.org/publicdomain/zero/1.0/
--->
-<html class="reftest-wait"><head>
-  <meta charset="utf-8">
-  <title>CSS Test: file control with dynamic change to max-width</title>
-  <style type="text/css">
-
-    input { max-width: 10em; }
-
-  </style>
-  <script>
-    function tweak() {
-      [...document.querySelectorAll('input')].forEach(function(e) {
-        e.style.maxWidth = 'initial';
-      });
-      document.documentElement.removeAttribute("class");
-    }
-    window.addEventListener("MozReftestInvalidate", tweak);
-  </script>
-</head>
-<body onload="test()">
-
-<input type=file dir=rtl>
-
-<br>
-
-<input type=file>
-
-
-</body>
-</html>
--- a/layout/reftests/forms/input/file/reftest.list
+++ b/layout/reftests/forms/input/file/reftest.list
@@ -1,8 +1,7 @@
 fuzzy-if(gtkWidget||webrender,0-1,0-34) fails-if(Android) == simple.html simple-ref.xul
 fuzzy-if(gtkWidget||webrender,0-1,0-17) fails-if(Android) == rtl.html rtl-ref.xul
 fuzzy-if(gtkWidget||webrender,0-1,0-34) fails-if(Android) == size.html simple-ref.xul
 fuzzy-if(gtkWidget||webrender,0-1,0-10) fails-if(Android) == background.html background-ref.xul
 fuzzy-if(gtkWidget,0-1,0-10) fails-if(Android) == style.html style-ref.xul
 != width-clip.html width-clip-ref.html
 fails-if(Android) == color-inherit.html color-inherit-ref.html
-fuzzy-if(Android,1-2,2-2) == dynamic-max-width.html dynamic-max-width-ref.html
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
   Styles for old GFX form widgets
  **/
 
 
 @namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
+@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
 
 *|*::-moz-fieldset-content {
   display: block; /* StyleAdjuster::adjust_for_fieldset_content overrides this in some cases */
   unicode-bidi: inherit;
   text-overflow: inherit;
   overflow: inherit;
   overflow-clip-box: inherit;
   /* Need to inherit border-radius too, so when the fieldset has rounded
@@ -474,42 +475,45 @@ input[type="image"]:disabled {
 input[type="image"]:-moz-focusring {
   /* Don't specify the outline-color, we should always use initial value. */
   outline: 1px dotted;
 }
 
 /* file selector */
 input[type="file"] {
   display: inline-block;
-  white-space: nowrap !important;
+  white-space: nowrap;
   overflow: hidden;
   overflow-clip-box: padding-box;
   color: unset;
 
   /* Revert rules which apply on all inputs. */
   -moz-appearance: none;
   -moz-binding: none;
   cursor: default;
 
   border: none;
   background-color: transparent;
   padding: unset;
 }
 
-input[type="file"] > label {
+input[type="file"] > xul|label {
   min-inline-size: 12em;
   padding-inline-start: 5px;
   text-align: match-parent;
 
   color: unset;
   font-size: unset;
   letter-spacing: unset;
 
-  -moz-user-select: none;
-  unicode-bidi: plaintext;
+  /*
+   * Force the text to have LTR directionality. Otherwise filenames containing
+   * RTL characters will be reordered with chaotic results.
+   */
+  direction: ltr !important;
 }
 
 /* button part of file selector */
 input[type="file"] > button[type="button"] {
   block-size: inherit;
   font-size: unset;
   letter-spacing: unset;
   cursor: unset;
@@ -523,16 +527,24 @@ input[type="color"]::-moz-color-swatch {
   min-height: 3px;
   margin-inline-start: auto;
   margin-inline-end: auto;
   box-sizing: border-box;
   border: 1px solid grey;
   display: block;
 }
 
+/* Try to make RTL <input type='file'> look nicer. */
+/* TODO: find a better solution than forcing direction: ltr on all file
+   input labels and remove this override -- bug 1161482 */
+input[type="file"]:dir(rtl) > xul|label {
+  padding-inline-start: 0px;
+  padding-inline-end: 5px;
+}
+
 /* radio buttons */
 input[type="radio"] {
   display: inline-block;
   -moz-appearance: radio;
   margin-block-start: 3px;
   margin-block-end: 0px;
   margin-inline-start: 5px;
   margin-inline-end: 3px;