From fe7867f8a7f309fe16b454fe977bd2f1870d59c2 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 23 Dec 2014 16:09:43 -0800 Subject: [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 --- bincompat-forward.whitelist.conf | 8 +++++ .../scala/xml/parsing/MarkupParserCommon.scala | 3 +- src/library/scala/xml/pull/XMLEventReader.scala | 9 ++++-- test/files/run/t4339.check | 3 ++ test/files/run/t4339.scala | 35 ++++++++++++++++++++++ 5 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 test/files/run/t4339.check create mode 100644 test/files/run/t4339.scala 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/>",) +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 = """ + while (r.hasNext) println(r.next()) + } + ) +} -- cgit v1.2.3 From b4e3becbf348bad95f48da5a94f4ddb4272b2891 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 24 Dec 2014 17:59:49 -0800 Subject: [backport] SI-9060 Backpatch fifth-edition names Because the compiler and library share some code in this version, compiler must exclude xml tags that look like Scala operators, such as `<:`. This is an upstream port of: scala-xml/commit/968f7bd94e934c781c19e25847ab09ac98cfbaf6 --- .../scala/tools/nsc/ast/parser/Scanners.scala | 4 +- src/library/scala/xml/parsing/TokenTests.scala | 56 ++++++++-------------- test/files/jvm/unittest_xml.scala | 4 +- 3 files changed, 25 insertions(+), 39 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 8d295a28d0..3ee7941995 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -367,7 +367,9 @@ trait Scanners extends ScannersCommon { val last = if (charOffset >= 2) buf(charOffset - 2) else ' ' nextChar() last match { - case ' ' | '\t' | '\n' | '{' | '(' | '>' if isNameStart(ch) || ch == '!' || ch == '?' => + // exclude valid xml names that happen to be Scala operator chars + case ' ' | '\t' | '\n' | '{' | '(' | '>' if (isNameStart(ch) && ch != ':' && !isSpecial(ch)) + || ch == '!' || ch == '?' => token = XMLSTART case _ => // Console.println("found '<', but last is '"+in.last+"'"); // DEBUG diff --git a/src/library/scala/xml/parsing/TokenTests.scala b/src/library/scala/xml/parsing/TokenTests.scala index c9cafaeea1..ce7accbd98 100644 --- a/src/library/scala/xml/parsing/TokenTests.scala +++ b/src/library/scala/xml/parsing/TokenTests.scala @@ -30,43 +30,25 @@ trait TokenTests { def isAlpha(c: Char) = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') def isAlphaDigit(c: Char) = isAlpha(c) || (c >= '0' && c <= '9') - /** {{{ - * NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' - * | CombiningChar | Extender - * }}} - * See [4] and Appendix B of XML 1.0 specification. - */ - def isNameChar(ch: Char) = { - import java.lang.Character._ - // The constants represent groups Mc, Me, Mn, Lm, and Nd. - - isNameStart(ch) || (getType(ch).toByte match { - case COMBINING_SPACING_MARK | - ENCLOSING_MARK | NON_SPACING_MARK | - MODIFIER_LETTER | DECIMAL_DIGIT_NUMBER => true - case _ => ".-:" contains ch - }) - } - - /** {{{ - * NameStart ::= ( Letter | '_' ) - * }}} - * where Letter means in one of the Unicode general - * categories `{ Ll, Lu, Lo, Lt, Nl }`. - * - * We do not allow a name to start with `:`. - * See [3] and Appendix B of XML 1.0 specification - */ - def isNameStart(ch: Char) = { - import java.lang.Character._ - - getType(ch).toByte match { - case LOWERCASE_LETTER | - UPPERCASE_LETTER | OTHER_LETTER | - TITLECASE_LETTER | LETTER_NUMBER => true - case _ => ch == '_' - } - } + def isNameChar(c: Char): Boolean = ( + isNameStart(c) || + (c >= '0' && c <= '9') || + c == '-' || + c == '.' || + c == 0xB7 || + (c >= 0x300 && c <= 0x36F) || + (c >= 0x203F && c <= 0x2040) + ) + def isNameStart(c: Char): Boolean = ( + if (c < 0x00C0) isAlpha(c) || c == ':' || c == '_' + else if (c < 0x0300) c != 0xD7 && c != 0xF7 + else if (c < 0x2000) c >= 0x370 && c != 0x37E + else if (c < 0x3001) c == 0x200C || c == 0x200D || (0x2070 to 0x218F contains c) || + (0x2C00 to 0x2FEF contains c) + else if (c < 0xD800) true + else if (c < 0x10000) (0xF900 to 0xFDCF contains c) || (0xFDF0 to 0xFFFD contains c) + else false // codepoint < 0xF0000 + ) /** {{{ * Name ::= ( Letter | '_' ) (NameChar)* diff --git a/test/files/jvm/unittest_xml.scala b/test/files/jvm/unittest_xml.scala index 106334e625..9ffd459fde 100644 --- a/test/files/jvm/unittest_xml.scala +++ b/test/files/jvm/unittest_xml.scala @@ -62,7 +62,9 @@ object Test { object UtilityTest { def run() { assert(Utility.isNameStart('b')) - assert(!Utility.isNameStart(':')) + + // no longer: this was a convenience for the implementation, not to spec. + //assert(!Utility.isNameStart(':')) val x = -- cgit v1.2.3 From f95b5b9b8002d0227f894dc6add43acf7994c0ed Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 20 Feb 2015 11:25:06 -0800 Subject: Scaladoc js location synch more robust Tested on: - Mac: FF35/Safari 8/Chrome 41 - Win: IE11 --- src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js index 96689ae701..38dd248c29 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js @@ -70,7 +70,7 @@ function setFrameSrcFromUrlFragment() { var loc = fragment.split("@")[0].replace(/\./g, "/"); if(loc.indexOf(".html") < 0) loc += ".html"; if(fragment.indexOf('@') > 0) loc += ("#" + fragment.split("@", 2)[1]); - frames["template"].location.replace(loc); + frames["template"].location.replace(location.protocol + loc); } else frames["template"].location.replace("package.html"); -- cgit v1.2.3