From a90a5cba08fdf6c0ceb95101c275108a152a3aed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:37 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- servo/ports/geckolib/Cargo.toml | 2 +- servo/ports/geckolib/cbindgen.toml | 2 +- servo/ports/geckolib/glue.rs | 490 +++++++++++++++++++++++++------------ 3 files changed, 338 insertions(+), 156 deletions(-) (limited to 'servo/ports/geckolib') diff --git a/servo/ports/geckolib/Cargo.toml b/servo/ports/geckolib/Cargo.toml index 1bdaaa80b7..37a44c2e61 100644 --- a/servo/ports/geckolib/Cargo.toml +++ b/servo/ports/geckolib/Cargo.toml @@ -15,7 +15,7 @@ gecko_refcount_logging = ["style/gecko_refcount_logging", "servo_arc/gecko_refco [dependencies] atomic_refcell = "0.1" bincode = "1.0" -cssparser = "0.33" +cssparser = "0.34" cstr = "0.2" dom = { path = "../../../dom/base/rust" } gecko-profiler = { path = "../../../tools/profiler/rust-api" } diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml index 3edab4dfbb..d608840cae 100644 --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml @@ -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*" diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs index 14614704b7..6efa274b46 100644 --- a/servo/ports/geckolib/glue.rs +++ b/servo/ports/geckolib/glue.rs @@ -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, 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; @@ -137,9 +135,9 @@ use style::stylesheets::{ AllowImportRules, ContainerRule, CounterStyleRule, CssRule, CssRuleType, CssRuleTypes, CssRules, CssRulesHelpers, DocumentRule, FontFaceRule, FontFeatureValuesRule, FontPaletteValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule, - MediaRule, NamespaceRule, Origin, OriginSet, PagePseudoClassFlags, PageRule, PropertyRule, - SanitizationData, SanitizationKind, StartingStyleRule, StyleRule, StylesheetContents, - StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData, ScopeRule, + MarginRule, MediaRule, NamespaceRule, Origin, OriginSet, PagePseudoClassFlags, PageRule, + PropertyRule, SanitizationData, SanitizationKind, ScopeRule, StartingStyleRule, StyleRule, + StylesheetContents, StylesheetLoader as StyleStylesheetLoader, SupportsRule, UrlExtraData, }; use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist}; use style::thread_state; @@ -162,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 { @@ -1263,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(); } @@ -1414,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, @@ -1426,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()); } } @@ -1691,7 +1684,7 @@ pub unsafe extern "C" fn Servo_ShutdownThreadPool() { #[no_mangle] pub unsafe extern "C" fn Servo_ThreadPool_GetThreadHandles( - handles: &mut ThinVec, + handles: &mut nsTArray, ) { StyleThreadPool::get_thread_handles(handles); } @@ -2156,7 +2149,7 @@ where #[no_mangle] pub extern "C" fn Servo_CssRules_ListTypes(rules: &LockedCssRules, result: &mut nsTArray) { 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)); }) } @@ -2402,6 +2395,13 @@ impl_group_rule_funcs! { (Media, MediaRule, MediaRule), changed: Servo_StyleSet_MediaRuleChanged, } +impl_basic_rule_funcs! { (Margin, MarginRule, MarginRule), + getter: Servo_CssRules_GetMarginRuleAt, + debug: Servo_MarginRule_Debug, + to_css: Servo_MarginRule_GetCssText, + changed: Servo_StyleSet_MarginRuleChanged, +} + impl_basic_rule_funcs! { (Namespace, NamespaceRule, NamespaceRule), getter: Servo_CssRules_GetNamespaceRuleAt, debug: Servo_NamespaceRule_Debug, @@ -2529,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 = None; for rule in rules.iter().rev() { selectors = Some(read_locked_arc(rule, |rule| match selectors { @@ -2540,9 +2540,16 @@ fn desugared_selector_list(rules: &ThinVec<&LockedStyleRule>) -> SelectorList { selectors.expect("Empty rule chain?") } +#[no_mangle] +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>, @@ -2566,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>, @@ -2574,7 +2581,8 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement( relevant_link_visited: bool, ) -> bool { use selectors::matching::{ - matches_selector, MatchingContext, MatchingMode, NeedsSelectorFlags, VisitedHandlingMode, + matches_selector, IncludeStartingStyle, MatchingContext, MatchingMode, NeedsSelectorFlags, + VisitedHandlingMode, }; let selectors = desugared_selector_list(rules); let Some(selector) = selectors.slice().get(index as usize) else { @@ -2615,6 +2623,7 @@ pub extern "C" fn Servo_StyleRule_SelectorMatchesElement( /* bloom_filter = */ None, &mut selector_caches, visited_mode, + IncludeStartingStyle::No, quirks_mode, NeedsSelectorFlags::No, MatchingForInvalidation::No, @@ -2938,6 +2947,16 @@ pub extern "C" fn Servo_NamespaceRule_GetURI(rule: &NamespaceRule) -> *mut nsAto rule.url.0.as_ptr() } +#[no_mangle] +pub extern "C" fn Servo_MarginRule_GetStyle(rule: &MarginRule) -> Strong { + rule.block.clone().into() +} + +#[no_mangle] +pub extern "C" fn Servo_MarginRule_GetName(rule: &MarginRule, out: &mut nsACString) { + out.assign(rule.name()); +} + #[no_mangle] pub extern "C" fn Servo_PageRule_GetStyle(rule: &LockedPageRule) -> Strong { read_locked_arc(rule, |rule: &PageRule| rule.block.clone().into()) @@ -3383,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, + out: &mut nsTArray, ) { - 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 { - Source::Url(ref url) => { - (if url.format_hint.is_some() { 2 } else { 1 }) + - (if url.tech_flags.is_empty() { 0 } else { 1 }) - }, - 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)); + for source in sources.0.iter() { + match *source { + Source::Url(ref url) => { + 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(), + }) + }, } - }, - Source::Local(ref name) => { - set_next(FontFaceSourceListComponent::Local(name.name.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())); + }, } } - - assert!(iter.next().is_none(), "miscalculated"); }) } #[no_mangle] pub unsafe extern "C" fn Servo_FontFaceRule_GetVariationSettings( rule: &LockedFontFaceRule, - variations: *mut nsTArray, + variations: &mut nsTArray, ) { read_locked_arc_worker(rule, |rule: &FontFaceRule| { let source_variations = match rule.variation_settings { @@ -3453,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, + features: &mut nsTArray, ) { read_locked_arc_worker(rule, |rule: &FontFaceRule| { let source_features = match rule.feature_settings { @@ -3474,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, + }), + ); }); } @@ -4343,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, @@ -5540,6 +5541,12 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue( structs::nsCSSUnit::eCSSUnit_CapHeight => { NoCalcLength::FontRelative(FontRelativeLength::Cap(value)) }, + structs::nsCSSUnit::eCSSUnit_LineHeight => { + NoCalcLength::FontRelative(FontRelativeLength::Lh(value)) + }, + structs::nsCSSUnit::eCSSUnit_RootLineHeight => { + NoCalcLength::FontRelative(FontRelativeLength::Rlh(value)) + }, structs::nsCSSUnit::eCSSUnit_Pixel => NoCalcLength::Absolute(AbsoluteLength::Px(value)), structs::nsCSSUnit::eCSSUnit_Inch => NoCalcLength::Absolute(AbsoluteLength::In(value)), structs::nsCSSUnit::eCSSUnit_Centimeter => { @@ -6307,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; }; @@ -6352,7 +6351,7 @@ pub extern "C" fn Servo_GetAnimationValues( element: &RawGeckoElement, style: &ComputedValues, raw_data: &PerDocumentStyleData, - animation_values: &mut ThinVec>, + animation_values: &mut nsTArray>, ) { let data = raw_data.borrow(); let element = GeckoElement(element); @@ -6389,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] @@ -6476,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, @@ -6496,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)); } } } @@ -6577,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, @@ -6598,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; @@ -6634,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( @@ -6647,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); @@ -6689,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, + rules: &mut nsTArray, ) { let data = raw_data.borrow(); debug_assert_eq!(rules.len(), 0); @@ -7563,7 +7567,6 @@ pub extern "C" fn Servo_StyleSet_HasNthOfCustomStateDependency( }) } - #[no_mangle] pub extern "C" fn Servo_StyleSet_HasNthOfStateDependency( raw_data: &PerDocumentStyleData, @@ -8125,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; @@ -9069,7 +9072,7 @@ impl PropDef { #[no_mangle] pub extern "C" fn Servo_GetRegisteredCustomProperties( per_doc_data: &PerDocumentStyleData, - custom_properties: &mut ThinVec, + custom_properties: &mut nsTArray, ) { let stylist = &per_doc_data.borrow().stylist; @@ -9109,7 +9112,7 @@ pub struct SelectorWarningData { #[no_mangle] pub extern "C" fn Servo_GetSelectorWarnings( rule: &LockedStyleRule, - warnings: &mut ThinVec, + warnings: &mut nsTArray, ) { read_locked_arc(rule, |r| { for (i, selector) in r.selectors.slice().iter().enumerate() { @@ -9121,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); @@ -9138,7 +9138,7 @@ pub extern "C" fn Servo_GetRuleBodyText( found_start = true; break; }, - _ => {} + _ => {}, } if token.is_parse_error() { @@ -9146,7 +9146,6 @@ pub extern "C" fn Servo_GetRuleBodyText( } } - if !found_start { ret_val.set_is_void(true); return; @@ -9154,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. @@ -9208,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 @@ -9228,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 { +fn get_byte_index_from_line_and_column(css_text: &str, line: u32, column: u32) -> Option { // Find the byte index of the start of the passed line within css_text let mut line_byte_index = Some(0); if line != 1 { @@ -9277,3 +9266,196 @@ fn get_byte_index_from_line_and_column( None } + +#[repr(C)] +pub struct CSSToken { + pub text: nsCString, + pub token_type: nsCString, + pub has_unit: bool, + pub unit: nsCString, + pub has_number: bool, + pub number: f32, + pub has_value: bool, + pub value: nsCString, + // line and column at which the token starts + pub line: u32, + pub column: u32, +} + +#[no_mangle] +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); + Box::into_raw(Box::new(input.state())) +} + +#[no_mangle] +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 { + return state.source_location().line; +} + +#[no_mangle] +pub unsafe extern "C" fn Servo_CSSParser_GetCurrentColumn(state: &ParserState) -> u32 { + return state.source_location().column; +} + +#[no_mangle] +pub unsafe extern "C" fn Servo_CSSParser_NextToken( + text: &nsACString, + state: &mut ParserState, + css_token: &mut CSSToken, +) -> bool { + let css_text = unsafe { text.as_str_unchecked() }; + let mut parser_input = ParserInput::new(&css_text); + let mut input = Parser::new(&mut parser_input); + input.reset(state); + + let token_start = input.position(); + let location_start = state.source_location(); + let Ok(token) = &input.next_including_whitespace_and_comments() else { + return false; + }; + + let token_type = match *token { + Token::Ident(_) => "Ident", + Token::AtKeyword(_) => "AtKeyword", + Token::Hash(_) => "Hash", + Token::IDHash(_) => "IDHash", + Token::QuotedString(_) => "QuotedString", + Token::UnquotedUrl(_) => "UnquotedUrl", + Token::Delim(_) => "Delim", + Token::Number { .. } => "Number", + Token::Percentage { .. } => "Percentage", + Token::Dimension { .. } => "Dimension", + Token::WhiteSpace(_) => "WhiteSpace", + Token::Comment(_) => "Comment", + Token::Colon => "Colon", + Token::Semicolon => "Semicolon", + Token::Comma => "Comma", + Token::IncludeMatch => "IncludeMatch", + Token::DashMatch => "DashMatch", + Token::PrefixMatch => "PrefixMatch", + Token::SuffixMatch => "SuffixMatch", + Token::SubstringMatch => "SubstringMatch", + Token::CDO => "CDO", + Token::CDC => "CDC", + Token::Function(_) => "Function", + Token::ParenthesisBlock => "ParenthesisBlock", + Token::SquareBracketBlock => "SquareBracketBlock", + Token::CurlyBracketBlock => "CurlyBracketBlock", + Token::BadUrl(_) => "BadUrl", + Token::BadString(_) => "BadString", + Token::CloseParenthesis => "CloseParenthesis", + Token::CloseSquareBracket => "CloseSquareBracket", + Token::CloseCurlyBracket => "CloseCurlyBracket", + }; + + let token_value = match *token { + Token::Ident(value) | + Token::AtKeyword(value) | + Token::Hash(value) | + Token::IDHash(value) | + Token::QuotedString(value) | + Token::UnquotedUrl(value) | + Token::Function(value) | + Token::BadUrl(value) | + Token::BadString(value) => { + let mut text = nsCString::new(); + text.assign(value.as_bytes()); + Some(text) + }, + // value is a str here, we need a different branch to handle it + Token::Comment(value) => { + let mut text = nsCString::new(); + text.assign(value.as_bytes()); + Some(text) + }, + // Delim and WhiteSpace also have value, but they will be similar to text, so don't + // include them + Token::Delim(_) | + Token::WhiteSpace(_) | + // Number, Percentage and Dimension expose numeric values that will be exposed in `number` + Token::Number{..} | + Token::Percentage{..} | + Token::Dimension{..} | + // The rest of the tokens don't expose a string value + Token::Colon | + Token::Semicolon | + Token::Comma | + Token::IncludeMatch | + Token::DashMatch | + Token::PrefixMatch | + Token::SuffixMatch | + Token::SubstringMatch | + Token::CDO | + Token::CDC | + Token::ParenthesisBlock | + Token::SquareBracketBlock | + Token::CurlyBracketBlock | + Token::CloseParenthesis | + Token::CloseSquareBracket | + Token::CloseCurlyBracket => None + }; + + let token_unit = match *token { + Token::Dimension { ref unit, .. } => { + let mut unit_text = nsCString::new(); + unit_text.assign(unit.as_bytes()); + Some(unit_text) + }, + _ => 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, + }; + css_token.has_number = token_number.is_some(); + if css_token.has_number { + css_token.number = *token_number.unwrap(); + } + + let need_to_parse_nested_block = match *token { + Token::Function(_) | + Token::ParenthesisBlock | + Token::CurlyBracketBlock | + Token::SquareBracketBlock => true, + _ => false, + }; + + let mut text = nsCString::new(); + text.assign(&input.slice_from(token_start)); + + css_token.text = text; + css_token.token_type = token_type.into(); + css_token.has_value = token_value.is_some(); + if css_token.has_value { + css_token.value = token_value.unwrap(); + } + css_token.has_unit = token_unit.is_some(); + if css_token.has_unit { + css_token.unit = token_unit.unwrap(); + } + + css_token.line = location_start.line; + 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(()) + }); + } else { + *state = input.state(); + } + + return true; +} -- cgit v1.2.3