script: Remove dead code in xpath implementation (#39454)

Testing: Verified by the fact that the code still compiles, and existing
web platform tests of course
Part of https://github.com/servo/servo/issues/34527

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-09-23 23:58:17 +02:00 committed by GitHub
parent ac8895c3ae
commit dd8e4f231c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 0 additions and 281 deletions

View file

@ -29,25 +29,15 @@ use crate::xpath::context::PredicateCtx;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) enum Error { pub(crate) enum Error {
NotANodeset, NotANodeset,
InvalidPath,
UnknownFunction {
name: QualName,
},
/// It is not clear where variables used in XPath expression should come from. /// It is not clear where variables used in XPath expression should come from.
/// Firefox throws "NS_ERROR_ILLEGAL_VALUE" when using them, chrome seems to return /// Firefox throws "NS_ERROR_ILLEGAL_VALUE" when using them, chrome seems to return
/// an empty result. We also error out. /// an empty result. We also error out.
/// ///
/// See <https://github.com/whatwg/dom/issues/67> /// See <https://github.com/whatwg/dom/issues/67>
CannotUseVariables, CannotUseVariables,
UnknownNamespace {
prefix: String,
},
InvalidQName { InvalidQName {
qname: ParserQualName, qname: ParserQualName,
}, },
FunctionEvaluation {
fname: String,
},
Internal { Internal {
msg: String, msg: String,
}, },
@ -59,18 +49,10 @@ impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Error::NotANodeset => write!(f, "expression did not evaluate to a nodeset"), Error::NotANodeset => write!(f, "expression did not evaluate to a nodeset"),
Error::InvalidPath => write!(f, "invalid path expression"),
Error::UnknownFunction { name } => write!(f, "unknown function {:?}", name),
Error::CannotUseVariables => write!(f, "cannot use variables"), Error::CannotUseVariables => write!(f, "cannot use variables"),
Error::UnknownNamespace { prefix } => {
write!(f, "unknown namespace prefix {:?}", prefix)
},
Error::InvalidQName { qname } => { Error::InvalidQName { qname } => {
write!(f, "invalid QName {:?}", qname) write!(f, "invalid QName {:?}", qname)
}, },
Error::FunctionEvaluation { fname } => {
write!(f, "error while evaluating function: {}", fname)
},
Error::Internal { msg } => { Error::Internal { msg } => {
write!(f, "internal error: {}", msg) write!(f, "internal error: {}", msg)
}, },
@ -92,8 +74,6 @@ pub(crate) fn try_extract_nodeset(v: Value) -> Result<Vec<DomRoot<Node>>, Error>
pub(crate) trait Evaluatable: fmt::Debug { pub(crate) trait Evaluatable: fmt::Debug {
fn evaluate(&self, context: &EvaluationCtx) -> Result<Value, Error>; fn evaluate(&self, context: &EvaluationCtx) -> Result<Value, Error>;
/// Returns true if this expression evaluates to a primitive value, without needing to touch the DOM
fn is_primitive(&self) -> bool;
} }
impl<T: ?Sized> Evaluatable for Box<T> impl<T: ?Sized> Evaluatable for Box<T>
@ -103,10 +83,6 @@ where
fn evaluate(&self, context: &EvaluationCtx) -> Result<Value, Error> { fn evaluate(&self, context: &EvaluationCtx) -> Result<Value, Error> {
(**self).evaluate(context) (**self).evaluate(context)
} }
fn is_primitive(&self) -> bool {
(**self).is_primitive()
}
} }
impl<T> Evaluatable for Option<T> impl<T> Evaluatable for Option<T>
@ -119,10 +95,6 @@ where
None => Ok(Value::Nodeset(vec![])), None => Ok(Value::Nodeset(vec![])),
} }
} }
fn is_primitive(&self) -> bool {
self.as_ref().is_some_and(|t| T::is_primitive(t))
}
} }
impl Evaluatable for Expr { impl Evaluatable for Expr {
@ -201,20 +173,6 @@ impl Evaluatable for Expr {
Expr::Path(path_expr) => path_expr.evaluate(context), Expr::Path(path_expr) => path_expr.evaluate(context),
} }
} }
fn is_primitive(&self) -> bool {
match self {
Expr::Or(left, right) => left.is_primitive() && right.is_primitive(),
Expr::And(left, right) => left.is_primitive() && right.is_primitive(),
Expr::Equality(left, _, right) => left.is_primitive() && right.is_primitive(),
Expr::Relational(left, _, right) => left.is_primitive() && right.is_primitive(),
Expr::Additive(left, _, right) => left.is_primitive() && right.is_primitive(),
Expr::Multiplicative(left, _, right) => left.is_primitive() && right.is_primitive(),
Expr::Unary(_, expr) => expr.is_primitive(),
Expr::Union(_, _) => false,
Expr::Path(path_expr) => path_expr.is_primitive(),
}
}
} }
impl Evaluatable for PathExpr { impl Evaluatable for PathExpr {
@ -268,13 +226,6 @@ impl Evaluatable for PathExpr {
Ok(Value::Nodeset(current_nodes)) Ok(Value::Nodeset(current_nodes))
} }
fn is_primitive(&self) -> bool {
!self.is_absolute &&
!self.is_descendant &&
self.steps.len() == 1 &&
self.steps[0].is_primitive()
}
} }
/// Error types for validate and extract a qualified name following /// Error types for validate and extract a qualified name following
@ -612,13 +563,6 @@ impl Evaluatable for StepExpr {
}, },
} }
} }
fn is_primitive(&self) -> bool {
match self {
StepExpr::Filter(filter_expr) => filter_expr.is_primitive(),
StepExpr::Axis(_) => false,
}
}
} }
impl Evaluatable for PredicateListExpr { impl Evaluatable for PredicateListExpr {
@ -668,10 +612,6 @@ impl Evaluatable for PredicateListExpr {
}) })
} }
} }
fn is_primitive(&self) -> bool {
self.predicates.len() == 1 && self.predicates[0].is_primitive()
}
} }
impl Evaluatable for PredicateExpr { impl Evaluatable for PredicateExpr {
@ -704,10 +644,6 @@ impl Evaluatable for PredicateExpr {
Ok(Value::Nodeset(narrowed_nodes?)) Ok(Value::Nodeset(narrowed_nodes?))
} }
fn is_primitive(&self) -> bool {
self.expr.is_primitive()
}
} }
impl Evaluatable for FilterExpr { impl Evaluatable for FilterExpr {
@ -738,10 +674,6 @@ impl Evaluatable for FilterExpr {
(true, _) => Err(Error::NotANodeset), (true, _) => Err(Error::NotANodeset),
} }
} }
fn is_primitive(&self) -> bool {
self.predicates.predicates.is_empty() && self.primary.is_primitive()
}
} }
impl Evaluatable for PrimaryExpr { impl Evaluatable for PrimaryExpr {
@ -754,16 +686,6 @@ impl Evaluatable for PrimaryExpr {
PrimaryExpr::Function(core_function) => core_function.evaluate(context), PrimaryExpr::Function(core_function) => core_function.evaluate(context),
} }
} }
fn is_primitive(&self) -> bool {
match self {
PrimaryExpr::Literal(_) => true,
PrimaryExpr::Variable(_qname) => false,
PrimaryExpr::Parenthesized(expr) => expr.is_primitive(),
PrimaryExpr::ContextItem => false,
PrimaryExpr::Function(_) => false,
}
}
} }
impl Evaluatable for Literal { impl Evaluatable for Literal {
@ -777,8 +699,4 @@ impl Evaluatable for Literal {
Literal::String(s) => Ok(Value::String(s.into())), Literal::String(s) => Ok(Value::String(s.into())),
} }
} }
fn is_primitive(&self) -> bool {
true
}
} }

