[Fwd: My Mistake in ScriptRuntime method]]]
Date:
Tue, 16 Jan 2001 15:48:26 +0100
From:
Igor Bukanov <igor@icesoft.no>
To:
Norris Boyd <nboyd@atg.com>
Hi, Norris!
With my previous patch to fix in
org/mozilla/javascript/ScriptRuntime.java Integer.MIN_VALUE as index
problem I also added a bug to the unrelated code: I tried to minimize
object creation and unfortunately that untested "optimization" slippet
into my patch as well.
I replaced the lines 290, 291 in toNumber(String s) method from
String sub = s.substring(start, end+1);
if (sub.equals("Infinity"))
to
if (s.regionMatches(start, "Infinity", 0, 8))
But that should be
if (start + 7 == end && s.regionMatches(start, "Infinity", 0, 8))
Sory for troubles, Igor
290c290
< if (s.regionMatches(start, "Infinity", 0, 8))
---
> if (start + 7 == end && s.regionMatches(start, "Infinity", 0, 8))
Re: Debugger problem
Date:
Mon, 08 Jan 2001 14:16:30 -0800
From:
Christopher Oliver <coliver@mminternet.com>
Organization:
Primary Interface LLC
To:
Kurt Westerfeld <kurt@ManagedObjects.com>
CC:
Norris Boyd <nboyd@atg.com>
References:
1 , 2 , 3
Kurt, Norris,
Yes, with the change to the shell this should be possible. The problem before
was that if you loaded the same file with different relative path names, two
different windows in the debugger were created because everything (windows,
breakpoints, etc) is keyed off the source name.
The attached file contains the fix (and includes the workaround for
Desktop.getSelectedFrame).
There are still some bugs in transferring focus between the windows in the
Desktop. I haven't had time to track down the problem or a solution.
Chris
Kurt Westerfeld wrote:
> I would point out that "Source Name" of a script isn't necessarily a
> filename. In our system, scripts are run remotely from a script library
> that has no file system backing. Canonicalizing the file names is really
> unnecessary.
>
> Can't you just modify JSDebugger to not care what the name of the file is?
> If access to the original script is unavailable except through the file
> system, I'd be surprised.
>
> ----- Original Message -----
> From: Christopher Oliver <coliver@mminternet.com>
> To: Kurt Westerfeld <kurt@ManagedObjects.com>
> Cc: Norris Boyd <nboyd@atg.com>
> Sent: Sunday, January 07, 2001 2:23 AM
> Subject: Re: Debugger problem
>
> > Hi Kurt,
> >
> > I rather would say that it is a problem with the processFile method in the
> > shell's Main class. If you change the current working directory or the
> value
> > of the System property "user.dir" after compiling a script, relative path
> names
> > can become ambiguous. Norris, would it be ok to modify the shell to
> > "canonicalize" the names of files it compiles? That way the source name
> that
> > shows up in the stack and in DebuggableScript will always be unique. For
> > example:
> >
> > public static void processFile(Context cx, Scriptable scope,
> > String filename)
> > {
> > Reader in = null;
> > try {
> > in = new PushbackReader(new FileReader(filename));
> > int c = in.read();
> > // Support the executable script #! syntax: If
> > // the first line begins with a '#', treat the whole
> > // line as a comment.
> > if (c == '#') {
> > while ((c = in.read()) != -1) {
> > if (c == '\n' || c == '\r')
> > break;
> > }
> > ((PushbackReader) in).unread(c);
> > } else {
> > // No '#' line, just reopen the file and forget it
> > // ever happened. OPT closing and reopening
> > // undoubtedly carries some cost. Is this faster
> > // or slower than leaving the PushbackReader
> > // around?
> > in.close();
> > in = new FileReader(filename);
> > }
> > filename = new java.io.File(filename).getCanonicalPath();
> > <<<====== Add this
> > }
> > catch (FileNotFoundException ex) {
> > Context.reportError(ToolErrorReporter.getMessage(
> > "msg.couldnt.open",
> > filename));
> > exitCode = EXITCODE_FILE_NOT_FOUND;
> > return;
> > } catch (IOException ioe) {
> > globalState.getErr().println(ioe.toString());
> > }
> >
> > // Here we evalute the entire contents of the file as
> > // a script. Text is printed only if the print() function
> > // is called.
> > evaluateReader(cx, scope, in, filename, 1);
> > }
> >
> >
> > Attached is *my* latest version of the debugger code. Norris, have you
> made
> > any progress on cvs commit priveledges? The attached version fixes a
> number of
> > GUI bugs:
> >
> > 1) If you undocked the Variables window and popped up the Context
> combo-box and
> > then closed the window with the system menu, the Context pop-up was not
> cleaned
> > up properly.
> > 2) The first time you minimize a file window it appeared to dissappear
> when you
> > tried to restore it. This was due to the fact that I forgot to "pack" its
> > contents and as a result its requested size was 0x0.
> >
> > I also added a menu item to toggle whether to break on exceptions and one
> which
> > allows you to open (and compile) a JavaScript file without actually
> executing
> > it.
> >
> > I have also attached a Word document with some basic documentation for the
> > Debugger.
> >
> > Note that this version also includes all the changes to support debugging
> > scripts in the AWT dispatch thread.
> >
> > Chris
> >
> > Kurt Westerfeld wrote:
> >
> > > Hello. I ran into a null pointer exception in JSDebugger tonight, and I
> > > thought I'd drop you a note.
> > >
> > > The problem line is 2336, where a breakpoint is hit. To simulate, load
> the
> > > debugger using the command line syntax on a file that has not been
> resolved
> > > to cannonical path.
> > >
> > > Example,
> > >
> > > jshell -debug -f \myfile.fs
> > >
> > > At any rate, the "handleCompilationDone" routine takes \myfile.fs and
> turns
> > > it into a canonical path. If you hit a breakpoint in this file and say
> > > "go", when the breakpoint hits the file is not found, because the same
> > > canonical path resolution is not done. The resolution seems dubious,
> since
> > > it is only done in the compilation done callback, but I don't know the
> best
> > > way to suggest a fix since it seems that code had some purpose.
> > >
> > > Anyway, thought you'd wanna know.
> > >
> > > ________________________________________________________________________
> > > Kurt Westerfeld
> > > Senior Software Architect
> > > Managed Objects
> > > mailto:kwester@ManagedObjects.com
> > > 703.770.7225
> > > http://www.ManagedObjects.com
> > >
> > > Managed Objects: manage technology > rule business
> >
JSDebugger.java
Name:
JSDebugger.java
Type:
Java Class File (java/*)
Encoding:
base64
* Make use of DebuggableEngine interface to keep Context API smaller
* Change org.mozilla.javascript.debug.Frame to DebugFrame to avoid
confusion with java.awt.Frame
Subject:
Re: Rhino bug - Wrapper ??
Date:
Fri, 05 Jan 2001 03:46:11 +0530
From:
Mukund Balasubramanian <mukund@cs.stanford.edu>
Organization:
Another Netscape Collabra Server User
Newsgroups:
netscape.public.mozilla.jseng
References:
1 , 2 , 3 , 4 , 5 , 6
That works too,
Should I assume that this would be a part of the next tip ? I agree with the
part about
overloading code too.
Anyways, thanks a load for your help and just tell me if I could be of any
help in any other
respects of the rhino project.
ThanX,
Mukund Balasubaramanian
Norris Boyd wrote:
> Actually, I was considering removing the unwrapping code from
NativeJavaConstructor. I was
> suprised that it was there. The code dates from before we implemented proper
method and
> constructor overloading in Rhino. It's the overloading code that should have
the responsibility
> for unwrapping.
>
> Does this patch work for you:
>
> Index: NativeJavaObject.java
> ===================================================================
> RCS file:
/cvsroot/mozilla/js/rhino/org/mozilla/javascript/NativeJavaObject.java
> ,v
> retrieving revision 1.29
> diff -u -r1.29 NativeJavaObject.java
> --- NativeJavaObject.java 2000/11/13 22:10:32 1.29
> +++ NativeJavaObject.java 2001/01/04 21:33:55
> @@ -673,6 +673,12 @@
>
> return Result;
> }
> + else if (value instanceof Wrapper) {
> + value = ((Wrapper)value).unwrap();
> + if (type.isInstance(value))
> + return value;
> + reportConversionError(value, type);
> + }
> else {
> reportConversionError(value, type);
> }
>
> This handles the case where the object is both a Scriptable and a Wrapper.
>
> --N
>
> Mukund Balasubramanian wrote:
>
> > Yes they do implement Scriptable.
> > From my preliminary inspection of the code, findFunction seems to be
preceediong the
> > coerceType call and I presume findFunction call is going to fail if the
arguments are
> > wrapped (bad types mismatching signature).
> > The constructor case DOES go through an explicit unwrapping stage as
shown by the cut
> > and paste code. My question is whether the same preamble in NativeJavaMethod
is a valid bug
> > fix.
> >
> > ThanX,
> >
> > Mukund Balasubramanian
> >
> > Norris Boyd wrote:
> >
> > > Do your objects that implement Wrapper also implement Scriptable? From
simple inspection
> > > of the code I'd think that both the constructor and method cases would go
through
> > > NativeJavaMethod.coerceType, which should unwrap. However, Scriptable
objects are picked
> > > off and handled before any unwrapping is considered.
> > >
> > > --N
> > >
> > > Mukund Balasubramanian wrote:
> > >
> > > > Yup,
> > > > Here it is - Line numbers 173-178 are cut and paste from
> > > > NativeJavaConstructor.java inside NativeJavaMethod.java
> > > >
> > > > /*** Call in NativeJavaMethod.java
> > > > public Object call(Context cx, Scriptable scope, Scriptable thisObj,
> > > > Object[] args)
> > > > throws JavaScriptException
> > > > {
> > > > // Eliminate useless args[0] and unwrap if required
> > > > for (int i = 0; i < args.length; i++) {
> > > > if (args[i] instanceof Wrapper) {
> > > > args[i] = ((Wrapper)args[i]).unwrap();
> > > > }
> > > > }
> > > >
> > > > // Find a method that matches the types given.
> > > > if (methods.length == 0) {
> > > > ****/
> > > >
> > > > Is this correct ? I presume it is because of the fact that the
constructor
> > > > does this.
> > > >
> > > > Any luck with my other question regarding generalizing the WrapHandler
to all
> > > > objects (including those returned by scriptable) and not only those
returned
> > > > through nativeJava***
> > > >
> > > > ThanX,
> > > >
> > > > Mukund Balasubramanian
> > > >
> > > > Norris Boyd wrote:
> > > >
> > > > > Could you post your proposed patch?
> > > > >
> > > > > Thanks,
> > > > > Norris
> > > > >
> > > > > Mukund Balasubramanian wrote:
> > > > >
> > > > > > Hi all,
> > > > > > I am trying to play around with writing a custom WrapHandler for
my
> > > > > > Java objects in Rhino. I found WrapHandler very useful.
> > > > > > Now I am stuck at a point where, even though my wrappers
implement
> > > > > > "Wrapper", they get unwrapped only on calles to Constructors using
> > > > > > Liveconnect. Normal methods dont seem to be doing any unwrapping.
> > > > > > Managed to build rhino with a bug fix (cut and paste code from
> > > > > > NativeJavaConstructor to NativeJavamethod), and it works.
> > > > > > Just wanted to verify if it is a known bug (while I wait for
> > > > > > bugzilla to mail me a passwd).
> > > > > >
> > > > > > BTW, also found something interesting, WrapHandler gets called only
when
> > > > > > the object is returned from NativeJava***, not ANY Object. Is that
the
> > > > > > way it is supposed to work ??
> > > > > >
> > > > > > ThanX for any help,
> > > > > >
> > > > > > Mukund Balasubramanian
Subject:
[Rhino] Script compiler bug?
Date:
Tue, 12 Dec 2000 22:08:23 GMT
From:
dave russo <d-russo@ti.com>
Organization:
Deja.com
Newsgroups:
netscape.public.mozilla.jseng
The following script does not seem to compile properly (using Rhino
1.5R1):
test.js:
var test = {};
test.foo = function () { print('foo')}
test.bar = function () { print('bar')}
After compiling test.js ("java org.mozilla.javascript.tools.jsc.Main
test.js"):
js> loadClass('test')
js> test.foo()
bar
js> load('test.js')
js> test.foo()
foo
Note that changing test.js to read:
var test = {};
test.foo = function foo() { print('foo')}
test.bar = function bar() { print('bar')}
Works around the problem. Is there a problem with anonymous functions?
Sent via Deja.com
http://www.deja.com/
[Rhino] importPackage() when not in Rhino shell?
Date:
Tue, 14 Nov 2000 09:37:39 -0000
From:
"Benjamin Geer" <geerb@midas-kapiti.com>
Organization:
Another Netscape Collabra Server User
Newsgroups:
netscape.public.mozilla.jseng
The importPackage() and importClass() functions provided by the Rhino shell
seems as if they would be very generally useful. Unless I've missed
something, they don't seem to be available to scripts compiled using the
JavaScript compiler, or to scripts that are run using Script.exec(). Is
there any chance these functions could be made available for all scripts to
use? This would save a lot of typing; one could then always write a = new
Foo() instead of a = new Package.com.baz.bar.foo.Foo().
--Benjamin Geer
slobo@espial.com wrote:
>
> Hello Mike
>
> In the following test case, tester returns "undefined cat" in Rhino
> while in NN it returns "meow cat".
>
> Thanks
>
> Steven
>
> /////////////////////////////////////////////////////////////////////
> function tester(nest){
> var nest = nest+" cat";
> alert(nest);
> // nest now contains the value undefined.
> }
>
> tester("meow");
More changes to support non NativeJavaObject wrappers
Date:
Fri, 03 Nov 2000 17:56:38 +0100
From:
Igor Bukanov <igor@icesoft.no>
To:
nboyd@atg.com
Hi, Norris,
In post 1.5 rhino one can introduce own wrappers for arbitrary Java
objects. But I think to fully support this
org.mozilla.javascript.ScriptRuntime should be changes as well: its eq
and shallow_eq contain references to NativeJavaObject, this should be
replaced at least to Wrapper (see the atached patch). Even better
solution would be to add to WrapHandler methods to compare wrappers: I
can send a patch for that as well.
There is a small usability problem as well: if
org.mozilla.javascript.JavaMembers would be public I do not need to copy
it to a package with non NativeJavaObject.java wrapper.
Regards, Igor
56318 function literals with names don't work right
57045 negative integers as object properties: weird behavior
58479 functions defined within conditional phrases are always crea
[Rhino] Optimization for OptRuntime.thisGet
Date:
Mon, 23 Oct 2000 17:50:53 +0200
From:
Hannes Wallnoefer <hannes@helma.at>
Organization:
Another Netscape Collabra Server User
Newsgroups:
netscape.public.mozilla.jseng
I found a little oddity in
org.mozilla.javascript.optimizer.OptRuntime.thisGet().
get() is called twice on thisObj, once right at the beginning, and once
when starting to walk down the prototype chain. Below is what I think
this should look like - the prototype walk now begins with thisObj's
prototype, if it exists.
Also, (thisObj == null) was checked only after thisObj.get() was called,
so I moved that up in front.
Hannes
PS: I just made the changes in the news msg editor, so there may be
stupid mistakes.
updated Global, Main and ImporterTopLevel
Date:
Mon, 23 Oct 2000 14:37:45 +0100
From:
Matthias Radestock <matthias@lshift.net>
To:
nboyd@atg.com
Norris,
I've made some more changes to shell.Main and shell.Global in order to
reduce their mutual dependency, enable "quit" and get "load" to operate
in the local scope.
see attachments for updated .diffs.
Matthias.
A Rhino user has complained about concurrency problems in the interpreter,
and I think the attached diff fixes some problems that could be caused if
the same interpreted function or script was called simultaneously from
two different threads.
Re: Rhino1.5.R1: problems with multithreaded embedded application.
Date:
Mon, 03 Jul 2000 14:38:56 -0400
From:
Norris Boyd <nboyd@atg.com>
Organization:
Art Technology Group
To:
Fergus Gallagher <Fergus.Gallagher@orbisuk.com>
Newsgroups:
netscape.public.mozilla.jseng
References:
1
You found a bug in Rhino; I wonder if others have been running into the same thing.
The problem is with a class called LazilyLoadedCtor. I wrote this class to reduce the
time
required by initStandardObjects by only creating standard objects when the associated
constructors are first accessed. The problem is that this class was not threadsafe.
I've
made changes to that class, and to ScriptableObject as well. The design of dynamic
properties calling getters and setters (which LazilyLoadedCtor uses) didn't really
allow
any way for the getter/setter to replace itself without a thread hazard. I've now
extended
setters so that they can return a value which replaces the getter/setter to avoid this
problem.
Thanks for finding this problem. There have been a couple of other reports of problems
in
this area, so I hope this will fix them.
The patch follows.
--N
Index: LazilyLoadedCtor.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/org/mozilla/javascript/LazilyLoadedCtor.java,v
retrieving revision 1.1
diff -u -r1.1 LazilyLoadedCtor.java
--- LazilyLoadedCtor.java 2000/02/29 21:34:37 1.1
+++ LazilyLoadedCtor.java 2000/07/03 18:31:03
@@ -58,9 +58,12 @@
}
public Object getProperty(ScriptableObject obj) {
- obj.delete(ctorName);
try {
- ScriptableObject.defineClass(obj, Class.forName(className));
+ synchronized (obj) {
+ if (!isReplaced)
+ ScriptableObject.defineClass(obj, Class.forName(className));
+ isReplaced = true;
+ }
}
catch (ClassNotFoundException e) {
throw WrappedException.wrapException(e);
@@ -83,11 +86,14 @@
return obj.get(ctorName, obj);
}
- public void setProperty(ScriptableObject obj, Object val) {
- obj.delete(ctorName);
- obj.put(ctorName, obj, val);
+ public Object setProperty(ScriptableObject obj, Object val) {
+ synchronized (obj) {
+ isReplaced = true;
+ return val;
+ }
}
private String ctorName;
private String className;
+ private boolean isReplaced;
}
Index: ScriptableObject.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/org/mozilla/javascript/ScriptableObject.java,v
retrieving revision 1.17
diff -u -r1.17 ScriptableObject.java
--- ScriptableObject.java 2000/03/13 17:12:36 1.17
+++ ScriptableObject.java 2000/07/03 18:31:04
@@ -246,11 +246,21 @@
break;
}
}
- getterSlot.setter.invoke(start, arg);
+ Object v = getterSlot.setter.invoke(start, arg);
+ if (getterSlot.setterReturnsValue) {
+ slots[slotIndex].value = v;
+ if (!(v instanceof Method))
+ slots[slotIndex].flags = 0;
+ }
return;
}
Object[] args = { this, actualArg };
- getterSlot.setter.invoke(getterSlot.delegateTo, args);
+ Object v = getterSlot.setter.invoke(getterSlot.delegateTo, args);
+ if (getterSlot.setterReturnsValue) {
+ slots[slotIndex].value = v;
+ if (!(v instanceof Method))
+ slots[slotIndex].flags = 0;
+ }
return;
}
catch (InvocationTargetException e) {
@@ -1183,6 +1193,7 @@
slot.delegateTo = delegateTo;
slot.getter = getter;
slot.setter = setter;
+ slot.setterReturnsValue = setter != null && setter.getReturnType() !=
Void.TYPE;
slot.value = null;
slot.attributes = (short) attributes;
slot.flags = flags;
@@ -1551,6 +1562,7 @@
Object delegateTo; // OPT: merge with "value"
Method getter;
Method setter;
+ boolean setterReturnsValue;
}
Fergus Gallagher wrote:
> I am having problems getting my head around contexts and scopes and my
> multi-threaded application fall over.
>
> If I set "global=false" the following code used a per-thread
> initStandardObject() and this seems to work. But when I set
> "global=true", the global "parentScope" is used and I get some wierd
> errors.
>
> If I change "__CODE__.slice(0,5)" to
> 1. "__CODE__" - works
> 2. "__CODE__.substring(0,5)" - fails
> 3. "__CODE__.toString()" - works
>
> Any help appreciated.
>
> Fergus
>
> ===== Test.java =========================================
> import java.io.*;
> import org.mozilla.javascript.*;
>
> public class Test implements Runnable {
> private Script script;
> private Scriptable parentScope;
> private String __CODE__="ABCDEFGHIJK";
> private boolean global = true;
> private static Context globalContext = null;
> public Test() throws Exception {
> String js= "java.lang.System.out.println(__CODE__.slice(0,5));";
> globalContext.setCompileFunctionsWithDynamicScope(false);
> parentScope = globalContext.initStandardObjects(null);
> StringReader sr = new StringReader(js);
> script = globalContext.compileReader(parentScope, sr, "(compiled)",
> 1,null);
> }
>
> public void run() {
> try {
> Context context = Context.enter();
> Scriptable threadScope;
> if (global) {
> threadScope = context.newObject(parentScope);
> threadScope.setPrototype(parentScope);
> threadScope.setParentScope(null);
> } else {
> threadScope = context.initStandardObjects(null);
> }
> threadScope.put("__CODE__",threadScope,__CODE__);
> script.exec(context,threadScope);
> }
> catch (Exception e) {
> System.err.println(e.getClass().getName()+":
"+e.getMessage());
> }
> finally {
> Context.exit();
> }
> }
>
> public static void main(String args[]) throws Exception {
> globalContext = Context.enter();
> Test me = new Test();
> int count=10;
> Thread[] threads = new Thread[count];
> for (int i=0; i<count; i++) {
> Thread t = new Thread(me);
> threads[i] = t;
> t.start();
> }
> for (int i=0; i<count; i++) {
> threads[i].join();
> }
> Context.exit();
> }
> }
>
> ==== OUTPUT ===============================================
> ABCDE
> ABCDE
> org.mozilla.javascript.EcmaError: undefined is not a function.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> org.mozilla.javascript.EvaluatorException: Constructor for "String" not
> found.
> ===========================================================
>
> The number and type of exceptions is highly variable from run to run -
> anywhere from 1-9 out of 10.
> The EcmaError in particular only happens occasionally.
>
> --
> Fergus Gallagher Tel: +44 (20) 8 987 0717
> Orbis Fax: +44 (20) 8 742 2649
> The Swan Centre email: Fergus.Gallagher@orbisuk.com
> Fishers Lane Web: http://www.orbisuk.com
> London W4 1RX / UK
Commit the following contributions:
* Andi Vajda's changes to allow embedders to capture the generated bytecode (and thus control
generated class names).
* Marshall Cline's changes to allow embedders to override the default Java object wrapping
behavior
* Kurt Westerfeld's change to handle calling static methods better
Subject:
Odd behaviour on placement of .jar files?!
Date:
Mon, 05 Jun 2000 10:46:08 -0700
From:
John Raykowski <xski@xski.org>
To:
nboyd@atg.com
Hello,
I didn't want to post this directly as a rhino bug 'coz I think it may
be more of a JDK thing, but I thought I'd toss it to you as well.
The goal is to create a JavaScript object that implements a Java
interface. Straightforward enough and the example on the page using
ActionListener works without a hitch. However, when I try to do the
same with my own interface, I get an error message: error instantiating
({0}): class {1} is interface or abstract (coming from
NativeJavaClass.construct).
Here's where it gets a bit strange. Normally, I run with the jar files
in jre/lib/ext. When I remove the rhino files from jre/lib/ext and
reference them explicitly on the commandline with the -cp option, it
works as expected and my script can implement the interface just fine.
Go figure.
Anyhoo, there ya go. Like I said, I think its a JDK issue, but I
thought you'd be interested. The attached zipfile contains a set of
sample code to demonstrate this problem.
Thanks heaps,
-jmr
resulting in a NullPointerException on the following code when run on the MS VM with -opt 9:
var testcases = getTestCases();
function getTestCases() {
return new Boolean(new MyObject(true));
}
function MyObject( value ) {
this.value = value;
this.valueOf = new Function( "return this.value" );
return this;
}
Subject:
JavaAdapter return type conversion
Date:
Wed, 19 Apr 2000 12:12:47 +0100
From:
Matthias Radestock <rade@logee.com>
Organization:
Logee
To:
norris@netscape.com
CC:
mccabe@netscape.com, beard@netscape.com, rogerl@netscape.com
Dear Rhino team,
When returning an array from a scripted Java object (i.e. a JS object
that implements a Java interface), no type conversion is performed, ie.
a NativeArray is returned instead of a Java array. Example:
Java:
interface Foo {
public String[] boo();
}
JS:
FooI = {
boo: function() { return ["Boo"];}
}
myFoo = new Packages.Foo(FooI);
myFoo.boo(); //==> breaks with a ClassCastException
Looking at the JavaAdapter code, there is no code for array conversion.
This is particularly bad because precisely such a conversion *does*
happen when calling a Java method from JS. So we end up with a
discrepancy.
See attachment for a patch to fix this and little test program. The
patch works by calling the coerceType function on NativeJavaObject,
which is the function responsible for doing the conversion when calling
from JS to Java. I've simplified the code so that this function gets
called for all non-primitive return type, not just arrays. There are
probably more efficient solutions but I'm not a Java bytecode hacker.
Matthias
PS: I didn't open a bug for this because I wasn't sure whether you guys
would agree that this is indeed a problem ;)
public interface JSReturnTest {
public boolean returnBoolean();
public char returnChar();
public int returnInt();
public String returnString();
public org.mozilla.javascript.Scriptable returnScriptable();
public Object returnObject();
public boolean[] returnBooleanA();
public char[] returnCharA();
public int[] returnIntA();
public String[] returnStringA();
public org.mozilla.javascript.Scriptable[] returnScriptableA();
public Object[] returnObjectA();
public Object[][] returnObjectAA();
}
Index: JavaAdapter.java
===================================================================
RCS file: /cvsroot/mozilla/js/rhino/org/mozilla/javascript/JavaAdapter.java,v
retrieving revision 1.21
diff -r1.21 JavaAdapter.java
54c54,59
<
---
>
> public static Object convertResult(Object result, String classname)
> throws ClassNotFoundException {
> return NativeJavaObject.coerceType(Class.forName(classname),
> result);
> }
467,474c472,474
< } else if (retType.equals(String.class)) {
< cfw.add(ByteCode.INVOKESTATIC,
< "org/mozilla/javascript/Context",
< "toString", "(Ljava/lang/Object;)",
< "Ljava/lang/String;");
< cfw.add(ByteCode.ARETURN);
< } else if (retType.equals(Scriptable.class)) {
< cfw.add(ByteCode.ALOAD_0); // load 'this' to find scope from
---
> } else {
> String retTypeStr = retType.getName();
> cfw.addLoadConstant(retTypeStr);
476,477c476,477
< "org/mozilla/javascript/Context",
< "toObject",
---
> "org/mozilla/javascript/JavaAdapter",
> "convertResult",
479,500c479,480
< "Lorg/mozilla/javascript/Scriptable;)",
< "Lorg/mozilla/javascript/Scriptable;");
< cfw.add(ByteCode.ARETURN);
< } else {
< // If it is a wrapped type, cast to Wrapper and call unwrap()
< cfw.add(ByteCode.DUP);
< cfw.add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Wrapper");
< // skip 3 for IFEQ, 3 for CHECKCAST, and 5 for INVOKEINTERFACE
< cfw.add(ByteCode.IFEQ, 11);
< cfw.add(ByteCode.CHECKCAST, "org/mozilla/javascript/Wrapper");
< cfw.add(ByteCode.INVOKEINTERFACE,
< "org/mozilla/javascript/Wrapper",
< "unwrap", "()", "Ljava/lang/Object;");
<
< // If Undefined, return null
< cfw.add(ByteCode.DUP);
< cfw.add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Undefined");
< // skip 3 for IFEQ, 1 for ACONST_NULL, 1 for ARETURN
< cfw.add(ByteCode.IFEQ, 5);
< cfw.add(ByteCode.ACONST_NULL);
< cfw.add(ByteCode.ARETURN);
<
---
> "Ljava/lang/String;)",
> "Ljava/lang/Object;");
502,503c482
< String retTypeStr = retType.getName().replace('.', '/');
< cfw.add(ByteCode.CHECKCAST, retTypeStr);
---
> cfw.add(ByteCode.CHECKCAST, retTypeStr.replace('.', '/'));
testpatch.js
Name:
testpatch.js
Type:
JavaScript Program (application/x-javascript)
Encoding:
7bit
contextClassloader problem in ScriptRuntime.java
Date:
Tue, 11 Apr 2000 09:45:36 -0400
From:
"Howard Lin" <howard@softcom.com>
To:
"Norris Boyd" <norris@netscape.com>
CC:
"Andrew Wason" <aw@softcom.com>
Hi, Norris, we are trying to create a Java class in JavaScript. When security manager is on, everything works fine. But when security
manager is off, we got an error saying the "... is not defined". The problem is that in ScriptRuntime.java, when security is on,
getContextClassLoader is null due to SecurityException and Class.forName is used to find the class, which works fine. When security
is off, ContextClassLoaderMethod is invoked to find the class. Since we use a separate thread to load third party jar files,
ContextClassLoaderMethod will throw a ClassNotFound exception.
To illustrate this problem, I wrote a simple applet, evaluating a simple js file in its paint method, which is running on a separate thread.
When security is off, I got the following:
ReferenceError: "Global" is not defined.
at org.mozilla.javascript.NativeGlobal.constructError(NativeGlobal.java:
494)
at org.mozilla.javascript.ScriptRuntime.name(ScriptRuntime.java, Compile
d Code)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java, Compil
ed Code)
at org.mozilla.javascript.InterpretedScript.call(InterpretedScript.java:
67)
at org.mozilla.javascript.InterpretedScript.exec(InterpretedScript.java:
54)
at org.mozilla.javascript.Context.evaluateReader(Context.java:739)
at test.evaluate(test.java:26)
at test.paint(test.java:16)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:117)
at java.awt.Component.dispatchEventImpl(Component.java:2447)
at java.awt.Container.dispatchEventImpl(Container.java:1035)
at java.awt.Component.dispatchEvent(Component.java:2307)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:287)
at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:10
1)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:92)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:83)
When security is on, it runs fine. Or if the code moved to init method, it works fine regardless of security. We are using JDK 1.2.2.
Howard
step += (InLeapYear(t) ? 29 : 28);
with the form
if (InLeapYear(t))
step += 29;
else
step += 28;
to work around an apparent JRE bug in which the code always returns 28.
2. Change from using Class.getDeclaredMethods to Class.getMethods since the former may cause
security problems. Implement a cache to ameleorate the possible performance degredation.
3. Add a new class to lazily load constructors to improve performance
This was caused by a previous bug fix in which I moved the try stack
decrement to the end of the catch clause because it was getting skipped
by the final statement in the try block (which is always a goto around the
catch block). Better is to make sure the endTry is the statment just before
that goto, and do the try stack decrement in the catch the way god intended.
Subject:
Rhino request URGENT
Date:
Thu, 02 Dec 1999 15:58:40 -0500
From:
slobo@espialgroup.com
To:
Norris Boyd <norris@netscape.com>
References:
1 , 2
Hello Norris
In Rhino, the following script gives the error : "function does not always return a value" during the parsing phase. The script
runs perfectly fine in Netscape 4.61. It is an urgent requirement. Many thanks in advance.
Steven
///////////////////////////////////////////////////////SCRIPT BEGIN ///////////////////////////////////////////////
function test (a) {
this.arg = a;
if (a>20)
return;
return this;
}
//print = alert;
function joe() {
a = new test (20);
print (a.arg);
a = new test (25);
print (a.arg);
}
joe();
///////////////////////////////////////////////////////SCRIPT END ///////////////////////////////////////////////