Bug 37468 - Implement ServoStyleRule::SetSelectorText method for setting CSS rule selectorText from JS. r=xidorn
authorKerem Kat <keremkat@gmail.com>
Sat, 14 Apr 2018 19:05:44 +0300
changeset 466922 4d7067c22f47dc071f085d27139a296d6bfc1f69
parent 466921 93723d7f125b8f9edfdc148b398b238e6d1e9705
child 466923 7343e39bf9854651c4f8c2525767b825666d38fd
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);