From b1ecbb62ba430d003a9c94c2b66f4601ef555bf4 Mon Sep 17 00:00:00 2001 From: "norris%netscape.com" Date: Mon, 4 Oct 1999 18:27:30 +0000 Subject: [PATCH] Fix bug found by Andrew Wason (see below). Problem was that one transformation of a node to GETVAR wasn't protected by a check of inWithStatement(). ====================================== Subject: multiple scopes Date: Fri, 01 Oct 1999 12:39:14 -0400 From: Andrew Wason To: norris@netscape.com CC: Howard Lin When I create two scopes, and one scope evaulates a string in the other scope, it works. However, if I do this while handling an exception thrown within a JavaAdapter method, it fails with an exception. Run the attached Java program with the two script files. scope1.js evaluates a string "printMessage" in the scope of scope2.js. This returns a function object which is then invoked. This works in 3 cases, but fails in the 4th (in the catch in the JavaAdapter). Even in the 4th case where it fails, printing the function object looks normal. Am I doing something wrong, or is there a bug here? java CrossScope scope1.js scope2.js Outside of JavaAdapter works before exception works after exception Inside of JavaAdapter works before exception Caught exception pma= function printMessage(msg) { java.lang.System.out.println(msg); } Exception in thread "main" org.mozilla.javascript.JavaScriptException: org.mozilla.javascript.EvaluatorException: The undefined value has no properties. at org.mozilla.javascript.JavaScriptException.wrapException(JavaScriptException .java:61) at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java, Compiled Code) at org.mozilla.javascript.ScriptRuntime.call(ScriptRuntime.java:1256) at org.mozilla.javascript.Interpreter.interpret(Interpreter.java, Compiled Code) at org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java:49) at org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java:37) at org.mozilla.javascript.Context.evaluateReader(Context.java:697) at CrossScope.(CrossScope.java:30) at CrossScope.main(CrossScope.java:10) Thanks, Andrew import java.io.*; import org.mozilla.javascript.*; public class CrossScope { private Context m_jsContext; private Scriptable m_scope1; private Scriptable m_scope2; public static void main(String args[]) throws Exception { new CrossScope(args[0], args[1]); } private CrossScope(String strFile1, String strFile2) throws Exception { // Associate Context with main thread m_jsContext = Context.enter(); m_jsContext.setOptimizationLevel(-1); // Init scope1, expose Scope object m_scope1 = m_jsContext.initStandardObjects(new ImporterTopLevel()); m_scope1.put("Scope", m_scope1, this); // Init scope2 m_scope2 = m_jsContext.initStandardObjects(new ImporterTopLevel()); // Run script in scope2 Reader r2 = new FileReader(strFile2); m_jsContext.evaluateReader(m_scope2, r2, strFile2, 1, null); // Eval input JS in scope1 - it can in turn eval JS over in scope2 Reader r1 = new FileReader(strFile1); Object obj = m_jsContext.evaluateReader(m_scope1, r1, strFile1, 1, null); if (obj instanceof Throwable) ((Throwable)obj).printStackTrace(); m_jsContext.exit(); } public Object scope1Eval(String str) throws JavaScriptException { Context cx = Context.enter(m_jsContext); Object objResult = cx.evaluateString(m_scope1, str, "scope1EvalString", 1, null); cx.exit(); return objResult; } public Object scope2Eval(String str) throws JavaScriptException { Context cx = Context.enter(m_jsContext); Object objResult = cx.evaluateString(m_scope2, str, "scope2EvalString", 1, null); cx.exit(); return objResult; } } // Scope1 importPackage(java.lang); System.out.println("Outside of JavaAdapter"); try { var pm = Scope.scope2Eval("printMessage"); pm("works before exception"); System.arraycopy(null, 5, null, 5, 100); } catch (e) { var pma = Scope.scope2Eval("printMessage"); pma("works after exception"); } var obj = new Runnable() { run: function() { System.out.println("Inside of JavaAdapter"); try { var pm = Scope.scope2Eval("printMessage"); pm("works before exception"); System.arraycopy(null, 5, null, 5, 100); } catch (e) { System.out.println("Caught exception"); var pma = Scope.scope2Eval("printMessage"); System.out.println("pma=" + pma); pma("works after exception"); } } }; obj.run(); // Scope2 function printMessage(msg) { java.lang.System.out.println(msg); } --- js/rhino/org/mozilla/javascript/NodeTransformer.java | 4 ++-- js/rhino/src/org/mozilla/javascript/NodeTransformer.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/rhino/org/mozilla/javascript/NodeTransformer.java b/js/rhino/org/mozilla/javascript/NodeTransformer.java index 8a3c236fd659..40b913927e88 100644 --- a/js/rhino/org/mozilla/javascript/NodeTransformer.java +++ b/js/rhino/org/mozilla/javascript/NodeTransformer.java @@ -463,7 +463,7 @@ public class NodeTransformer { break; String name = node.getString(); if (name.equals("arguments")) { - // Use of "arguments" requires a an activation object. + // Use of "arguments" requires an activation object. ((FunctionNode) tree).setRequiresActivation(true); } VariableTable vars = getVariableTable(tree); @@ -541,7 +541,7 @@ public class NodeTransformer { if (left.getType() == TokenStream.NAME) { VariableTable vars = getVariableTable(tree); String name = left.getString(); - if (inFunction && vars.get(name) != null) { + if (inFunction && vars.get(name) != null && !inWithStatement()) { // call to a var. Transform to Call(GetVar("a"), b, c) left.setType(TokenStream.GETVAR); // fall through to code to add GetParent diff --git a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java index 8a3c236fd659..40b913927e88 100644 --- a/js/rhino/src/org/mozilla/javascript/NodeTransformer.java +++ b/js/rhino/src/org/mozilla/javascript/NodeTransformer.java @@ -463,7 +463,7 @@ public class NodeTransformer { break; String name = node.getString(); if (name.equals("arguments")) { - // Use of "arguments" requires a an activation object. + // Use of "arguments" requires an activation object. ((FunctionNode) tree).setRequiresActivation(true); } VariableTable vars = getVariableTable(tree); @@ -541,7 +541,7 @@ public class NodeTransformer { if (left.getType() == TokenStream.NAME) { VariableTable vars = getVariableTable(tree); String name = left.getString(); - if (inFunction && vars.get(name) != null) { + if (inFunction && vars.get(name) != null && !inWithStatement()) { // call to a var. Transform to Call(GetVar("a"), b, c) left.setType(TokenStream.GETVAR); // fall through to code to add GetParent