Skip to content

Commit adb2e6f

Browse files
committed
Add initial variable processing
This supports the work in whatwg/html#11392 with a new processor found in variables.rs, documented there. This also updates the parser to store the line numbers for each element, for use in error messages. For now this contains commented-out code to error on `<var>`s outside of `algorithm` and `var-scope` scopes, since CI will prevent us from merging a html-build change that cannot build the current main branch of whatwg/html. After the HTML PR is merged, we can uncomment that code.
1 parent 4d5441d commit adb2e6f

File tree

4 files changed

+470
-9
lines changed

4 files changed

+470
-9
lines changed

src/dom_utils.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub trait NodeHandleExt {
2828
/// Sets an attribute on the element. Must be an element.
2929
fn set_attribute(&self, name: &QualName, value: StrTendril);
3030

31+
/// Removes an attribute from the element, if present. Must be an element.
32+
fn remove_attribute(&self, name: &QualName);
33+
3134
/// Returns true if the node is an element.
3235
fn is_element(&self) -> bool;
3336

@@ -225,6 +228,16 @@ impl NodeHandleExt for Handle {
225228
}
226229
}
227230

231+
fn remove_attribute(&self, name: &QualName) {
232+
let mut attrs = match self.data {
233+
NodeData::Element { ref attrs, .. } => attrs.borrow_mut(),
234+
_ => panic!("not an element"),
235+
};
236+
if let Some(i) = attrs.iter().position(|a| &a.name == name) {
237+
attrs.remove(i);
238+
}
239+
}
240+
228241
fn is_element(&self) -> bool {
229242
matches!(&self.data, NodeData::Element { .. })
230243
}

src/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod rcdom_with_line_numbers;
1919
mod represents;
2020
mod self_link;
2121
mod tag_omission;
22+
mod variables;
2223

2324
#[tokio::main]
2425
async fn main() -> io::Result<()> {
@@ -60,11 +61,13 @@ async fn run_preprocess() -> io::Result<()> {
6061
let mut tag_omission = tag_omission::Processor::new();
6162
let mut interface_index = interface_index::Processor::new();
6263
let mut self_link = self_link::Processor::new();
64+
let mut variables = variables::Processor::new(&parsed);
6365

6466
// We do exactly one pass to identify the changes that need to be made.
6567
dom_utils::scan_dom(&document, &mut |h| {
6668
boilerplate.visit(h);
6769
represents.visit(h);
70+
variables.visit(h);
6871
annotate_attributes.visit(h);
6972
tag_omission.visit(h);
7073
interface_index.visit(h);
@@ -76,6 +79,7 @@ async fn run_preprocess() -> io::Result<()> {
7679
// conflicts between them.
7780
boilerplate.apply().await?;
7881
represents.apply()?;
82+
variables.apply()?;
7983
annotate_attributes.apply().await?;
8084
tag_omission.apply()?;
8185
interface_index.apply()?;

src/rcdom_with_line_numbers.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@ use html5ever::{
77
tendril::StrTendril,
88
tree_builder::{ElementFlags, NodeOrText, QuirksMode},
99
};
10-
use markup5ever_rcdom::{Handle, RcDom};
10+
use markup5ever_rcdom::{Handle, Node, RcDom};
1111
use std::borrow::Cow;
12-
use std::cell::Cell;
12+
use std::cell::{Cell, RefCell};
13+
use std::collections::HashMap;
1314
use std::io;
15+
use std::rc::Rc;
1416

1517
pub struct RcDomWithLineNumbers {
1618
dom: RcDom,
1719
current_line: Cell<u64>,
20+
node_line_map: RefCell<HashMap<*const Node, u64>>,
1821
}
1922

2023
#[cfg(test)]
@@ -48,13 +51,21 @@ impl RcDomWithLineNumbers {
4851
Ok(())
4952
}
5053
}
54+
55+
/// Returns the 1-based line number where the element represented by `handle`
56+
/// was created, if known.
57+
pub fn line_number_for(&self, handle: &Handle) -> Option<u64> {
58+
let key = Rc::as_ptr(handle);
59+
self.node_line_map.borrow().get(&key).cloned()
60+
}
5161
}
5262

5363
impl Default for RcDomWithLineNumbers {
5464
fn default() -> Self {
5565
Self {
5666
dom: RcDom::default(),
5767
current_line: Cell::new(1),
68+
node_line_map: RefCell::new(HashMap::new()),
5869
}
5970
}
6071
}
@@ -81,20 +92,27 @@ impl TreeSink for RcDomWithLineNumbers {
8192
self
8293
}
8394

95+
// Override to record the current line number for each created element handle.
96+
fn create_element(
97+
&self,
98+
name: QualName,
99+
attrs: Vec<Attribute>,
100+
flags: ElementFlags,
101+
) -> Self::Handle {
102+
let h = self.dom.create_element(name, attrs, flags);
103+
let key = Rc::as_ptr(&h);
104+
let line = self.current_line.get();
105+
self.node_line_map.borrow_mut().insert(key, line);
106+
h
107+
}
108+
84109
// Delegate all other methods to RcDom.
85110
delegate! {
86111
to self.dom {
87112
fn get_document(&self) -> Self::Handle;
88113

89114
fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> ExpandedName<'a>;
90115

91-
fn create_element(
92-
&self,
93-
name: QualName,
94-
attrs: Vec<Attribute>,
95-
flags: ElementFlags,
96-
) -> Self::Handle;
97-
98116
fn create_comment(&self, text: StrTendril) -> Self::Handle;
99117

100118
fn create_pi(&self, target: StrTendril, data: StrTendril) -> Self::Handle;

0 commit comments

Comments
 (0)