зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1882581) for causing bustage on InspectorUtils.cpp. CLOSED TREE
Backed out changeset 9f390afd0df5 (bug 1882581) Backed out changeset 4781bbc7324f (bug 1882581)
This commit is contained in:
Родитель
39646463bc
Коммит
3db9556f81
|
@ -1,14 +0,0 @@
|
|||
/* -*- Mode: IDL; 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://drafts.csswg.org/css-cascade-6/#the-cssscoperule-interface
|
||||
*/
|
||||
|
||||
[Exposed=Window, Pref="layout.css.at-scope.enabled"]
|
||||
interface CSSScopeRule : CSSGroupingRule {
|
||||
readonly attribute UTF8String? start;
|
||||
readonly attribute UTF8String? end;
|
||||
};
|
|
@ -492,7 +492,6 @@ WEBIDL_FILES = [
|
|||
"CSSPseudoElement.webidl",
|
||||
"CSSRule.webidl",
|
||||
"CSSRuleList.webidl",
|
||||
"CSSScopeRule.webidl",
|
||||
"CSSStyleDeclaration.webidl",
|
||||
"CSSStyleRule.webidl",
|
||||
"CSSStyleSheet.webidl",
|
||||
|
|
|
@ -86,8 +86,7 @@ void ServoStyleRuleMap::RuleRemoved(StyleSheet& aStyleSheet,
|
|||
case StyleCssRuleType::Supports:
|
||||
case StyleCssRuleType::LayerBlock:
|
||||
case StyleCssRuleType::Container:
|
||||
case StyleCssRuleType::Document:
|
||||
case StyleCssRuleType::Scope: {
|
||||
case StyleCssRuleType::Document: {
|
||||
// See the comment in SheetRemoved.
|
||||
mTable.Clear();
|
||||
break;
|
||||
|
@ -125,8 +124,7 @@ void ServoStyleRuleMap::FillTableFromRule(css::Rule& aRule) {
|
|||
case StyleCssRuleType::Media:
|
||||
case StyleCssRuleType::Supports:
|
||||
case StyleCssRuleType::Container:
|
||||
case StyleCssRuleType::Document:
|
||||
case StyleCssRuleType::Scope: {
|
||||
case StyleCssRuleType::Document: {
|
||||
auto& rule = static_cast<css::GroupRule&>(aRule);
|
||||
FillTableFromRuleList(*rule.CssRules());
|
||||
break;
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/CSSScopeRule.h"
|
||||
#include "mozilla/dom/CSSScopeRuleBinding.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
CSSScopeRule::CSSScopeRule(RefPtr<StyleScopeRule> aRawRule, StyleSheet* aSheet,
|
||||
css::Rule* aParentRule, uint32_t aLine,
|
||||
uint32_t aColumn)
|
||||
: css::GroupRule(aSheet, aParentRule, aLine, aColumn),
|
||||
mRawRule(std::move(aRawRule)) {}
|
||||
|
||||
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(CSSScopeRule, css::GroupRule)
|
||||
|
||||
// QueryInterface implementation for SupportsRule
|
||||
|
||||
#ifdef DEBUG
|
||||
void CSSScopeRule::List(FILE* out, int32_t aIndent) const {
|
||||
nsAutoCString str;
|
||||
for (int32_t i = 0; i < aIndent; i++) {
|
||||
str.AppendLiteral(" ");
|
||||
}
|
||||
Servo_ScopeRule_Debug(mRawRule, &str);
|
||||
fprintf_stderr(out, "%s\n", str.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
StyleCssRuleType CSSScopeRule::Type() const { return StyleCssRuleType::Scope; }
|
||||
|
||||
already_AddRefed<StyleLockedCssRules> CSSScopeRule::GetOrCreateRawRules() {
|
||||
return Servo_ScopeRule_GetRules(mRawRule).Consume();
|
||||
}
|
||||
|
||||
void CSSScopeRule::SetRawAfterClone(RefPtr<StyleScopeRule> aRaw) {
|
||||
mRawRule = std::move(aRaw);
|
||||
css::GroupRule::DidSetRawAfterClone();
|
||||
}
|
||||
|
||||
void CSSScopeRule::GetCssText(nsACString& aCssText) const {
|
||||
Servo_ScopeRule_GetCssText(mRawRule.get(), &aCssText);
|
||||
}
|
||||
|
||||
void CSSScopeRule::GetStart(nsACString& aStart) const {
|
||||
Servo_ScopeRule_GetStart(mRawRule.get(), &aStart);
|
||||
}
|
||||
|
||||
void CSSScopeRule::GetEnd(nsACString& aEnd) const {
|
||||
Servo_ScopeRule_GetEnd(mRawRule.get(), &aEnd);
|
||||
}
|
||||
|
||||
size_t CSSScopeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
|
||||
return aMallocSizeOf(this);
|
||||
}
|
||||
|
||||
JSObject* CSSScopeRule::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
return CSSScopeRule_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -1,49 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 CSSScopeRule_h___
|
||||
#define CSSScopeRule_h___
|
||||
|
||||
#include "mozilla/css/GroupRule.h"
|
||||
#include "mozilla/ServoBindingTypes.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class CSSScopeRule final : public css::GroupRule {
|
||||
public:
|
||||
CSSScopeRule(RefPtr<StyleScopeRule> aRawRule, StyleSheet* aSheet,
|
||||
css::Rule* aParentRule, uint32_t aLine, uint32_t aColumn);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
#ifdef DEBUG
|
||||
void List(FILE* out = stdout, int32_t aIndent = 0) const final;
|
||||
#endif
|
||||
|
||||
StyleScopeRule* Raw() const { return mRawRule; }
|
||||
void SetRawAfterClone(RefPtr<StyleScopeRule>);
|
||||
|
||||
already_AddRefed<StyleLockedCssRules> GetOrCreateRawRules() final;
|
||||
|
||||
// WebIDL interface
|
||||
StyleCssRuleType Type() const final;
|
||||
void GetCssText(nsACString& aCssText) const final;
|
||||
|
||||
void GetStart(nsACString& aStart) const;
|
||||
void GetEnd(nsACString& aEnd) const;
|
||||
|
||||
size_t SizeOfIncludingThis(MallocSizeOf) const override;
|
||||
JSObject* WrapObject(JSContext*, JS::Handle<JSObject*>) override;
|
||||
|
||||
private:
|
||||
~CSSScopeRule() = default;
|
||||
|
||||
RefPtr<StyleScopeRule> mRawRule;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif
|
|
@ -100,13 +100,13 @@ void Rule::AssertParentRuleType() {
|
|||
// this->Type() here since it's virtual.
|
||||
if (mParentRule) {
|
||||
auto type = mParentRule->Type();
|
||||
MOZ_ASSERT(
|
||||
type == StyleCssRuleType::Media || type == StyleCssRuleType::Style ||
|
||||
type == StyleCssRuleType::Document ||
|
||||
type == StyleCssRuleType::Supports ||
|
||||
type == StyleCssRuleType::Keyframes ||
|
||||
type == StyleCssRuleType::LayerBlock ||
|
||||
type == StyleCssRuleType::Container || type == StyleCssRuleType::Scope);
|
||||
MOZ_ASSERT(type == StyleCssRuleType::Media ||
|
||||
type == StyleCssRuleType::Style ||
|
||||
type == StyleCssRuleType::Document ||
|
||||
type == StyleCssRuleType::Supports ||
|
||||
type == StyleCssRuleType::Keyframes ||
|
||||
type == StyleCssRuleType::LayerBlock ||
|
||||
type == StyleCssRuleType::Container);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -129,7 +129,6 @@ UNLOCKED_RULE_TYPE(Supports)
|
|||
UNLOCKED_RULE_TYPE(Document)
|
||||
UNLOCKED_RULE_TYPE(FontFeatureValues)
|
||||
UNLOCKED_RULE_TYPE(FontPaletteValues)
|
||||
UNLOCKED_RULE_TYPE(Scope)
|
||||
|
||||
SERVO_ARC_TYPE(AnimationValue, mozilla::StyleAnimationValue)
|
||||
SERVO_ARC_TYPE(ComputedStyle, mozilla::ComputedStyle)
|
||||
|
|
|
@ -87,7 +87,6 @@ BASIC_RULE_FUNCS_UNLOCKED(FontPaletteValues)
|
|||
BASIC_RULE_FUNCS_LOCKED(FontFace)
|
||||
BASIC_RULE_FUNCS_LOCKED(CounterStyle)
|
||||
GROUP_RULE_FUNCS_UNLOCKED(Container)
|
||||
GROUP_RULE_FUNCS_UNLOCKED(Scope)
|
||||
|
||||
#undef GROUP_RULE_FUNCS_LOCKED
|
||||
#undef GROUP_RULE_FUNCS_UNLOCKED
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "mozilla/dom/CSSPropertyRule.h"
|
||||
#include "mozilla/dom/CSSStyleRule.h"
|
||||
#include "mozilla/dom/CSSSupportsRule.h"
|
||||
#include "mozilla/dom/CSSScopeRule.h"
|
||||
#include "mozilla/IntegerRange.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
|
@ -99,7 +98,6 @@ css::Rule* ServoCSSRuleList::GetRule(uint32_t aIndex) {
|
|||
CASE_RULE_UNLOCKED(LayerBlock, LayerBlock)
|
||||
CASE_RULE_UNLOCKED(LayerStatement, LayerStatement)
|
||||
CASE_RULE_UNLOCKED(Container, Container)
|
||||
CASE_RULE_UNLOCKED(Scope, Scope)
|
||||
#undef CASE_RULE_LOCKED
|
||||
#undef CASE_RULE_UNLOCKED
|
||||
#undef CASE_RULE_WITH_PREFIX
|
||||
|
@ -278,7 +276,6 @@ void ServoCSSRuleList::SetRawContents(RefPtr<StyleLockedCssRules> aNewRules,
|
|||
RULE_CASE_UNLOCKED(LayerBlock, LayerBlock)
|
||||
RULE_CASE_UNLOCKED(LayerStatement, LayerStatement)
|
||||
RULE_CASE_UNLOCKED(Container, Container)
|
||||
RULE_CASE_UNLOCKED(Scope, Scope)
|
||||
case StyleCssRuleType::Keyframe:
|
||||
MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
|
||||
break;
|
||||
|
|
|
@ -53,7 +53,6 @@ template struct StyleStrong<StyleFontPaletteValuesRule>;
|
|||
template struct StyleStrong<StyleLockedFontFaceRule>;
|
||||
template struct StyleStrong<StyleLockedCounterStyleRule>;
|
||||
template struct StyleStrong<StyleContainerRule>;
|
||||
template struct StyleStrong<StyleScopeRule>;
|
||||
|
||||
template <typename T>
|
||||
inline void StyleOwnedSlice<T>::Clear() {
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "mozilla/dom/CSSNamespaceRule.h"
|
||||
#include "mozilla/dom/CSSPageRule.h"
|
||||
#include "mozilla/dom/CSSPropertyRule.h"
|
||||
#include "mozilla/dom/CSSScopeRule.h"
|
||||
#include "mozilla/dom/CSSSupportsRule.h"
|
||||
#include "mozilla/dom/FontFaceSet.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
@ -1003,7 +1002,6 @@ void ServoStyleSet::RuleChangedInternal(StyleSheet& aSheet, css::Rule& aRule,
|
|||
CASE_FOR(LayerBlock, LayerBlock)
|
||||
CASE_FOR(LayerStatement, LayerStatement)
|
||||
CASE_FOR(Container, Container)
|
||||
CASE_FOR(Scope, Scope)
|
||||
// @namespace can only be inserted / removed when there are only other
|
||||
// @namespace and @import rules, and can't be mutated.
|
||||
case StyleCssRuleType::Namespace:
|
||||
|
|
|
@ -143,7 +143,6 @@ EXPORTS.mozilla.dom += [
|
|||
"CSSPageRule.h",
|
||||
"CSSPropertyRule.h",
|
||||
"CSSRuleList.h",
|
||||
"CSSScopeRule.h",
|
||||
"CSSStyleRule.h",
|
||||
"CSSSupportsRule.h",
|
||||
"CSSValue.h",
|
||||
|
@ -195,7 +194,6 @@ UNIFIED_SOURCES += [
|
|||
"CSSPageRule.cpp",
|
||||
"CSSPropertyRule.cpp",
|
||||
"CSSRuleList.cpp",
|
||||
"CSSScopeRule.cpp",
|
||||
"CSSStyleRule.cpp",
|
||||
"CSSSupportsRule.cpp",
|
||||
"DeclarationBlock.cpp",
|
||||
|
|
|
@ -8740,13 +8740,6 @@
|
|||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Whether @scope rule is enabled
|
||||
- name: layout.css.at-scope.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
rust: true
|
||||
|
||||
# Dictates whether or not the prefers contrast media query will be
|
||||
# usable.
|
||||
# true: prefers-contrast will toggle based on OS and browser settings.
|
||||
|
|
|
@ -438,9 +438,6 @@ pub enum ParseRelative {
|
|||
/// Allow selectors to start with a combinator, prepending a parent selector if so. Do nothing
|
||||
/// otherwise
|
||||
ForNesting,
|
||||
/// Allow selectors to start with a combinator, prepending a scope selector if so. Do nothing
|
||||
/// otherwise
|
||||
ForScope,
|
||||
/// Treat as parse error if any selector begins with a combinator.
|
||||
No,
|
||||
}
|
||||
|
@ -472,23 +469,6 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn parse_forgiving<'i, 't, P>(
|
||||
parser: &P,
|
||||
input: &mut CssParser<'i, 't>,
|
||||
parse_relative: ParseRelative,
|
||||
) -> Result<Self, ParseError<'i, P::Error>>
|
||||
where
|
||||
P: Parser<'i, Impl = Impl>,
|
||||
{
|
||||
Self::parse_with_state(
|
||||
parser,
|
||||
input,
|
||||
SelectorParsingState::empty(),
|
||||
ForgivingParsing::Yes,
|
||||
parse_relative,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parse_with_state<'i, 't, P>(
|
||||
parser: &P,
|
||||
|
@ -2622,14 +2602,9 @@ where
|
|||
// combinator.
|
||||
builder.push_combinator(combinator.unwrap_or(Combinator::Descendant));
|
||||
},
|
||||
ParseRelative::ForNesting | ParseRelative::ForScope => {
|
||||
ParseRelative::ForNesting => {
|
||||
if let Ok(combinator) = combinator {
|
||||
let selector = match parse_relative {
|
||||
ParseRelative::ForHas | ParseRelative::No => unreachable!(),
|
||||
ParseRelative::ForNesting => Component::ParentSelector,
|
||||
ParseRelative::ForScope => Component::Scope,
|
||||
};
|
||||
builder.push_simple_selector(selector);
|
||||
builder.push_simple_selector(Component::ParentSelector);
|
||||
builder.push_combinator(combinator);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::stylesheets::keyframes_rule::Keyframe;
|
|||
use crate::stylesheets::{
|
||||
ContainerRule, CounterStyleRule, CssRules, DocumentRule, FontFaceRule, FontFeatureValuesRule,
|
||||
FontPaletteValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule,
|
||||
MediaRule, NamespaceRule, PageRule, PropertyRule, ScopeRule, StyleRule, StylesheetContents, SupportsRule,
|
||||
MediaRule, NamespaceRule, PageRule, PropertyRule, StyleRule, StylesheetContents, SupportsRule,
|
||||
};
|
||||
use servo_arc::Arc;
|
||||
|
||||
|
@ -169,8 +169,3 @@ impl_simple_arc_ffi!(
|
|||
Servo_AnimationValue_AddRef,
|
||||
Servo_AnimationValue_Release
|
||||
);
|
||||
impl_simple_arc_ffi!(
|
||||
ScopeRule,
|
||||
Servo_ScopeRule_AddRef,
|
||||
Servo_ScopeRule_Release
|
||||
);
|
||||
|
|
|
@ -646,11 +646,6 @@ impl StylesheetInvalidationSet {
|
|||
debug!(" > Found unsupported rule, marking the whole subtree invalid.");
|
||||
self.invalidate_fully();
|
||||
},
|
||||
Scope(..) => {
|
||||
// Addition/removal of @scope requires re-evaluation of scope proximity to properly
|
||||
// figure out the styling order.
|
||||
self.invalidate_fully();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ mod rules_iterator;
|
|||
mod style_rule;
|
||||
mod stylesheet;
|
||||
pub mod supports_rule;
|
||||
mod scope_rule;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
use crate::gecko_bindings::sugar::refptr::RefCounted;
|
||||
|
@ -71,7 +70,6 @@ pub use self::rules_iterator::{
|
|||
EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator,
|
||||
};
|
||||
pub use self::style_rule::StyleRule;
|
||||
pub use self::scope_rule::ScopeRule;
|
||||
pub use self::stylesheet::{AllowImportRules, SanitizationData, SanitizationKind};
|
||||
pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet};
|
||||
pub use self::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentStylesheets};
|
||||
|
@ -267,7 +265,6 @@ pub enum CssRule {
|
|||
Document(Arc<DocumentRule>),
|
||||
LayerBlock(Arc<LayerBlockRule>),
|
||||
LayerStatement(Arc<LayerStatementRule>),
|
||||
Scope(Arc<ScopeRule>),
|
||||
}
|
||||
|
||||
impl CssRule {
|
||||
|
@ -314,9 +311,6 @@ impl CssRule {
|
|||
},
|
||||
// TODO(emilio): Add memory reporting for these rules.
|
||||
CssRule::LayerBlock(_) | CssRule::LayerStatement(_) => 0,
|
||||
CssRule::Scope(ref rule) => {
|
||||
rule.unconditional_shallow_size_of(ops) + rule.size_of(guard, ops)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +349,6 @@ pub enum CssRuleType {
|
|||
FontPaletteValues = 19,
|
||||
// 20 is an arbitrary number to use for Property.
|
||||
Property = 20,
|
||||
Scope = 21,
|
||||
}
|
||||
|
||||
impl CssRuleType {
|
||||
|
@ -443,7 +436,6 @@ impl CssRule {
|
|||
CssRule::LayerBlock(_) => CssRuleType::LayerBlock,
|
||||
CssRule::LayerStatement(_) => CssRuleType::LayerStatement,
|
||||
CssRule::Container(_) => CssRuleType::Container,
|
||||
CssRule::Scope(_) => CssRuleType::Scope,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,9 +567,6 @@ impl DeepCloneWithLock for CssRule {
|
|||
CssRule::LayerBlock(ref arc) => {
|
||||
CssRule::LayerBlock(Arc::new(arc.deep_clone_with_lock(lock, guard, params)))
|
||||
},
|
||||
CssRule::Scope(ref arc) => {
|
||||
CssRule::Scope(Arc::new(arc.deep_clone_with_lock(lock, guard, params)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -603,7 +592,6 @@ impl ToCssWithGuard for CssRule {
|
|||
CssRule::LayerBlock(ref rule) => rule.to_css(guard, dest),
|
||||
CssRule::LayerStatement(ref rule) => rule.to_css(guard, dest),
|
||||
CssRule::Container(ref rule) => rule.to_css(guard, dest),
|
||||
CssRule::Scope(ref rule) => rule.to_css(guard, dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ use crate::stylesheets::import_rule::{ImportLayer, ImportRule, ImportSupportsCon
|
|||
use crate::stylesheets::keyframes_rule::parse_keyframe_list;
|
||||
use crate::stylesheets::layer_rule::{LayerBlockRule, LayerName, LayerStatementRule};
|
||||
use crate::stylesheets::supports_rule::SupportsCondition;
|
||||
use crate::stylesheets::scope_rule::{ScopeBounds, ScopeRule};
|
||||
use crate::stylesheets::{
|
||||
AllowImportRules, CorsMode, CssRule, CssRuleType, CssRuleTypes, CssRules, DocumentRule,
|
||||
FontFeatureValuesRule, FontPaletteValuesRule, KeyframesRule, MarginRule, MarginRuleType,
|
||||
|
@ -232,8 +231,6 @@ pub enum AtRulePrelude {
|
|||
Namespace(Option<Prefix>, Namespace),
|
||||
/// A @layer rule prelude.
|
||||
Layer(Vec<LayerName>),
|
||||
/// A @scope rule prelude.
|
||||
Scope(ScopeBounds),
|
||||
}
|
||||
|
||||
impl AtRulePrelude {
|
||||
|
@ -254,7 +251,6 @@ impl AtRulePrelude {
|
|||
Self::Margin(..) => "margin",
|
||||
Self::Namespace(..) => "namespace",
|
||||
Self::Layer(..) => "layer",
|
||||
Self::Scope(..) => "scope",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -511,8 +507,7 @@ impl<'a, 'i> NestedRuleParser<'a, 'i> {
|
|||
AtRulePrelude::Supports(..) |
|
||||
AtRulePrelude::Container(..) |
|
||||
AtRulePrelude::Document(..) |
|
||||
AtRulePrelude::Layer(..) |
|
||||
AtRulePrelude::Scope(..) => true,
|
||||
AtRulePrelude::Layer(..) => true,
|
||||
|
||||
AtRulePrelude::Namespace(..) |
|
||||
AtRulePrelude::FontFace |
|
||||
|
@ -706,10 +701,6 @@ impl<'a, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'i> {
|
|||
let cond = DocumentCondition::parse(&self.context, input)?;
|
||||
AtRulePrelude::Document(cond)
|
||||
},
|
||||
"scope" if static_prefs::pref!("layout.css.at-scope.enabled") => {
|
||||
let bounds = ScopeBounds::parse(&self.context, input, self.in_style_rule());
|
||||
AtRulePrelude::Scope(bounds)
|
||||
},
|
||||
_ => {
|
||||
if static_prefs::pref!("layout.css.margin-rules.enabled") {
|
||||
if let Some(margin_rule_type) = MarginRuleType::match_name(&name) {
|
||||
|
@ -876,16 +867,6 @@ impl<'a, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'i> {
|
|||
// These rules don't have blocks.
|
||||
return Err(input.new_unexpected_token_error(cssparser::Token::CurlyBracketBlock));
|
||||
},
|
||||
AtRulePrelude::Scope(bounds) => {
|
||||
let source_location = start.source_location();
|
||||
CssRule::Scope(Arc::new(ScopeRule {
|
||||
bounds,
|
||||
rules: self
|
||||
.parse_nested(input, CssRuleType::Scope)
|
||||
.into_rules(self.shared_lock, source_location),
|
||||
source_location,
|
||||
}))
|
||||
},
|
||||
};
|
||||
self.rules.push(rule);
|
||||
Ok(())
|
||||
|
|
|
@ -116,7 +116,6 @@ where
|
|||
Some(supports_rule.rules.read_with(guard).0.iter())
|
||||
},
|
||||
CssRule::LayerBlock(ref layer_rule) => Some(layer_rule.rules.read_with(guard).0.iter()),
|
||||
CssRule::Scope(ref rule) => Some(rule.rules.read_with(guard).0.iter())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! A [`@scope`][scope] rule.
|
||||
//!
|
||||
//! [scope]: https://drafts.csswg.org/css-cascade-6/#scoped-styles
|
||||
|
||||
use crate::parser::ParserContext;
|
||||
use crate::selector_parser::{SelectorImpl, SelectorParser};
|
||||
use crate::shared_lock::{
|
||||
DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard,
|
||||
};
|
||||
use crate::str::CssStringWriter;
|
||||
use crate::stylesheets::CssRules;
|
||||
use cssparser::{Parser, SourceLocation, ToCss};
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalSizeOf, MallocUnconditionalShallowSizeOf};
|
||||
use selectors::parser::{ParseRelative, SelectorList};
|
||||
use servo_arc::Arc;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::CssWriter;
|
||||
|
||||
/// A scoped rule.
|
||||
#[derive(Debug, ToShmem)]
|
||||
pub struct ScopeRule {
|
||||
/// Bounds at which this rule applies.
|
||||
pub bounds: ScopeBounds,
|
||||
/// The nested rules inside the block.
|
||||
pub rules: Arc<Locked<CssRules>>,
|
||||
/// The source position where this rule was found.
|
||||
pub source_location: SourceLocation,
|
||||
}
|
||||
|
||||
impl DeepCloneWithLock for ScopeRule {
|
||||
fn deep_clone_with_lock(
|
||||
&self,
|
||||
lock: &SharedRwLock,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
params: &DeepCloneParams,
|
||||
) -> Self {
|
||||
let rules = self.rules.read_with(guard);
|
||||
Self {
|
||||
bounds: self.bounds.clone(),
|
||||
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
|
||||
source_location: self.source_location.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCssWithGuard for ScopeRule {
|
||||
fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
|
||||
dest.write_str("@scope")?;
|
||||
{
|
||||
let mut writer = CssWriter::new(dest);
|
||||
if let Some(start) = self.bounds.start.as_ref() {
|
||||
writer.write_str(" (")?;
|
||||
start.to_css(&mut writer)?;
|
||||
writer.write_char(')')?;
|
||||
}
|
||||
if let Some(end) = self.bounds.end.as_ref() {
|
||||
writer.write_str(" to (")?;
|
||||
end.to_css(&mut writer)?;
|
||||
writer.write_char(')')?;
|
||||
}
|
||||
}
|
||||
self.rules.read_with(guard).to_css_block(guard, dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl ScopeRule {
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.rules.unconditional_shallow_size_of(ops) +
|
||||
self.rules.read_with(guard).size_of(guard, ops) +
|
||||
self.bounds.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
/// Bounds of the scope.
|
||||
#[derive(Debug, Clone, ToShmem)]
|
||||
pub struct ScopeBounds {
|
||||
/// Start of the scope.
|
||||
pub start: Option<SelectorList<SelectorImpl>>,
|
||||
/// End of the scope.
|
||||
pub end: Option<SelectorList<SelectorImpl>>,
|
||||
}
|
||||
|
||||
impl ScopeBounds {
|
||||
#[cfg(feature = "gecko")]
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
fn bound_size_of(bound: &Option<SelectorList<SelectorImpl>>, ops: &mut MallocSizeOfOps) -> usize {
|
||||
bound.as_ref().map(|list| list.unconditional_size_of(ops)).unwrap_or(0)
|
||||
}
|
||||
bound_size_of(&self.start, ops) + bound_size_of(&self.end, ops)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_scope<'a>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'a, '_>,
|
||||
in_style_rule: bool,
|
||||
for_end: bool
|
||||
) -> Option<SelectorList<SelectorImpl>> {
|
||||
input.try_parse(|input| {
|
||||
if for_end {
|
||||
input.expect_ident_matching("to")?;
|
||||
}
|
||||
input.expect_parenthesis_block()?;
|
||||
input.parse_nested_block(|input| {
|
||||
if input.is_exhausted() {
|
||||
return Ok(None);
|
||||
}
|
||||
let selector_parser = SelectorParser {
|
||||
stylesheet_origin: context.stylesheet_origin,
|
||||
namespaces: &context.namespaces,
|
||||
url_data: context.url_data,
|
||||
for_supports_rule: false,
|
||||
};
|
||||
let parse_relative = if for_end {
|
||||
ParseRelative::ForScope
|
||||
} else if in_style_rule {
|
||||
ParseRelative::ForNesting
|
||||
} else {
|
||||
ParseRelative::No
|
||||
};
|
||||
Ok(Some(SelectorList::parse_forgiving(
|
||||
&selector_parser,
|
||||
input,
|
||||
parse_relative,
|
||||
)?))
|
||||
})
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
}
|
||||
|
||||
impl ScopeBounds {
|
||||
/// Parse a container condition.
|
||||
pub fn parse<'a>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'a, '_>,
|
||||
in_style_rule: bool,
|
||||
) -> Self {
|
||||
let start = parse_scope(
|
||||
context,
|
||||
input,
|
||||
in_style_rule,
|
||||
false
|
||||
);
|
||||
|
||||
let end = parse_scope(
|
||||
context,
|
||||
input,
|
||||
in_style_rule,
|
||||
true
|
||||
);
|
||||
Self { start, end }
|
||||
}
|
||||
}
|
|
@ -333,10 +333,7 @@ impl SanitizationKind {
|
|||
// TODO(emilio): Perhaps Layer should not be always sanitized? But
|
||||
// we sanitize @media and co, so this seems safer for now.
|
||||
CssRule::LayerStatement(..) |
|
||||
CssRule::LayerBlock(..) |
|
||||
// TODO(dshin): Same comment as Layer applies - shouldn't give away
|
||||
// something like display size - erring on the side of "safe" for now.
|
||||
CssRule::Scope(..) => false,
|
||||
CssRule::LayerBlock(..) => false,
|
||||
|
||||
CssRule::FontFace(..) | CssRule::Namespace(..) | CssRule::Style(..) => true,
|
||||
|
||||
|
|
|
@ -3234,8 +3234,7 @@ impl CascadeData {
|
|||
CssRule::LayerBlock(..) |
|
||||
CssRule::LayerStatement(..) |
|
||||
CssRule::FontPaletteValues(..) |
|
||||
CssRule::FontFeatureValues(..) |
|
||||
CssRule::Scope(..) => {
|
||||
CssRule::FontFeatureValues(..) => {
|
||||
// Not affected by device changes.
|
||||
continue;
|
||||
},
|
||||
|
|
|
@ -139,7 +139,7 @@ use style::stylesheets::{
|
|||
FontPaletteValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule,
|
||||
MediaRule, NamespaceRule, Origin, OriginSet, PagePseudoClassFlags, PageRule, PropertyRule,
|
||||
SanitizationData, SanitizationKind, StyleRule, StylesheetContents,
|
||||
StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData, ScopeRule,
|
||||
StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData,
|
||||
};
|
||||
use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist};
|
||||
use style::thread_state;
|
||||
|
@ -2478,14 +2478,6 @@ impl_basic_rule_funcs! { (CounterStyle, CounterStyleRule, Locked<CounterStyleRul
|
|||
changed: Servo_StyleSet_CounterStyleRuleChanged,
|
||||
}
|
||||
|
||||
impl_group_rule_funcs! { (Scope, ScopeRule, ScopeRule),
|
||||
get_rules: Servo_ScopeRule_GetRules,
|
||||
getter: Servo_CssRules_GetScopeRuleAt,
|
||||
debug: Servo_ScopeRule_Debug,
|
||||
to_css: Servo_ScopeRule_GetCssText,
|
||||
changed: Servo_StyleSet_ScopeRuleChanged,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_StyleRule_GetStyle(
|
||||
rule: &LockedStyleRule,
|
||||
|
@ -8654,24 +8646,6 @@ pub extern "C" fn Servo_LayerBlockRule_GetName(rule: &LayerBlockRule, result: &m
|
|||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ScopeRule_GetStart(rule: &ScopeRule, result: &mut nsACString) {
|
||||
if let Some(v) = rule.bounds.start.as_ref() {
|
||||
v.to_css(&mut CssWriter::new(result)).unwrap();
|
||||
} else {
|
||||
result.set_is_void(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_ScopeRule_GetEnd(rule: &ScopeRule, result: &mut nsACString) {
|
||||
if let Some(v) = rule.bounds.end.as_ref() {
|
||||
v.to_css(&mut CssWriter::new(result)).unwrap();
|
||||
} else {
|
||||
result.set_is_void(true);
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Servo_LayerStatementRule_GetNameCount(rule: &LayerStatementRule) -> usize {
|
||||
rule.names.len()
|
||||
|
|
|
@ -244,7 +244,7 @@ class StartupCache : public nsIMemoryReporter {
|
|||
nsTArray<decltype(mTable)> mOldTables MOZ_GUARDED_BY(mTableLock);
|
||||
size_t mAllowedInvalidationsCount;
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
mozilla::loader::AutoMemMap mCacheData MOZ_GUARDED_BY(mTableLock);
|
||||
loader::AutoMemMap mCacheData MOZ_GUARDED_BY(mTableLock);
|
||||
Mutex mTableLock;
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
|
|
|
@ -1 +1 @@
|
|||
prefs: [layout.css.import-supports.enabled:true, layout.css.properties-and-values.enabled:true, layout.css.at-scope.enabled:true]
|
||||
prefs: [layout.css.import-supports.enabled:true, layout.css.properties-and-values.enabled:true]
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
[at-scope-parsing.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[@scope (.a) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a + .b) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a:hover) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a:hover, #b, div) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (:is(div, span)) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (.b) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a)to (.b) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (.b:hover, #c, div) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.c <> .d) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a, .c <> .d) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a <> .b, .c) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (div::before) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (div::after) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (slotted(div)) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (div::before) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (&) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (& > &) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (> .b) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (+ .b) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (.a) to (~ .b) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope to (.a) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope (> &) to (>>) is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope () is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope to () is valid]
|
||||
expected: FAIL
|
||||
|
||||
[@scope () to () is valid]
|
||||
expected: FAIL
|
|
@ -0,0 +1,35 @@
|
|||
[idlharness.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[CSSScopeRule interface: existence and properties of interface object]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface object length]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface object name]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: existence and properties of interface prototype object's "constructor" property]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: attribute start]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: attribute end]
|
||||
expected: FAIL
|
||||
|
||||
[Stringification of scope]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: scope must inherit property "start" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule interface: scope must inherit property "end" with the proper type]
|
||||
expected: FAIL
|
|
@ -0,0 +1,39 @@
|
|||
[scope-cssom.html]
|
||||
[CSSScopeRule.cssText, implicit scope]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.cssText, root only]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.cssText, root and limit]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.cssText, limit only]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.start, implicit scope]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.start, root only]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.start, root and limit]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.start, limit only]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.end, implicit scope]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.end, root only]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.end, root and limit]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule.end, limit only]
|
||||
expected: FAIL
|
||||
|
||||
[CSSScopeRule is a CSSGroupingRule]
|
||||
expected: FAIL
|
|
@ -0,0 +1,5 @@
|
|||
[scope-deep.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Deep @scope nesting]
|
||||
expected: FAIL
|
|
@ -17,6 +17,9 @@
|
|||
[Inner @scope with :scope in from-selector]
|
||||
expected: FAIL
|
||||
|
||||
[Multiple scopes from same @scope-rule, only one limited]
|
||||
expected: FAIL
|
||||
|
||||
[Nested scopes]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -40,15 +43,3 @@
|
|||
|
||||
[Scope root with :has()]
|
||||
expected: FAIL
|
||||
|
||||
[Scope can not match its own root without :scope]
|
||||
expected: FAIL
|
||||
|
||||
[Multiple scopes from same @scope-rule, both limited]
|
||||
expected: FAIL
|
||||
|
||||
[Nested scopes, reverse]
|
||||
expected: FAIL
|
||||
|
||||
[Scope with no elements]
|
||||
expected: FAIL
|
||||
|
|
|
@ -16,9 +16,3 @@
|
|||
|
||||
[Implicit @scope with limit]
|
||||
expected: FAIL
|
||||
|
||||
[@scope with effectively empty :is() must not match anything]
|
||||
expected: FAIL
|
||||
|
||||
[Implicit @scope has implicitly added :scope descendant combinator]
|
||||
expected: FAIL
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
[scope-name-defining-rules.html]
|
||||
[@keyframes is unaffected by @scope]
|
||||
expected: FAIL
|
||||
|
||||
[@keyframes is unaffected by non-matching @scope]
|
||||
expected: FAIL
|
||||
|
||||
[@property is unaffected by @scope]
|
||||
expected: FAIL
|
||||
|
||||
[@property is unaffected by non-matching @scope]
|
||||
expected: FAIL
|
|
@ -46,6 +46,3 @@
|
|||
|
||||
[Scoped nested group rule]
|
||||
expected: FAIL
|
||||
|
||||
[Nesting-selector in <scope-end>]
|
||||
expected: FAIL
|
||||
|
|
|
@ -6,3 +6,6 @@
|
|||
|
||||
[Proximity wins over order of appearance]
|
||||
expected: FAIL
|
||||
|
||||
[Specificity wins over proximity]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
[scope-shadow.tentative.html]
|
||||
[@scope can match :host]
|
||||
expected: FAIL
|
||||
|
||||
[@scope can match :host(...)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
[scope-visited-cssom.html]
|
||||
[:link as scoped selector]
|
||||
expected: FAIL
|
||||
|
||||
[:not(:visited) as scoped selector]
|
||||
expected: FAIL
|
||||
|
||||
[:link as scoping root]
|
||||
expected: FAIL
|
||||
|
||||
[:not(:visited) as scoping root]
|
||||
expected: FAIL
|
||||
|
||||
[:link as scoping root, :scope]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -10,9 +22,3 @@
|
|||
|
||||
[:not(:link) as scoping limit]
|
||||
expected: FAIL
|
||||
|
||||
[:visited as scoping root]
|
||||
expected: FAIL
|
||||
|
||||
[:not(:link) as scoping root]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
prefs: [layout.css.at-scope.enabled:true]
|
||||
[conditional-rules.html]
|
||||
expected: FAIL
|
|
@ -42,9 +42,9 @@
|
|||
test_valid('@scope to (.a)');
|
||||
test_valid('@scope (.a) to (&)');
|
||||
test_valid('@scope (.a) to (& > &)');
|
||||
test_valid('@scope (.a) to (> .b)', '@scope (.a) to (:scope > .b)');
|
||||
test_valid('@scope (.a) to (+ .b)', '@scope (.a) to (:scope + .b)');
|
||||
test_valid('@scope (.a) to (~ .b)', '@scope (.a) to (:scope ~ .b)');
|
||||
test_valid('@scope (.a) to (> .b)');
|
||||
test_valid('@scope (.a) to (+ .b)');
|
||||
test_valid('@scope (.a) to (~ .b)');
|
||||
test_valid('@scope ()', '@scope');
|
||||
test_valid('@scope to ()', '@scope');
|
||||
test_valid('@scope () to ()', '@scope');
|
||||
|
@ -75,5 +75,4 @@
|
|||
test_invalid('@scope (.a');
|
||||
test_invalid('@scope (.a to (.b)');
|
||||
test_invalid('@scope ( to (.b)');
|
||||
test_invalid('@scope (.a) from (.c)');
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче