Bug 37468 - Implement ServoStyleRule::SetSelectorText method for setting CSS rule selectorText from JS. r=xidorn
☠☠ backed out by 93723d7f125b ☠ ☠
authorKerem Kat <keremkat@gmail.com>
Sat, 14 Apr 2018 19:05:44 +0300
changeset 466918 bd0a3fdb037c308ae7eab0be3c68d00fcb9b6056
parent 466917 0c7db264c68e1f3074462cc17c488047a16f85c4
child 466919 5e7a1db60298306b7c55e5c2ebd0075d7e77c258
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs37468
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 37468 - Implement ServoStyleRule::SetSelectorText method for setting CSS rule selectorText from JS. r=xidorn
layout/style/ServoBindingList.h
layout/style/ServoStyleRule.cpp
layout/style/StyleSheet.h
layout/style/StyleSheetInlines.h
servo/ports/geckolib/glue.rs
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -284,16 +284,19 @@ SERVO_BINDING_FUNC(Servo_StyleRule_GetSe
 SERVO_BINDING_FUNC(Servo_StyleRule_GetSpecificityAtIndex, void,
                    RawServoStyleRuleBorrowed rule, uint32_t index,
                    uint64_t* specificity)
 SERVO_BINDING_FUNC(Servo_StyleRule_GetSelectorCount, void,
                    RawServoStyleRuleBorrowed rule, uint32_t* count)
 SERVO_BINDING_FUNC(Servo_StyleRule_SelectorMatchesElement, bool,
                    RawServoStyleRuleBorrowed, RawGeckoElementBorrowed,
                    uint32_t index, mozilla::CSSPseudoElementType pseudo_type)
+SERVO_BINDING_FUNC(Servo_StyleRule_SetSelectorText, bool,
+                   RawServoStyleSheetContentsBorrowed sheet,
+                   RawServoStyleRuleBorrowed rule, const nsAString* text)
 SERVO_BINDING_FUNC(Servo_ImportRule_GetHref, void,
                    RawServoImportRuleBorrowed rule, nsAString* result)
 SERVO_BINDING_FUNC(Servo_ImportRule_GetSheet,
                    const mozilla::ServoStyleSheet*,
                    RawServoImportRuleBorrowed rule)
 SERVO_BINDING_FUNC(Servo_Keyframe_GetKeyText, void,
                    RawServoKeyframeBorrowed keyframe, nsAString* result)
 // Returns whether it successfully changes the key text.
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -201,19 +201,33 @@ void
 ServoStyleRule::GetSelectorText(nsAString& aSelectorText)
 {
   Servo_StyleRule_GetSelectorText(mRawRule, &aSelectorText);
 }
 
 void
 ServoStyleRule::SetSelectorText(const nsAString& aSelectorText)
 {
-  // XXX We need to implement this... But Gecko doesn't have this either
-  //     so it's probably okay to leave it unimplemented currently?
-  //     See bug 37468 and mozilla::css::StyleRule::SetSelectorText.
+  if (RefPtr<StyleSheet> sheet = GetStyleSheet()) {
+    ServoStyleSheet* servoSheet = sheet->AsServo();
+    nsIDocument* doc = sheet->GetAssociatedDocument();
+
+    mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, true);
+
+    // StyleRule lives inside of the Inner, it is unsafe to call WillDirty
+    // if sheet does not already have a unique Inner.
+    sheet->AssertHasUniqueInner();
+    sheet->WillDirty();
+
+    const RawServoStyleSheetContents* contents = servoSheet->RawContents();
+    if (Servo_StyleRule_SetSelectorText(contents, mRawRule, &aSelectorText)) {
+      sheet->DidDirty();
+      sheet->RuleChanged(this);
+    }
+  }
 }
 
 uint32_t
 ServoStyleRule::GetSelectorCount()
 {
   uint32_t aCount;
   Servo_StyleRule_GetSelectorCount(mRawRule, &aCount);
 
--- a/layout/style/StyleSheet.h
+++ b/layout/style/StyleSheet.h
@@ -9,16 +9,17 @@
 
 #include "mozilla/css/SheetParsingMode.h"
 #include "mozilla/dom/CSSStyleSheetBinding.h"
 #include "mozilla/net/ReferrerPolicy.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/ServoUtils.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsWrapperCache.h"
+#include "StyleSheetInfo.h"
 
 class nsIDocument;
 class nsINode;
 class nsIPrincipal;
 class nsCSSRuleProcessor;
 
 namespace mozilla {
 
@@ -144,16 +145,17 @@ public:
 
   void ClearModifiedRules()
   {
     mDirtyFlags &= ~MODIFIED_RULES;
   }
 
   inline bool HasUniqueInner() const;
   void EnsureUniqueInner();
+  inline void AssertHasUniqueInner() const;
 
   // Append all of this sheet's child sheets to aArray.
   void AppendAllChildSheets(nsTArray<StyleSheet*>& aArray);
 
   // style sheet owner info
   enum DocumentAssociationMode : uint8_t {
     // OwnedByDocument means mDocument owns us (possibly via a chain of other
     // stylesheets).
--- a/layout/style/StyleSheetInlines.h
+++ b/layout/style/StyleSheetInlines.h
@@ -128,12 +128,18 @@ StyleSheet::GetIntegrity(dom::SRIMetadat
   aResult = SheetInfo().mIntegrity;
 }
 
 bool
 StyleSheet::HasUniqueInner() const
 {
   return mInner->mSheets.Length() == 1;
 }
+
+void
+StyleSheet::AssertHasUniqueInner() const
+{
+  MOZ_ASSERT(HasUniqueInner());
+}
 
 }
 
 #endif // mozilla_StyleSheetInlines_h
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1,17 +1,17 @@
 /* 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/. */
 
 use cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation};
 use cssparser::ToCss as ParserToCss;
 use env_logger::Builder;
 use malloc_size_of::MallocSizeOfOps;
-use selectors::NthIndexCache;
+use selectors::{NthIndexCache, SelectorList};
 use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
 use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
 use smallvec::SmallVec;
 use std::cell::RefCell;
 use std::env;
 use std::fmt::Write;
 use std::iter;
 use std::mem;
@@ -1898,16 +1898,47 @@ pub extern "C" fn Servo_StyleRule_Select
         let quirks_mode = element.as_node().owner_doc().quirks_mode();
         let mut ctx =
             MatchingContext::new(matching_mode, None, None, quirks_mode);
         matches_selector(selector, 0, None, &element, &mut ctx, &mut |_, _| {})
     })
 }
 
 #[no_mangle]
