Commit d9eb969a authored by commit-queue@webkit.org's avatar commit-queue@webkit.org
Browse files

XMLSerializer escapes < > & correctly inside <script> and <style> tags.

https://bugs.webkit.org/show_bug.cgi?id=123914

Patch by Victor Costan <costan@gmail.com> on 2013-11-14
Reviewed by Darin Adler.

Source/WebCore:

Test: fast/dom/XMLSerializer-entities.html

* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::serializeNodesWithNamespaces): vim removed some whitespace.
(WebCore::MarkupAccumulator::entityMaskForText): Fixed the returned value for <script> etc in XML.

LayoutTests:

* fast/dom/SelectorAPI/resig-SelectorsAPI-test-expected.txt: fix incorrect expectations.
* fast/dom/SelectorAPI/resig-SelectorsAPI-test.xhtml: use CDATA consistently.
* fast/dom/XMLSerializer-entities-expected.txt: Added.
* fast/dom/XMLSerializer-entities.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@159326 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 40a09c02
2013-11-14 Victor Costan <costan@gmail.com>
XMLSerializer escapes < > & correctly inside <script> and <style> tags.
https://bugs.webkit.org/show_bug.cgi?id=123914
Reviewed by Darin Adler.
* fast/dom/SelectorAPI/resig-SelectorsAPI-test-expected.txt: fix incorrect expectations.
* fast/dom/SelectorAPI/resig-SelectorsAPI-test.xhtml: use CDATA consistently.
* fast/dom/XMLSerializer-entities-expected.txt: Added.
* fast/dom/XMLSerializer-entities.html: Added.
2013-11-14 Victor Costan <costan@gmail.com>
 