View file

@ -304,63 +304,6 @@ impl Evaluatable for CoreFunction {
}, },
} }
} }
fn is_primitive(&self) -> bool {
match self {
CoreFunction::Last => false,
CoreFunction::Position => false,
CoreFunction::Count(_) => false,
CoreFunction::Id(_) => false,
CoreFunction::LocalName(_) => false,
CoreFunction::NamespaceUri(_) => false,
CoreFunction::Name(_) => false,
CoreFunction::String(expr_opt) => expr_opt
.as_ref()
.map(|expr| expr.is_primitive())
.unwrap_or(false),
CoreFunction::Concat(vec) => vec.iter().all(|expr| expr.is_primitive()),
CoreFunction::StartsWith(expr, substr) => expr.is_primitive() && substr.is_primitive(),
CoreFunction::Contains(expr, substr) => expr.is_primitive() && substr.is_primitive(),
CoreFunction::SubstringBefore(expr, substr) => {
expr.is_primitive() && substr.is_primitive()
},
CoreFunction::SubstringAfter(expr, substr) => {
expr.is_primitive() && substr.is_primitive()
},
CoreFunction::Substring(expr, start_pos, length_opt) => {
expr.is_primitive() &&
start_pos.is_primitive() &&
length_opt
.as_ref()
.map(|length| length.is_primitive())
.unwrap_or(false)
},
CoreFunction::StringLength(expr_opt) => expr_opt
.as_ref()
.map(|expr| expr.is_primitive())
.unwrap_or(false),
CoreFunction::NormalizeSpace(expr_opt) => expr_opt
.as_ref()
.map(|expr| expr.is_primitive())
.unwrap_or(false),
CoreFunction::Translate(expr, from_chars, to_chars) => {
expr.is_primitive() && from_chars.is_primitive() && to_chars.is_primitive()
},
CoreFunction::Number(expr_opt) => expr_opt
.as_ref()
.map(|expr| expr.is_primitive())
.unwrap_or(false),
CoreFunction::Sum(expr) => expr.is_primitive(),
CoreFunction::Floor(expr) => expr.is_primitive(),
CoreFunction::Ceiling(expr) => expr.is_primitive(),
CoreFunction::Round(expr) => expr.is_primitive(),
CoreFunction::Boolean(expr) => expr.is_primitive(),
CoreFunction::Not(expr) => expr.is_primitive(),
CoreFunction::True => true,
CoreFunction::False => true,
CoreFunction::Lang(_) => false,
}
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -86,10 +86,6 @@ impl Value {
} }
} }
pub(crate) fn into_boolean(self) -> bool {
self.boolean()
}
pub(crate) fn number(&self) -> f64 { pub(crate) fn number(&self) -> f64 {
match *self { match *self {
Value::Boolean(val) => { Value::Boolean(val) => {
@ -105,10 +101,6 @@ impl Value {
} }
} }
pub(crate) fn into_number(self) -> f64 {
self.number()
}
pub(crate) fn string(&self) -> string::String { pub(crate) fn string(&self) -> string::String {
match *self { match *self {
Value::Boolean(v) => v.to_string(), Value::Boolean(v) => v.to_string(),
@ -133,13 +125,6 @@ impl Value {
}, },
} }
} }
pub(crate) fn into_string(self) -> string::String {
match self {
Value::String(val) => val,
other => other.string(),
}
}
} }
macro_rules! from_impl { macro_rules! from_impl {

View file

@ -14,12 +14,9 @@ use crate::dom::bindings::codegen::Bindings::XPathNSResolverBinding::XPathNSReso
use crate::dom::bindings::error::{Error as JsError, Error, Fallible}; use crate::dom::bindings::error::{Error as JsError, Error, Fallible};
mod context; mod context;
#[allow(dead_code)]
mod eval; mod eval;
mod eval_function; mod eval_function;
#[allow(dead_code)]
mod eval_value; mod eval_value;
#[allow(dead_code)]
mod parser; mod parser;
/// Parse an XPath expression from a string /// Parse an XPath expression from a string

View file

@ -234,130 +234,6 @@ pub(crate) enum CoreFunction {
Lang(Box<Expr>), Lang(Box<Expr>),
} }
impl CoreFunction {
pub(crate) fn name(&self) -> &'static str {
match self {
CoreFunction::Last => "last",
CoreFunction::Position => "position",
CoreFunction::Count(_) => "count",
CoreFunction::Id(_) => "id",
CoreFunction::LocalName(_) => "local-name",
CoreFunction::NamespaceUri(_) => "namespace-uri",
CoreFunction::Name(_) => "name",
CoreFunction::String(_) => "string",
CoreFunction::Concat(_) => "concat",
CoreFunction::StartsWith(_, _) => "starts-with",
CoreFunction::Contains(_, _) => "contains",
CoreFunction::SubstringBefore(_, _) => "substring-before",
CoreFunction::SubstringAfter(_, _) => "substring-after",
CoreFunction::Substring(_, _, _) => "substring",
CoreFunction::StringLength(_) => "string-length",
CoreFunction::NormalizeSpace(_) => "normalize-space",
CoreFunction::Translate(_, _, _) => "translate",
CoreFunction::Number(_) => "number",
CoreFunction::Sum(_) => "sum",
CoreFunction::Floor(_) => "floor",
CoreFunction::Ceiling(_) => "ceiling",
CoreFunction::Round(_) => "round",
CoreFunction::Boolean(_) => "boolean",
CoreFunction::Not(_) => "not",
CoreFunction::True => "true",
CoreFunction::False => "false",
CoreFunction::Lang(_) => "lang",
}
}
pub(crate) fn min_args(&self) -> usize {
match self {
// No args
CoreFunction::Last |
CoreFunction::Position |
CoreFunction::True |
CoreFunction::False => 0,
// Optional single arg
CoreFunction::LocalName(_) |
CoreFunction::NamespaceUri(_) |
CoreFunction::Name(_) |
CoreFunction::String(_) |
CoreFunction::StringLength(_) |
CoreFunction::NormalizeSpace(_) |
CoreFunction::Number(_) => 0,
// Required single arg
CoreFunction::Count(_) |
CoreFunction::Id(_) |
CoreFunction::Sum(_) |
CoreFunction::Floor(_) |
CoreFunction::Ceiling(_) |
CoreFunction::Round(_) |
CoreFunction::Boolean(_) |
CoreFunction::Not(_) |
CoreFunction::Lang(_) => 1,
// Required two args
CoreFunction::StartsWith(_, _) |
CoreFunction::Contains(_, _) |
CoreFunction::SubstringBefore(_, _) |
CoreFunction::SubstringAfter(_, _) => 2,
// Special cases
CoreFunction::Concat(_) => 2, // Minimum 2 args
CoreFunction::Substring(_, _, _) => 2, // 2 or 3 args
CoreFunction::Translate(_, _, _) => 3, // Exactly 3 args
}
}
pub(crate) fn max_args(&self) -> Option<usize> {
match self {
// No args
CoreFunction::Last |
CoreFunction::Position |
CoreFunction::True |
CoreFunction::False => Some(0),
// Optional single arg (0 or 1)
CoreFunction::LocalName(_) |
CoreFunction::NamespaceUri(_) |
CoreFunction::Name(_) |
CoreFunction::String(_) |
CoreFunction::StringLength(_) |
CoreFunction::NormalizeSpace(_) |
CoreFunction::Number(_) => Some(1),
// Exactly one arg
CoreFunction::Count(_) |
CoreFunction::Id(_) |
CoreFunction::Sum(_) |
CoreFunction::Floor(_) |
CoreFunction::Ceiling(_) |
CoreFunction::Round(_) |
CoreFunction::Boolean(_) |
CoreFunction::Not(_) |
CoreFunction::Lang(_) => Some(1),
// Exactly two args
CoreFunction::StartsWith(_, _) |
CoreFunction::Contains(_, _) |
CoreFunction::SubstringBefore(_, _) |
CoreFunction::SubstringAfter(_, _) => Some(2),
// Special cases
CoreFunction::Concat(_) => None, // Unlimited args
CoreFunction::Substring(_, _, _) => Some(3), // 2 or 3 args
CoreFunction::Translate(_, _, _) => Some(3), // Exactly 3 args
}
}
/// Returns true if the number of arguments is valid for this function
pub(crate) fn is_valid_arity(&self, num_args: usize) -> bool {
let min = self.min_args();
let max = self.max_args();
num_args >= min && max.is_none_or(|max| num_args <= max)
}
}
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub(crate) struct OwnedParserError { pub(crate) struct OwnedParserError {
input: String, input: String,