summaryrefslogtreecommitdiffstats
path: root/WebCore/xml
diff options
context:
space:
mode:
authorFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
committerFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
commit5f1ab04193ad0130ca8204aadaceae083aca9881 (patch)
tree5a92cd389e2cfe7fb67197ce14b38469462379f8 /WebCore/xml
parent194315e5a908cc8ed67d597010544803eef1ac59 (diff)
downloadexternal_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2
Get WebKit r44544.
Diffstat (limited to 'WebCore/xml')
-rw-r--r--WebCore/xml/XMLHttpRequest.cpp43
-rw-r--r--WebCore/xml/XMLHttpRequest.h4
-rw-r--r--WebCore/xml/XMLHttpRequest.idl2
-rw-r--r--WebCore/xml/XMLHttpRequestException.idl2
-rw-r--r--WebCore/xml/XPathException.idl2
-rw-r--r--WebCore/xml/XPathExpression.cpp19
-rw-r--r--WebCore/xml/XPathExpressionNode.cpp4
-rw-r--r--WebCore/xml/XPathExpressionNode.h32
-rw-r--r--WebCore/xml/XPathFunctions.cpp115
-rw-r--r--WebCore/xml/XPathFunctions.h12
-rw-r--r--WebCore/xml/XPathNodeSet.h16
-rw-r--r--WebCore/xml/XPathPath.cpp92
-rw-r--r--WebCore/xml/XPathPath.h12
-rw-r--r--WebCore/xml/XPathPredicate.cpp2
-rw-r--r--WebCore/xml/XPathPredicate.h16
-rw-r--r--WebCore/xml/XPathResult.cpp46
-rw-r--r--WebCore/xml/XPathResult.h22
-rw-r--r--WebCore/xml/XPathStep.cpp277
-rw-r--r--WebCore/xml/XPathStep.h41
-rw-r--r--WebCore/xml/XPathUtil.cpp20
-rw-r--r--WebCore/xml/XPathValue.cpp22
-rw-r--r--WebCore/xml/XPathVariableReference.h4
-rw-r--r--WebCore/xml/XSLStyleSheet.cpp14
-rw-r--r--WebCore/xml/XSLTProcessor.cpp5
24 files changed, 510 insertions, 314 deletions
diff --git a/WebCore/xml/XMLHttpRequest.cpp b/WebCore/xml/XMLHttpRequest.cpp
index dd3f361..76ee048 100644
--- a/WebCore/xml/XMLHttpRequest.cpp
+++ b/WebCore/xml/XMLHttpRequest.cpp
@@ -66,7 +66,6 @@ XMLHttpRequestStaticData::XMLHttpRequestStaticData()
m_forbiddenRequestHeaders.add("accept-encoding");
m_forbiddenRequestHeaders.add("access-control-request-headers");
m_forbiddenRequestHeaders.add("access-control-request-method");
- m_forbiddenRequestHeaders.add("authorization");
m_forbiddenRequestHeaders.add("connection");
m_forbiddenRequestHeaders.add("content-length");
m_forbiddenRequestHeaders.add("content-transfer-encoding");
@@ -284,10 +283,20 @@ void XMLHttpRequest::callReadyStateChangeListener()
dispatchReadyStateChangeEvent();
- if (m_state == DONE)
+ if (m_state == DONE && !m_error)
dispatchLoadEvent();
}
+void XMLHttpRequest::setWithCredentials(bool value, ExceptionCode& ec)
+{
+ if (m_state != OPENED || m_loader) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+
+ m_includeCredentials = value;
+}
+
void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec)
{
internalAbort();
@@ -381,7 +390,7 @@ void XMLHttpRequest::send(Document* document, ExceptionCode& ec)
if (!initSend(ec))
return;
- if (m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {
+ if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
String contentType = getRequestHeader("Content-Type");
if (contentType.isEmpty()) {
#if ENABLE(DASHBOARD_SUPPORT)
@@ -412,7 +421,7 @@ void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
if (!initSend(ec))
return;
- if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {
+ if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
String contentType = getRequestHeader("Content-Type");
if (contentType.isEmpty()) {
#if ENABLE(DASHBOARD_SUPPORT)
@@ -436,7 +445,7 @@ void XMLHttpRequest::send(File* body, ExceptionCode& ec)
if (!initSend(ec))
return;
- if (m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {
+ if (m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
// FIXME: Should we set a Content-Type if one is not set.
// FIXME: add support for uploading bundles.
m_requestEntityBody = FormData::create();
@@ -509,10 +518,17 @@ void XMLHttpRequest::makeSimpleCrossOriginAccessRequest(ExceptionCode& ec)
{
ASSERT(isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders));
+ // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
+ if (!m_url.protocolInHTTPFamily()) {
+ ec = XMLHttpRequestException::NETWORK_ERR;
+ networkError();
+ return;
+ }
+
KURL url = m_url;
url.setUser(String());
url.setPass(String());
-
+
ResourceRequest request(url);
request.setHTTPMethod(m_method);
request.setAllowHTTPCookies(m_includeCredentials);
@@ -636,7 +652,9 @@ void XMLHttpRequest::loadRequestSynchronously(ResourceRequest& request, Exceptio
m_loader = 0;
m_exceptionCode = 0;
- ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this);
+ StoredCredentials storedCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
+
+ ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this, storedCredentials);
if (!m_exceptionCode && m_error)
m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;
ec = m_exceptionCode;
@@ -650,15 +668,13 @@ void XMLHttpRequest::loadRequestAsynchronously(ResourceRequest& request)
// This is true while running onunload handlers.
// FIXME: We need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
// FIXME: Maybe create can return null for other reasons too?
- // We need to keep content sniffing enabled for local files due to CFNetwork not providing a MIME type
- // for local files otherwise, <rdar://problem/5671813>.
LoadCallbacks callbacks = m_inPreflight ? DoNotSendLoadCallbacks : SendLoadCallbacks;
- ContentSniff contentSniff = request.url().isLocalFile() ? SniffContent : DoNotSniffContent;
+ StoredCredentials storedCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
if (m_upload)
request.setReportUploadProgress(true);
- m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, callbacks, contentSniff);
+ m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, callbacks, DoNotSniffContent, storedCredentials, RequireSameRedirectOrigin);
if (m_loader) {
// Neither this object nor the JavaScript wrapper should be deleted while
@@ -682,7 +698,7 @@ void XMLHttpRequest::abort()
if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
m_state = UNSENT;
- else {
+ else {
ASSERT(!m_loader);
changeState(DONE);
m_state = UNSENT;
@@ -736,8 +752,7 @@ void XMLHttpRequest::genericError()
clearRequest();
m_error = true;
- // The spec says we should "Synchronously switch the state to DONE." and then "Synchronously dispatch a readystatechange event on the object"
- // but this does not match Firefox.
+ changeState(DONE);
}
void XMLHttpRequest::networkError()
diff --git a/WebCore/xml/XMLHttpRequest.h b/WebCore/xml/XMLHttpRequest.h
index 544866a..6955c11 100644
--- a/WebCore/xml/XMLHttpRequest.h
+++ b/WebCore/xml/XMLHttpRequest.h
@@ -63,6 +63,8 @@ public:
String statusText(ExceptionCode&) const;
int status(ExceptionCode&) const;
State readyState() const;
+ bool withCredentials() const { return m_includeCredentials; }
+ void setWithCredentials(bool, ExceptionCode&);
void open(const String& method, const KURL&, bool async, ExceptionCode&);
void open(const String& method, const KURL&, bool async, const String& user, ExceptionCode&);
void open(const String& method, const KURL&, bool async, const String& user, const String& password, ExceptionCode&);
@@ -195,7 +197,7 @@ private:
RefPtr<FormData> m_requestEntityBody;
String m_mimeTypeOverride;
bool m_async;
- bool m_includeCredentials; // FIXME: Currently, setting this flag is not implemented, so it is always false.
+ bool m_includeCredentials;
RefPtr<ThreadableLoader> m_loader;
State m_state;
diff --git a/WebCore/xml/XMLHttpRequest.idl b/WebCore/xml/XMLHttpRequest.idl
index 3187160..79005e2 100644
--- a/WebCore/xml/XMLHttpRequest.idl
+++ b/WebCore/xml/XMLHttpRequest.idl
@@ -53,6 +53,8 @@ module xml {
readonly attribute unsigned short readyState;
// request
+ attribute boolean withCredentials
+ setter raises(DOMException);
// void open(in DOMString method, in DOMString url);
// void open(in DOMString method, in DOMString url, in boolean async);
// void open(in DOMString method, in DOMString url, in boolean async, in DOMString user);
diff --git a/WebCore/xml/XMLHttpRequestException.idl b/WebCore/xml/XMLHttpRequestException.idl
index 706beb2..380e426 100644
--- a/WebCore/xml/XMLHttpRequestException.idl
+++ b/WebCore/xml/XMLHttpRequestException.idl
@@ -37,7 +37,7 @@ module xml {
readonly attribute DOMString name;
readonly attribute DOMString message;
-#if defined(LANGUAGE_JAVASCRIPT)
+#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
// Override in a Mozilla compatible format
[DontEnum] DOMString toString();
#endif
diff --git a/WebCore/xml/XPathException.idl b/WebCore/xml/XPathException.idl
index 6e25514..c3c95e3 100644
--- a/WebCore/xml/XPathException.idl
+++ b/WebCore/xml/XPathException.idl
@@ -37,7 +37,7 @@ module xpath {
readonly attribute DOMString name;
readonly attribute DOMString message;
-#if defined(LANGUAGE_JAVASCRIPT)
+#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
// Override in a Mozilla compatible format
[DontEnum] DOMString toString();
#endif
diff --git a/WebCore/xml/XPathExpression.cpp b/WebCore/xml/XPathExpression.cpp
index ecec79e..6188426 100644
--- a/WebCore/xml/XPathExpression.cpp
+++ b/WebCore/xml/XPathExpression.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,9 +30,8 @@
#if ENABLE(XPATH)
#include "Document.h"
-#include "ExceptionCode.h"
-#include "Node.h"
#include "PlatformString.h"
+#include "XPathException.h"
#include "XPathExpressionNode.h"
#include "XPathNSResolver.h"
#include "XPathParser.h"
@@ -67,15 +66,21 @@ PassRefPtr<XPathResult> XPathExpression::evaluate(Node* contextNode, unsigned sh
return 0;
}
- Node* eventTarget = contextNode->ownerDocument() ? contextNode->ownerDocument() : contextNode;
-
EvaluationContext& evaluationContext = Expression::evaluationContext();
evaluationContext.node = contextNode;
evaluationContext.size = 1;
evaluationContext.position = 1;
- RefPtr<XPathResult> result = XPathResult::create(eventTarget, m_topExpression->evaluate());
+ evaluationContext.hadTypeConversionError = false;
+ RefPtr<XPathResult> result = XPathResult::create(contextNode->document(), m_topExpression->evaluate());
evaluationContext.node = 0; // Do not hold a reference to the context node, as this may prevent the whole document from being destroyed in time.
+ if (evaluationContext.hadTypeConversionError) {
+ // It is not specified what to do if type conversion fails while evaluating an expression, and INVALID_EXPRESSION_ERR is not exactly right
+ // when the failure happens in an otherwise valid expression because of a variable. But XPathEvaluator does not support variables, so it's close enough.
+ ec = XPathException::INVALID_EXPRESSION_ERR;
+ return 0;
+ }
+
if (type != XPathResult::ANY_TYPE) {
ec = 0;
result->convertTo(type, ec);
diff --git a/WebCore/xml/XPathExpressionNode.cpp b/WebCore/xml/XPathExpressionNode.cpp
index 647c6af..4656f8d 100644
--- a/WebCore/xml/XPathExpressionNode.cpp
+++ b/WebCore/xml/XPathExpressionNode.cpp
@@ -30,7 +30,6 @@
#if ENABLE(XPATH)
#include "Node.h"
-#include "XPathValue.h"
#include <wtf/StdLibExtras.h>
namespace WebCore {
@@ -43,6 +42,9 @@ EvaluationContext& Expression::evaluationContext()
}
Expression::Expression()
+ : m_isContextNodeSensitive(false)
+ , m_isContextPositionSensitive(false)
+ , m_isContextSizeSensitive(false)
{
}
diff --git a/WebCore/xml/XPathExpressionNode.h b/WebCore/xml/XPathExpressionNode.h
index 9c5f79b..d12b451 100644
--- a/WebCore/xml/XPathExpressionNode.h
+++ b/WebCore/xml/XPathExpressionNode.h
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,23 +31,21 @@
#include "StringHash.h"
#include "Node.h"
+#include "XPathValue.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
namespace WebCore {
namespace XPath {
-
- class Value;
struct EvaluationContext {
- EvaluationContext() : node(0), size(0), position(0) { }
-
RefPtr<Node> node;
unsigned long size;
unsigned long position;
HashMap<String, String> variableBindings;
+ bool hadTypeConversionError;
};
class ParseNode {
@@ -64,7 +62,22 @@ namespace WebCore {
virtual Value evaluate() const = 0;
- void addSubExpression(Expression* expr) { m_subExpressions.append(expr); }
+ void addSubExpression(Expression* expr)
+ {
+ m_subExpressions.append(expr);
+ m_isContextNodeSensitive |= expr->m_isContextNodeSensitive;
+ m_isContextPositionSensitive |= expr->m_isContextPositionSensitive;
+ m_isContextSizeSensitive |= expr->m_isContextSizeSensitive;
+ }
+
+ bool isContextNodeSensitive() const { return m_isContextNodeSensitive; }
+ bool isContextPositionSensitive() const { return m_isContextPositionSensitive; }
+ bool isContextSizeSensitive() const { return m_isContextSizeSensitive; }
+ void setIsContextNodeSensitive(bool value) { m_isContextNodeSensitive = value; }
+ void setIsContextPositionSensitive(bool value) { m_isContextPositionSensitive = value; }
+ void setIsContextSizeSensitive(bool value) { m_isContextSizeSensitive = value; }
+
+ virtual Value::Type resultType() const = 0;
protected:
unsigned subExprCount() const { return m_subExpressions.size(); }
@@ -73,6 +86,11 @@ namespace WebCore {
private:
Vector<Expression*> m_subExpressions;
+
+ // Evaluation details that can be used for optimization.
+ bool m_isContextNodeSensitive;
+ bool m_isContextPositionSensitive;
+ bool m_isContextSizeSensitive;
};
}
diff --git a/WebCore/xml/XPathFunctions.cpp b/WebCore/xml/XPathFunctions.cpp
index 3abd603..da39443 100644
--- a/WebCore/xml/XPathFunctions.cpp
+++ b/WebCore/xml/XPathFunctions.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,8 @@
#include "Document.h"
#include "Element.h"
-#include "NamedAttrMap.h"
+#include "NamedNodeMap.h"
+#include "ProcessingInstruction.h"
#include "XMLNames.h"
#include "XPathUtil.h"
#include "XPathValue.h"
@@ -74,110 +75,157 @@ static HashMap<String, FunctionRec>* functionMap;
class FunLast : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunLast() { setIsContextSizeSensitive(true); }
};
class FunPosition : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunPosition() { setIsContextPositionSensitive(true); }
};
class FunCount : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
};
class FunId : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
};
class FunLocalName : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunLocalName() { setIsContextNodeSensitive(true); } // local-name() with no arguments uses context node.
};
class FunNamespaceURI : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunNamespaceURI() { setIsContextNodeSensitive(true); } // namespace-uri() with no arguments uses context node.
};
class FunName : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunName() { setIsContextNodeSensitive(true); } // name() with no arguments uses context node.
};
class FunString : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunString() { setIsContextNodeSensitive(true); } // string() with no arguments uses context node.
};
class FunConcat : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
};
class FunStartsWith : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
};
class FunContains : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
};
class FunSubstringBefore : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
};
class FunSubstringAfter : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
};
class FunSubstring : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
};
class FunStringLength : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunStringLength() { setIsContextNodeSensitive(true); } // string-length() with no arguments uses context node.
};
class FunNormalizeSpace : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+public:
+ FunNormalizeSpace() { setIsContextNodeSensitive(true); } // normalize-space() with no arguments uses context node.
};
class FunTranslate : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
};
class FunBoolean : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
};
class FunNot : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
};
class FunTrue : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
};
class FunFalse : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
};
class FunLang : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
+public:
+ FunLang() { setIsContextNodeSensitive(true); } // lang() always works on context node.
};
class FunNumber : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+public:
+ FunNumber() { setIsContextNodeSensitive(true); } // number() with no arguments uses context node.
};
class FunSum : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
};
class FunFloor : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
};
class FunCeiling : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
};
class FunRound : public Function {
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
public:
static double round(double);
};
@@ -246,8 +294,13 @@ inline bool Interval::contains(int value) const
void Function::setArguments(const Vector<Expression*>& args)
{
- Vector<Expression*>::const_iterator end = args.end();
+ ASSERT(!subExprCount());
+
+ // Some functions use context node as implicit argument, so when explicit arguments are added, they may no longer be context node sensitive.
+ if (m_name != "lang" && !args.isEmpty())
+ setIsContextNodeSensitive(false);
+ Vector<Expression*>::const_iterator end = args.end();
for (Vector<Expression*>::const_iterator it = args.begin(); it != end; it++)
addSubExpression(*it);
}
@@ -310,71 +363,67 @@ Value FunId::evaluate() const
return Value(result, Value::adopt);
}
+static inline String expandedNameLocalPart(Node* node)
+{
+ // The local part of an XPath expanded-name matches DOM local name for most node types, except for namespace nodes and processing instruction nodes.
+ ASSERT(node->nodeType() != Node::XPATH_NAMESPACE_NODE); // Not supported yet.
+ if (node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
+ return static_cast<ProcessingInstruction*>(node)->target();
+ return node->localName().string();
+}
+
+static inline String expandedName(Node* node)
+{
+ const AtomicString& prefix = node->prefix();
+ return prefix.isEmpty() ? expandedNameLocalPart(node) : prefix + ":" + expandedNameLocalPart(node);
+}
+
Value FunLocalName::evaluate() const
{
- Node* node = 0;
if (argCount() > 0) {
Value a = arg(0)->evaluate();
if (!a.isNodeSet())
return "";
- node = a.toNodeSet().firstNode();
- if (!node)
- return "";
+ Node* node = a.toNodeSet().firstNode();
+ return node ? expandedNameLocalPart(node) : "";
}
- if (!node)
- node = evaluationContext().node.get();
-
- return node->localName().string();
+ return expandedNameLocalPart(evaluationContext().node.get());
}
Value FunNamespaceURI::evaluate() const
{
- Node* node = 0;
if (argCount() > 0) {
Value a = arg(0)->evaluate();
if (!a.isNodeSet())
return "";
- node = a.toNodeSet().firstNode();
- if (!node)
- return "";
+ Node* node = a.toNodeSet().firstNode();
+ return node ? node->namespaceURI().string() : "";
}
- if (!node)
- node = evaluationContext().node.get();
-
- return node->namespaceURI().string();
+ return evaluationContext().node->namespaceURI().string();
}
Value FunName::evaluate() const
{
- Node* node = 0;
if (argCount() > 0) {
Value a = arg(0)->evaluate();
if (!a.isNodeSet())
return "";
- node = a.toNodeSet().firstNode();
- if (!node)
- return "";
+ Node* node = a.toNodeSet().firstNode();
+ return node ? expandedName(node) : "";
}
- if (!node)
- node = evaluationContext().node.get();
-
- const AtomicString& prefix = node->prefix();
- return prefix.isEmpty() ? node->localName().string() : prefix + ":" + node->localName();
+ return expandedName(evaluationContext().node.get());
}
Value FunCount::evaluate() const
{
Value a = arg(0)->evaluate();
- if (!a.isNodeSet())
- return 0.0;
-
return double(a.toNodeSet().size());
}
@@ -537,7 +586,7 @@ Value FunLang::evaluate() const
Attribute* languageAttribute = 0;
Node* node = evaluationContext().node.get();
while (node) {
- NamedAttrMap* attrs = node->attributes();
+ NamedNodeMap* attrs = node->attributes();
if (attrs)
languageAttribute = attrs->getAttributeItem(XMLNames::langAttr);
if (languageAttribute)
diff --git a/WebCore/xml/XPathFunctions.h b/WebCore/xml/XPathFunctions.h
index f22d3ef..62d687f 100644
--- a/WebCore/xml/XPathFunctions.h
+++ b/WebCore/xml/XPathFunctions.h
@@ -1,6 +1,6 @@
/*
- * functions.h - Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,7 +39,6 @@ namespace WebCore {
public:
void setArguments(const Vector<Expression*>&);
void setName(const String& name) { m_name = name; }
-
protected:
Expression* arg(int pos) { return subExpr(pos); }
const Expression* arg(int pos) const { return subExpr(pos); }
@@ -52,11 +51,10 @@ namespace WebCore {
Function* createFunction(const String& name, const Vector<Expression*>& args = Vector<Expression*>());
- }
+ } // namespace XPath
-}
+} // namespace WebCore
#endif // ENABLE(XPATH)
-#endif // XPath_Functions_H
-
+#endif // XPathFunctions_h
diff --git a/WebCore/xml/XPathNodeSet.h b/WebCore/xml/XPathNodeSet.h
index 2ab6f1f..1130488 100644
--- a/WebCore/xml/XPathNodeSet.h
+++ b/WebCore/xml/XPathNodeSet.h
@@ -39,17 +39,14 @@ namespace WebCore {
class NodeSet {
public:
-
- NodeSet() : m_isSorted(true) {}
- NodeSet(const NodeSet& other) : m_isSorted(other.m_isSorted), m_nodes(other.m_nodes) {}
- NodeSet& operator=(const NodeSet& other) { m_isSorted = other.m_isSorted; m_nodes = other.m_nodes; return *this; }
+ NodeSet() : m_isSorted(true), m_subtreesAreDisjoint(false) { }
size_t size() const { return m_nodes.size(); }
bool isEmpty() const { return !m_nodes.size(); }
Node* operator[](unsigned i) const { return m_nodes.at(i).get(); }
void reserveCapacity(size_t newCapacity) { m_nodes.reserveCapacity(newCapacity); }
void clear() { m_nodes.clear(); }
- void swap(NodeSet& other) { std::swap(m_isSorted, other.m_isSorted); m_nodes.swap(other.m_nodes); }
+ void swap(NodeSet& other) { std::swap(m_isSorted, other.m_isSorted); std::swap(m_subtreesAreDisjoint, other.m_subtreesAreDisjoint); m_nodes.swap(other.m_nodes); }
// NodeSet itself does not verify that nodes in it are unique.
void append(Node* node) { m_nodes.append(node); }
@@ -62,16 +59,21 @@ namespace WebCore {
// Returns 0 if the set is empty.
Node* anyNode() const;
- // NodeSet itself doesn't check if it is contains sorted data - the caller should tell it if it does not.
+ // NodeSet itself doesn't check if it contains nodes in document order - the caller should tell it if it does not.
void markSorted(bool isSorted) { m_isSorted = isSorted; }
- bool isSorted() const { return m_isSorted; }
+ bool isSorted() const { return m_isSorted || m_nodes.size() < 2; }
void sort() const;
+ // No node in the set is ancestor of another. Unlike m_isSorted, this is assumed to be false, unless the caller sets it to true.
+ void markSubtreesDisjoint(bool disjoint) { m_subtreesAreDisjoint = disjoint; }
+ bool subtreesAreDisjoint() const { return m_subtreesAreDisjoint || m_nodes.size() < 2; }
+
void reverse();
private:
bool m_isSorted;
+ bool m_subtreesAreDisjoint;
Vector<RefPtr<Node> > m_nodes;
};
diff --git a/WebCore/xml/XPathPath.cpp b/WebCore/xml/XPathPath.cpp
index bc7b153..1a7ed3f 100644
--- a/WebCore/xml/XPathPath.cpp
+++ b/WebCore/xml/XPathPath.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,9 @@ namespace XPath {
Filter::Filter(Expression* expr, const Vector<Predicate*>& predicates)
: m_expr(expr), m_predicates(predicates)
{
+ setIsContextNodeSensitive(m_expr->isContextNodeSensitive());
+ setIsContextPositionSensitive(m_expr->isContextPositionSensitive());
+ setIsContextSizeSensitive(m_expr->isContextSizeSensitive());
}
Filter::~Filter()
@@ -53,9 +56,6 @@ Value Filter::evaluate() const
{
Value v = m_expr->evaluate();
- if (!v.isNodeSet())
- return v;
-
NodeSet& nodes = v.modifiableNodeSet();
nodes.sort();
@@ -83,6 +83,7 @@ Value Filter::evaluate() const
LocationPath::LocationPath()
: m_absolute(false)
{
+ setIsContextNodeSensitive(true);
}
LocationPath::~LocationPath()
@@ -94,9 +95,8 @@ Value LocationPath::evaluate() const
{
EvaluationContext& evaluationContext = Expression::evaluationContext();
EvaluationContext backupContext = evaluationContext;
- /* For absolute location paths, the context node is ignored - the
- * document's root node is used instead.
- */
+ // For absolute location paths, the context node is ignored - the
+ // document's root node is used instead.
Node* context = evaluationContext.node.get();
if (m_absolute && context->nodeType() != Node::DOCUMENT_NODE)
context = context->ownerDocument();
@@ -111,18 +111,33 @@ Value LocationPath::evaluate() const
void LocationPath::evaluate(NodeSet& nodes) const
{
+ bool resultIsSorted = nodes.isSorted();
+
for (unsigned i = 0; i < m_steps.size(); i++) {
Step* step = m_steps[i];
NodeSet newNodes;
HashSet<Node*> newNodesSet;
+ bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step->axis() != Step::ChildAxis && step->axis() != Step::SelfAxis
+ && step->axis() != Step::DescendantAxis && step->axis() != Step::DescendantOrSelfAxis && step->axis() != Step::AttributeAxis);
+
+ if (needToCheckForDuplicateNodes)
+ resultIsSorted = false;
+
+ // This is a simplified check that can be improved to handle more cases.
+ if (nodes.subtreesAreDisjoint() && (step->axis() == Step::ChildAxis || step->axis() == Step::SelfAxis))
+ newNodes.markSubtreesDisjoint(true);
+
for (unsigned j = 0; j < nodes.size(); j++) {
NodeSet matches;
step->evaluate(nodes[j], matches);
-
+
+ if (!matches.isSorted())
+ resultIsSorted = false;
+
for (size_t nodeIndex = 0; nodeIndex < matches.size(); ++nodeIndex) {
Node* node = matches[nodeIndex];
- if (newNodesSet.add(node).second)
+ if (!needToCheckForDuplicateNodes || newNodesSet.add(node).second)
newNodes.append(node);
}
}
@@ -130,53 +145,46 @@ void LocationPath::evaluate(NodeSet& nodes) const
nodes.swap(newNodes);
}
- nodes.markSorted(false);
+ nodes.markSorted(resultIsSorted);
}
-void LocationPath::optimizeStepPair(unsigned index)
+void LocationPath::appendStep(Step* step)
{
- Step* first = m_steps[index];
-
- if (first->axis() == Step::DescendantOrSelfAxis
- && first->nodeTest().kind() == Step::NodeTest::AnyNodeTest
- && first->predicates().size() == 0) {
-
- Step* second = m_steps[index + 1];
- if (second->axis() == Step::ChildAxis
- && second->nodeTest().namespaceURI().isEmpty()
- && second->nodeTest().kind() == Step::NodeTest::NameTest
- && second->nodeTest().data() == "*") {
-
- // Optimize the common case of "//*" AKA descendant-or-self::node()/child::*.
- first->setAxis(Step::DescendantAxis);
- second->setAxis(Step::SelfAxis);
- second->setNodeTest(Step::NodeTest::ElementNodeTest);
- ASSERT(second->nodeTest().data().isEmpty());
+ unsigned stepCount = m_steps.size();
+ if (stepCount) {
+ bool dropSecondStep;
+ optimizeStepPair(m_steps[stepCount - 1], step, dropSecondStep);
+ if (dropSecondStep) {
+ delete step;
+ return;
}
}
-}
-
-void LocationPath::appendStep(Step* step)
-{
+ step->optimize();
m_steps.append(step);
-
- unsigned stepCount = m_steps.size();
- if (stepCount > 1)
- optimizeStepPair(stepCount - 2);
}
void LocationPath::insertFirstStep(Step* step)
{
+ if (m_steps.size()) {
+ bool dropSecondStep;
+ optimizeStepPair(step, m_steps[0], dropSecondStep);
+ if (dropSecondStep) {
+ delete m_steps[0];
+ m_steps[0] = step;
+ return;
+ }
+ }
+ step->optimize();
m_steps.insert(0, step);
-
- if (m_steps.size() > 1)
- optimizeStepPair(0);
}
Path::Path(Filter* filter, LocationPath* path)
- : m_filter(filter),
- m_path(path)
+ : m_filter(filter)
+ , m_path(path)
{
+ setIsContextNodeSensitive(filter->isContextNodeSensitive());
+ setIsContextPositionSensitive(filter->isContextPositionSensitive());
+ setIsContextSizeSensitive(filter->isContextSizeSensitive());
}
Path::~Path()
diff --git a/WebCore/xml/XPathPath.h b/WebCore/xml/XPathPath.h
index 46e57ff..dc77971 100644
--- a/WebCore/xml/XPathPath.h
+++ b/WebCore/xml/XPathPath.h
@@ -1,6 +1,6 @@
/*
- * path.h - Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -47,6 +47,8 @@ namespace WebCore {
virtual Value evaluate() const;
private:
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+
Expression* m_expr;
Vector<Predicate*> m_predicates;
};
@@ -55,7 +57,7 @@ namespace WebCore {
public:
LocationPath();
virtual ~LocationPath();
- void setAbsolute(bool value) { m_absolute = value; }
+ void setAbsolute(bool value) { m_absolute = value; setIsContextNodeSensitive(!m_absolute); }
virtual Value evaluate() const;
void evaluate(NodeSet& nodes) const; // nodes is an input/output parameter
@@ -64,7 +66,7 @@ namespace WebCore {
void insertFirstStep(Step* step);
private:
- void optimizeStepPair(unsigned index);
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
Vector<Step*> m_steps;
bool m_absolute;
@@ -79,6 +81,8 @@ namespace WebCore {
virtual Value evaluate() const;
private:
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
+
Filter* m_filter;
LocationPath* m_path;
};
diff --git a/WebCore/xml/XPathPredicate.cpp b/WebCore/xml/XPathPredicate.cpp
index 7b3e4d8..2a6482f 100644
--- a/WebCore/xml/XPathPredicate.cpp
+++ b/WebCore/xml/XPathPredicate.cpp
@@ -233,8 +233,6 @@ Value Union::evaluate() const
{
Value lhsResult = subExpr(0)->evaluate();
Value rhs = subExpr(1)->evaluate();
- if (!lhsResult.isNodeSet() || !rhs.isNodeSet())
- return NodeSet();
NodeSet& resultSet = lhsResult.modifiableNodeSet();
const NodeSet& rhsNodes = rhs.toNodeSet();
diff --git a/WebCore/xml/XPathPredicate.h b/WebCore/xml/XPathPredicate.h
index 8d1b0d8..6c9d413 100644
--- a/WebCore/xml/XPathPredicate.h
+++ b/WebCore/xml/XPathPredicate.h
@@ -41,6 +41,8 @@ namespace WebCore {
Number(double);
private:
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+
Value m_value;
};
@@ -49,12 +51,15 @@ namespace WebCore {
StringExpression(const String&);
private:
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::StringValue; }
+
Value m_value;
};
class Negative : public Expression {
private:
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
};
class NumericOp : public Expression {
@@ -65,6 +70,8 @@ namespace WebCore {
NumericOp(Opcode, Expression* lhs, Expression* rhs);
private:
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NumberValue; }
+
Opcode m_opcode;
};
@@ -74,7 +81,9 @@ namespace WebCore {
EqTestOp(Opcode, Expression* lhs, Expression* rhs);
virtual Value evaluate() const;
private:
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
bool compare(const Value&, const Value&) const;
+
Opcode m_opcode;
};
@@ -83,14 +92,17 @@ namespace WebCore {
enum Opcode { OP_And, OP_Or };
LogicalOp(Opcode, Expression* lhs, Expression* rhs);
private:
+ virtual Value::Type resultType() const { return Value::BooleanValue; }
bool shortCircuitOn() const;
virtual Value evaluate() const;
+
Opcode m_opcode;
};
class Union : public Expression {
private:
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { return Value::NodeSetValue; }
};
class Predicate : Noncopyable {
@@ -98,6 +110,10 @@ namespace WebCore {
Predicate(Expression*);
~Predicate();
bool evaluate() const;
+
+ bool isContextPositionSensitive() const { return m_expr->isContextPositionSensitive() || m_expr->resultType() == Value::NumberValue; }
+ bool isContextSizeSensitive() const { return m_expr->isContextSizeSensitive(); }
+
private:
Expression* m_expr;
};
diff --git a/WebCore/xml/XPathResult.cpp b/WebCore/xml/XPathResult.cpp
index a1c8a08..b608280 100644
--- a/WebCore/xml/XPathResult.cpp
+++ b/WebCore/xml/XPathResult.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,8 +29,7 @@
#if ENABLE(XPATH)
-#include "EventListener.h"
-#include "EventNames.h"
+#include "Document.h"
#include "Node.h"
#include "ExceptionCode.h"
#include "XPathEvaluator.h"
@@ -40,22 +39,9 @@ namespace WebCore {
using namespace XPath;
-class InvalidatingEventListener : public EventListener {
-public:
- static PassRefPtr<InvalidatingEventListener> create(XPathResult* result) { return adoptRef(new InvalidatingEventListener(result)); }
- virtual void handleEvent(Event*, bool) { m_result->invalidateIteratorState(); }
-
-private:
- InvalidatingEventListener(XPathResult* result) : m_result(result) { }
- XPathResult* m_result;
-};
-
-XPathResult::XPathResult(Node* eventTarget, const Value& value)
+XPathResult::XPathResult(Document* document, const Value& value)
: m_value(value)
- , m_eventTarget(eventTarget)
{
- m_eventListener = InvalidatingEventListener::create(this);
- m_eventTarget->addEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener, false);
switch (m_value.type()) {
case Value::BooleanValue:
m_resultType = BOOLEAN_TYPE;
@@ -70,7 +56,8 @@ XPathResult::XPathResult(Node* eventTarget, const Value& value)
m_resultType = UNORDERED_NODE_ITERATOR_TYPE;
m_nodeSetPosition = 0;
m_nodeSet = m_value.toNodeSet();
- m_invalidIteratorState = false;
+ m_document = document;
+ m_domTreeVersion = document->domTreeVersion();
return;
}
ASSERT_NOT_REACHED();
@@ -78,8 +65,6 @@ XPathResult::XPathResult(Node* eventTarget, const Value& value)
XPathResult::~XPathResult()
{
- if (m_eventTarget)
- m_eventTarget->removeEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false);
}
void XPathResult::convertTo(unsigned short type, ExceptionCode& ec)
@@ -174,24 +159,13 @@ Node* XPathResult::singleNodeValue(ExceptionCode& ec) const
return nodes.anyNode();
}
-void XPathResult::invalidateIteratorState()
-{
- m_invalidIteratorState = true;
-
- ASSERT(m_eventTarget);
- ASSERT(m_eventListener);
-
- m_eventTarget->removeEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false);
-
- m_eventTarget = 0;
-}
-
bool XPathResult::invalidIteratorState() const
{
if (resultType() != UNORDERED_NODE_ITERATOR_TYPE && resultType() != ORDERED_NODE_ITERATOR_TYPE)
return false;
-
- return m_invalidIteratorState;
+
+ ASSERT(m_document);
+ return m_document->domTreeVersion() != m_domTreeVersion;
}
unsigned long XPathResult::snapshotLength(ExceptionCode& ec) const
@@ -211,7 +185,7 @@ Node* XPathResult::iterateNext(ExceptionCode& ec)
return 0;
}
- if (m_invalidIteratorState) {
+ if (invalidIteratorState()) {
ec = INVALID_STATE_ERR;
return 0;
}
diff --git a/WebCore/xml/XPathResult.h b/WebCore/xml/XPathResult.h
index 03accc6..3b91d66 100644
--- a/WebCore/xml/XPathResult.h
+++ b/WebCore/xml/XPathResult.h
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,15 +29,14 @@
#if ENABLE(XPATH)
-#include <wtf/RefCounted.h>
#include "XPathValue.h"
+#include <wtf/RefCounted.h>
namespace WebCore {
typedef int ExceptionCode;
- class EventListener;
- class Node;
+ class Document;
class Node;
class String;
@@ -56,7 +55,7 @@ namespace WebCore {
FIRST_ORDERED_NODE_TYPE = 9
};
- static PassRefPtr<XPathResult> create(Node* eventTarget, const XPath::Value& value) { return adoptRef(new XPathResult(eventTarget, value)); }
+ static PassRefPtr<XPathResult> create(Document* document, const XPath::Value& value) { return adoptRef(new XPathResult(document, value)); }
~XPathResult();
void convertTo(unsigned short type, ExceptionCode&);
@@ -73,21 +72,18 @@ namespace WebCore {
Node* iterateNext(ExceptionCode&);
Node* snapshotItem(unsigned long index, ExceptionCode&);
- void invalidateIteratorState();
-
private:
- XPathResult(Node*, const XPath::Value&);
+ XPathResult(Document*, const XPath::Value&);
XPath::Value m_value;
unsigned m_nodeSetPosition;
XPath::NodeSet m_nodeSet; // FIXME: why duplicate the node set stored in m_value?
unsigned short m_resultType;
- bool m_invalidIteratorState;
- RefPtr<Node> m_eventTarget;
- RefPtr<EventListener> m_eventListener;
+ RefPtr<Document> m_document;
+ unsigned m_domTreeVersion;
};
-}
+} // namespace WebCore
#endif // ENABLE(XPATH)
diff --git a/WebCore/xml/XPathStep.cpp b/WebCore/xml/XPathStep.cpp
index ae8d9c4..411b616 100644
--- a/WebCore/xml/XPathStep.cpp
+++ b/WebCore/xml/XPathStep.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -30,10 +30,10 @@
#if ENABLE(XPATH)
+#include "Attr.h"
#include "Document.h"
#include "Element.h"
-#include "NamedAttrMap.h"
-#include "XPathNSResolver.h"
+#include "NamedNodeMap.h"
#include "XPathParser.h"
#include "XPathUtil.h"
@@ -50,14 +50,74 @@ Step::Step(Axis axis, const NodeTest& nodeTest, const Vector<Predicate*>& predic
Step::~Step()
{
deleteAllValues(m_predicates);
+ deleteAllValues(m_nodeTest.mergedPredicates());
+}
+
+void Step::optimize()
+{
+ // Evaluate predicates as part of node test if possible to avoid building unnecessary NodeSets.
+ // E.g., there is no need to build a set of all "foo" nodes to evaluate "foo[@bar]", we can check the predicate while enumerating.
+ // This optimization can be applied to predicates that are not context node list sensitive, or to first predicate that is only context position sensitive, e.g. foo[position() mod 2 = 0].
+ Vector<Predicate*> remainingPredicates;
+ for (size_t i = 0; i < m_predicates.size(); ++i) {
+ Predicate* predicate = m_predicates[i];
+ if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredicates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates.isEmpty()) {
+ m_nodeTest.mergedPredicates().append(predicate);
+ } else
+ remainingPredicates.append(predicate);
+ }
+ swap(remainingPredicates, m_predicates);
+}
+
+void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep)
+{
+ dropSecondStep = false;
+
+ if (first->m_axis == Step::DescendantOrSelfAxis
+ && first->m_nodeTest.kind() == Step::NodeTest::AnyNodeTest
+ && !first->m_predicates.size()
+ && !first->m_nodeTest.mergedPredicates().size()) {
+
+ ASSERT(first->m_nodeTest.data().isEmpty());
+ ASSERT(first->m_nodeTest.namespaceURI().isEmpty());
+
+ // Optimize the common case of "//" AKA /descendant-or-self::node()/child::NodeTest to /descendant::NodeTest.
+ if (second->m_axis == Step::ChildAxis && second->predicatesAreContextListInsensitive()) {
+ first->m_axis = Step::DescendantAxis;
+ first->m_nodeTest = Step::NodeTest(second->m_nodeTest.kind(), second->m_nodeTest.data(), second->m_nodeTest.namespaceURI());
+ swap(second->m_nodeTest.mergedPredicates(), first->m_nodeTest.mergedPredicates());
+ swap(second->m_predicates, first->m_predicates);
+ first->optimize();
+ dropSecondStep = true;
+ }
+ }
+}
+
+bool Step::predicatesAreContextListInsensitive() const
+{
+ for (size_t i = 0; i < m_predicates.size(); ++i) {
+ Predicate* predicate = m_predicates[i];
+ if (predicate->isContextPositionSensitive() || predicate->isContextSizeSensitive())
+ return false;
+ }
+
+ for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) {
+ Predicate* predicate = m_nodeTest.mergedPredicates()[i];
+ if (predicate->isContextPositionSensitive() || predicate->isContextSizeSensitive())
+ return false;
+ }
+
+ return true;
}
void Step::evaluate(Node* context, NodeSet& nodes) const
{
- nodesInAxis(context, nodes);
-
EvaluationContext& evaluationContext = Expression::evaluationContext();
-
+ evaluationContext.position = 0;
+
+ nodesInAxis(context, nodes);
+
+ // Check predicates that couldn't be merged into node test.
for (unsigned i = 0; i < m_predicates.size(); i++) {
Predicate* predicate = m_predicates[i];
@@ -68,7 +128,7 @@ void Step::evaluate(Node* context, NodeSet& nodes) const
for (unsigned j = 0; j < nodes.size(); j++) {
Node* node = nodes[j];
- Expression::evaluationContext().node = node;
+ evaluationContext.node = node;
evaluationContext.size = nodes.size();
evaluationContext.position = j + 1;
if (predicate->evaluate())
@@ -79,6 +139,95 @@ void Step::evaluate(Node* context, NodeSet& nodes) const
}
}
+static inline Node::NodeType primaryNodeType(Step::Axis axis)
+{
+ switch (axis) {
+ case Step::AttributeAxis:
+ return Node::ATTRIBUTE_NODE;
+ case Step::NamespaceAxis:
+ return Node::XPATH_NAMESPACE_NODE;
+ default:
+ return Node::ELEMENT_NODE;
+ }
+}
+
+// Evaluate NodeTest without considering merged predicates.
+static inline bool nodeMatchesBasicTest(Node* node, Step::Axis axis, const Step::NodeTest& nodeTest)
+{
+ switch (nodeTest.kind()) {
+ case Step::NodeTest::TextNodeTest:
+ return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE;
+ case Step::NodeTest::CommentNodeTest:
+ return node->nodeType() == Node::COMMENT_NODE;
+ case Step::NodeTest::ProcessingInstructionNodeTest: {
+ const AtomicString& name = nodeTest.data();
+ return node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE && (name.isEmpty() || node->nodeName() == name);
+ }
+ case Step::NodeTest::AnyNodeTest:
+ return true;
+ case Step::NodeTest::NameTest: {
+ const AtomicString& name = nodeTest.data();
+ const AtomicString& namespaceURI = nodeTest.namespaceURI();
+
+ if (axis == Step::AttributeAxis) {
+ ASSERT(node->isAttributeNode());
+
+ // In XPath land, namespace nodes are not accessible on the attribute axis.
+ if (node->namespaceURI() == "http://www.w3.org/2000/xmlns/")
+ return false;
+
+ if (name == starAtom)
+ return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI;
+
+ return node->localName() == name && node->namespaceURI() == namespaceURI;
+ }
+
+ // Node test on the namespace axis is not implemented yet, the caller has a check for it.
+ ASSERT(axis != Step::NamespaceAxis);
+
+ // For other axes, the principal node type is element.
+ ASSERT(primaryNodeType(axis) == Node::ELEMENT_NODE);
+ if (node->nodeType() != Node::ELEMENT_NODE)
+ return false;
+
+ if (name == starAtom)
+ return namespaceURI.isEmpty() || namespaceURI == node->namespaceURI();
+
+ if (node->isHTMLElement() && node->document()->isHTMLDocument()) {
+ // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace. Names are compared case-insensitively.
+ return equalIgnoringCase(static_cast<Element*>(node)->localName(), name) && (namespaceURI.isNull() || namespaceURI == node->namespaceURI());
+ }
+ return static_cast<Element*>(node)->hasLocalName(name) && namespaceURI == node->namespaceURI();
+ }
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest& nodeTest)
+{
+ if (!nodeMatchesBasicTest(node, axis, nodeTest))
+ return false;
+
+ EvaluationContext& evaluationContext = Expression::evaluationContext();
+
+ // Only the first merged predicate may depend on position.
+ ++evaluationContext.position;
+
+ const Vector<Predicate*>& mergedPredicates = nodeTest.mergedPredicates();
+ for (unsigned i = 0; i < mergedPredicates.size(); i++) {
+ Predicate* predicate = mergedPredicates[i];
+
+ evaluationContext.node = node;
+ // No need to set context size - we only get here when evaluating predicates that do not depend on it.
+ if (!predicate->evaluate())
+ return false;
+ }
+
+ return true;
+}
+
+// Result nodes are ordered in axis order. Node test (including merged predicates) is applied.
void Step::nodesInAxis(Node* context, NodeSet& nodes) const
{
ASSERT(nodes.isEmpty());
@@ -88,7 +237,7 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
return;
for (Node* n = context->firstChild(); n; n = n->nextSibling())
- if (nodeMatches(n))
+ if (nodeMatches(n, ChildAxis, m_nodeTest))
nodes.append(n);
return;
case DescendantAxis:
@@ -96,17 +245,17 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
return;
for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context))
- if (nodeMatches(n))
+ if (nodeMatches(n, DescendantAxis, m_nodeTest))
nodes.append(n);
return;
case ParentAxis:
if (context->isAttributeNode()) {
Node* n = static_cast<Attr*>(context)->ownerElement();
- if (nodeMatches(n))
+ if (nodeMatches(n, ParentAxis, m_nodeTest))
nodes.append(n);
} else {
Node* n = context->parentNode();
- if (n && nodeMatches(n))
+ if (n && nodeMatches(n, ParentAxis, m_nodeTest))
nodes.append(n);
}
return;
@@ -114,11 +263,11 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
Node* n = context;
if (context->isAttributeNode()) {
n = static_cast<Attr*>(context)->ownerElement();
- if (nodeMatches(n))
+ if (nodeMatches(n, AncestorAxis, m_nodeTest))
nodes.append(n);
}
for (n = n->parentNode(); n; n = n->parentNode())
- if (nodeMatches(n))
+ if (nodeMatches(n, AncestorAxis, m_nodeTest))
nodes.append(n);
nodes.markSorted(false);
return;
@@ -129,7 +278,7 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
return;
for (Node* n = context->nextSibling(); n; n = n->nextSibling())
- if (nodeMatches(n))
+ if (nodeMatches(n, FollowingSiblingAxis, m_nodeTest))
nodes.append(n);
return;
case PrecedingSiblingAxis:
@@ -138,7 +287,7 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
return;
for (Node* n = context->previousSibling(); n; n = n->previousSibling())
- if (nodeMatches(n))
+ if (nodeMatches(n, PrecedingSiblingAxis, m_nodeTest))
nodes.append(n);
nodes.markSorted(false);
@@ -147,15 +296,15 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
if (context->isAttributeNode()) {
Node* p = static_cast<Attr*>(context)->ownerElement();
while ((p = p->traverseNextNode()))
- if (nodeMatches(p))
+ if (nodeMatches(p, FollowingAxis, m_nodeTest))
nodes.append(p);
} else {
for (Node* p = context; !isRootDomNode(p); p = p->parentNode()) {
for (Node* n = p->nextSibling(); n; n = n->nextSibling()) {
- if (nodeMatches(n))
+ if (nodeMatches(n, FollowingAxis, m_nodeTest))
nodes.append(n);
for (Node* c = n->firstChild(); c; c = c->traverseNextNode(n))
- if (nodeMatches(c))
+ if (nodeMatches(c, FollowingAxis, m_nodeTest))
nodes.append(c);
}
}
@@ -168,7 +317,7 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
Node* n = context;
while (Node* parent = n->parent()) {
for (n = n->traversePreviousNode(); n != parent; n = n->traversePreviousNode())
- if (nodeMatches(n))
+ if (nodeMatches(n, PrecedingAxis, m_nodeTest))
nodes.append(n);
n = parent;
}
@@ -180,20 +329,22 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
return;
// Avoid lazily creating attribute nodes for attributes that we do not need anyway.
- if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != "*") {
+ if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != starAtom) {
RefPtr<Node> n = static_cast<Element*>(context)->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data());
- if (n && n->namespaceURI() != "http://www.w3.org/2000/xmlns/") // In XPath land, namespace nodes are not accessible on the attribute axis.
- nodes.append(n.release());
+ if (n && n->namespaceURI() != "http://www.w3.org/2000/xmlns/") { // In XPath land, namespace nodes are not accessible on the attribute axis.
+ if (nodeMatches(n.get(), AttributeAxis, m_nodeTest)) // Still need to check merged predicates.
+ nodes.append(n.release());
+ }
return;
}
- NamedAttrMap* attrs = context->attributes();
+ NamedNodeMap* attrs = context->attributes();
if (!attrs)
return;
for (unsigned i = 0; i < attrs->length(); ++i) {
RefPtr<Attr> attr = attrs->attributeItem(i)->createAttrIfNeeded(static_cast<Element*>(context));
- if (nodeMatches(attr.get()))
+ if (nodeMatches(attr.get(), AttributeAxis, m_nodeTest))
nodes.append(attr.release());
}
return;
@@ -202,30 +353,30 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
// XPath namespace nodes are not implemented yet.
return;
case SelfAxis:
- if (nodeMatches(context))
+ if (nodeMatches(context, SelfAxis, m_nodeTest))
nodes.append(context);
return;
case DescendantOrSelfAxis:
- if (nodeMatches(context))
+ if (nodeMatches(context, DescendantOrSelfAxis, m_nodeTest))
nodes.append(context);
if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
return;
for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context))
- if (nodeMatches(n))
+ if (nodeMatches(n, DescendantOrSelfAxis, m_nodeTest))
nodes.append(n);
return;
case AncestorOrSelfAxis: {
- if (nodeMatches(context))
+ if (nodeMatches(context, AncestorOrSelfAxis, m_nodeTest))
nodes.append(context);
Node* n = context;
if (context->isAttributeNode()) {
n = static_cast<Attr*>(context)->ownerElement();
- if (nodeMatches(n))
+ if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
nodes.append(n);
}
for (n = n->parentNode(); n; n = n->parentNode())
- if (nodeMatches(n))
+ if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
nodes.append(n);
nodes.markSorted(false);
@@ -236,70 +387,6 @@ void Step::nodesInAxis(Node* context, NodeSet& nodes) const
}
-bool Step::nodeMatches(Node* node) const
-{
- switch (m_nodeTest.kind()) {
- case NodeTest::TextNodeTest:
- return node->nodeType() == Node::TEXT_NODE || node->nodeType() == Node::CDATA_SECTION_NODE;
- case NodeTest::CommentNodeTest:
- return node->nodeType() == Node::COMMENT_NODE;
- case NodeTest::ProcessingInstructionNodeTest: {
- const String& name = m_nodeTest.data();
- return node->nodeType() == Node::PROCESSING_INSTRUCTION_NODE && (name.isEmpty() || node->nodeName() == name);
- }
- case NodeTest::ElementNodeTest:
- return node->isElementNode();
- case NodeTest::AnyNodeTest:
- return true;
- case NodeTest::NameTest: {
- const String& name = m_nodeTest.data();
- const String& namespaceURI = m_nodeTest.namespaceURI();
-
- if (m_axis == AttributeAxis) {
- ASSERT(node->isAttributeNode());
-
- // In XPath land, namespace nodes are not accessible on the attribute axis.
- if (node->namespaceURI() == "http://www.w3.org/2000/xmlns/")
- return false;
-
- if (name == "*")
- return namespaceURI.isEmpty() || node->namespaceURI() == namespaceURI;
-
- return node->localName() == name && node->namespaceURI() == namespaceURI;
- }
-
- if (m_axis == NamespaceAxis) {
- // Node test on the namespace axis is not implemented yet
- return false;
- }
-
- if (name == "*")
- return node->nodeType() == primaryNodeType(m_axis) && (namespaceURI.isEmpty() || namespaceURI == node->namespaceURI());
-
- // We use tagQName here because we don't want the element name in uppercase
- // like we get with HTML elements.
- // Paths without namespaces should match HTML elements in HTML documents despite those having an XHTML namespace.
- return node->nodeType() == Node::ELEMENT_NODE
- && static_cast<Element*>(node)->tagQName().localName() == name
- && ((node->isHTMLElement() && node->document()->isHTMLDocument() && namespaceURI.isNull()) || namespaceURI == node->namespaceURI());
- }
- }
- ASSERT_NOT_REACHED();
- return false;
-}
-
-Node::NodeType Step::primaryNodeType(Axis axis) const
-{
- switch (axis) {
- case AttributeAxis:
- return Node::ATTRIBUTE_NODE;
- case NamespaceAxis:
- return Node::XPATH_NAMESPACE_NODE;
- default:
- return Node::ELEMENT_NODE;
- }
-}
-
}
}
diff --git a/WebCore/xml/XPathStep.h b/WebCore/xml/XPathStep.h
index f1420d0..1c26327 100644
--- a/WebCore/xml/XPathStep.h
+++ b/WebCore/xml/XPathStep.h
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -52,8 +52,7 @@ namespace WebCore {
class NodeTest {
public:
enum Kind {
- TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest,
- ElementNodeTest // XPath 2.0
+ TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest
};
NodeTest(Kind kind) : m_kind(kind) {}
@@ -61,44 +60,48 @@ namespace WebCore {
NodeTest(Kind kind, const String& data, const String& namespaceURI) : m_kind(kind), m_data(data), m_namespaceURI(namespaceURI) {}
Kind kind() const { return m_kind; }
- const String data() const { return m_data; }
- const String namespaceURI() const { return m_namespaceURI; }
+ const AtomicString& data() const { return m_data; }
+ const AtomicString& namespaceURI() const { return m_namespaceURI; }
+ Vector<Predicate*>& mergedPredicates() { return m_mergedPredicates; }
+ const Vector<Predicate*>& mergedPredicates() const { return m_mergedPredicates; }
private:
Kind m_kind;
- String m_data;
- String m_namespaceURI;
+ AtomicString m_data;
+ AtomicString m_namespaceURI;
+
+ // When possible, we merge some or all predicates with node test for better performance.
+ Vector<Predicate*> m_mergedPredicates;
};
Step(Axis, const NodeTest& nodeTest, const Vector<Predicate*>& predicates = Vector<Predicate*>());
~Step();
+ void optimize();
+
void evaluate(Node* context, NodeSet&) const;
-
+
Axis axis() const { return m_axis; }
- NodeTest nodeTest() const { return m_nodeTest; }
- const Vector<Predicate*>& predicates() const { return m_predicates; }
-
- void setAxis(Axis axis) { m_axis = axis; }
- void setNodeTest(NodeTest nodeTest) { m_nodeTest = nodeTest; }
- void setPredicates(const Vector<Predicate*>& predicates) { m_predicates = predicates; }
-
+ const NodeTest& nodeTest() const { return m_nodeTest; }
+
private:
+ friend void optimizeStepPair(Step*, Step*, bool&);
+ bool predicatesAreContextListInsensitive() const;
+
void parseNodeTest(const String&);
void nodesInAxis(Node* context, NodeSet&) const;
- bool nodeMatches(Node*) const;
String namespaceFromNodetest(const String& nodeTest) const;
- Node::NodeType primaryNodeType(Axis) const;
Axis m_axis;
NodeTest m_nodeTest;
Vector<Predicate*> m_predicates;
};
+ void optimizeStepPair(Step*, Step*, bool& dropSecondStep);
}
}
#endif // ENABLE(XPATH)
-#endif // XPath_Step_H
+#endif // XPathStep_h
diff --git a/WebCore/xml/XPathUtil.cpp b/WebCore/xml/XPathUtil.cpp
index ab4b1d4..0100bea 100644
--- a/WebCore/xml/XPathUtil.cpp
+++ b/WebCore/xml/XPathUtil.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright 2005 Frerich Raabe <raabe@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,13 +51,17 @@ String stringValue(Node* node)
return node->nodeValue();
default:
if (isRootDomNode(node) || node->nodeType() == Node::ELEMENT_NODE) {
- String str;
-
- for (Node* n = node->firstChild(); n; n = n->traverseNextNode(node))
- if (n->isTextNode())
- str += n->nodeValue();
+ Vector<UChar> result;
+ result.reserveCapacity(1024);
- return str;
+ for (Node* n = node->firstChild(); n; n = n->traverseNextNode(node)) {
+ if (n->isTextNode()) {
+ const String& nodeValue = n->nodeValue();
+ result.append(nodeValue.characters(), nodeValue.length());
+ }
+ }
+
+ return String::adopt(result);
}
}
diff --git a/WebCore/xml/XPathValue.cpp b/WebCore/xml/XPathValue.cpp
index bac0e13..29e211e 100644
--- a/WebCore/xml/XPathValue.cpp
+++ b/WebCore/xml/XPathValue.cpp
@@ -30,11 +30,11 @@
#if ENABLE(XPATH)
#include "Node.h"
+#include "XPathExpressionNode.h"
#include "XPathUtil.h"
-
+#include <limits>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
-#include <limits>
using std::numeric_limits;
@@ -45,6 +45,9 @@ const Value::AdoptTag Value::adopt = {};
const NodeSet& Value::toNodeSet() const
{
+ if (!isNodeSet())
+ Expression::evaluationContext().hadTypeConversionError = true;
+
if (!m_data) {
DEFINE_STATIC_LOCAL(NodeSet, emptyNodeSet, ());
return emptyNodeSet;
@@ -55,6 +58,9 @@ const NodeSet& Value::toNodeSet() const
NodeSet& Value::modifiableNodeSet()
{
+ if (!isNodeSet())
+ Expression::evaluationContext().hadTypeConversionError = true;
+
if (!m_data)
m_data = ValueData::create();
@@ -86,8 +92,18 @@ double Value::toNumber() const
case NumberValue:
return m_number;
case StringValue: {
+ const String& str = m_data->m_string.simplifyWhiteSpace();
+
+ // String::toDouble() supports exponential notation, which is not allowed in XPath.
+ unsigned len = str.length();
+ for (unsigned i = 0; i < len; ++i) {
+ UChar c = str[i];
+ if (!isASCIIDigit(c) && c != '.' && c != '-')
+ return numeric_limits<double>::quiet_NaN();
+ }
+
bool canConvert;
- double value = m_data->m_string.simplifyWhiteSpace().toDouble(&canConvert);
+ double value = str.toDouble(&canConvert);
if (canConvert)
return value;
return numeric_limits<double>::quiet_NaN();
diff --git a/WebCore/xml/XPathVariableReference.h b/WebCore/xml/XPathVariableReference.h
index 811176d..5e5a59a 100644
--- a/WebCore/xml/XPathVariableReference.h
+++ b/WebCore/xml/XPathVariableReference.h
@@ -33,12 +33,14 @@
namespace WebCore {
namespace XPath {
-
+
+ // Variable references are not used with XPathEvaluator.
class VariableReference : public Expression {
public:
VariableReference(const String& name);
private:
virtual Value evaluate() const;
+ virtual Value::Type resultType() const { ASSERT_NOT_REACHED(); return Value::NumberValue; }
String m_name;
};
diff --git a/WebCore/xml/XSLStyleSheet.cpp b/WebCore/xml/XSLStyleSheet.cpp
index 0d112a5..b7d52f8 100644
--- a/WebCore/xml/XSLStyleSheet.cpp
+++ b/WebCore/xml/XSLStyleSheet.cpp
@@ -30,11 +30,12 @@
#include "DocLoader.h"
#include "Document.h"
#include "Frame.h"
-#include "loader.h"
#include "Node.h"
#include "XMLTokenizer.h"
+#include "XMLTokenizerScope.h"
#include "XSLImportRule.h"
#include "XSLTProcessor.h"
+#include "loader.h"
#include <libxml/uri.h>
#include <libxslt/xsltutils.h>
@@ -138,7 +139,6 @@ bool XSLStyleSheet::parseString(const String& string, bool)
// Parse in a single chunk into an xmlDocPtr
const UChar BOM = 0xFEFF;
const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
- setLoaderForLibXMLCallbacks(docLoader());
if (!m_stylesheetDocTaken)
xmlFreeDoc(m_stylesheetDoc);
m_stylesheetDocTaken = false;
@@ -146,8 +146,8 @@ bool XSLStyleSheet::parseString(const String& string, bool)
Console* console = 0;
if (Frame* frame = ownerDocument()->frame())
console = frame->domWindow()->console();
- xmlSetStructuredErrorFunc(console, XSLTProcessor::parseErrorFunc);
- xmlSetGenericErrorFunc(console, XSLTProcessor::genericErrorFunc);
+
+ XMLTokenizerScope scope(docLoader(), XSLTProcessor::genericErrorFunc, XSLTProcessor::parseErrorFunc, console);
const char* buffer = reinterpret_cast<const char*>(string.characters());
int size = string.length() * sizeof(UChar);
@@ -171,13 +171,9 @@ bool XSLStyleSheet::parseString(const String& string, bool)
BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_NOWARNING | XML_PARSE_NOCDATA);
xmlFreeParserCtxt(ctxt);
-
- loadChildSheets();
- xmlSetStructuredErrorFunc(0, 0);
- xmlSetGenericErrorFunc(0, 0);
+ loadChildSheets();
- setLoaderForLibXMLCallbacks(0);
return m_stylesheetDoc;
}
diff --git a/WebCore/xml/XSLTProcessor.cpp b/WebCore/xml/XSLTProcessor.cpp
index 198c90c..3865124 100644
--- a/WebCore/xml/XSLTProcessor.cpp
+++ b/WebCore/xml/XSLTProcessor.cpp
@@ -55,11 +55,10 @@
#include <wtf/Assertions.h>
#include <wtf/Platform.h>
#include <wtf/Vector.h>
+
#if PLATFORM(MAC)
#include "SoftLinking.h"
-#endif
-#if PLATFORM(MAC)
SOFT_LINK_LIBRARY(libxslt);
SOFT_LINK(libxslt, xsltFreeStylesheet, void, (xsltStylesheetPtr sheet), (sheet))
SOFT_LINK(libxslt, xsltFreeTransformContext, void, (xsltTransformContextPtr ctxt), (ctxt))
@@ -128,7 +127,7 @@ static xmlDocPtr docLoaderFunc(const xmlChar* uri,
bool requestAllowed = globalDocLoader->frame() && globalDocLoader->doc()->securityOrigin()->canRequest(url);
if (requestAllowed) {
- globalDocLoader->frame()->loader()->loadResourceSynchronously(url, error, response, data);
+ globalDocLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data);
requestAllowed = globalDocLoader->doc()->securityOrigin()->canRequest(response.url());
}
if (!requestAllowed) {