Bug 1281158 - Improve interaction of ThinVec in the style system. r=dshin

This is the logical continuation of bug 1121792. This improves on the
existing support by totally removing all the manual nsTArray bindings,
which have always been a bit clumsy.

This is a prerequisite for bug 1281158 because I want to use ThinVec to
avoid a few extra heap allocations in the computed values of the Content
property.

Differential Revision: https://phabricator.services.mozilla.com/D209689
This commit is contained in:
Emilio Cobos Álvarez 2024-05-08 16:06:46 +00:00
parent 5668d88093
commit dc9b47aecf
21 changed files with 232 additions and 485 deletions

1
Cargo.lock generated
View file

@ -5542,6 +5542,7 @@ dependencies = [
"selectors",
"serde",
"servo_arc",
"thin-vec",
"to_shmem",
"to_shmem_derive",
]

View file

@ -988,34 +988,6 @@ const AnonymousCounterStyle* Gecko_CounterStyle_GetAnonymous(
return aPtr->AsAnonymous();
}
void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
size_t aElemSize) {
auto base =
reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
nsTArray_RelocateUsingMemutils>*>(aArray);
base->EnsureCapacity<nsTArrayInfallibleAllocator>(aCapacity, aElemSize);
}
void Gecko_ClearPODTArray(void* aArray, size_t aElementSize,
size_t aElementAlign) {
auto base =
reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
nsTArray_RelocateUsingMemutils>*>(aArray);
base->template ShiftData<nsTArrayInfallibleAllocator>(
0, base->Length(), 0, aElementSize, aElementAlign);
}
void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* aArray,
uint32_t aLength) {
aArray->SetLength(aLength);
}
void Gecko_ResizeAtomArray(nsTArray<RefPtr<nsAtom>>* aArray, uint32_t aLength) {
aArray->SetLength(aLength);
}
void Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
nsStyleImageLayers::LayerType aLayerType) {
size_t oldLength = aLayers->mLayers.Length();
@ -1135,16 +1107,6 @@ Keyframe* Gecko_GetOrCreateFinalKeyframe(
KeyframeInsertPosition::LastForOffset);
}
PropertyValuePair* Gecko_AppendPropertyValuePair(
nsTArray<PropertyValuePair>* aProperties,
const mozilla::AnimatedPropertyID* aProperty) {
MOZ_ASSERT(aProperties);
MOZ_ASSERT(
aProperty->IsCustom() ||
!nsCSSProps::PropHasFlags(aProperty->mID, CSSPropFlags::IsLogical));
return aProperties->AppendElement(PropertyValuePair{*aProperty});
}
void Gecko_GetComputedURLSpec(const StyleComputedUrl* aURL, nsCString* aOut) {
MOZ_ASSERT(aURL);
MOZ_ASSERT(aOut);

View file

@ -375,20 +375,6 @@ const mozilla::ServoElementSnapshot* Gecko_GetElementSnapshot(
// Have we seen this pointer before?
bool Gecko_HaveSeenPtr(mozilla::SeenPtrs* table, const void* ptr);
// `array` must be an nsTArray
// If changing this signature, please update the
// friend function declaration in nsTArray.h
void Gecko_EnsureTArrayCapacity(void* array, size_t capacity, size_t elem_size);
// Same here, `array` must be an nsTArray<T>, for some T.
//
// Important note: Only valid for POD types, since destructors won't be run
// otherwise. This is ensured with rust traits for the relevant structs.
void Gecko_ClearPODTArray(void* array, size_t elem_size, size_t elem_align);
void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* array, uint32_t length);
void Gecko_ResizeAtomArray(nsTArray<RefPtr<nsAtom>>* array, uint32_t length);
void Gecko_EnsureImageLayersLength(nsStyleImageLayers* layers, size_t len,
nsStyleImageLayers::LayerType layer_type);
@ -438,13 +424,6 @@ mozilla::Keyframe* Gecko_GetOrCreateFinalKeyframe(
const mozilla::StyleComputedTimingFunction* timingFunction,
const mozilla::dom::CompositeOperationOrAuto composition);
// Appends and returns a new PropertyValuePair to |aProperties| initialized with
// its mProperty member set to |aProperty| and all other members initialized to
// their default values.
mozilla::PropertyValuePair* Gecko_AppendPropertyValuePair(
nsTArray<mozilla::PropertyValuePair>*,
const mozilla::AnimatedPropertyID* aProperty);
void Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len);
void Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest);

View file

@ -54,6 +54,7 @@ hide-types = [
"mozilla::StyleTimingFunction.*",
# https://github.com/rust-lang/rust-bindgen/issues/1559
"mozilla::StyleGeneric.*",
"nsTArray_.*",
".*ErrorResult.*",
]
bitfield-enums = [
@ -290,7 +291,6 @@ allowlist-types = [
"nsStyleUI",
"nsStyleVisibility",
"nsStyleXUL",
"nsTArrayHeader",
"mozilla::UniquePtr",
"mozilla::DeclarationBlock",
"mozilla::DefaultDelete",
@ -632,6 +632,8 @@ mapped-generic-types = [
{ generic = false, gecko = "nsAString", servo = "nsstring::nsAString" },
{ generic = false, gecko = "nsCString", servo = "nsstring::nsCString" },
{ generic = false, gecko = "nsString", servo = "nsstring::nsString" },
{ generic = true, gecko = "nsTArray", servo = "thin_vec::ThinVec" },
{ generic = true, gecko = "CopyableTArray", servo = "thin_vec::ThinVec" },
]
allowlist-functions = ["Servo_.*", "Gecko_.*"]

View file

@ -2054,35 +2054,4 @@ struct UniquePtr_Simple {
STATIC_ASSERT_TYPE_LAYOUTS_MATCH(mozilla::UniquePtr<int>,
UniquePtr_Simple<int>);
/**
* <div rustbindgen replaces="nsTArray"></div>
*/
template <typename T>
class nsTArray_Simple {
protected:
T* mBuffer;
public:
~nsTArray_Simple() {
// The existence of a user-provided, and therefore non-trivial, destructor
// here prevents bindgen from deriving the Clone trait via a simple memory
// copy.
}
};
/**
* <div rustbindgen replaces="CopyableTArray"></div>
*/
template <typename T>
class CopyableTArray_Simple : public nsTArray_Simple<T> {};
STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<nsStyleImageLayers::Layer>,
nsTArray_Simple<nsStyleImageLayers::Layer>);
STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleTransition>,
nsTArray_Simple<mozilla::StyleTransition>);
STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleAnimation>,
nsTArray_Simple<mozilla::StyleAnimation>);
STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleViewTimeline>,
nsTArray_Simple<mozilla::StyleViewTimeline>);
#endif /* nsStyleStruct_h___ */

