summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-12-23 16:09:43 -0800
committerSom Snytt <som.snytt@gmail.com>2015-02-13 09:15:52 -0800
commitfe7867f8a7f309fe16b454fe977bd2f1870d59c2 (patch)
tree9d421598203e2d2eb0fbc8e8b4f14b0d292e9e67
parentad0ddd4603e6ec134460491333444d505d376883 (diff)
downloadscala-fe7867f8a7f309fe16b454fe977bd2f1870d59c2.tar.gz
scala-fe7867f8a7f309fe16b454fe977bd2f1870d59c2.tar.bz2
scala-fe7867f8a7f309fe16b454fe977bd2f1870d59c2.zip
[backport] SI-4339 Event errors and attribute fix
Improve attribute parsing and propagate errors across event thread. Otherwise tests just hang. This is tested, right? This is an upstream port of scala-xml 5f2cfadeb9e8574ed66f37dc7a7a868eb129a8a9
-rw-r--r--bincompat-forward.whitelist.conf8
-rw-r--r--src/library/scala/xml/parsing/MarkupParserCommon.scala3
-rwxr-xr-xsrc/library/scala/xml/pull/XMLEventReader.scala9
-rw-r--r--test/files/run/t4339.check3
-rw-r--r--test/files/run/t4339.scala35
5 files changed, 55 insertions, 3 deletions
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf
index c9cf4f74b9..1c532889c2 100644
--- a/bincompat-forward.whitelist.conf
+++ b/bincompat-forward.whitelist.conf
@@ -187,6 +187,14 @@ filter {
{
matchName="scala.xml.dtd.ElementValidator.scala$xml$dtd$ElementValidator$$find$2"
problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.xml.pull.ExceptionEvent"
+ problemName=MissingClassProblem
+ },
+ {
+ matchName="scala.xml.pull.ExceptionEvent$"
+ problemName=MissingClassProblem
}
]
}
diff --git a/src/library/scala/xml/parsing/MarkupParserCommon.scala b/src/library/scala/xml/parsing/MarkupParserCommon.scala
index da640484e0..4dbe5aed9d 100644
--- a/src/library/scala/xml/parsing/MarkupParserCommon.scala
+++ b/src/library/scala/xml/parsing/MarkupParserCommon.scala
@@ -58,8 +58,9 @@ private[scala] trait MarkupParserCommon extends TokenTests {
@param endCh either `'` or `"`
*/
def xAttributeValue(endCh: Char): String = {
+ require(endCh == '\'' || endCh == '"', s"Expected single or double quote, found $endCh")
val buf = new StringBuilder
- while (ch != endCh) {
+ while (ch != endCh && !eof) {
// well-formedness constraint
if (ch == '<') return errorAndResult("'<' not allowed in attrib value", "")
else if (ch == SU) truncatedError("")
diff --git a/src/library/scala/xml/pull/XMLEventReader.scala b/src/library/scala/xml/pull/XMLEventReader.scala
index 428c305055..26572c9946 100755
--- a/src/library/scala/xml/pull/XMLEventReader.scala
+++ b/src/library/scala/xml/pull/XMLEventReader.scala
@@ -91,12 +91,16 @@ extends scala.collection.AbstractIterator[XMLEvent]
override def run() {
curInput = input
- interruptibly { this.initialize.document() }
- setEvent(POISON)
+ try interruptibly { this.initialize.document() }
+ catch { case e:Exception => setEvent(ExceptionEvent(e)) }
+ finally setEvent(POISON)
}
}
}
+// An internal class used to propagate exception from helper threads to API end users.
+private case class ExceptionEvent(exception:Exception) extends XMLEvent
+
// An iterator designed for one or more producers to generate
// elements, and a single consumer to iterate. Iteration will continue
// until closeIterator() is called, after which point producers
@@ -141,6 +145,7 @@ trait ProducerConsumerIterator[T >: Null] extends Iterator[T] {
def next() = {
if (eos) throw new NoSuchElementException("ProducerConsumerIterator")
if (buffer == null) fillBuffer
+ if (buffer.isInstanceOf[ExceptionEvent]) throw buffer.asInstanceOf[ExceptionEvent].exception
drainBuffer
}
diff --git a/test/files/run/t4339.check b/test/files/run/t4339.check
new file mode 100644
index 0000000000..46eabbe42b
--- /dev/null
+++ b/test/files/run/t4339.check
@@ -0,0 +1,3 @@
+Saw failure: scala.xml.parsing.FatalError: expected closing tag of foo
+EvElemStart(null,foo, bar="baz/&gt;",)
+Saw failure: scala.xml.parsing.FatalError: expected closing tag of foo
diff --git a/test/files/run/t4339.scala b/test/files/run/t4339.scala
new file mode 100644
index 0000000000..bb8b847ec3
--- /dev/null
+++ b/test/files/run/t4339.scala
@@ -0,0 +1,35 @@
+
+import scala.util.{ Try, Success, Failure }
+import xml._
+import scala.io.Source.fromString
+import java.io.PrintStream
+
+object Test extends App {
+
+ def quietSource(text: String) = new io.Source {
+ override protected val iter = io.Source fromString text
+ override def report(pos: Int, msg: String, out: PrintStream) = ()
+ }
+ def reading(text: String)(f: pull.XMLEventReader => Unit): Unit = {
+ val r = new pull.XMLEventReader(quietSource(text))
+ try f(r)
+ finally r.stop()
+ }
+ def trying(body: => Unit): Unit =
+ Try (body) match {
+ case Success(_) => Console println "Expected failure"
+ case Failure(e) => Console println s"Saw failure: $e"
+ }
+
+ val problematic = """<foo bar="baz/>"""
+
+ trying (
+ parsing.ConstructingParser.fromSource(quietSource(problematic), false).document.docElem
+ )
+
+ trying (
+ reading(problematic) { r =>
+ while (r.hasNext) println(r.next())
+ }
+ )
+}