8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
Reviewed-by: lagergren, jlaskey
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Thu Oct 10 11:48:56 2013 +0200
@@ -162,7 +162,7 @@
LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) {
@Override
FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
- return (FunctionNode)fn.accept(new Lower());
+ return (FunctionNode)fn.accept(new Lower(compiler));
}
@Override
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Thu Oct 10 11:48:56 2013 +0200
@@ -86,10 +86,13 @@
private static final DebugLogger LOG = new DebugLogger("lower");
+ // needed only to get unique eval id from code installer
+ private final Compiler compiler;
+
/**
* Constructor.
*/
- Lower() {
+ Lower(final Compiler compiler) {
super(new BlockLexicalContext() {
@Override
@@ -132,6 +135,7 @@
return block.setIsTerminal(this, false);
}
});
+ this.compiler = compiler;
}
@Override
@@ -529,11 +533,15 @@
*/
private String evalLocation(final IdentNode node) {
final Source source = lc.getCurrentFunction().getSource();
+ final int pos = node.position();
return new StringBuilder().
append(source.getName()).
append('#').
- append(source.getLine(node.position())).
- append("<eval>").
+ append(source.getLine(pos)).
+ append(':').
+ append(source.getColumn(pos)).
+ append("<eval>@").
+ append(compiler.getCodeInstaller().getUniqueEvalId()).
toString();
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java Thu Oct 10 11:48:56 2013 +0200
@@ -68,4 +68,10 @@
* @return unique script id
*/
public long getUniqueScriptId();
+
+ /**
+ * Get next unique eval id
+ * @return unique eval id
+ */
+ public long getUniqueEvalId();
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java Thu Oct 10 11:48:56 2013 +0200
@@ -139,6 +139,11 @@
public long getUniqueScriptId() {
return context.getUniqueScriptId();
}
+
+ @Override
+ public long getUniqueEvalId() {
+ return context.getUniqueEvalId();
+ }
}
/** Is Context global debug mode enabled ? */
@@ -238,6 +243,9 @@
/** Unique id for script. Used only when --loader-per-compile=false */
private final AtomicLong uniqueScriptId;
+ /** Unique id for 'eval' */
+ private final AtomicLong uniqueEvalId;
+
private static final ClassLoader myLoader = Context.class.getClassLoader();
private static final StructureLoader sharedLoader;
@@ -320,6 +328,7 @@
this.uniqueScriptId = new AtomicLong();
}
this.errors = errors;
+ this.uniqueEvalId = new AtomicLong();
// if user passed -classpath option, make a class loader with that and set it as
// thread context class loader so that script can access classes from that path.
@@ -954,6 +963,10 @@
}, CREATE_LOADER_ACC_CTXT);
}
+ private long getUniqueEvalId() {
+ return uniqueEvalId.getAndIncrement();
+ }
+
private long getUniqueScriptId() {
return uniqueScriptId.getAndIncrement();
}
--- a/nashorn/test/script/assert.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/assert.js Thu Oct 10 11:48:56 2013 +0200
@@ -61,3 +61,22 @@
}
}
});
+
+Object.defineProperty(this, "printError", {
+ configuable: true,
+ enumerable: false,
+ writable: true,
+ value: function (e) {
+ var msg = e.message;
+ var str = e.name + ':';
+ if (e.lineNumber > 0) {
+ str += e.lineNumber + ':';
+ }
+ if (e.columnNumber > 0) {
+ str += e.columnNumber + ':';
+ }
+ str += msg.substring(msg.indexOf(' ') + 1);
+ print(str);
+ }
+});
+
--- a/nashorn/test/script/basic/JDK-8019508.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019508.js Thu Oct 10 11:48:56 2013 +0200
@@ -36,7 +36,7 @@
if (! (e instanceof SyntaxError)) {
fail("expected SyntaxError, got " + e);
}
- print(e.message.replace(/\\/g, '/'));
+ printError(e);
}
}
--- a/nashorn/test/script/basic/JDK-8019508.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019508.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,12 +1,12 @@
-test/script/basic/JDK-8019508.js#33<eval>:1:2 Expected property id but found ,
+SyntaxError:33:Expected property id but found ,
({,})
^
-test/script/basic/JDK-8019508.js#33<eval>:1:2 Expected property id but found ,
+SyntaxError:33:Expected property id but found ,
({, a:2 })
^
-test/script/basic/JDK-8019508.js#33<eval>:1:6 Expected property id but found ,
+SyntaxError:33:Expected property id but found ,
({a:3,,})
^
-test/script/basic/JDK-8019508.js#33<eval>:1:6 Expected comma but found ident
+SyntaxError:33:Expected comma but found ident
({a:3 b:2}
^
--- a/nashorn/test/script/basic/JDK-8019553.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019553.js Thu Oct 10 11:48:56 2013 +0200
@@ -33,7 +33,7 @@
eval(str);
fail("SyntaxError expected for: " + str);
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
}
--- a/nashorn/test/script/basic/JDK-8019553.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019553.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,12 +1,12 @@
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found +
+SyntaxError:33:Expected l-value but found +
++ +3
^
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found -
+SyntaxError:33:Expected l-value but found -
++ -7
^
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found +
+SyntaxError:33:Expected l-value but found +
-- +2
^
-SyntaxError: test/script/basic/JDK-8019553.js#33<eval>:1:3 Expected l-value but found -
+SyntaxError:33:Expected l-value but found -
-- -8
^
--- a/nashorn/test/script/basic/JDK-8019791.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019791.js Thu Oct 10 11:48:56 2013 +0200
@@ -33,7 +33,7 @@
eval('"" ~ ""');
print("FAILED: SyntaxError expected for: \"\" ~ \"\"");
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
// Used to crash instead of SyntaxError
@@ -41,7 +41,7 @@
eval("function() { if (1~0) return 0; return 1 }");
print("FAILED: SyntaxError expected for: if (1~0) ");
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
// The following are valid, but used to crash
--- a/nashorn/test/script/basic/JDK-8019791.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019791.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,6 +1,6 @@
-SyntaxError: test/script/basic/JDK-8019791.js#33<eval>:1:3 Expected ; but found ~
+SyntaxError:33:Expected ; but found ~
"" ~ ""
^
-SyntaxError: test/script/basic/JDK-8019791.js#41<eval>:1:18 Expected ) but found ~
+SyntaxError:41:Expected ) but found ~
function() { if (1~0) return 0; return 1 }
^
--- a/nashorn/test/script/basic/JDK-8019805.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019805.js Thu Oct 10 11:48:56 2013 +0200
@@ -32,5 +32,5 @@
eval("for each(var v=0;false;);");
print("FAILED: for each(var v=0; false;); should have thrown error");
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
--- a/nashorn/test/script/basic/JDK-8019805.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/JDK-8019805.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/JDK-8019805.js#32<eval>:1:16 for each can only be used with for..in
+SyntaxError:32:for each can only be used with for..in
for each(var v=0;false;);
^
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8026167.js Thu Oct 10 11:48:56 2013 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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-8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName('js');
+
+// leave the whitespace - need both eval("e") at same column for this test!
+
+e.eval('function f(e) { eval("e") } f()');
+e.eval('function f() { var e = 33; eval("e") } f()');
+
+function f() {
+ Function.call.call(function x() { eval("x") }); eval("x")
+}
+
+try {
+ f();
+ fail("Should have thrown ReferenceError");
+} catch (e) {
+ if (! (e instanceof ReferenceError)) {
+ fail("ReferenceError expected but got " + e);
+ }
+}
--- a/nashorn/test/script/basic/NASHORN-100.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-100.js Thu Oct 10 11:48:56 2013 +0200
@@ -35,5 +35,5 @@
if (! (e instanceof SyntaxError)) {
fail("#2 expected SyntaxError got " + e);
}
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
--- a/nashorn/test/script/basic/NASHORN-100.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-100.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,3 +1,3 @@
-SyntaxError: test/script/basic/NASHORN-100.js#32<eval>:1:0 Invalid return statement
+SyntaxError:32:Invalid return statement
return;
^
--- a/nashorn/test/script/basic/NASHORN-293.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-293.js Thu Oct 10 11:48:56 2013 +0200
@@ -40,15 +40,13 @@
try {
eval(src);
} catch (e) {
- var location = e.fileName ? e.fileName.slice(-9) : "unknown source";
- print(e.name, "@", location);
+ printError(e);
}
}
for (var i = 0; i < 3; i++) {
try {
eval(src);
} catch (e) {
- var location = e.fileName ? e.fileName.slice(-9) : "unknown source";
- print(e.name, "@", location);
+ printError(e);
}
}
--- a/nashorn/test/script/basic/NASHORN-293.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-293.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,9 +1,9 @@
hello
hello
hello
-TypeError @ #41<eval>
-TypeError @ #41<eval>
-TypeError @ #41<eval>
-TypeError @ #49<eval>
-TypeError @ #49<eval>
-TypeError @ #49<eval>
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
+TypeError:1:read property "foo" from undefined
--- a/nashorn/test/script/basic/NASHORN-40.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-40.js Thu Oct 10 11:48:56 2013 +0200
@@ -31,11 +31,11 @@
try {
eval("print(.foo)");
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
try {
eval(".bar = 3423;");
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
--- a/nashorn/test/script/basic/NASHORN-40.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-40.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,6 +1,6 @@
-SyntaxError: test/script/basic/NASHORN-40.js#32<eval>:1:6 Expected an operand but found .
+SyntaxError:32:Expected an operand but found .
print(.foo)
^
-SyntaxError: test/script/basic/NASHORN-40.js#38<eval>:1:0 Expected an operand but found .
+SyntaxError:38:Expected an operand but found .
.bar = 3423;
^
--- a/nashorn/test/script/basic/NASHORN-51.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-51.js Thu Oct 10 11:48:56 2013 +0200
@@ -35,28 +35,28 @@
eval(literals[i] + "++");
print("ERROR!! post increment : " + literals[i]);
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
try {
eval(literals[i] + "--");
print("ERROR!! post decrement : " + literals[i]);
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
try {
eval("++" + literals[i]);
print("ERROR!! pre increment : " + literals[i]);
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
try {
eval("--" + literals[i]);
print("ERROR!! pre decrement : " + literals[i]);
} catch (e) {
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
}
--- a/nashorn/test/script/basic/NASHORN-51.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-51.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,72 +1,72 @@
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
1++
^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
1--
^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
++1
^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
--1
^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
0++
^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
0--
^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
++0
^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
--0
^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
3.14++
^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
3.14--
^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
++3.14
^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
--3.14
^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
true++
^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
true--
^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
++true
^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
--true
^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
false++
^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
false--
^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
++false
^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
--false
^
-ReferenceError: test/script/basic/NASHORN-51.js#35<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:35:Invalid left hand side for assignment
null++
^
-ReferenceError: test/script/basic/NASHORN-51.js#42<eval>:1:0 Invalid left hand side for assignment
+ReferenceError:42:Invalid left hand side for assignment
null--
^
-ReferenceError: test/script/basic/NASHORN-51.js#49<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:49:Invalid left hand side for assignment
++null
^
-ReferenceError: test/script/basic/NASHORN-51.js#56<eval>:1:2 Invalid left hand side for assignment
+ReferenceError:56:Invalid left hand side for assignment
--null
^
--- a/nashorn/test/script/basic/NASHORN-98.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-98.js Thu Oct 10 11:48:56 2013 +0200
@@ -34,7 +34,7 @@
if (! (e instanceof SyntaxError)) {
fail("syntax error expected here got " + e);
}
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
try {
@@ -43,5 +43,5 @@
if (! (e instanceof SyntaxError)) {
fail("syntax error expected here got " + e);
}
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
--- a/nashorn/test/script/basic/NASHORN-98.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/NASHORN-98.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -1,6 +1,6 @@
-SyntaxError: test/script/basic/NASHORN-98.js#32<eval>:1:13 Expected comma but found decimal
+SyntaxError:32:Expected comma but found decimal
var x = [ 23 34 ]
^
-SyntaxError: test/script/basic/NASHORN-98.js#41<eval>:1:18 Expected comma but found ident
+SyntaxError:41:Expected comma but found ident
var x = { foo: 33 bar: 'hello' }
^
--- a/nashorn/test/script/basic/eval.js Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/eval.js Thu Oct 10 11:48:56 2013 +0200
@@ -69,5 +69,5 @@
eval("print('hello)");
} catch (e) {
print("is syntax error? " + (e instanceof SyntaxError));
- print(e.toString().replace(/\\/g, '/'));
+ printError(e);
}
--- a/nashorn/test/script/basic/eval.js.EXPECTED Wed Oct 09 17:53:22 2013 +0200
+++ b/nashorn/test/script/basic/eval.js.EXPECTED Thu Oct 10 11:48:56 2013 +0200
@@ -10,6 +10,6 @@
100
3300
is syntax error? true
-SyntaxError: test/script/basic/eval.js#69<eval>:1:13 Missing close quote
+SyntaxError:69:Missing close quote
print('hello)
^