View file

@ -577,14 +577,14 @@ pub enum GeckoChildrenIterator<'a> {
/// replaces it with the next sibling when requested.
Current(Option<GeckoNode<'a>>),
/// A Gecko-implemented iterator we need to drop appropriately.
GeckoIterator(structs::StyleChildrenIterator),
GeckoIterator(std::mem::ManuallyDrop<structs::StyleChildrenIterator>),
}
impl<'a> Drop for GeckoChildrenIterator<'a> {
fn drop(&mut self) {
if let GeckoChildrenIterator::GeckoIterator(ref mut it) = *self {
unsafe {
bindings::Gecko_DestroyStyleChildrenIterator(it);
bindings::Gecko_DestroyStyleChildrenIterator(&mut **it);
}
}
}
@ -605,7 +605,7 @@ impl<'a> Iterator for GeckoChildrenIterator<'a> {
// however we can't express this easily with bindgen, and it would
// introduce functions with two input lifetimes into bindgen,
// which would be out of scope for elision.
bindings::Gecko_GetNextStyleChild(&mut *(it as *mut _))
bindings::Gecko_GetNextStyleChild(&mut **it)
.as_ref()
.map(GeckoNode)
},
@ -1015,9 +1015,9 @@ impl<'le> TElement for GeckoElement<'le> {
self.may_have_anonymous_children()
{
unsafe {
let mut iter: structs::StyleChildrenIterator = ::std::mem::zeroed();
bindings::Gecko_ConstructStyleChildrenIterator(self.0, &mut iter);
return LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter));
let mut iter = std::mem::MaybeUninit::<structs::StyleChildrenIterator>::uninit();
bindings::Gecko_ConstructStyleChildrenIterator(self.0, iter.as_mut_ptr());
return LayoutIterator(GeckoChildrenIterator::GeckoIterator(std::mem::ManuallyDrop::new(iter.assume_init())));
}
}

View file

@ -7,7 +7,6 @@
mod ns_com_ptr;
mod ns_compatibility;
mod ns_style_auto_array;
mod ns_t_array;
pub mod origin_flags;
pub mod ownership;
pub mod refptr;

View file

@ -1,144 +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/. */
//! Rust helpers for Gecko's nsTArray.
use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::{nsTArray, nsTArrayHeader, CopyableTArray};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::slice;
impl<T> Deref for nsTArray<T> {
type Target = [T];
#[inline]
fn deref<'a>(&'a self) -> &'a [T] {
unsafe { slice::from_raw_parts(self.slice_begin(), self.header().mLength as usize) }
}
}
impl<T> DerefMut for nsTArray<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
unsafe { slice::from_raw_parts_mut(self.slice_begin(), self.header().mLength as usize) }
}
}
impl<T> nsTArray<T> {
#[inline]
fn header<'a>(&'a self) -> &'a nsTArrayHeader {
debug_assert!(!self.mBuffer.is_null());
unsafe { mem::transmute(self.mBuffer) }
}
// unsafe, since header may be in shared static or something
unsafe fn header_mut<'a>(&'a mut self) -> &'a mut nsTArrayHeader {
debug_assert!(!self.mBuffer.is_null());
mem::transmute(self.mBuffer)
}
#[inline]
unsafe fn slice_begin(&self) -> *mut T {
debug_assert!(!self.mBuffer.is_null());
(self.mBuffer as *const nsTArrayHeader).offset(1) as *mut _
}
/// Ensures the array has enough capacity at least to hold `cap` elements.
///
/// NOTE: This doesn't call the constructor on the values!
pub fn ensure_capacity(&mut self, cap: usize) {
if cap >= self.len() {
unsafe {
bindings::Gecko_EnsureTArrayCapacity(
self as *mut nsTArray<T> as *mut _,
cap,
mem::size_of::<T>(),
)
}
}
}
/// Clears the array storage without calling the destructor on the values.
#[inline]
pub unsafe fn clear(&mut self) {
if self.len() != 0 {
bindings::Gecko_ClearPODTArray(
self as *mut nsTArray<T> as *mut _,
mem::size_of::<T>(),
mem::align_of::<T>(),
);
}
}
/// Clears a POD array. This is safe since copy types are memcopyable.
#[inline]
pub fn clear_pod(&mut self)
where
T: Copy,
{
unsafe { self.clear() }
}
/// Resize and set the length of the array to `len`.
///
/// unsafe because this may leave the array with uninitialized elements.
///
/// This will not call constructors. If you need that, either manually add
/// bindings or run the typed `EnsureCapacity` call on the gecko side.
pub unsafe fn set_len(&mut self, len: u32) {
// this can leak
debug_assert!(len >= self.len() as u32);
if self.len() == len as usize {
return;
}
self.ensure_capacity(len as usize);
self.header_mut().mLength = len;
}
/// Resizes an array containing only POD elements
///
/// unsafe because this may leave the array with uninitialized elements.
///
/// This will not leak since it only works on POD types (and thus doesn't assert)
pub unsafe fn set_len_pod(&mut self, len: u32)
where
T: Copy,
{
if self.len() == len as usize {
return;
}
self.ensure_capacity(len as usize);
let header = self.header_mut();
header.mLength = len;
}
/// Collects the given iterator into this array.
///
/// Not unsafe because we won't leave uninitialized elements in the array.
pub fn assign_from_iter_pod<I>(&mut self, iter: I)
where
T: Copy,
I: ExactSizeIterator + Iterator<Item = T>,
{
debug_assert!(iter.len() <= 0xFFFFFFFF);
unsafe {
self.set_len_pod(iter.len() as u32);
}
self.iter_mut().zip(iter).for_each(|(r, v)| *r = v);
}
}
impl<T> Deref for CopyableTArray<T> {
type Target = nsTArray<T>;
fn deref(&self) -> &Self::Target {
&self._base
}
}
impl<T> DerefMut for CopyableTArray<T> {
fn deref_mut(&mut self) -> &mut nsTArray<T> {
&mut self._base
}
}

