Commit e41aedfe authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

XPath: Simplify had_type_conversion_error handling

EvaluationContext had |bool had_type_conversion_error| field, and we had to copy
the field manually whenever we cloned an EvaluationContext object to propagate
an error to the top-level EvaluationContext.
This CL changes the field to a mutable reference to bool, and it is shared
between cloned EvaluationContext objects.

Change-Id: I5f7e71a25337cfaf413ca98fccc9d3f16a04dba4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1975472
Commit-Queue: Kent Tamura <tkent@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726634}
parent acfe6534
...@@ -70,11 +70,13 @@ XPathResult* XPathExpression::evaluate(Node* context_node, ...@@ -70,11 +70,13 @@ XPathResult* XPathExpression::evaluate(Node* context_node,
return nullptr; return nullptr;
} }
xpath::EvaluationContext evaluation_context(*context_node); bool had_type_conversion_error = false;
xpath::EvaluationContext evaluation_context(*context_node,
had_type_conversion_error);
auto* result = MakeGarbageCollected<XPathResult>( auto* result = MakeGarbageCollected<XPathResult>(
evaluation_context, top_expression_->Evaluate(evaluation_context)); evaluation_context, top_expression_->Evaluate(evaluation_context));
if (evaluation_context.had_type_conversion_error) { if (had_type_conversion_error) {
// It is not specified what to do if type conversion fails while evaluating // It is not specified what to do if type conversion fails while evaluating
// an expression. // an expression.
exception_state.ThrowDOMException( exception_state.ThrowDOMException(
......
...@@ -31,11 +31,12 @@ ...@@ -31,11 +31,12 @@
namespace blink { namespace blink {
namespace xpath { namespace xpath {
EvaluationContext::EvaluationContext(Node& context_node) EvaluationContext::EvaluationContext(Node& context_node,
bool& had_type_conversion_error)
: node(context_node), : node(context_node),
size(1), size(1),
position(1), position(1),
had_type_conversion_error(false) {} had_type_conversion_error(had_type_conversion_error) {}
Expression::Expression() Expression::Expression()
: is_context_node_sensitive_(false), : is_context_node_sensitive_(false),
......
...@@ -43,14 +43,16 @@ struct CORE_EXPORT EvaluationContext { ...@@ -43,14 +43,16 @@ struct CORE_EXPORT EvaluationContext {
STACK_ALLOCATED(); STACK_ALLOCATED();
public: public:
explicit EvaluationContext(Node&); // |had_type_conversion_error| must be a reference to a variable of
// which lifetime is same as this object, or longer than this object.
EvaluationContext(Node&, bool& had_type_conversion_error);
Member<Node> node; Member<Node> node;
wtf_size_t size; wtf_size_t size;
wtf_size_t position; wtf_size_t position;
HashMap<String, String> variable_bindings; HashMap<String, String> variable_bindings;
bool had_type_conversion_error; bool& had_type_conversion_error;
}; };
class CORE_EXPORT ParseNode : public GarbageCollected<ParseNode> { class CORE_EXPORT ParseNode : public GarbageCollected<ParseNode> {
......
...@@ -25,13 +25,15 @@ class XPathContext { ...@@ -25,13 +25,15 @@ class XPathContext {
public: public:
XPathContext() XPathContext()
: document_(MakeGarbageCollected<Document>()), context_(*document_) {} : document_(MakeGarbageCollected<Document>()),
context_(*document_, had_type_conversion_error_) {}
xpath::EvaluationContext& Context() { return context_; } xpath::EvaluationContext& Context() { return context_; }
Document& GetDocument() { return *document_; } Document& GetDocument() { return *document_; }
private: private:
const Member<Document> document_; const Member<Document> document_;
bool had_type_conversion_error_ = false;
xpath::EvaluationContext context_; xpath::EvaluationContext context_;
}; };
......
...@@ -237,12 +237,9 @@ Value Union::Evaluate(EvaluationContext& context) const { ...@@ -237,12 +237,9 @@ Value Union::Evaluate(EvaluationContext& context) const {
EvaluationContext cloned_context = context; EvaluationContext cloned_context = context;
Value lhs_result = SubExpr(0)->Evaluate(context); Value lhs_result = SubExpr(0)->Evaluate(context);
Value rhs = SubExpr(1)->Evaluate(cloned_context); Value rhs = SubExpr(1)->Evaluate(cloned_context);
context.had_type_conversion_error |= cloned_context.had_type_conversion_error;
NodeSet& result_set = lhs_result.ModifiableNodeSet(context); NodeSet& result_set = lhs_result.ModifiableNodeSet(context);
// We should pass |&context|, not |&cloned_context|, in order to propagate const NodeSet& rhs_nodes = rhs.ToNodeSet(&cloned_context);
// a type conversion error to the parent context.
const NodeSet& rhs_nodes = rhs.ToNodeSet(&context);
HeapHashSet<Member<Node>> nodes; HeapHashSet<Member<Node>> nodes;
for (const auto& node : result_set) for (const auto& node : result_set)
...@@ -273,7 +270,6 @@ bool Predicate::Evaluate(EvaluationContext& context) const { ...@@ -273,7 +270,6 @@ bool Predicate::Evaluate(EvaluationContext& context) const {
// context node. // context node.
EvaluationContext cloned_context = context; EvaluationContext cloned_context = context;
Value result(expr_->Evaluate(cloned_context)); Value result(expr_->Evaluate(cloned_context));
context.had_type_conversion_error |= cloned_context.had_type_conversion_error;
// foo[3] means foo[position()=3] // foo[3] means foo[position()=3]
if (result.IsNumber()) if (result.IsNumber())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment