Merge
authorlana
Wed, 17 Apr 2013 21:50:54 -0700
changeset 16949 6fc834025287
parent 16817 da9a4c931281 (current diff)
parent 16948 4d560817293f (diff)
child 16950 5884314a2095
Merge
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java	Wed Apr 17 21:50:54 2013 -0700
@@ -210,42 +210,10 @@
     }
 
     private static ClassLoader getAppClassLoader() {
-        if (System.getSecurityManager() == null) {
-            return Thread.currentThread().getContextClassLoader();
-        }
-
-        // Try to determine the caller class loader. Use that if it can be
-        // found. If not, use the class loader of nashorn itself as the
-        // "application" class loader for scripts.
-
-        // User could have called ScriptEngineFactory.getScriptEngine()
-        //
-        // <caller>
-        //  <factory.getScriptEngine()>
-        //   <factory.getAppClassLoader()>
-        //    <Reflection.getCallerClass()>
-        //
-        // or used one of the getEngineByABC methods of ScriptEngineManager.
-        //
-        // <caller>
-        //  <ScriptEngineManager.getEngineByName()>
-        //   <factory.getScriptEngine()>
-        //    <factory.getAppClassLoader()>
-        //     <Reflection.getCallerClass()>
-
-        // So, stack depth is 3 or 4 (recall it is zero based). We try
-        // stack depths 3, 4 and look for non-bootstrap caller.
-        Class<?> caller = null;
-        for (int depth = 3; depth < 5; depth++) {
-            caller = Reflection.getCallerClass(depth);
-            if (caller != null && caller.getClassLoader() != null) {
-                // found a non-bootstrap caller
-                break;
-            }
-        }
-
-        final ClassLoader ccl = (caller == null)? null : caller.getClassLoader();
-        // if caller loader is null, then use nashorn's own loader
+        // Revisit: script engine implementation needs the capability to
+        // find the class loader of the context in which the script engine
+        // is running so that classes will be found and loaded properly
+        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
         return (ccl == null)? NashornScriptEngineFactory.class.getClassLoader() : ccl;
     }
 }
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java	Wed Apr 17 21:50:54 2013 -0700
@@ -76,7 +76,7 @@
 
     private static final MethodHandle REDUCE_CALLBACK_INVOKER = Bootstrap.createDynamicInvoker("dyn:call", Object.class,
             Object.class, Undefined.class, Object.class, Object.class, int.class, Object.class);