Clean up sequence handling in Blob constructor
......
......@@ -563,8 +563,8 @@ PASS Syntax Error: Element.querySelectorAll: div,
PASS Syntax Error: Element.querySelector: div,
PASS Syntax Error: Element.querySelectorAll: .5cm
PASS Syntax Error: Element.querySelector: .5cm
PASS Syntax Error: Element.querySelectorAll: foo & address, p
PASS Syntax Error: Element.querySelector: foo & address, p
PASS Syntax Error: Element.querySelectorAll: foo &amp; address, p
PASS Syntax Error: Element.querySelector: foo &amp; address, p
PASS Syntax Error: Element.querySelectorAll: [*=test]
PASS Syntax Error: Element.querySelector: [*=test]
PASS Syntax Error: Element.querySelectorAll: [*|*=test]
......@@ -1161,8 +1161,8 @@ PASS Syntax Error: Disconnected Element.querySelectorAll: div,
PASS Syntax Error: Disconnected Element.querySelector: div,
PASS Syntax Error: Disconnected Element.querySelectorAll: .5cm
PASS Syntax Error: Disconnected Element.querySelector: .5cm
PASS Syntax Error: Disconnected Element.querySelectorAll: foo & address, p
PASS Syntax Error: Disconnected Element.querySelector: foo & address, p
PASS Syntax Error: Disconnected Element.querySelectorAll: foo &amp; address, p
PASS Syntax Error: Disconnected Element.querySelector: foo &amp; address, p
PASS Syntax Error: Disconnected Element.querySelectorAll: [*=test]
PASS Syntax Error: Disconnected Element.querySelector: [*=test]
PASS Syntax Error: Disconnected Element.querySelectorAll: [*|*=test]
......@@ -1642,8 +1642,8 @@ PASS Syntax Error: Fragment.querySelectorAll: div,
PASS Syntax Error: Fragment.querySelector: div,
PASS Syntax Error: Fragment.querySelectorAll: .5cm
PASS Syntax Error: Fragment.querySelector: .5cm
PASS Syntax Error: Fragment.querySelectorAll: foo & address, p
PASS Syntax Error: Fragment.querySelector: foo & address, p
PASS Syntax Error: Fragment.querySelectorAll: foo &amp; address, p
PASS Syntax Error: Fragment.querySelector: foo &amp; address, p
PASS Syntax Error: Fragment.querySelectorAll: [*=test]
PASS Syntax Error: Fragment.querySelector: [*=test]
PASS Syntax Error: Fragment.querySelectorAll: [*|*=test]
......@@ -2005,8 +2005,8 @@ PASS Syntax Error: Document.querySelectorAll: div,
PASS Syntax Error: Document.querySelector: div,
PASS Syntax Error: Document.querySelectorAll: .5cm
PASS Syntax Error: Document.querySelector: .5cm
PASS Syntax Error: Document.querySelectorAll: foo & address, p
PASS Syntax Error: Document.querySelector: foo & address, p
PASS Syntax Error: Document.querySelectorAll: foo &amp; address, p
PASS Syntax Error: Document.querySelector: foo &amp; address, p
PASS Syntax Error: Document.querySelectorAll: [*=test]
PASS Syntax Error: Document.querySelector: [*=test]
PASS Syntax Error: Document.querySelectorAll: [*|*=test]
......
......@@ -37,7 +37,7 @@
html.nopass .pass { display: none; }
]]></style>
<style type="text/test" id="test">
<style type="text/test" id="test"><![CDATA[
/* :target selector */
.target :target { background-color: lime; }
......@@ -192,8 +192,8 @@
.plus .t1, .plus .t2 { background-color: white; }
.plus .t1 + .unitTest + .unitTest { background-color: lime; }
.plus .t1:hover + .unitTest + .unitTest { background-color: red; }
</style>
<style type="text/test" id="error">
]]></style>
<style type="text/test" id="error"><![CDATA[
.blox16:not(.blox15[foo="blox14"]) { background-color: red; }
/* Tests from http://www.w3.org/Style/CSS/Test/CSS3/Selectors/20060307/html/index.html */
......@@ -222,7 +222,7 @@
..test { background: red; color: yellow; }
.foo..quux { background: red; color: yellow; }
.bar. { background: red; color: yellow; }
</style>
]]></style>
<script><![CDATA[
if (window.testRunner) {
testRunner.dumpAsText();
......@@ -284,14 +284,14 @@
cacheCheck( "Fragment", fragment );
root.parentNode.removeChild( root );
interfaceCheck(document, "Document");
runTest( css, "Document", document, true );
check( "Document", document, true, false );
runTest( ecss, "Syntax Error: Document", document, false );
jqTests("Document", document, "querySelectorAll");
cacheCheck( "Document", document );
done();
function interfaceCheck(obj, type){
......@@ -399,10 +399,10 @@
var test = css[i];
if ( test.length == 2 ) {
var query = test[0], color = test[1].match(/: ([^\s;]+)/)[1];
try {
var found = root.querySelectorAll(query);
for ( var f = 0; f < found.length; f++ ) {
found[f].style.backgroundColor = color;
}
......@@ -510,13 +510,13 @@
} catch(e) {
pass = typeof DOMException !== "undefined" && e.code == DOMException.SYNTAX_ERR;
}
assert( pass, type + ": " + name + " (" + nq + ")" +
(pass ? "" : " Expected: " + extra(ids) + " Received: " + extra(results)) );
function hasPassed(results, ids){
var pass = (results && results.length == ids.length) || (!results && !ids);
if ( ids && results ) {
for ( var i = 0; ids && i < ids.length; i++ ) {
if ( ids[i] !== results[i].getAttribute("id") ) {
......@@ -537,7 +537,7 @@
extra += (extra.length > 2 ? "," : "") + "'" + (results[i].id || results[i]) + "'";
}
}
extra += "]";
return extra;
}
......@@ -573,7 +573,7 @@
var param = query("#object1 param");
assert( param && param.length == 2, type + ": Object/param as context" );
var l = query("#length");
var l = query("#length");
assert( l && l.length, type + ': &lt;input name="length"&gt; cannot be found under IE' );
var lin = query("#lengthtest input");
assert( lin && lin.length, type + ': &lt;input name="length"&gt; cannot be found under IE' );
......@@ -596,18 +596,18 @@
t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] );
t( "Descendant ID selector using UTF8", "div #台北", ["台北"] );
t( "Child ID selector using UTF8", "form > #台北", ["台北"] );
t( "Escaped ID", "#foo\\:bar", ["foo:bar"] );
t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Descendant escaped ID", "div #foo\\:bar", ["foo:bar"] );
t( "Descendant escaped ID", "div #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Child escaped ID", "form > #foo\\:bar", ["foo:bar"] );
t( "Child escaped ID", "form > #test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267
t( "ID Selector, not an ancestor ID", "#form #first", [] );
t( "ID Selector, not a child ID", "#form > #option1a", [] );
t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] );
t( "All Children of ID with no children", "#firstUL > *", [] );
......@@ -619,14 +619,14 @@
t( "Class Selector", ".blog.link", ["simon"] );
t( "Class Selector w/ Element", "a.blog", ["mark","simon"] );
t( "Parent Class Selector", "p .blog", ["mark","simon"] );
t( "Class selector using UTF8", ".台北Táiběi", ["utf8class1"] );
t( "Class selector using UTF8", ".台北", ["utf8class1","utf8class2"] );
t( "Class selector using UTF8", ".台北Táiběi.台北", ["utf8class1"] );
t( "Class selector using UTF8", ".台北Táiběi, .台北", ["utf8class1","utf8class2"] );
t( "Descendant class selector using UTF8", "div .台北Táiběi", ["utf8class1"] );
t( "Child class selector using UTF8", "form > .台北Táiběi", ["utf8class1"] );
t( "Escaped Class", ".foo\\:bar", ["foo:bar"] );
t( "Escaped Class", ".test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
t( "Descendant scaped Class", "div .foo\\:bar", ["foo:bar"] );
......@@ -652,13 +652,13 @@
t( "Adjacent", "a+a", ["groups"] );
t( "Adjacent", "p + p", ["ap","en","sap"] );
t( "Comma, Child, and Adjacent", "a + a, code > a", ["groups","anchor1","anchor2"] );
t( "First Child", "p:first-child", ["firstp","sndp"] );
t( "Nth Child", "p:nth-child(1)", ["firstp","sndp"] );
t( "Last Child", "p:last-child", ["sap"] );
t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon"] );
t( "Nth-child", "#main form#form > *:nth-child(2)", ["text2"] );
t( "Nth-child", "#main form#form > :nth-child(2)", ["text2"] );
......@@ -684,27 +684,27 @@
t( "Attribute Exists", "a[title]", ["google"] );
t( "Attribute Exists", "*[title]", ["google"] );
t( "Attribute Exists", "[title]", ["google"] );
t( "Attribute Equals", "a[rel='bookmark']", ["simon1"] );
t( "Attribute Equals", 'a[rel="bookmark"]', ["simon1"] );
t( "Attribute Equals", "a[rel=bookmark]", ["simon1"] );
t( "Multiple Attribute Equals", "#form input[type='hidden'],#form input[type='radio']", ['radio1','radio2','hidden1'] );
t( "Multiple Attribute Equals", "#form input[type=\"hidden\"],#form input[type='radio']", ['radio1','radio2','hidden1'] );
t( "Multiple Attribute Equals", "#form input[type=hidden],#form input[type=radio]", ['radio1','radio2','hidden1'] );
t( "Attribute selector using UTF8", "span[lang=中文]", ["台北"] );
t( "Attribute Begins With", "a[href ^= 'http://www']", ["google","yahoo"] );
t( "Attribute Ends With", "a[href $= 'org/']", ["mark"] );
t( "Attribute Contains", "a[href *= 'google']", ["google","groups"] );
// t("Select options via [selected]", "#select1 option[selected]", ["option1a"] );
t("Select options via [selected]", "#select1 option[selected]", [] );
t("Select options via [selected]", "#select2 option[selected]", ["option2d"] );
t("Select options via [selected]", "#select3 option[selected]", ["option3b", "option3c"] );
t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] );
t( ":not() Existing attribute", "#form select:not([multiple])", ["select1", "select2"]);
t( ":not() Equals attribute", "#form select:not([name=select1])", ["select2", "select3"]);
t( ":not() Equals quoted attribute", "#form select:not([name='select1'])", ["select2", "select3"]);
......@@ -1176,7 +1176,7 @@
<h1 id="header">jQuery Test Suite</h1>
<h2 id="banner"></h2>
<h2 id="userAgent"></h2>
<!-- Test HTML -->
<div id="nothiddendiv" style="height:1px;background:white;">
......@@ -1189,9 +1189,9 @@
<p id="firstp">See <a id="simon1" href="http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector" rel="bookmark">this blog entry</a> for more information.</p>
<p id="ap">
Here are some links in a normal paragraph: <a id="google" href="http://www.google.com/" title="Google!">Google</a>,
<a id="groups" href="http://groups.google.com/">Google Groups</a>.
This link has <code><a href="http://smin" id="anchor1">class="blog"</a></code>:
Here are some links in a normal paragraph: <a id="google" href="http://www.google.com/" title="Google!">Google</a>,
<a id="groups" href="http://groups.google.com/">Google Groups</a>.
This link has <code><a href="http://smin" id="anchor1">class="blog"</a></code>:
<a href="http://diveintomark.org/" class="blog" hreflang="en" id="mark">diveintomark</a>
</p>
......@@ -1218,14 +1218,14 @@
<input type="hidden" name="hidden" id="hidden1"/>
<input type="text" style="display:none;" name="foo[bar]" id="hidden2"/>
<input type="text" id="name" name="name" value="name" />
<button id="button" name="button">Button</button>
<textarea id="area1" maxlength="30">foobar</textarea>
<select name="select1" id="select1">
<option id="option1a" class="emptyopt" value="">Nothing</option>
<option id="option1b" value="1">1</option>
......@@ -1246,20 +1246,20 @@
<option id="option3c" selected="selected" value="2">2</option>
<option id="option3d" value="3">3</option>
</select>
<object id="object1" codebase="stupid">
<param name="p1" value="x1" />
<param name="p2" value="x2" />
</object>
<span id="台北Táiběi"></span>
<span id="台北" lang="中文"></span>
<span id="utf8class1" class="台北Táiběi 台北"></span>
<span id="utf8class2" class="台北"></span>
<span id="foo:bar" class="foo:bar"></span>
<span id="test.foo[5]bar" class="test.foo[5]bar"></span>
<foo_bar id="foobar">test element</foo_bar>
</form>
......@@ -1271,27 +1271,27 @@
</form>
<table id="table"></table>
<div id="fx-queue">
<div id="fadein" class='chain test'>fadeIn<div>fadeIn</div></div>
<div id="fadeout" class='chain test out'>fadeOut<div>fadeOut</div></div>
<div id="show" class='chain test'>show<div>show</div></div>
<div id="hide" class='chain test out'>hide<div>hide</div></div>
<div id="togglein" class='chain test'>togglein<div>togglein</div></div>
<div id="toggleout" class='chain test out'>toggleout<div>toggleout</div></div>
<div id="slideup" class='chain test'>slideUp<div>slideUp</div></div>
<div id="slidedown" class='chain test out'>slideDown<div>slideDown</div></div>
<div id="slidetogglein" class='chain test'>slideToggleIn<div>slideToggleIn</div></div>
<div id="slidetoggleout" class='chain test out'>slideToggleOut<div>slideToggleOut</div></div>
</div>
<div id="fx-tests"></div>
<form id="testForm" action="#" method="get">
......@@ -1358,7 +1358,7 @@ Z</textarea>
</div>
</div>
</dl>
<ol id="tests"></ol>
</div>
<ol id="results"></ol>
......
<html xmlns="http://www.w3.org/1999/xhtml"><p>(0 &lt; 1 &amp;&amp; 1 &gt; 0)</p><script>if (0 &lt; 1 &amp;&amp; 1 &gt; 0) { };</script><style>/* &lt; &gt; &amp; */</style></html>
<html>
<head>
<script type="text/javascript">
function runTest()
{
if (window.testRunner)
testRunner.dumpAsText();
var ns = 'http://www.w3.org/1999/xhtml';
var xhtml = document.implementation.createDocument(ns , 'html', null);
var p = xhtml.createElementNS(ns, 'p');
p.textContent = '(0 < 1 && 1 > 0)';
xhtml.documentElement.appendChild(p);
var script = xhtml.createElementNS(ns, 'script');
script.textContent = 'if (0 < 1 && 1 > 0) { };';
xhtml.documentElement.appendChild(script);
var style = xhtml.createElementNS(ns, 'style');
style.textContent = '/* < > & */';
xhtml.documentElement.appendChild(style);
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(xhtml);
var outputText = document.getElementById("output");
outputText.textContent = xmlString;
}
</script>
</head>
<body onload="runTest()">
<div id="output"/>
</body>
</html>
2013-11-14 Victor Costan <costan@gmail.com>
XMLSerializer escapes < > & correctly inside <script> and <style> tags.
https://bugs.webkit.org/show_bug.cgi?id=123914
Reviewed by Darin Adler.
Test: fast/dom/XMLSerializer-entities.html
* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::serializeNodesWithNamespaces): vim removed some whitespace.
(WebCore::MarkupAccumulator::entityMaskForText): Fixed the returned value for <script> etc in XML.
2013-11-14 Bem Jones-Bey <bjonesbe@adobe.com>
 
ASSERTION FAILED: rangesIntersect(m_renderer.pixelSnappedLogicalTopForFloat(floatingObject), m_renderer.pixelSnappedLogicalBottomForFloat(floatingObject), m_lineTop, m_lineBottom) ../../Source/WebCore/rendering/FloatingObjects.cpp(463)
......
......@@ -123,7 +123,7 @@ void MarkupAccumulator::serializeNodesWithNamespaces(Node& targetNode, Node* nod
{
if (&targetNode == nodeToSkip)
return;
if (tagNamesToSkip && targetNode.isElementNode()) {
for (size_t i = 0; i < tagNamesToSkip->size(); ++i) {
if (targetNode.hasTagName(tagNamesToSkip->at(i)))
......@@ -330,14 +330,16 @@ void MarkupAccumulator::appendNamespace(StringBuilder& result, const AtomicStrin
EntityMask MarkupAccumulator::entityMaskForText(const Text& text) const
{
if (!text.document().isHTMLDocument())
return EntityMaskInPCDATA;
const QualifiedName* parentName = 0;
if (text.parentElement())
parentName = &text.parentElement()->tagQName();
if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag))
return EntityMaskInCDATA;
return text.document().isHTMLDocument() ? EntityMaskInHTMLPCDATA : EntityMaskInPCDATA;
return EntityMaskInHTMLPCDATA;
}
void MarkupAccumulator::appendText(StringBuilder& result, const Text& text)
......
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