View file

@ -69,6 +69,8 @@ extern crate static_assertions;
#[macro_use]
extern crate style_derive;
#[macro_use]
extern crate thin_vec;
#[macro_use]
extern crate to_shmem_derive;
#[macro_use]

View file

@ -580,26 +580,18 @@ impl Clone for ${style_struct.gecko_struct_name} {
</%def>
<%def name="impl_font_settings(ident, gecko_type, tag_type, value_type, gecko_value_type)">
<%
gecko_ffi_name = to_camel_case_lower(ident)
%>
<% gecko_ffi_name = to_camel_case_lower(ident) %>
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
let iter = v.0.iter().map(|other| structs::${gecko_type} {
mTag: other.tag.0,
mValue: other.value as ${gecko_value_type},
});
self.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter);
self.mFont.${gecko_ffi_name}.clear();
self.mFont.${gecko_ffi_name}.extend(iter);
}
pub fn copy_${ident}_from(&mut self, other: &Self) {
let iter = other.mFont.${gecko_ffi_name}.iter().map(|s| *s);
self.mFont.${gecko_ffi_name}.assign_from_iter_pod(iter);
}
pub fn reset_${ident}(&mut self, other: &Self) {
self.copy_${ident}_from(other)
}
<% impl_simple_copy(ident, "mFont." + gecko_ffi_name) %>
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
use crate::values::generics::font::{FontSettings, FontTag, ${tag_type}};

View file

@ -1104,14 +1104,12 @@ impl<'a> PropertyDeclarationId<'a> {
}
/// Convert a `PropertyDeclarationId` into an `AnimatedPropertyID`
/// Note that the rust AnimatedPropertyID doesn't implement Drop, so owned controls whether the
/// custom name should be addrefed or not.
///
/// FIXME(emilio, bug 1870107): This is a bit error-prone. We should consider using cbindgen to
/// generate the property id representation or so.
/// FIXME(emilio, bug 1870107): We should consider using cbindgen to generate the property id
/// representation or so.
#[cfg(feature = "gecko")]
#[inline]
pub fn to_gecko_animated_property_id(&self, owned: bool) -> AnimatedPropertyID {
pub fn to_gecko_animated_property_id(&self) -> AnimatedPropertyID {
match self {
Self::Longhand(id) => AnimatedPropertyID {
mID: id.to_nscsspropertyid(),
@ -1122,11 +1120,7 @@ impl<'a> PropertyDeclarationId<'a> {
mID: nsCSSPropertyID::eCSSPropertyExtra_variable,
mCustomName: RefPtr::null(),
};
property_id.mCustomName.mRawPtr = if owned {
(*name).clone().into_addrefed()
} else {
name.as_ptr()
};
property_id.mCustomName.mRawPtr = (*name).clone().into_addrefed();
property_id
},
}

View file

@ -10,7 +10,7 @@ use crate::error_reporting::ContextualParseError;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::bindings::Gecko_AppendFeatureValueHashEntry;
#[cfg(feature = "gecko")]
use crate::gecko_bindings::structs::{self, gfxFontFeatureValueSet, nsTArray};
use crate::gecko_bindings::structs::{self, gfxFontFeatureValueSet};
use crate::parser::{Parse, ParserContext};
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use crate::str::CssStringWriter;
@ -24,6 +24,7 @@ use cssparser::{
};
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
use thin_vec::ThinVec;
/// A @font-feature-values block declaration.
/// It is `<ident>: <integer>+`.
@ -54,8 +55,8 @@ impl<T: ToCss> ToCss for FFVDeclaration<T> {
/// A trait for @font-feature-values rule to gecko values conversion.
#[cfg(feature = "gecko")]
pub trait ToGeckoFontFeatureValues {
/// Sets the equivalent of declaration to gecko `nsTArray<u32>` array.
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>);
/// Sets the equivalent of declaration to gecko `ThinVec<u32>` array.
fn to_gecko_font_feature_values(&self) -> ThinVec<u32>;
}
/// A @font-feature-values block declaration value that keeps one value.
@ -79,11 +80,8 @@ impl Parse for SingleValue {
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for SingleValue {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
unsafe {
array.set_len_pod(1);
}
array[0] = self.0 as u32;
fn to_gecko_font_feature_values(&self) -> ThinVec<u32> {
thin_vec::thin_vec![self.0 as u32]
}
}
@ -118,16 +116,12 @@ impl Parse for PairValues {
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for PairValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
let len = if self.1.is_some() { 2 } else { 1 };
unsafe {
array.set_len_pod(len);
}
array[0] = self.0 as u32;
fn to_gecko_font_feature_values(&self) -> ThinVec<u32> {
let mut result = thin_vec::thin_vec![self.0 as u32];
if let Some(second) = self.1 {
array[1] = second as u32;
};
result.push(second as u32);
}
result
}
}
@ -165,8 +159,8 @@ impl Parse for VectorValues {
#[cfg(feature = "gecko")]
impl ToGeckoFontFeatureValues for VectorValues {
fn to_gecko_font_feature_values(&self, array: &mut nsTArray<u32>) {
array.assign_from_iter_pod(self.0.iter().map(|v| *v));
fn to_gecko_font_feature_values(&self) -> ThinVec<u32> {
self.0.iter().copied().collect()
}
}
@ -338,7 +332,7 @@ macro_rules! font_feature_values_blocks {
)
};
unsafe {
val.value.to_gecko_font_feature_values(&mut *array);
*array = val.value.to_gecko_font_feature_values();
}
}
}

View file

@ -273,6 +273,23 @@ where
}
}
impl<T> ToAnimatedValue for thin_vec::ThinVec<T>
where
T: ToAnimatedValue,
{
type AnimatedValue = thin_vec::ThinVec<<T as ToAnimatedValue>::AnimatedValue>;
#[inline]
fn to_animated_value(self) -> Self::AnimatedValue {
self.into_iter().map(T::to_animated_value).collect()
}
#[inline]
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
animated.into_iter().map(T::from_animated_value).collect()
}
}
impl<T> ToAnimatedValue for Box<T>
where
T: ToAnimatedValue,
@ -452,6 +469,16 @@ where
}
}
impl<T> ToAnimatedZero for thin_vec::ThinVec<T>
where
T: ToAnimatedZero,
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
self.iter().map(|v| v.to_animated_zero()).collect()
}
}
impl<T> ToAnimatedZero for Box<[T]>
where
T: ToAnimatedZero,