+pub unsafe extern "C" fn Servo_StyleRule_SetSelectorText(
+    sheet: RawServoStyleSheetContentsBorrowed,
+    rule: RawServoStyleRuleBorrowed,
+    text: *const nsAString,
+) -> bool {
+    let value_str = (*text).to_string();
+
+    write_locked_arc(rule, |rule: &mut StyleRule| {
+        use style::selector_parser::SelectorParser;
+
+        let contents = StylesheetContents::as_arc(&sheet);
+        let namespaces = contents.namespaces.read();
+        let url_data = contents.url_data.read();
+        let parser = SelectorParser {
+            stylesheet_origin: contents.origin,
+            namespaces: &namespaces,
+            url_data: Some(&url_data),
+        };
+
+        let mut parser_input = ParserInput::new(&value_str);
+        match SelectorList::parse(&parser, &mut Parser::new(&mut parser_input)) {
+            Ok(selectors) => {
+                rule.selectors = selectors;
+                true
+            }
+            Err(_) => false,
+        }
+    })
+}
+
+#[no_mangle]
 pub unsafe extern "C" fn Servo_SelectorList_Closest(
     element: RawGeckoElementBorrowed,
     selectors: RawServoSelectorListBorrowed,
 ) -> *const structs::RawGeckoElement {
     use std::borrow::Borrow;
     use style::dom_apis;
 
     let element = GeckoElement(element);