Do not allow unmatched closing tag at root
This commit is contained in:
parent
d024d21274
commit
d7ddda3f21
|
@ -1,9 +1,10 @@
|
|||
// Implement debug to allow .unwrap().
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum ErrorType {
|
||||
ClosingTagMismatch { expected: String, got: String },
|
||||
NotFound(&'static str),
|
||||
UnexpectedEnd,
|
||||
UnexpectedClosingTag,
|
||||
}
|
||||
|
||||
impl ErrorType {
|
||||
|
@ -18,6 +19,9 @@ impl ErrorType {
|
|||
ErrorType::UnexpectedEnd => {
|
||||
format!("Unexpected end of source code.")
|
||||
}
|
||||
ErrorType::UnexpectedClosingTag => {
|
||||
format!("Unexpected closing tag.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@ mod unit;
|
|||
pub fn in_place(code: &mut [u8], cfg: &Cfg) -> Result<usize, Error> {
|
||||
let mut proc = Processor::new(code);
|
||||
process_content(&mut proc, cfg, Namespace::Html, None)
|
||||
.and_then(|_| if !proc.at_end() {
|
||||
Err(ErrorType::UnexpectedClosingTag)
|
||||
} else {
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|error_type| Error {
|
||||
error_type,
|
||||
position: proc.read_len(),
|
||||
|
|
|
@ -362,8 +362,7 @@ impl<'d> Processor<'d> {
|
|||
#[cfg(not(feature = "js-esbuild"))]
|
||||
#[inline(always)]
|
||||
pub fn finish(self) -> Result<usize, Error> {
|
||||
// NOTE: Do not assert that we are at the end, as invalid HTML can end prematurely e.g.
|
||||
// `<html>hello</html>outside`.
|
||||
debug_assert!(self.at_end());
|
||||
Ok(self.write_next)
|
||||
}
|
||||
|
||||
|
@ -371,8 +370,7 @@ impl<'d> Processor<'d> {
|
|||
#[cfg(feature = "js-esbuild")]
|
||||
#[inline(always)]
|
||||
pub fn finish(self) -> Result<usize, Error> {
|
||||
// NOTE: Do not assert that we are at the end, as invalid HTML can end prematurely e.g.
|
||||
// `<html>hello</html>outside`.
|
||||
debug_assert!(self.at_end());
|
||||
self.script_wg.wait();
|
||||
let mut results = Arc::try_unwrap(self.script_results)
|
||||
.unwrap_or_else(|_| panic!("failed to acquire script results"))
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
#[cfg(test)]
|
||||
use {
|
||||
crate::ErrorType
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
fn _eval(src: &'static [u8], expected: &'static [u8], cfg: &super::Cfg) -> () {
|
||||
let mut code = src.to_vec();
|
||||
|
@ -13,6 +18,12 @@ fn _eval(src: &'static [u8], expected: &'static [u8], cfg: &super::Cfg) -> () {
|
|||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn _eval_error(src: &'static [u8], expected: ErrorType, cfg: &super::Cfg) -> () {
|
||||
let mut code = src.to_vec();
|
||||
assert_eq!(super::in_place(&mut code, cfg).unwrap_err().error_type, expected);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn eval(src: &'static [u8], expected: &'static [u8]) -> () {
|
||||
_eval(src, expected, &super::Cfg {
|
||||
|
@ -20,6 +31,13 @@ fn eval(src: &'static [u8], expected: &'static [u8]) -> () {
|
|||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn eval_error(src: &'static [u8], expected: ErrorType) -> () {
|
||||
_eval_error(src, expected, &super::Cfg {
|
||||
minify_js: false,
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "js-esbuild")]
|
||||
fn eval_with_js_min(src: &'static [u8], expected: &'static [u8]) -> () {
|
||||
|
@ -79,10 +97,21 @@ fn test_parsing_with_omitted_tags() {
|
|||
eval(b"<rt><rp>1</rp><div></div>", b"<rt><rp>1</rp><div></div>");
|
||||
eval(b"<div><rt></div>", b"<div><rt></div>");
|
||||
eval(b"<html><head><body>", b"<html><head><body>");
|
||||
eval(b"<html><head><body>", b"<html><head><body>");
|
||||
// Tag names should be case insensitive.
|
||||
eval(b"<rt>", b"<rt>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unmatched_closing_tag() {
|
||||
eval_error(b"Hello</p>Goodbye", ErrorType::UnexpectedClosingTag);
|
||||
eval_error(b"Hello<br></br>Goodbye", ErrorType::UnexpectedClosingTag);
|
||||
eval_error(b"<div>Hello</p>Goodbye", ErrorType::ClosingTagMismatch { expected: "div".to_string(), got: "p".to_string() });
|
||||
eval_error(b"<ul><li>a</p>", ErrorType::ClosingTagMismatch { expected: "ul".to_string(), got: "p".to_string() });
|
||||
eval_error(b"<ul><li><rt>a</p>", ErrorType::ClosingTagMismatch { expected: "ul".to_string(), got: "p".to_string() });
|
||||
eval_error(b"<html><head><body><ul><li><rt>a</p>", ErrorType::ClosingTagMismatch { expected: "ul".to_string(), got: "p".to_string() });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_removal_of_optional_tags() {
|
||||
eval(b"<ul><li>1</li><li>2</li><li>3</li></ul>", b"<ul><li>1<li>2<li>3</ul>");
|
||||
|
|
|
@ -47,7 +47,7 @@ impl ContentType {
|
|||
}
|
||||
|
||||
pub struct ProcessedContent {
|
||||
pub(crate) closing_tag_omitted: bool,
|
||||
pub closing_tag_omitted: bool,
|
||||
}
|
||||
|
||||
pub fn process_content(proc: &mut Processor, cfg: &Cfg, ns: Namespace, parent: Option<ProcessorRange>) -> ProcessingResult<ProcessedContent> {
|
||||
|
|
Loading…
Reference in New Issue