View file

@ -649,6 +649,25 @@ where
}
}
impl<T> ToComputedValue for thin_vec::ThinVec<T>
where
T: ToComputedValue,
{
type ComputedValue = thin_vec::ThinVec<<T as ToComputedValue>::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
self.iter()
.map(|item| item.to_computed_value(context))
.collect()
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
computed.iter().map(T::from_computed_value).collect()
}
}
// NOTE(emilio): This is implementable more generically, but it's unlikely
// what you want there, as it forces you to have an extra allocation.
//

View file

@ -180,6 +180,25 @@ where
}
}
impl<T> ToResolvedValue for thin_vec::ThinVec<T>
where
T: ToResolvedValue,
{
type ResolvedValue = thin_vec::ThinVec<<T as ToResolvedValue>::ResolvedValue>;
#[inline]
fn to_resolved_value(self, context: &Context) -> Self::ResolvedValue {
self.into_iter()
.map(|item| item.to_resolved_value(context))
.collect()
}
#[inline]
fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
resolved.into_iter().map(T::from_resolved_value).collect()
}
}
impl<T> ToResolvedValue for Box<T>
where
T: ToResolvedValue,

View file

@ -27,6 +27,7 @@ serde = "1.0"
servo_arc = { path = "../servo_arc" }
servo_atoms = { path = "../atoms", optional = true }
servo_url = { path = "../url", optional = true }
thin-vec = "0.2"
to_shmem = { path = "../to_shmem" }
to_shmem_derive = { path = "../to_shmem_derive" }
webrender_api = { git = "https://github.com/servo/webrender", optional = true }

View file

@ -29,6 +29,7 @@ extern crate servo_arc;
extern crate servo_atoms;
#[cfg(feature = "servo")]
extern crate servo_url;
extern crate thin_vec;
extern crate to_shmem;
#[macro_use]
extern crate to_shmem_derive;

View file