-    private static final MethodHandle CALL_CMP                = Bootstrap.createDynamicInvoker("dyn:call", int.class,
+    private static final MethodHandle CALL_CMP                = Bootstrap.createDynamicInvoker("dyn:call", double.class,
             ScriptFunction.class, Object.class, Object.class, Object.class);
 
     private static final InvokeByName TO_LOCALE_STRING = new InvokeByName("toLocaleString", ScriptObject.class, String.class);
@@ -793,11 +793,15 @@
     }
 
     private static ScriptFunction compareFunction(final Object comparefn) {
-        try {
-            return (ScriptFunction)comparefn;
-        } catch (final ClassCastException e) {
-            return null; //undefined or null
+        if (comparefn == ScriptRuntime.UNDEFINED) {
+            return null;
         }
+
+        if (! (comparefn instanceof ScriptFunction)) {
+            throw typeError("not.a.function", ScriptRuntime.safeToString(comparefn));
+        }
+
+        return (ScriptFunction)comparefn;
     }
 
     private static Object[] sort(final Object[] array, final Object comparefn) {
@@ -819,7 +823,7 @@
 
                 if (cmp != null) {
                     try {
-                        return (int)CALL_CMP.invokeExact(cmp, cmpThis, x, y);
+                        return (int)Math.signum((double)CALL_CMP.invokeExact(cmp, cmpThis, x, y));
                     } catch (final RuntimeException | Error e) {
                         throw e;
                     } catch (final Throwable t) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java	Wed Apr 17 21:50:54 2013 -0700
@@ -56,6 +56,7 @@
 import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
 import jdk.nashorn.internal.runtime.options.Options;
+import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 
 /**
@@ -113,11 +114,12 @@
      * Get the current global scope
      * @return the current global scope
      */
+    @CallerSensitive
     public static ScriptObject getGlobal() {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             // skip getCallerClass and getGlobal and get to the real caller
-            Class<?> caller = Reflection.getCallerClass(2);
+            Class<?> caller = Reflection.getCallerClass();
             ClassLoader callerLoader = caller.getClassLoader();
 
             // Allow this method only for nashorn's own classes, objects
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java	Wed Apr 17 21:50:54 2013 -0700
@@ -40,7 +40,7 @@
     private final static String JONI = "joni";
 
     static {
-        final String impl = Options.getStringProperty("nashorn.regexp.impl", JDK);
+        final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI);
         switch (impl) {
             case JONI:
                 instance = new JoniRegExp.Factory();
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java	Wed Apr 17 21:50:54 2013 -0700
@@ -47,9 +47,6 @@
      */
     private final StringBuilder sb;
 
-    /** Is this the special case of a regexp that never matches anything */
-    private boolean neverMatches;
-
     /** Expected token table */
     private final Map<Character, Integer> expected = new HashMap<>();
 
@@ -99,24 +96,17 @@
     }
 
     private void processForwardReferences() {
-        if (neverMatches()) {
-            return;
-        }
 
         Iterator<Integer> iterator = forwardReferences.descendingIterator();
         while (iterator.hasNext()) {
             final int pos = iterator.next();
             final int num = iterator.next();
             if (num > caps.size()) {
-                // Non-existing reference should never match, if smaller than 8 convert to octal escape
-                // to be compatible with other engines.
-                if (num < 8) {
-                    String escape = "\\x0" + num;
-                    sb.insert(pos, escape);
-                } else {
-                    neverMatches = true;
-                    break;
-                }
+                // Non-existing backreference. If the number begins with a valid octal convert it to
+                // Unicode escape and append the rest to a literal character sequence.
+                final StringBuilder buffer = new StringBuilder();
+                octalOrLiteral(Integer.toString(num), buffer);
+                sb.insert(pos, buffer);
             }
         }
 
@@ -140,9 +130,6 @@
         }
 
         scanner.processForwardReferences();
-        if (scanner.neverMatches()) {
-            return null; // never matches
-        }
 
         // Throw syntax error unless we parsed the entire JavaScript regexp without syntax errors
         if (scanner.position != string.length()) {
@@ -151,16 +138,6 @@
         }
 
         return scanner;
-     }
-
-    /**
-     * Does this regexp ever match anything? Use of e.g. [], which is legal in JavaScript,
-     * is an example where we never match
-     *
-     * @return boolean
-     */
-    private boolean neverMatches() {
-        return neverMatches;
     }
 
     final StringBuilder getStringBuilder() {
@@ -282,23 +259,16 @@
         }
 
         if (atom()) {
-            boolean emptyCharacterClass = false;
+            // Check for character classes that never or always match
             if (sb.toString().endsWith("[]")) {
-                emptyCharacterClass = true;
+                sb.setLength(sb.length() - 1);
+                sb.append("^\\s\\S]");
             } else if (sb.toString().endsWith("[^]")) {
                 sb.setLength(sb.length() - 2);
                 sb.append("\\s\\S]");
             }
 
-            boolean quantifier = quantifier();
-
-            if (emptyCharacterClass) {
-                if (!quantifier) {
-                    neverMatches = true; //never matches ever.
-                }
-                // Note: we could check if quantifier has min zero to mark empty character class as dead.
-            }
-
+            quantifier();
             return true;
         }
 
@@ -626,13 +596,14 @@
      *      ABCDEFGHIJKLMNOPQRSTUVWXYZ
      */
     private boolean controlLetter() {
-        final char c = Character.toUpperCase(ch0);
-        if (c >= 'A' && c <= 'Z') {
+        // To match other engines we also accept '0'..'9' and '_' as control letters inside a character class.
+        if ((ch0 >= 'A' && ch0 <= 'Z') || (ch0 >= 'a' && ch0 <= 'z')
+                || (inCharClass && (isDecimalDigit(ch0) || ch0 == '_'))) {
             // for some reason java regexps don't like control characters on the
             // form "\\ca".match([string with ascii 1 at char0]). Translating
             // them to unicode does it though.
             sb.setLength(sb.length() - 1);
-            unicode(c - 'A' + 1);
+            unicode(ch0 % 32, sb);
             skip(1);
             return true;
         }
@@ -651,14 +622,7 @@
         }
         // ES 5.1 A.7 requires "not IdentifierPart" here but all major engines accept any character here.
         if (ch0 == 'c') {
-            // Ignore invalid control letter escape if within a character class
-            if (inCharClass && ch1 != ']') {
-                sb.setLength(sb.length() - 1);
-                skip(2);
-                return true;
-            } else {
-                sb.append('\\'); // Treat invalid \c control sequence as \\c
-            }
+            sb.append('\\'); // Treat invalid \c control sequence as \\c
         } else if (NON_IDENT_ESCAPES.indexOf(ch0) == -1) {
             sb.setLength(sb.length() - 1);
         }
@@ -673,7 +637,7 @@
         final int startIn  = position;
         final int startOut = sb.length();
 
-        if (ch0 == '0' && !isDecimalDigit(ch1)) {
+        if (ch0 == '0' && !isOctalDigit(ch1)) {
             skip(1);
             //  DecimalEscape :: 0. If i is zero, return the EscapeValue consisting of a <NUL> character (Unicodevalue0000);
             sb.append("\u0000");
@@ -681,50 +645,56 @@
         }
 
         if (isDecimalDigit(ch0)) {
-            final int num = ch0 - '0';
 
-            // Single digit escape, treat as backreference.
-            if (!isDecimalDigit(ch1)) {
-                if (num <= caps.size() && caps.get(num - 1).getNegativeLookaheadLevel() > 0) {
-                    //  Captures that live inside a negative lookahead are dead after the
-                    //  lookahead and will be undefined if referenced from outside.
-                    if (caps.get(num - 1).getNegativeLookaheadLevel() > negativeLookaheadLevel) {
-                        sb.setLength(sb.length() - 1);
-                    } else {
-                        sb.append(ch0);
+            if (ch0 == '0') {
+                // We know this is an octal escape.
+                if (inCharClass) {
+                    // Convert octal escape to unicode escape if inside character class.
+                    int octalValue = 0;
+                    while (isOctalDigit(ch0)) {
+                        octalValue = octalValue * 8 + ch0 - '0';
+                        skip(1);
                     }
-                    skip(1);
-                    return true;
-                } else if (num > caps.size()) {
-                    // Forward reference to a capture group. Forward references are always undefined so we
-                    // can omit it from the output buffer. Additionally, if the capture group does not exist
-                    // the whole regexp becomes invalid, so register the reference for later processing.
-                    sb.setLength(sb.length() - 1);
-                    forwardReferences.add(num);
-                    forwardReferences.add(sb.length());
-                    skip(1);
-                    return true;
+
+                    unicode(octalValue, sb);
+
+                } else {
+                    // Copy decimal escape as-is
+                    decimalDigits();
                 }
-            }
-
-            if (inCharClass) {
-                // Convert octal escape to unicode escape if inside character class.
-                StringBuilder digit = new StringBuilder(4);
+            } else {
+                // This should be a backreference, but could also be an octal escape or even a literal string.
+                int decimalValue = 0;
                 while (isDecimalDigit(ch0)) {
-                    digit.append(ch0);
+                    decimalValue = decimalValue * 10 + ch0 - '0';
                     skip(1);
                 }
 
-                int value = Integer.parseInt(digit.toString(), 8); //throws exception that leads to SyntaxError if not octal
-                if (value > 0xff) {
-                    throw new NumberFormatException(digit.toString());
+                if (inCharClass) {
+                    // No backreferences in character classes. Encode as unicode escape or literal char sequence
+                    sb.setLength(sb.length() - 1);
+                    octalOrLiteral(Integer.toString(decimalValue), sb);
+
+                } else if (decimalValue <= caps.size() && caps.get(decimalValue - 1).getNegativeLookaheadLevel() > 0) {
+                    //  Captures that live inside a negative lookahead are dead after the
+                    //  lookahead and will be undefined if referenced from outside.
+                    if (caps.get(decimalValue - 1).getNegativeLookaheadLevel() > negativeLookaheadLevel) {
+                        sb.setLength(sb.length() - 1);
+                    } else {
+                        sb.append(decimalValue);
+                    }
+                } else if (decimalValue > caps.size()) {
+                    // Forward reference to a capture group. Forward references are always undefined so we can omit
+                    // it from the output buffer. However, if the target capture does not exist, we need to rewrite
+                    // the reference as hex escape or literal string, so register the reference for later processing.
+                    sb.setLength(sb.length() - 1);
+                    forwardReferences.add(decimalValue);
+                    forwardReferences.add(sb.length());
+                } else {
+                    // Append as backreference
+                    sb.append(decimalValue);
                 }
 
-                unicode(value);
-
-            } else {
-                // Copy decimal escape as-is
-                decimalDigits();
             }
             return true;
         }
@@ -904,7 +874,6 @@
         switch (ch0) {
         case ']':
         case '-':
-        case '\0':
             return false;
 
         case '[':
@@ -965,13 +934,41 @@
         return true;
     }
 
-    private void unicode(final int value) {
+    private void unicode(final int value, final StringBuilder buffer) {
         final String hex = Integer.toHexString(value);
-        sb.append('u');
+        buffer.append('u');
         for (int i = 0; i < 4 - hex.length(); i++) {
-            sb.append('0');
+            buffer.append('0');
         }
-        sb.append(hex);
+        buffer.append(hex);
+    }
+
+    // Convert what would have been a backreference into a unicode escape, or a number literal, or both.
+    private void octalOrLiteral(final String numberLiteral, final StringBuilder buffer) {
+        final int length = numberLiteral.length();
+        int octalValue = 0;
+        int pos = 0;
+        // Maximum value for octal escape is 0377 (255) so we stop the loop at 32
+        while (pos < length && octalValue < 0x20) {
+            final char ch = numberLiteral.charAt(pos);
+            if (isOctalDigit(ch)) {
+                octalValue = octalValue * 8 + ch - '0';
+            } else {
+                break;
+            }
+            pos++;
+        }
+        if (octalValue > 0) {
+            buffer.append('\\');
+            unicode(octalValue, buffer);
+            buffer.append(numberLiteral.substring(pos));
+        } else {
+            buffer.append(numberLiteral);
+        }
+    }
+
+    private static boolean isOctalDigit(final char ch) {
+        return ch >= '0' && ch <= '7';
     }
 
     private static boolean isDecimalDigit(final char ch) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java	Wed Apr 17 21:50:54 2013 -0700
@@ -156,9 +156,6 @@
 
         env.memNodes = null;
 
-        new ArrayCompiler(this).compile();
-        //new AsmCompiler(this).compile();
-
         if (regex.numRepeat != 0 || regex.btMemEnd != 0) {
             regex.stackPopLevel = StackPopLevel.ALL;
         } else {
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java	Wed Apr 17 21:50:54 2013 -0700
@@ -55,8 +55,9 @@
     int[]repeatRangeLo;
     int[]repeatRangeHi;
 
-    public WarnCallback warnings;
-    public MatcherFactory factory;
+    WarnCallback warnings;
+    MatcherFactory factory;
+    private Analyser analyser;
 
     int options;
     int userOptions;
@@ -140,19 +141,33 @@
         this.caseFoldFlag = caseFoldFlag;
         this.warnings = warnings;
 
-        new Analyser(new ScanEnvironment(this, syntax), chars, p, end).compile();
+        this.analyser = new Analyser(new ScanEnvironment(this, syntax), chars, p, end);
+        this.analyser.compile();
 
         this.warnings = null;
     }
 
+    public void compile() {
+        if (factory == null && analyser != null) {
+            Compiler compiler = new ArrayCompiler(analyser);
+            analyser = null; // only do this once
+            compiler.compile();
+        }
+    }
+
     public Matcher matcher(char[] chars) {
         return matcher(chars, 0, chars.length);
     }
 
     public Matcher matcher(char[] chars, int p, int end) {
+        compile();
         return factory.create(this, chars, p, end);
     }
 
+    public WarnCallback getWarnings() {
+        return warnings;
+    }
+
     public int numberOfCaptures() {
         return numMem;
     }
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java	Wed Jul 05 18:50:42 2017 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java	Wed Apr 17 21:50:54 2013 -0700
@@ -231,12 +231,12 @@
                         break;
 
                     case DEL:
-                        env.reg.warnings.warn(new String(chars, p, end) +
+                        env.reg.getWarnings().warn(new String(chars, p, end) +
                                 " redundant nested repeat operator");
                         break;
 
                     default:
-                        env.reg.warnings.warn(new String(chars, p, end) +
+                        env.reg.getWarnings().warn(new String(chars, p, end) +
                                 " nested repeat operator " + Reduce.PopularQStr[targetQNum] +
                                 " and " + Reduce.PopularQStr[nestQNum] + " was replaced with '" +
                                 Reduce.ReduceQStr[Reduce.REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011714.js	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011714: Regexp decimal escape handling still not correct
+ *
+ * @test
+ * @run
+ */
+
+// \0 should be interpreted as <NUL> character here
+print(/\08/.test("\x008"));
+print(/[\08]/.test("8"));
+print(/[\08]/.test("\x00"));
+
+// Can't be converted to octal thus encoded as literal char sequence
+print(/\8/.exec("\\8"));
+print(/[\8]/.exec("\\"));
+print(/[\8]/.exec("8"));
+
+// 0471 is too high for an octal escape so it is \047 outside a character class
+// and \\471 inside a character class
+print(/\471/.exec("\x271"));
+print(/[\471]/.exec("1"));
+print(/[\471]/.exec("\x27"));
+
+// 0366 is a valid octal escape (246)
+print(/\366/.test("\xf6"));
+print(/[\366]/.test("\xf6"));
+print(/[\366]/.test("\xf6"));
+
+// more tests for conversion of invalid backreferences to octal escapes or literals
+print(/(a)(b)(c)(d)\4/.exec("abcdd"));
+print(/(a)(b)(c)(d)\4x/.exec("abcddx"));
+print(/(a)(b)(c)(d)\47/.exec("abcdd7"));
+print(/(a)(b)(c)(d)\47/.exec("abcd\x27"));
+print(/(a)(b)(c)(d)\47xyz/.exec("abcd\x27xyz"));
+print(/(a)(b)(c)(d)[\47]/.exec("abcd\x27"));
+print(/(a)(b)(c)(d)[\47]xyz/.exec("abcd\x27xyz"));
+print(/(a)(b)(c)(d)\48/.exec("abcd\x048"));
+print(/(a)(b)(c)(d)\48xyz/.exec("abcd\x048xyz"));
+print(/(a)(b)(c)(d)[\48]/.exec("abcd\x04"));
+print(/(a)(b)(c)(d)[\48]xyz/.exec("abcd\x04xyz"));
+print(/(a)(b)(c)(d)\84/.exec("abcd84"));
+print(/(a)(b)(c)(d)\84xyz/.exec("abcd84xyz"));
+print(/(a)(b)(c)(d)[\84]/.exec("abcd8"));
+print(/(a)(b)(c)(d)[\84]xyz/.exec("abcd8xyz"));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011714.js.EXPECTED	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,27 @@
+true
+true
+true
+8
+null
+8
+'1
+1
+'
+true
+true
+true
+abcdd,a,b,c,d
+abcddx,a,b,c,d
+null
+abcd',a,b,c,d
+abcd'xyz,a,b,c,d
+abcd',a,b,c,d
+abcd'xyz,a,b,c,d
+abcd8,a,b,c,d
+abcd8xyz,a,b,c,d
+abcd,a,b,c,d
+abcdxyz,a,b,c,d
+abcd84,a,b,c,d
+abcd84xyz,a,b,c,d
+abcd8,a,b,c,d
+abcd8xyz,a,b,c,d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011749.js	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011749: Bugs with empty character class handling
+ *
+ * @test
+ * @run
+ */
+
+// empty class in alternative
+print(/[]|[^]/.exec("a"));
+print(/[]|[]/.test("a"));
+print(/[]|[]|[a]/.exec("a"));
+
+// empty class in negative lookahead
+print(/(?![])/.test(""));
+print(/(?![])./.exec("a"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011749.js.EXPECTED	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,5 @@
+a
+false
+a
+true
+a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011756.js	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011756: Wrong characters supported in RegExp \c escape
+ *
+ * @test
+ * @run
+ */
+
+
+// Invalid control letters should be escaped:
+print(/\cı/.test("\x09"));
+print(/\cı/.test("\\cı"));
+
+print(/\cſ/.test("\x13"));
+print(/\cſ/.test("\\cſ"));
+
+print(/[\cſ]/.test("\x13"));
+print(/[\cſ]/.test("\\"));
+print(/[\cſ]/.test("c"));
+print(/[\cſ]/.test("ſ"));
+
+print(/[\c#]/.test("\\"));
+print(/[\c#]/.test("c"));
+print(/[\c#]/.test("#"));
+
+// The characters that are supported by other engines are '0'-'9', '_':
+print(/[\c0]/.test("\x10"));
+print(/[\c1]/.test("\x11"));
+print(/[\c2]/.test("\x12"));
+print(/[\c3]/.test("\x13"));
+print(/[\c4]/.test("\x14"));
+print(/[\c5]/.test("\x15"));
+print(/[\c6]/.test("\x16"));
+print(/[\c7]/.test("\x17"));
+print(/[\c8]/.test("\x18"));
+print(/[\c9]/.test("\x19"));
+print(/[\c_]/.test("\x1F"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011756.js.EXPECTED	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,22 @@
+false
+true
+false
+true
+false
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011960.js	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011960: [2,1].sort(null) should throw TypeError
+ *
+ * @test
+ * @run
+ */
+
+function check(func) {
+    try {
+        [2,1].sort(func);
+        fail("should have thrown TypeError for :" + func);
+    } catch (e) {
+        if (! (e instanceof TypeError)) {
+            fail("TypeError not thrown for sort comparefn: " + func);
+        }
+    }
+}
+
+// should not result in TypeError for undefined
+[1, 2].sort(undefined);
+
+// TypeError for null
+check(null);
+
+// should result in TypeError other non-callable params
+check(32);
+check("foo");
+check(false);
+check({});
+check([]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011974.js	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011974: Comparator function returning negative and positive Infinity does not work as expected with Array.prototype.sort
+ *
+ * @test
+ * @run
+ */
+
+function compare(x, y) {
+    return x < y? -Infinity : (x > y? Infinity: 0)
+}
+
+var sorted =  [5, 4, 3, 2, 1].sort(compare);
+
+if (sorted + '' != "1,2,3,4,5") {
+    fail("Array.prototype.sort does not work when compare returns +/-Infinity");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011980.js	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011980: Allow NUL character in character class
+ *
+ * @test
+ * @run
+ */
+
+print(RegExp("\0").test("\0"));
+print(RegExp("[\0]").test("\0"));
+print(RegExp("[\x00]").test("\0"));
+print(RegExp("[\u0000]").test("\0"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8011980.js.EXPECTED	Wed Apr 17 21:50:54 2013 -0700
@@ -0,0 +1,4 @@
+true
+true
+true
+true