Skip to content

Commit

Permalink
stylo: Store location information for keyframe rules.
Browse files Browse the repository at this point in the history
So far, we only store location info for the whole Keyframes block, not for each
of the keyframe rule. Without this info, the devtool can't present the rules
on the devtool panel properly.

In this patch, we collect the source location info while parsing keyframe selector.
The binding function, Servo_KeyframesRule_GetKeyframe, is also fixed (and renamed
to Servo_KeyframesRule_GetKeyframeAt to match the fix) to accept line and column
parameters from Gecko, so we can pass/set them with the source location from Servo.
  • Loading branch information
chenpighead committed Sep 4, 2017
1 parent e5efbee commit 28d4824
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 13 deletions.
7 changes: 4 additions & 3 deletions components/style/gecko/generated/bindings.rs
Expand Up @@ -2337,9 +2337,10 @@ extern "C" {
-> u32;
}
extern "C" {
pub fn Servo_KeyframesRule_GetKeyframe(rule:
RawServoKeyframesRuleBorrowed,
index: u32)
pub fn Servo_KeyframesRule_GetKeyframeAt(rule:
RawServoKeyframesRuleBorrowed,
index: u32, line: *mut u32,
column: *mut u32)
-> RawServoKeyframeStrong;
}
extern "C" {
Expand Down
25 changes: 21 additions & 4 deletions components/style/stylesheets/keyframes_rule.rs
Expand Up @@ -20,7 +20,7 @@ use std::fmt;
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
use style_traits::PropertyDeclarationParseError;
use stylesheets::{CssRuleType, StylesheetContents};
use stylesheets::rule_parser::VendorPrefix;
use stylesheets::rule_parser::{VendorPrefix, get_location_with_offset};
use values::{KeyframesName, serialize_percentage};

/// A [`@keyframes`][keyframes] rule.
Expand Down Expand Up @@ -192,6 +192,9 @@ pub struct Keyframe {
/// Note that `!important` rules in keyframes don't apply, but we keep this
/// `Arc` just for convenience.
pub block: Arc<Locked<PropertyDeclarationBlock>>,

/// The line and column of the rule's source code.
pub source_location: SourceLocation,
}

impl ToCssWithGuard for Keyframe {
Expand Down Expand Up @@ -249,6 +252,7 @@ impl DeepCloneWithLock for Keyframe {
Keyframe {
selector: self.selector.clone(),
block: Arc::new(lock.wrap(self.block.read_with(guard).clone())),
source_location: self.source_location.clone(),
}
}
}
Expand Down Expand Up @@ -483,16 +487,28 @@ impl<'a, 'i, R> AtRuleParser<'i> for KeyframeListParser<'a, R> {
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}

/// A wrapper to wraps the KeyframeSelector with its source location
struct KeyframeSelectorParserPrelude {
selector: KeyframeSelector,
source_location: SourceLocation,
}

impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for KeyframeListParser<'a, R> {
type Prelude = KeyframeSelector;
type Prelude = KeyframeSelectorParserPrelude;
type QualifiedRule = Arc<Locked<Keyframe>>;
type Error = SelectorParseError<'i, StyleParseError<'i>>;

fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result<Self::Prelude, ParseError<'i>> {
let start_position = input.position();
let start_location = input.current_source_location();
let location = get_location_with_offset(start_location);
match KeyframeSelector::parse(input) {
Ok(sel) => Ok(sel),
Ok(sel) => {
Ok(KeyframeSelectorParserPrelude {
selector: sel,
source_location: location,
})
},
Err(e) => {
let error = ContextualParseError::InvalidKeyframeRule(input.slice_from(start_position), e.clone());
self.context.log_css_error(self.error_context, start_location, error);
Expand Down Expand Up @@ -530,8 +546,9 @@ impl<'a, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for KeyframeListPars
// `parse_important` is not called here, `!important` is not allowed in keyframe blocks.
}
Ok(Arc::new(self.shared_lock.wrap(Keyframe {
selector: prelude,
selector: prelude.selector,
block: Arc::new(self.shared_lock.wrap(block)),
source_location: prelude.source_location,
})))
}
}
Expand Down
2 changes: 1 addition & 1 deletion components/style/stylesheets/rule_parser.rs
Expand Up @@ -587,7 +587,7 @@ impl<'a, 'b, 'i, R: ParseErrorReporter> QualifiedRuleParser<'i> for NestedRulePa
}

/// Adjust a location's column to accommodate DevTools.
fn get_location_with_offset(location: SourceLocation) -> SourceLocation {
pub fn get_location_with_offset(location: SourceLocation) -> SourceLocation {
SourceLocation {
line: location.line,
// Column offsets are not yet supported, but Gecko devtools expect 1-based columns.
Expand Down
15 changes: 10 additions & 5 deletions ports/geckolib/glue.rs
Expand Up @@ -1509,11 +1509,16 @@ pub extern "C" fn Servo_KeyframesRule_GetCount(rule: RawServoKeyframesRuleBorrow
}

#[no_mangle]
pub extern "C" fn Servo_KeyframesRule_GetKeyframe(rule: RawServoKeyframesRuleBorrowed, index: u32)
-> RawServoKeyframeStrong {
read_locked_arc(rule, |rule: &KeyframesRule| {
rule.keyframes[index as usize].clone().into_strong()
})
pub extern "C" fn Servo_KeyframesRule_GetKeyframeAt(rule: RawServoKeyframesRuleBorrowed, index: u32,
line: *mut u32, column: *mut u32) -> RawServoKeyframeStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let key = Locked::<KeyframesRule>::as_arc(&rule).read_with(&guard)
.keyframes[index as usize].clone();
let location = key.read_with(&guard).source_location;
*unsafe { line.as_mut().unwrap() } = location.line as u32;
*unsafe { column.as_mut().unwrap() } = location.column as u32;
key.into_strong()
}

#[no_mangle]
Expand Down

0 comments on commit 28d4824

Please sign in to comment.