@ -9,6 +9,7 @@ use crate::owned_slice::OwnedSlice;
use servo_arc::Arc;
use std::ops::Range;
use std::sync::Arc as StdArc;
use thin_vec::ThinVec;
/// Type of value that a property supports. This is used by Gecko's
/// devtools to make sense about value it parses, and types listed
@ -119,6 +120,7 @@ macro_rules! impl_generic_specified_value_info {
impl_generic_specified_value_info!(Option<T>);
impl_generic_specified_value_info!(OwnedSlice<T>);
impl_generic_specified_value_info!(Vec<T>);
impl_generic_specified_value_info!(ThinVec<T>);
impl_generic_specified_value_info!(Arc<T>);
impl_generic_specified_value_info!(StdArc<T>);
impl_generic_specified_value_info!(ArcSlice<T>);

View file

@ -350,7 +350,7 @@ renaming_overrides_prefixing = true
"BeforeFlag" = "StyleEasingBeforeFlag"
"FontPaletteValueSet" = "gfx::FontPaletteValueSet"
"PaletteValues" = "gfx::FontPaletteValueSet::PaletteValues"
"ThinVec" = "nsTArray"
"ThinVec" = "CopyableTArray"
"RawPthread" = "pthread_t"
"RawHandle" = "void*"

View file

@ -6,7 +6,10 @@ use super::error_reporter::ErrorReporter;
use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};
use bincode::{deserialize, serialize};
use cssparser::ToCss as ParserToCss;
use cssparser::{BasicParseError, ParseError as CssParseError, Parser, ParserInput, ParserState, SourceLocation, UnicodeRange, Token};
use cssparser::{
BasicParseError, ParseError as CssParseError, Parser, ParserInput, ParserState, SourceLocation,
Token, UnicodeRange,
};
use dom::{DocumentState, ElementState};
use malloc_size_of::MallocSizeOfOps;
use nsstring::{nsCString, nsString};
@ -51,12 +54,8 @@ use style::gecko_bindings::bindings;
use style::gecko_bindings::bindings::nsACString;
use style::gecko_bindings::bindings::nsAString;
use style::gecko_bindings::bindings::Gecko_AddPropertyToSet;
use style::gecko_bindings::bindings::Gecko_AppendPropertyValuePair;
use style::gecko_bindings::bindings::Gecko_ConstructFontFeatureValueSet;
use style::gecko_bindings::bindings::Gecko_ConstructFontPaletteValueSet;
use style::gecko_bindings::bindings::Gecko_GetOrCreateFinalKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
use style::gecko_bindings::bindings::Gecko_HaveSeenPtr;
use style::gecko_bindings::structs;
use style::gecko_bindings::structs::gfx::FontPaletteValueSet;
@ -69,7 +68,6 @@ use style::gecko_bindings::structs::nsCSSPropertyID;
use style::gecko_bindings::structs::nsChangeHint;
use style::gecko_bindings::structs::nsCompatibility;
use style::gecko_bindings::structs::nsStyleTransformMatrix::MatrixTransformOperator;
use style::gecko_bindings::structs::nsTArray;
use style::gecko_bindings::structs::nsresult;
use style::gecko_bindings::structs::CallerType;
use style::gecko_bindings::structs::CompositeOperation;
@ -138,9 +136,8 @@ use style::stylesheets::{
CssRules, CssRulesHelpers, DocumentRule, FontFaceRule, FontFeatureValuesRule,
FontPaletteValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule,
MarginRule, MediaRule, NamespaceRule, Origin, OriginSet, PagePseudoClassFlags, PageRule,
PropertyRule, SanitizationData, SanitizationKind, StartingStyleRule, StyleRule,
PropertyRule, SanitizationData, SanitizationKind, ScopeRule, StartingStyleRule, StyleRule,
StylesheetContents, StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData,
ScopeRule,
};
use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist};
use style::thread_state;
@ -163,7 +160,7 @@ use style::values::specified::source_size_list::SourceSizeList;
use style::values::specified::{AbsoluteLength, NoCalcLength};
use style::values::{specified, AtomIdent, CustomIdent, KeyframesName};
use style_traits::{CssWriter, ParseError, ParsingMode, ToCss};
use thin_vec::ThinVec;
use thin_vec::ThinVec as nsTArray;
use to_shmem::SharedMemoryBuilder;
trait ClosureHelper {
@ -1264,9 +1261,9 @@ pub extern "C" fn Servo_ComputedValues_ShouldTransition(
let Some(old_value) = AnimationValue::from_computed_values(prop, old) else {
return Default::default();
};
if old_value == new_value
|| (matches!(behavior, computed::TransitionBehavior::Normal)
&& !old_value.interpolable_with(&new_value))
if old_value == new_value ||
(matches!(behavior, computed::TransitionBehavior::Normal) &&
!old_value.interpolable_with(&new_value))
{
return Default::default();
}
@ -1415,7 +1412,6 @@ pub unsafe extern "C" fn Servo_Property_SupportsType(
prop_id.supports_type(ty)
}
// TODO(emilio): We could use ThinVec instead of nsTArray.
#[no_mangle]
pub unsafe extern "C" fn Servo_Property_GetCSSValuesForProperty(
prop_name: &nsACString,
@ -1427,18 +1423,14 @@ pub unsafe extern "C" fn Servo_Property_GetCSSValuesForProperty(
let mut values = BTreeSet::<&'static str>::new();
prop_id.collect_property_completion_keywords(&mut |list| values.extend(list.iter()));
let mut extras = vec![];
if values.contains("transparent") {
// This is a special value devtools use to avoid inserting the
// long list of color keywords. We need to prepend it to values.
extras.push("COLOR");
result.push("COLOR".into());
}
let len = extras.len() + values.len();
bindings::Gecko_ResizeTArrayForStrings(result, len as u32);
for (src, dest) in extras.iter().chain(values.iter()).zip(result.iter_mut()) {
dest.write_str(src).unwrap();
for value in values {
result.push(value.into());
}
}
@ -1692,7 +1684,7 @@ pub unsafe extern "C" fn Servo_ShutdownThreadPool() {
#[no_mangle]
pub unsafe extern "C" fn Servo_ThreadPool_GetThreadHandles(
handles: &mut ThinVec<PlatformThreadHandle>,
handles: &mut nsTArray<PlatformThreadHandle>,
) {
StyleThreadPool::get_thread_handles(handles);
}
@ -2157,7 +2149,7 @@ where
#[no_mangle]
pub extern "C" fn Servo_CssRules_ListTypes(rules: &LockedCssRules, result: &mut nsTArray<usize>) {
read_locked_arc(rules, |rules: &CssRules| {
result.assign_from_iter_pod(rules.0.iter().map(|rule| rule.rule_type() as usize));
result.extend(rules.0.iter().map(|rule| rule.rule_type() as usize));
})
}
@ -2537,7 +2529,7 @@ pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: &LockedStyleRule, result
read_locked_arc(rule, |rule| rule.selectors.to_css(result).unwrap());
}
fn desugared_selector_list(rules: &ThinVec<&LockedStyleRule>) -> SelectorList {
fn desugared_selector_list(rules: &nsTArray<&LockedStyleRule>) -> SelectorList {
let mut selectors: Option<SelectorList> = None;
for rule in rules.iter().rev() {
selectors = Some(read_locked_arc(rule, |rule| match selectors {
@ -2549,13 +2541,15 @@ fn desugared_selector_list(rules: &ThinVec<&LockedStyleRule>) -> SelectorList {
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetSelectorList(rules: &ThinVec<&LockedStyleRule>) -> *mut SelectorList {
pub extern "C" fn Servo_StyleRule_GetSelectorList(
rules: &nsTArray<&LockedStyleRule>,
) -> *mut SelectorList {
Box::into_raw(Box::new(desugared_selector_list(rules)))
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetSelectorDataAtIndex(
rules: &ThinVec<&LockedStyleRule>,
rules: &nsTArray<&LockedStyleRule>,
index: u32,
text: Option<&mut nsACString>,
specificity: Option<&mut u64>,
@ -2579,7 +2573,7 @@ pub extern "C" fn Servo_StyleRule_GetSelectorCount(rule: &LockedStyleRule) -> u3
#[no_mangle]
pub extern "C" fn Servo_StyleRule_SelectorMatchesElement(
rules: &ThinVec<&LockedStyleRule>,
rules: &nsTArray<&LockedStyleRule>,
element: &RawGeckoElement,
index: u32,
host: Option<&RawGeckoElement>,
@ -3408,69 +3402,47 @@ pub unsafe extern "C" fn Servo_FontFaceRule_GetUnicodeRanges(
#[no_mangle]
pub unsafe extern "C" fn Servo_FontFaceRule_GetSources(
rule: &LockedFontFaceRule,
out: *mut nsTArray<FontFaceSourceListComponent>,
out: &mut nsTArray<FontFaceSourceListComponent>,
) {
let out = &mut *out;
read_locked_arc_worker(rule, |rule: &FontFaceRule| {
let sources = match rule.sources {
Some(ref s) => s,
None => return,
};
let len = sources.0.iter().fold(0, |acc, src| {
acc + match *src {
for source in sources.0.iter() {
match *source {
Source::Url(ref url) => {
(if url.format_hint.is_some() { 2 } else { 1 }) +
(if url.tech_flags.is_empty() { 0 } else { 1 })
out.push(FontFaceSourceListComponent::Url(&url.url));
if let Some(hint) = &url.format_hint {
match hint {
FontFaceSourceFormat::Keyword(kw) => {
out.push(FontFaceSourceListComponent::FormatHintKeyword(*kw))
},
FontFaceSourceFormat::String(s) => {
out.push(FontFaceSourceListComponent::FormatHintString {
length: s.len(),
utf8_bytes: s.as_ptr(),
})
},
}
}
if !url.tech_flags.is_empty() {
out.push(FontFaceSourceListComponent::TechFlags(url.tech_flags));
}
},
Source::Local(ref name) => {
out.push(FontFaceSourceListComponent::Local(name.name.as_ptr()));
},
Source::Local(_) => 1,
}
});
out.set_len(len as u32);
let mut iter = out.iter_mut();
{
let mut set_next = |component: FontFaceSourceListComponent| {
*iter.next().expect("miscalculated length") = component;
};
for source in sources.0.iter() {
match *source {
Source::Url(ref url) => {
set_next(FontFaceSourceListComponent::Url(&url.url));
if let Some(hint) = &url.format_hint {
match hint {
FontFaceSourceFormat::Keyword(kw) => {
set_next(FontFaceSourceListComponent::FormatHintKeyword(*kw))
},
FontFaceSourceFormat::String(s) => {
set_next(FontFaceSourceListComponent::FormatHintString {
length: s.len(),
utf8_bytes: s.as_ptr(),
})
},
}
}
if !url.tech_flags.is_empty() {
set_next(FontFaceSourceListComponent::TechFlags(url.tech_flags));
}
},
Source::Local(ref name) => {
set_next(FontFaceSourceListComponent::Local(name.name.as_ptr()));
},
}
}
}
assert!(iter.next().is_none(), "miscalculated");
})
}
#[no_mangle]
pub unsafe extern "C" fn Servo_FontFaceRule_GetVariationSettings(
rule: &LockedFontFaceRule,
variations: *mut nsTArray<structs::gfxFontVariation>,
variations: &mut nsTArray<structs::gfxFontVariation>,
) {
read_locked_arc_worker(rule, |rule: &FontFaceRule| {
let source_variations = match rule.variation_settings {
@ -3478,20 +3450,22 @@ pub unsafe extern "C" fn Servo_FontFaceRule_GetVariationSettings(
None => return,
};
(*variations).set_len(source_variations.0.len() as u32);
for (target, source) in (*variations).iter_mut().zip(source_variations.0.iter()) {
*target = structs::gfxFontVariation {
mTag: source.tag.0,
mValue: source.value.get(),
};
}
variations.extend(
source_variations
.0
.iter()
.map(|source| structs::gfxFontVariation {
mTag: source.tag.0,
mValue: source.value.get(),
}),
);
});
}
#[no_mangle]
pub unsafe extern "C" fn Servo_FontFaceRule_GetFeatureSettings(
rule: &LockedFontFaceRule,
features: *mut nsTArray<structs::gfxFontFeature>,
features: &mut nsTArray<structs::gfxFontFeature>,
) {
read_locked_arc_worker(rule, |rule: &FontFaceRule| {
let source_features = match rule.feature_settings {
@ -3499,13 +3473,15 @@ pub unsafe extern "C" fn Servo_FontFaceRule_GetFeatureSettings(
None => return,
};
(*features).set_len(source_features.0.len() as u32);
for (target, source) in (*features).iter_mut().zip(source_features.0.iter()) {
*target = structs::gfxFontFeature {
mTag: source.tag.0,
mValue: source.value.value() as u32,
};
}
features.extend(
source_features
.0
.iter()
.map(|source| structs::gfxFontFeature {
mTag: source.tag.0,
mValue: source.value.value() as u32,
}),
);
});
}
@ -4368,7 +4344,7 @@ pub extern "C" fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_GetStyleRuleList(
values: &ComputedValues,
rules: &mut ThinVec<*const LockedStyleRule>,
rules: &mut nsTArray<*const LockedStyleRule>,
) {
let rule_node = match values.rules {
Some(ref r) => r,
@ -6338,22 +6314,14 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
}
seen.insert(property);
// This is safe since we immediately write to the uninitialized values.
unsafe {
animation_values.set_len((property_index + 1) as u32);
ptr::write(
&mut animation_values[property_index],
structs::PropertyStyleAnimationValuePair {
mProperty: property
.to_gecko_animated_property_id(/* owned = */ true),
mValue: structs::AnimationValue {
mServo: value.map_or(structs::RefPtr::null(), |v| {
structs::RefPtr::from_arc(Arc::new(v))
}),
},
},
);
}
animation_values.push(structs::PropertyStyleAnimationValuePair {
mProperty: property.to_gecko_animated_property_id(),
mValue: structs::AnimationValue {
mServo: value.map_or(structs::RefPtr::null(), |v| {
structs::RefPtr::from_arc(Arc::new(v))
}),
},
});
property_index += 1;
};
@ -6383,7 +6351,7 @@ pub extern "C" fn Servo_GetAnimationValues(
element: &RawGeckoElement,
style: &ComputedValues,
raw_data: &PerDocumentStyleData,
animation_values: &mut ThinVec<structs::RefPtr<AnimationValue>>,
animation_values: &mut nsTArray<structs::RefPtr<AnimationValue>>,
) {
let data = raw_data.borrow();
let element = GeckoElement(element);
@ -6420,7 +6388,7 @@ pub extern "C" fn Servo_AnimationValue_GetPropertyId(
value: &AnimationValue,
property_id: &mut structs::AnimatedPropertyID,
) {
*property_id = value.id().to_gecko_animated_property_id(/* owned = */ true);
*property_id = value.id().to_gecko_animated_property_id();
}
#[no_mangle]
@ -6507,6 +6475,15 @@ enum Offset {
One,
}
fn property_value_pair_for(id: &PropertyDeclarationId) -> structs::PropertyValuePair {
structs::PropertyValuePair {
mProperty: id.to_gecko_animated_property_id(),
mServoDeclarationBlock: structs::RefPtr::null(),
#[cfg(feature = "gecko_debug")]
mSimulateComputeValuesFailure: false,
}
}
fn fill_in_missing_keyframe_values(
all_properties: &PropertyDeclarationIdSet,
timing_function: &ComputedTimingFunction,
@ -6527,22 +6504,25 @@ fn fill_in_missing_keyframe_values(
let composition = structs::CompositeOperationOrAuto::Auto;
let keyframe = match offset {
Offset::Zero => unsafe {
Gecko_GetOrCreateInitialKeyframe(keyframes, timing_function, composition)
&mut *bindings::Gecko_GetOrCreateInitialKeyframe(
keyframes,
timing_function,
composition,
)
},
Offset::One => unsafe {
Gecko_GetOrCreateFinalKeyframe(keyframes, timing_function, composition)
&mut *bindings::Gecko_GetOrCreateFinalKeyframe(
keyframes,
timing_function,
composition,
)
},
};
// Append properties that have not been set at this offset.
for property in all_properties.iter() {
if !properties_at_offset.contains(property) {
unsafe {
Gecko_AppendPropertyValuePair(
&mut *(*keyframe).mPropertyValues,
&property.to_gecko_animated_property_id(/* owned = */ false),
);
}
keyframe.mPropertyValues.push(property_value_pair_for(&property));
}
}
}
@ -6608,7 +6588,7 @@ pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
// Look for an existing keyframe with the same offset, timing function, and compsition, or
// else add a new keyframe at the beginning of the keyframe array.
let keyframe = Gecko_GetOrCreateKeyframeAtStart(
let keyframe = &mut *bindings::Gecko_GetOrCreateKeyframeAtStart(
keyframes,
step.start_percentage.0 as f32,
&timing_function,
@ -6629,11 +6609,7 @@ pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
continue;
}
seen.insert(property);
Gecko_AppendPropertyValuePair(
&mut *(*keyframe).mPropertyValues,
&property.to_gecko_animated_property_id(/* owned = */ false),
);
keyframe.mPropertyValues.push(property_value_pair_for(&property));
}
if current_offset == 0.0 {
has_complete_initial_keyframe = true;
@ -6665,12 +6641,8 @@ pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
continue;
}
let pair = Gecko_AppendPropertyValuePair(
&mut *(*keyframe).mPropertyValues,
&id.to_gecko_animated_property_id(/* owned = */ false),
);
(*pair).mServoDeclarationBlock.set_arc(Arc::new(
let mut pair = property_value_pair_for(&id);
pair.mServoDeclarationBlock.set_arc(Arc::new(
global_style_data
.shared_lock
.wrap(PropertyDeclarationBlock::with_one(
@ -6678,6 +6650,7 @@ pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
Importance::Normal,
)),
));
keyframe.mPropertyValues.push(pair);
if current_offset == 0.0 {
properties_set_at_start.insert(id);
@ -6720,7 +6693,7 @@ pub unsafe extern "C" fn Servo_StyleSet_GetKeyframesForName(
#[no_mangle]
pub extern "C" fn Servo_StyleSet_GetFontFaceRules(
raw_data: &PerDocumentStyleData,
rules: &mut ThinVec<structs::nsFontFaceRuleContainer>,
rules: &mut nsTArray<structs::nsFontFaceRuleContainer>,
) {
let data = raw_data.borrow();
debug_assert_eq!(rules.len(), 0);
@ -7594,7 +7567,6 @@ pub extern "C" fn Servo_StyleSet_HasNthOfCustomStateDependency(
})
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_HasNthOfStateDependency(
raw_data: &PerDocumentStyleData,
@ -8156,7 +8128,7 @@ pub unsafe extern "C" fn Servo_ColorTo(
.unwrap();
result_color.assign(&s);
result_components.assign_from_iter_pod(color.raw_components().iter().copied());
result_components.extend(color.raw_components().iter().copied());
// For now we don't do gamut mapping, so always false.
*result_adjusted = false;
@ -9100,7 +9072,7 @@ impl PropDef {
#[no_mangle]
pub extern "C" fn Servo_GetRegisteredCustomProperties(
per_doc_data: &PerDocumentStyleData,
custom_properties: &mut ThinVec<PropDef>,
custom_properties: &mut nsTArray<PropDef>,
) {
let stylist = &per_doc_data.borrow().stylist;
@ -9140,7 +9112,7 @@ pub struct SelectorWarningData {
#[no_mangle]
pub extern "C" fn Servo_GetSelectorWarnings(
rule: &LockedStyleRule,
warnings: &mut ThinVec<SelectorWarningData>,
warnings: &mut nsTArray<SelectorWarningData>,
) {
read_locked_arc(rule, |r| {
for (i, selector) in r.selectors.slice().iter().enumerate() {
@ -9152,10 +9124,7 @@ pub extern "C" fn Servo_GetSelectorWarnings(
}
#[no_mangle]
pub extern "C" fn Servo_GetRuleBodyText(
initial_text: &nsACString,
ret_val: &mut nsACString,
) {
pub extern "C" fn Servo_GetRuleBodyText(initial_text: &nsACString, ret_val: &mut nsACString) {
let css_text = unsafe { initial_text.as_str_unchecked() };
let mut input = ParserInput::new(&css_text);
let mut input = Parser::new(&mut input);
@ -9169,7 +9138,7 @@ pub extern "C" fn Servo_GetRuleBodyText(
found_start = true;
break;
},
_ => {}
_ => {},
}
if token.is_parse_error() {
@ -9177,7 +9146,6 @@ pub extern "C" fn Servo_GetRuleBodyText(
}
}
if !found_start {
ret_val.set_is_void(true);
return;
@ -9185,11 +9153,8 @@ pub extern "C" fn Servo_GetRuleBodyText(
let token_start = input.position();
// Parse the nested block to move the parser to the end of the block
let _ = input.parse_nested_block(
|_i| -> Result<(), CssParseError<'_, BasicParseError>> {
Ok(())
}
);
let _ =
input.parse_nested_block(|_i| -> Result<(), CssParseError<'_, BasicParseError>> { Ok(()) });
// We're not guaranteed to have a closing bracket, but when we do, we need to move
// the end offset before it.
@ -9239,11 +9204,8 @@ pub extern "C" fn Servo_ReplaceBlockRuleBodyTextInStylesheetText(
let token_start = input.position();
let rule_body_start = rule_start_index + token_start.byte_index();
// Parse the nested block to move the parser to the end of the block
let _ = input.parse_nested_block(
|_i| -> Result<(), CssParseError<'_, BasicParseError>> {
Ok(())
}
);
let _ =
input.parse_nested_block(|_i| -> Result<(), CssParseError<'_, BasicParseError>> { Ok(()) });
let mut rule_body_end = rule_start_index + input.position().byte_index();
// We're not guaranteed to have a closing bracket, but when we do, we need to move
@ -9259,11 +9221,7 @@ pub extern "C" fn Servo_ReplaceBlockRuleBodyTextInStylesheetText(
}
/// Find css_text byte position corresponding to the passed line and column
fn get_byte_index_from_line_and_column(
css_text: &str,
line: u32,
column: u32,
) -> Option<usize> {
fn get_byte_index_from_line_and_column(css_text: &str, line: u32, column: u32) -> Option<usize> {
// Find the byte index of the start of the passed line within css_text
let mut line_byte_index = Some(0);
if line != 1 {
@ -9325,9 +9283,7 @@ pub struct CSSToken {
}
#[no_mangle]
pub unsafe extern "C" fn Servo_CSSParser_create(
text: &nsACString,
) -> *mut ParserState {
pub unsafe extern "C" fn Servo_CSSParser_create(text: &nsACString) -> *mut ParserState {
let css_text = unsafe { text.as_str_unchecked() };
let mut parser_input = ParserInput::new(&css_text);
let input = Parser::new(&mut parser_input);
@ -9335,23 +9291,17 @@ pub unsafe extern "C" fn Servo_CSSParser_create(
}
#[no_mangle]
pub unsafe extern "C" fn Servo_CSSParser_destroy(
state: *mut ParserState,
) {
pub unsafe extern "C" fn Servo_CSSParser_destroy(state: *mut ParserState) {
drop(Box::from_raw(state));
}
#[no_mangle]
pub unsafe extern "C" fn Servo_CSSParser_GetCurrentLine(
state: &ParserState,
) -> u32 {
pub unsafe extern "C" fn Servo_CSSParser_GetCurrentLine(state: &ParserState) -> u32 {
return state.source_location().line;
}
#[no_mangle]
pub unsafe extern "C" fn Servo_CSSParser_GetCurrentColumn(
state: &ParserState,
) -> u32 {
pub unsafe extern "C" fn Servo_CSSParser_GetCurrentColumn(state: &ParserState) -> u32 {
return state.source_location().column;
}
@ -9380,9 +9330,9 @@ pub unsafe extern "C" fn Servo_CSSParser_NextToken(
Token::QuotedString(_) => "QuotedString",
Token::UnquotedUrl(_) => "UnquotedUrl",
Token::Delim(_) => "Delim",
Token::Number{..} => "Number",
Token::Percentage{..} => "Percentage",
Token::Dimension{..} => "Dimension",
Token::Number { .. } => "Number",
Token::Percentage { .. } => "Percentage",
Token::Dimension { .. } => "Dimension",
Token::WhiteSpace(_) => "WhiteSpace",
Token::Comment(_) => "Comment",
Token::Colon => "Colon",
@ -9454,27 +9404,19 @@ pub unsafe extern "C" fn Servo_CSSParser_NextToken(
};
let token_unit = match *token {
Token::Dimension{
ref unit, ..
} => {
Token::Dimension { ref unit, .. } => {
let mut unit_text = nsCString::new();
unit_text.assign(unit.as_bytes());
Some(unit_text)
},
_ => None
_ => None,
};
let token_number = match *token {
Token::Dimension {
ref value, ..
} => Some(value),
Token::Number{
ref value, ..
} => Some(value),
Token::Percentage{
ref unit_value, ..
} => Some(unit_value),
_ => None
Token::Dimension { ref value, .. } => Some(value),
Token::Number { ref value, .. } => Some(value),
Token::Percentage { ref unit_value, .. } => Some(unit_value),
_ => None,
};
css_token.has_number = token_number.is_some();
if css_token.has_number {
@ -9507,12 +9449,10 @@ pub unsafe extern "C" fn Servo_CSSParser_NextToken(
css_token.column = location_start.column;
if need_to_parse_nested_block {
let _ = input.parse_nested_block(
|i| -> Result<(), CssParseError<'_, BasicParseError>> {
*state = i.state();
Ok(())
},
);
let _ = input.parse_nested_block(|i| -> Result<(), CssParseError<'_, BasicParseError>> {
*state = i.state();
Ok(())
});
} else {
*state = input.state();
}

View file

@ -369,13 +369,6 @@ struct nsTArray_SafeElementAtHelper<mozilla::OwningNonNull<E>, Derived>
: public nsTArray_SafeElementAtSmartPtrHelper<mozilla::OwningNonNull<E>,
Derived> {};
// Servo bindings.
extern "C" void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
size_t aElementSize);
extern "C" void Gecko_ClearPODTArray(void* aArray, size_t aElementSize,
size_t aElementAlign);
//
// This class serves as a base class for nsTArray. It shouldn't be used
// directly. It holds common implementation code that does not depend on the
// element type of the nsTArray.
@ -393,11 +386,6 @@ class nsTArray_base {
template <class E, class XAlloc>
friend class nsTArray_Impl;
friend void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity,
size_t aElemSize);
friend void Gecko_ClearPODTArray(void* aTArray, size_t aElementSize,
size_t aElementAlign);
protected:
typedef nsTArrayHeader Header;