TokenStream.java: third octal digit is a part of the octal escape in strings only if the result is <= 0377.
resources/Messages.properties: removal of unused msg.oct.esc.too.large
The change also allows with simple modifications of Context.getCurrentContext and Context.setThreadContext to use java.lang.ThreadLocal from JDK 1.2 to remove any synchronization on global data structures during Context.enter/Context.exit/Context.getCurrentContext.
#155289 - String.prototype.XXX.length has some wrong values
#155291 - RegExp properties should be DontEnum
Plus fix for matching against RegEXp captures with undefined value.
I keep getting syntax errors with no line numbers as well.
That happens when I use Context.compileReader(..) to compile the script. The
DefaultErrorReporter will throw an exception with only the message and not the
line it happened on.
It is of course easy to workaround using your own error reporter, but I've
attached a patch to add on the line and source name so the DefaultErrorReporter
gives the similar output as EcmaError if that is wanted.
> Norris Boyd wrote:
>
> Igor Bukaniv wrote:
> >
> > I am curios, why there is a need to have a special JSObject support in Rhino? Was it used for anything? The implementation in the ICEbrowser does not use it as in rare cases where conversion from JSObject to/from JS type may be needed (like calling JSObject.getWindow from a script), it seems that WrapHandler (or similar modifications to pre Rhino 1.5R2 sources) and Wrapper are enough to cover all the cases.
> Yes, we should probably just remove the JSObject code. We added it early on when Rhino was first written and we thought we might need JSObject compatibility with the JS + Java implementation in Navigator 4.x. That's not important now, so we should just remove this code (which likely doesn't work at this point anyway).
given the following object :
----------------------------------------------
function SomeObject() {}
SomeObject.prototype.exec = function() {
var local = this.someField;
}
----------------------------------------------
i create an 'instance', set a field and call the exec method :
----------------------------------------------
var someField = "global field value";
var anInstance = new SomeObject();
anInstance.someField = "instance field value";
anInstance.exec();
----------------------------------------------
then the local variable 'local' in the exec() method is assigned the value
of the global 'someField' variable instead of the instance field value.
the problem seems to be in the ScriptRuntime.callOrNewSpecial() method,
which is called, because the parser treats the name 'exec' specially. in
this method the exec() method gets called with
return call(cx, fun, thisArg, args, scope);
where the 'thisArg' parameter really is the global this value instead of
the dynamic this value, which is in the jsThis variable and which would be
the one needed...
is it legitimate to replace the above call in callOrNewSpecial() with the
following line :
return call(cx, fun, jsThis, args, scope);
this seems to only happen for methods named 'exec', which are identified as
special in the NodeTransformer.isSpecialCallName() method.
any help is appreciated. thank you very much for your time.
kind regards,
felix
The attached patch adds support for debugging eval and Function code transparently. It changes omj.NativeGlobal and omj.BaseFunction to embed line number of origin of eval and Function scripts into source name and pass 1 as base line for script code. In this way a debugger implementation can treat eval and Function code in the same way as scripts loaded from some url while giving more information about error location in case of an error in eval code as the error source would contain both line number of eval origin and line number in eval code itself.
I chose to embed line numbers via patterns like
sourcefile#<line-number>(eval)
sourcefile#<line-number>(Function)
just to be able to to pass the constructed name to URL constructor if the original sourcefile is a valid URL but it is pretty arbitrary.
I have noticed that attempting to call a java method like this:
public void foo(String foo, Serializable bar)
{
// un-important details
}
from script using foo("foo", "bar"); fails because the second argument
is not deemed coercable to Serializable. A preliminary look at the
coercion code shows that no check is made in this case with
isAssignableFrom().
The to type is only tested against StringClass and ObjectClass (non
primitive case).
(See NativeJavaObject.getConversionWeight())
I attach the patch to move away setting/quering for breakpoints from the Rhino core to application as a debugger implementation can check if a particular line has a breakpoint or not. The changes to omj/tools/debugger takes more then few lines I initially thought but they are mostly caused by refactoring to implement different view to set/query breakpoints.
The patch replaces getLineNumbers, placeBreakpoint and removeBreakpoint in DebuggableScript by getFirstLine, getEndLine and getInstructionLines where the last function fills a boolean array to indicate which script lines can ever occur in DebugFrame.onLineChange. These are read-only functions so InterpeterData are never mdofied by the debugger.
omj/tools/debugger/Main uses this information to check whether it is possible to place breakpoint at a particular line, and if possible, it sets to true entry at the boolean breakpoint array. In this way testing for break in onLineChange is simple and fast as it just needs to check if breakpoint array holds true at the given line number position.
1. Targeting of labels with 0x80000000 biscuits is moved from LabelTable to ClassFileWriter as this is classfile specific and is not necessary in Interpreter.
2. LabelTable allows for pc > Short.MAX_VALUE as this restriction is classfile specific. The only requirement is for jump offsets to stay within short range.
3. LabelTable is made private member of Interpreter and ClassFileWriter instead of being classes' superclass to avoid API leakage that forced optimizer.Codegen to declare few utility methods public as they got the same signature as LabelTable methods visible throw Interpreter inheritance.
1. Replacing omj.debug.Debugger.enterFrame() by omj.debug.Debugger.getFrame() and omj.debug.DebugFrame.onEnter() to allow to return null from omj.debug.Debugger.getFrame to enable full optimization with debugger set if it is not interested in monitoring a particular frame
2. Changing type for the source argument in omj.debug.Debugger.handleCompilationDone from StringBuffer to String as Debugger instances should not be able to modify source even by chance.
The patch uses the special NOT_FOUND value to flag deleted indexes. It also
make sure that original array object passed to Function.call is not modified,
as all changes goes to cloned copy. It is not necessary for the fix, but it is
the only place in the current Rhino that can alter Object[] array passed to
Function.call and I think it is better to remove this exceptional case.
These changes add the cache optimization to the has methods and remove cache update from the put methods under the assumption that newly assigned properties would not be used immediately.
hi Norris,
in our product, which makes heavy use of Rhino, we have many Java Objects
we wrap with ECMAScript wrappers, which extend the ScriptableObject class
and implement the Wrapper interface. Those wrappers automagically wrap the
native Java object with the help of a WrapHandler implementation.
we now ran into a problem :
we have a java class with two overloaded static methods like this :
public class Test {
public static String create(File f) {}
public static String create(Custom c) {}
}
The Custom class exists as a native Java implementation like
public class Custom {}
and a accompanying ECMAScript wrapper like
public class CustomWrapper
extends ScriptableObject
implements Wrapper {}
in our ECMAScripts we make the wrapper class known as a host object along
the lines of
defineClass("CustomWrapper");
and can then use the object as a normal ECMAScript host object. no big deal
and working great.
but : the code
var s = Test.creat( new Custom( "xyz") );
fails with the information, that the methods are ambiguous, which of course
they are not.
Looking at the code of NativeJavaMethod.findFunction() and the helpers in
NativeJavaObject it seems, that the fact of the Custom host object being a
Wrapper is not taken into account. in an easy fix of
NativeJavaMethod.findFunction(), i simply replace all arguments, which are
Wrapper imlpementation by the wrapped object. this solves my problem, but
of course i'm not sure on side effects.
i attach the testcase as well as the fixed NativeJavaMethod class in the
jar file. to run the test with and without the fix, extract the jar and do
ant test
please let me know, what you think of this.
regards and thanks, f.
Felix Meschberger
I think there's a small problem with Igor's changes. The modifed Interpreter.java
seems to create unnecessary activation objects for InterpretedScripts. You can
see this in the debugger (local variables are present even for top level scripts).
I believe the attached change will fix the problem.
Regards,
Chris
VariableModel.java:220:30:220:40: Caution: This try block cannot throw a "checked exception" (JLS section 14.7) that can be caught here. You may have intended to catch a RuntimeException instead of an Exception.
Changes to omj.tools.debugger are mostly due to renames and refactoring, the new code is limited to ContextData class which contains simplified version of the code for DebugFrame stack from the current DebuggableEngineImplementation and FrameHelper class implementing DebugFrame.
...
The idea is to make Debugger responsible for creation of DebugFrame in
Interpreter.interpret which gives simple way for a Debugger implementation to
observe function enter/exit while completely removing the need to have code
for debug frame stack in the Rhino core as the Debugger implementation can
easily support this on its own when necessary. So I suggest to have:
public interface Debugger { ... }
and
public interface DebugFrame { ... }
which eliminates omj.InterpreterFrame and as DebuggableEngine shrinks down to
3 methods set/getDebugger and getDebuggerContextData, I simply moved them to
Context. The 3rd method is useful to refer to per Context debug data from a
Debugger implementation, but it can be removed as well as the same effect can
be achieved via Context.set/getThreadLocal.
non-ScriptableObject implementations of Scriptable.
I checked in fixes for the problems of serializing objects with FunctionObjects or
GetterSlots. With Foo.class in the current directory, I can now do:
[rhino] java -classpath 'build/rhino1_5R4pre/js.jar;.' org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 4 0000 00 00 (in progress)
js> defineClass("Foo")
js> f = new Foo
[object Foo]
js> print(f.counter)
0
js> print(f.counter)
1
js> serialize(f, "f.ser")
js> quit()
[rhino] java -classpath 'build/rhino1_5R4pre/js.jar;.' org.mozilla.javascript.tools.shell.Main
Rhino 1.5 release 4 0000 00 00 (in progress)
js> f = deserialize("f.ser")
[object Foo]
js> f.counter
2
js> f.counter
3
Hi Norris,
I encountered the following exception with the below script in compiled
mode with RhinoLatest.zip:
java.lang.NullPointerException
at
org.mozilla.javascript.optimizer.Codegen.visitCall(Codegen.java:1790)
at
org.mozilla.javascript.optimizer.Codegen.generateCodeFromNode(Codegen.java:567)
at
org.mozilla.javascript.optimizer.Codegen.visitReturn(Codegen.java:2283)
at
org.mozilla.javascript.optimizer.Codegen.generateCodeFromNode(Codegen.java:592)
at
org.mozilla.javascript.optimizer.Codegen.generateCodeFromNode(Codegen.java:546)
at
org.mozilla.javascript.optimizer.Codegen.generateCodeFromNode(Codegen.java:546)
at
org.mozilla.javascript.optimizer.Codegen.generateCodeFromNode(Codegen.java:546)
at
org.mozilla.javascript.optimizer.Codegen.generateCode(Codegen.java:497)
at
org.mozilla.javascript.optimizer.Codegen.generateFunctionInits(Codegen.java:1292)
at
org.mozilla.javascript.optimizer.Codegen.generateInit(Codegen.java:1186)
at
org.mozilla.javascript.optimizer.Codegen.generateCode(Codegen.java:481)
at org.mozilla.javascript.optimizer.Codegen.compile(Codegen.java:88)
at org.mozilla.javascript.Context.compile(Context.java:1965)
at org.mozilla.javascript.Context.compile(Context.java:1874)
at org.mozilla.javascript.Context.compileReader(Context.java:895)
at org.mozilla.javascript.Context.evaluateReader(Context.java:813)
at
org.mozilla.javascript.tools.shell.Main.evaluateReader(Main.java:318)
at org.mozilla.javascript.tools.shell.Main.processFile(Main.java:309)
at org.mozilla.javascript.tools.shell.Main.processSource(Main.java:248)
at org.mozilla.javascript.tools.shell.Main.exec(Main.java:95)
at org.mozilla.javascript.tools.shell.Main.main(Main.java:68)
Exception in thread "main"
function tak(x, y, z, k) {
if (!(y < x)) {
return k(z);
} else {
return tak(x - 1,
y,
z,
function(v1) {
return tak(y - 1,
z,
x,
function(v2) {
return tak(z - 1,
x,
y,
function(v3) {
return tak(v1, v2, v3, k);
});
});
});
}
}
function cpstak(x, y, z) {
return tak(x, y, z, function(a) {return a;});
}
//;;; call: (cpstak 18 12 6)
//(run-benchmark "CPSTAK" (lambda () (cpstak 18 12 6)))
var start = new Date();
var res = cpstak(18, 12, 6);
var end = new Date();
print(res +": elapsed: " + (end - start));
Hi Norris,
Would you mind checking in the attached changes to the debugger. The
attached files include the following changes:
1) Use ScriptableObject.getAllIds to obtain an object's properties (if
the object extends ScriptableObject). This makes non-enumerable
properties visible in the debugger for ScriptableObject's.
2) Made the coding style more consistent with the rest of Rhino.
3) Better support for displaying and stepping through eval-ed code.
As Igor suggested to me once, it might be a good idea to define a new
interface to similarly support debugging host objects that don't extend
ScriptableObject, something like the following:
public interface Debuggable extends Scriptable {
public Object[] getAllIds();
}
The debugger could check for this interface and if a host object chose
to implement it, the debugger would be able to display its
non-enumerable properties.
Chris
I think recent Christopher suggestions about tail call elimination is worth
to consider, as it would allow to cut invocation cost of script functions
quite nicely in many cases. Plus I am thinking of not creating Object[] array
to pass arguments to callee if it is another interpreted function as it can
directly access the caller stack. But first I decided to make some
preparation work to simplify an implementation of these features later. The
attached patch includes:
1. Moving all code to setup scope from
InterpretedFunction.call/InterpretedFunction.call to Interpreter.interpret so
the call method simply calls Interpreter.interpret. It would make tail call
elimination code much simple. I also hope this simplifies changes Christopher
needs for the continuations support (but I have strong reservation about
possibility to implement it corectly).
2. Moving all declaration of temporary variables used only during processing
of the single ICODE to the case blocks.
3. Interpreter loop termination only in RETURN icodes, not when pc exceeds
icode size, so there is no need to check for this condition on each icode.
(Scripts are handled via the special END_ICODE token).
...
>I did some tinkering and found there are pure java.lang.Object
>instantiations deep inside all the "standard objects" added to the
>ImporterTopLevel with Context.initStandardObject(). This is what is keeping
>it from serializing.
This is due to presence of Scriptable.NOT_FOUND and IdScriptable.NULL_VALUE tags in the data to serialize.
I replaced the type for the tags from Object to UniqueTag which is serializable ad knows how to make restored tags the same objects as Scriptable.NOT_FOUND and IdScriptable.NULL_VALUE.
Similarly Undefined was made serializable and to restore to Undefined.instance upon reading.
While looking into optimizing the modifications I've
made, I noticed that one of the bottlenecks seemed to be calls to the Java
instanceof operator, particularly if the class argument to instanceof isn't
final. Based on this observation I tweaked ScriptRuntime.java to attempt to avoid
some of the many "instanceof Scriptable" calls in it (which I've attached). In
particular I optimized the comparison operators for the case where the arguments
are Number's. This seems to provide some significant performance improvement in
many cases particularly in compiled mode. See below (note the tests were
performed with today's rhinoLatest.zip code patched with the attached
ScriptRuntime.java and didn't include any of my other modifications).
2. ObjToIntMap.clear and UintMap.clear now do not discard internal buffers, but clears references to external objects to match behavior of Java Vector.clear and Hashtable.clear.
If I have a Java class with a normal method that throws an exception, Rhino
(1.5pre4) will let JavaScript catch the exception. If the Java class has a
getter method, Rhino will NOT let JavaScript catch the exception. Very
disturbing.
Here's a console dump to show you what I'm talking about:
D:\jsSandbox>cat GIJoe.java
public class GIJoe
{
// Getter
public static int getYoJoe()
throws Exception
{
throw new Exception("Please catch me!");
}
// Normal
public static int rebel()
throws Exception
{
throw new Exception("Please catch me too!");
}
}
D:\jsSandbox>javac GIJoe.java
D:\jsSandbox>cat gi.js
var gi = new Packages.GIJoe();
try
{
var i = gi.rebel();
java.lang.System.err.println("rebel(): uncaught");
}
catch(e1)
{
java.lang.System.err.println("rebel(): caught");
}
try
{
var i = gi.yoJoe;
java.lang.System.err.println("yoJoe: uncaught");
}
catch(e2)
{
java.lang.System.err.println("yoJoe: caught");
}
D:\jsSandbox>java -cp .;e:\javas\rhino1_5R4pre\js.jar
org.mozilla.javascript.too
ls.shell.Main
js> load("gi.js");
rebel(): caught
java.lang.Exception: Please catch me!
org.mozilla.javascript.WrappedException: WrappedException of Please catch
me!
at org.mozilla.javascript.JavaMembers.get(JavaMembers.java:105)
at
org.mozilla.javascript.NativeJavaObject.get(NativeJavaObject.java:93)
at
org.mozilla.javascript.ScriptRuntime.getProp(ScriptRuntime.java:691)
at
org.mozilla.javascript.Interpreter.interpret(Interpreter.java:1591)
at
org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java:
63)
at
org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java:
54)
at org.mozilla.javascript.Context.evaluateReader(Context.java:741)
at
org.mozilla.javascript.tools.shell.Main.evaluateReader(Main.java:347)
at
org.mozilla.javascript.tools.shell.Main.processSource(Main.java:336)
at org.mozilla.javascript.tools.shell.Global.load(Global.java:169)
at java.lang.reflect.Method.invoke(Native Method)
at
org.mozilla.javascript.FunctionObject.callVarargs(FunctionObject.java
:586)
at
org.mozilla.javascript.FunctionObject.call(FunctionObject.java:460)
at
org.mozilla.javascript.ScriptRuntime.call(ScriptRuntime.java:1216)
at
org.mozilla.javascript.Interpreter.interpret(Interpreter.java:1679)
at
org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java:
63)
at
org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java:
54)
at org.mozilla.javascript.Context.evaluateReader(Context.java:741)
at
org.mozilla.javascript.tools.shell.Main.evaluateReader(Main.java:347)
at
org.mozilla.javascript.tools.shell.Main.processSource(Main.java:284)
at org.mozilla.javascript.tools.shell.Main.exec(Main.java:146)
at org.mozilla.javascript.tools.shell.Main.main(Main.java:74)
js>
Due to a lack of an "uncaught" statement in the output, we see that the
exception from GIJoe::getYoJoe() was indeed thrown, but not caught by the
JavaScript.
Do any nightly builds past 1.5pre4 address this issue?
Todd Trimmer
[javac] Compiling 1427 source files to /data/gump/xml-batik/classes
[javac] /data/gump/xml-batik/sources/org/apache/batik/script/rhino/EventTargetWrapper.java:81:
coerceType(java.lang.Class,java.lang.Object,boolean)
in org.mozilla.javascript.NativeJavaObject cannot be applied to
(java.lang.Class,java.lang.Object)
Thanks!
As promised, I tried the debugger this afternoon and I had a problem with the '-f' option.
We use -f to run a standard "startup" script before executing the "main" script. For
example, we run the Rhino shell with the options "-f startup.js main.js".
When running the debugger's shell with the same options the debugger exits after the
startup.js completes; i.e., I can single step starting from startup.js but the debugger
exits at the end of startup.js without letting me single step into main.js. This worked
fine in the 1.5R2 release of Rhino and the debugger.
I have not had a chance to look into the problem closely, but a cursory look at the code
suggests (to me) that the problem can be in either the debugger or the shell (since the
debugger basically runs the shell after creating the right "hooks".) Of course, it could
also be a problem with my embedding.
So ... my question is, has anyone tried single stepping when the options to the debugger
include a '-f' option. If so, I'll continue to look for a problem in my embedding.
Any suggestions would be appreciated.
Thanks,
dave
Norris,
I realize this is probably a nuisance, but the following problem causes our
regression test suite to fail:
js> foo = new Error("bar")
undefined: bar
js> foo.name Error
js> foo.toString()
undefined: bar
Our test suite expects:
js> foo = new Error("bar")
Error: bar
js> foo.name Error
js> foo.toString()
Error: bar
I have not yet tried the debugger with the RC2 release, but I expect to get
to that later today.
I hope I'm not to late to influence the 1.5R3 release.
Thanks,
dave
We have found a problem in string.replace() when replacing a regular
expression with a dollar sign. The following code works right when the
replacement string does not contain "$":
$ java -jar js.jar
js> var re = new RegExp("%%%");
js> var price = "%%% 1.99";
js> price.replace(re, "USD");
USD 1.99
js> price.replace(re, "$");
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at
org.mozilla.javascript.regexp.ReplaceData.interpretDollar(RegExpImpl.java:40 0)
at
org.mozilla.javascript.regexp.ReplaceData.findReplen(RegExpImpl.java:502)
at
org.mozilla.javascript.regexp.RegExpImpl.replace(RegExpImpl.java:116)
at
org.mozilla.javascript.NativeString.execMethod(NativeString.java:266)
at org.mozilla.javascript.IdFunction.call(IdFunction.java:78)
at org.mozilla.javascript.ScriptRuntime.call(ScriptRuntime.java:1222)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:1940)
at
org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java:68)
at
org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java:59)
at org.mozilla.javascript.Context.evaluateReader(Context.java:773)
at
org.mozilla.javascript.tools.shell.Main.evaluateReader(Main.java:312)
at
org.mozilla.javascript.tools.shell.Main.processSource(Main.java:219)
at org.mozilla.javascript.tools.shell.Main.exec(Main.java:106)
at org.mozilla.javascript.tools.shell.Main.main(Main.java:68)
We are converting from spidermonkey to rhino and it appears that the
name property for the constructor function returns "constructor" for
all builtin types. Spidermonkey would return "Date" or "Array" or
whatever. Is there a workaround? This code needs to work with both
interpreters.
Here is an example of the rhino behavior:
js> var i=new Date;
js> i.constructor.name
constructor
js> Date.name
constructor
js> function bob(){}
js> bob.name
bob
js> var i = new Array();
js> i.constructor.name
constructor
js>