From: <rb...@us...> - 2014-01-11 15:41:10
|
Revision: 8963 http://sourceforge.net/p/htmlunit/code/8963 Author: rbri Date: 2014-01-11 15:41:04 +0000 (Sat, 11 Jan 2014) Log Message: ----------- regex fixes for IE11 (Frank Danek) Modified Paths: -------------- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/HtmlUnitContextFactory.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxy.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxyTest.java Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-11 12:51:56 UTC (rev 8962) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/BrowserVersionFeatures.java 2014-01-11 15:41:04 UTC (rev 8963) @@ -1208,6 +1208,14 @@ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_PREFIX_RETURNS_EMPTY_WHEN_UNDEFINED, + /** <code>RegExp.lastParen</code> returns an empty string if the RegExp has too many groups. */ + @BrowserFeature(@WebBrowser(value = IE, minVersion = 11)) + JS_REGEXP_EMPTY_LASTPAREN_IF_TOO_MANY_GROUPS, + + /** RegExp group <code>$0</code> returns the whole previous match (see {@link java.util.regex.Matcher#group()}. */ + @BrowserFeature(@WebBrowser(value = IE, minVersion = 11)) + JS_REGEXP_GROUP0_RETURNS_WHOLE_MATCH, + /** Javascript script.text(...) reexecutes the script (IE). */ @BrowserFeature(@WebBrowser(value = IE, maxVersion = 9)) JS_SCRIPT_ALWAYS_REEXECUTE_ON_SET_TEXT, Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/HtmlUnitContextFactory.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/HtmlUnitContextFactory.java 2014-01-11 12:51:56 UTC (rev 8962) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/HtmlUnitContextFactory.java 2014-01-11 15:41:04 UTC (rev 8963) @@ -266,7 +266,7 @@ } // register custom RegExp processing - ScriptRuntime.setRegExpProxy(cx, new HtmlUnitRegExpProxy(ScriptRuntime.getRegExpProxy(cx))); + ScriptRuntime.setRegExpProxy(cx, new HtmlUnitRegExpProxy(ScriptRuntime.getRegExpProxy(cx), browserVersion_)); cx.setMaximumInterpreterStackDepth(10000); Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxy.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxy.java 2014-01-11 12:51:56 UTC (rev 8962) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxy.java 2014-01-11 15:41:04 UTC (rev 8963) @@ -14,6 +14,9 @@ */ package com.gargoylesoftware.htmlunit.javascript.regexp; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_REGEXP_EMPTY_LASTPAREN_IF_TOO_MANY_GROUPS; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_REGEXP_GROUP0_RETURNS_WHOLE_MATCH; + import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -32,6 +35,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.gargoylesoftware.htmlunit.BrowserVersion; + /** * Begins customization of JavaScript RegExp base on JDK regular expression support. * @@ -46,13 +51,16 @@ private static final Pattern REPLACE_PATTERN = Pattern.compile("\\$\\$"); private final RegExpProxy wrapped_; + private final BrowserVersion browserVersion_; /** * Wraps a proxy to enhance it. * @param wrapped the original proxy + * @param browserVersion the current browser version */ - public HtmlUnitRegExpProxy(final RegExpProxy wrapped) { + public HtmlUnitRegExpProxy(final RegExpProxy wrapped, final BrowserVersion browserVersion) { wrapped_ = wrapped; + browserVersion_ = browserVersion; } /** @@ -184,7 +192,7 @@ return sb.toString(); } - static String computeReplacementValue(final String replacement, + String computeReplacementValue(final String replacement, final String originalString, final Matcher matcher) { int lastIndex = 0; @@ -223,6 +231,11 @@ case '&': ss = matcher.group(); break; + case '0': + if (browserVersion_.hasFeature(JS_REGEXP_GROUP0_RETURNS_WHOLE_MATCH)) { + ss = matcher.group(); + } + break; case '`': ss = originalString.substring(0, matcher.start()); break; @@ -298,12 +311,17 @@ // lastParen if (matcher.groupCount() > 0) { - final String last = matcher.group(matcher.groupCount()); - if (last == null) { + if (matcher.groupCount() > 9 && browserVersion_.hasFeature(JS_REGEXP_EMPTY_LASTPAREN_IF_TOO_MANY_GROUPS)) { lastParen = new SubString(); } else { - lastParen = new FixedSubString(last); + final String last = matcher.group(matcher.groupCount()); + if (last == null) { + lastParen = new SubString(); + } + else { + lastParen = new FixedSubString(last); + } } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxyTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxyTest.java 2014-01-11 12:51:56 UTC (rev 8962) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/javascript/regexp/HtmlUnitRegExpProxyTest.java 2014-01-11 15:41:04 UTC (rev 8963) @@ -26,6 +26,7 @@ import com.gargoylesoftware.htmlunit.BrowserRunner; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; import com.gargoylesoftware.htmlunit.BrowserRunner.Browsers; +import com.gargoylesoftware.htmlunit.BrowserVersion; import com.gargoylesoftware.htmlunit.WebDriverTestCase; /** @@ -277,18 +278,20 @@ final Matcher matcher1group = Pattern.compile("(h)").matcher("hello"); matcher1group.find(); - assertEquals("$", HtmlUnitRegExpProxy.computeReplacementValue("$$", theString, matcher0group)); - assertEquals("$$x$", HtmlUnitRegExpProxy.computeReplacementValue("$$$$x$$", theString, matcher0group)); + final HtmlUnitRegExpProxy proxy = new HtmlUnitRegExpProxy(null, BrowserVersion.FIREFOX_24); - assertEquals("$1", HtmlUnitRegExpProxy.computeReplacementValue("$1", theString, matcher0group)); - assertEquals("$2", HtmlUnitRegExpProxy.computeReplacementValue("$2", theString, matcher0group)); - assertEquals("h", HtmlUnitRegExpProxy.computeReplacementValue("$1", theString, matcher1group)); - assertEquals("$2", HtmlUnitRegExpProxy.computeReplacementValue("$2", theString, matcher1group)); + assertEquals("$", proxy.computeReplacementValue("$$", theString, matcher0group)); + assertEquals("$$x$", proxy.computeReplacementValue("$$$$x$$", theString, matcher0group)); - assertEquals("$", HtmlUnitRegExpProxy.computeReplacementValue("$", theString, matcher0group)); - assertEquals("$", HtmlUnitRegExpProxy.computeReplacementValue("$", theString, matcher1group)); - assertEquals("\\\\$", HtmlUnitRegExpProxy.computeReplacementValue("\\\\$", theString, matcher1group)); - assertEquals("$", HtmlUnitRegExpProxy.computeReplacementValue("$", theString, matcher1group)); + assertEquals("$1", proxy.computeReplacementValue("$1", theString, matcher0group)); + assertEquals("$2", proxy.computeReplacementValue("$2", theString, matcher0group)); + assertEquals("h", proxy.computeReplacementValue("$1", theString, matcher1group)); + assertEquals("$2", proxy.computeReplacementValue("$2", theString, matcher1group)); + + assertEquals("$", proxy.computeReplacementValue("$", theString, matcher0group)); + assertEquals("$", proxy.computeReplacementValue("$", theString, matcher1group)); + assertEquals("\\\\$", proxy.computeReplacementValue("\\\\$", theString, matcher1group)); + assertEquals("$", proxy.computeReplacementValue("$", theString, matcher1group)); } /** @@ -529,6 +532,59 @@ * @throws Exception if an error occurs */ @Test + @Alerts(DEFAULT = "ad$0db", + IE11 = "adfoodb") + public void replace_backReference_$0() throws Exception { + testEvaluate("'afoob'.replace(/(foo)/g, 'd$0d')"); + testEvaluate("'afoob'.replace(/(foo)/, 'd$0d')"); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "ad$0db", + IE11 = "adfkxxxkodb") + public void replace_backReference_$0WithMultipleGroups() throws Exception { + testEvaluate("'afkxxxkob'.replace(/(f)k(.*)k(o)/g, 'd$0d')"); + testEvaluate("'afkxxxkob'.replace(/(f)k(.*)k(o)/, 'd$0d')"); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "ad$0db", + IE11 = "adfoodb") + public void replace_backReference_$0WithNoGroups() throws Exception { + testEvaluate("'afoob'.replace(/foo/g, 'd$0d')"); + testEvaluate("'afoob'.replace(/foo/, 'd$0d')"); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "ad$0dbfuoc", + IE11 = "adfoodbfuoc") + public void replace_backReference_$0WithMultipleHits() throws Exception { + testEvaluate("'afoobfuoc'.replace(/(f.o)/, 'd$0d')"); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "ad$0dbd$0dc", + IE11 = "adfoodbdfuodc") + public void replace_backReference_$0WithMultipleHitsGlobal() throws Exception { + testEvaluate("'afoobfuoc'.replace(/(f.o)/g, 'd$0d')"); + } + + /** + * @throws Exception if an error occurs + */ + @Test @Alerts("kid\\'s toys") public void escapeQuote() throws Exception { testEvaluate("\"kid's toys\".replace(/'/g, \"\\\\'\")"); |