This is based on code contributed to Rhino by AgileDelta, Inc, www.agiledelta.com and in particular by
Ethan Hugg
Terry Lucas
Milen Nankov
John Schneider
Thanks!
the later is stored in the factory and not in static variables.
For compatibility an instance of ContextFactory stored in static variables
is used to provide support for old Context.addContextListener etc. API.
The static instance of the factory is also used by Context.enter to create
Context instances providing simple way to customize Context: one just need
to initialize the global static factory.
Context.call(new ContextAction() {
public Object run(Context cx) { ... }
});
or similar alternatives.
It prevents bugs with missed Context.exit and provides room for optimization of Context association with current thread and simplify implementation of safe environment for execution of untrusted applets and scripts.
In addition, Rhino now supports global SecurityController that take precedence over any per/Context controllers so the application can setup the controller once and for all.
Now Context defines new method "call" that provide optimized version of the following code:
Context cx = Context.enter()
try {
callable.call(cx, scope, thisObj, args);
} finally {
Context.exit();
}
Since Function extends Callable, it can be passed to this method directly thus simplifying ScriptableObject.call method and Java adapter code.
The new interface is used in SecurityController implementation which allows to pass interpreted functions there directly as well removing the need to have intermediate class in Interpreter.
2. Catch VirtualMachineError so on out-of-memory/stack-overflow the shell will exit with System.exit(EXITCODE_RUNTIME_ERROR), not with 1. It will allow to distinguish cases when script tried to consume all available stack/memory with bugs in Rhino itself leading to NullPointerException etc.
3. Remove code to rethrow ThreadDeath from JavaScriptExcception since ThreadDeath is re-thrown by the engine itself.
Changing behavior of sealed objects to throw an exception on any attempt to modify them including changing values of existing properties. In the same time making object sealed does not affect read-only status of its properties which allows to override properties of objects with a sealed object as a prototype.
Rhino shell now accepts -sealedlib option to seal all standard objects.
I just noticed that the changes introduced with
v1.29 of Main.java broke the ability to do hot
reloads of scripts. To be more explicit, the script
is actually reloaded but the source in the debugger
is not updated to reflect the newly loaded code.
...
Attached is a patch that restores the original behavior.
The refactorings are preserved but the handling of
previously loaded SourceInfo objects is restored and the
check for previously loaded ScriptItem instances
removed.
Have you considered adding a "Go" method to Main.java with
public visibility (same behavior as pressing the "Go" button in the debugger UI).
This would be a big help in a system where the debugger has been
embedded. Being able to close the debugger and ensure that any
breakpoints were removed and any blocked threads notified would
be a nice feature. Without this, closing the debugger can either
a) halt the application or b) destroy the debugger leaving blocked
threads in a permanent wait state. Note that the debugger is
not actually destroyed in this case because the waiting threads
prevent it from being wholly GCed.
This looks like a simple case of using the Hashtable key
instead of the value...
public void clearAllBreakpoints() {
// Igor - Use of keys() is inappropriate here. It produces
// a ClassCastException on the assignment below. The
// keys are String instances, not SourceInfo instances...
//
//Enumeration e = sourceNames.keys();
Enumeration e = sourceNames.elements();
...
}
For that I added new method createClasssLoader to Context, which by default returns new instance of DefiningClassLoader and changed the code to use this method instead of creating DefiningClassLoader directly. I moved DefiningClassLoader to org.mozilla.javascript package so core Rhino classes would not depend on org.mozilla.classfile package. I also changed SecurityController.createClasssLoader to take additional parentLoader argument to explicitly specify which class loader should be parent for generated code.
The new SecurityController in its current form does not allow to define more then one generated class class in the same class loader effectively preventing to use optimizer which needs to define classes that refer each other and should be defined in the same loader.
To fix this I replaced the defineClass method in SecurityController by
public GeneratedClassLoader createClassLoader(Object securityDomain);
which returns instance of the new GeneratedClassLoader interface which can be used to define several classes. I also made DefiningClassLoader to implement this interface to simplify code in JavaAdapter.java and optimizer/Codegen.java.
Patch from Marcus Crafter:
...
After speaking with Christopher Oliver, the problem seems to be a general JDK
1.4 bug that caches selected values in JComboBox, even after removeAllItems() is
called. Since its a general defect Christopher and I thought we'd report and get
it fixed in the main CVS tree.
...
It allows to implement the DebuggableScript interface only by omj/InterpreterData instead of 2 identical implementations by InterpretedFunction and InterpretedScript.
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 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.
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.
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
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
I'm the maintainer of JPackage project rhino package (see
jpackage.sourceforge.net). I just found two problems for building it (version
1.52 from cvs):
- the property src.debugger is badly initialised in toolsrc/build.xml. See
patch attached for correction. Moreover, this was a real pain to make offline
building possible. I guess it's a licensing problem that prevents you
including those files in rhino sources ?
- the produced javadoc has an empty (0 sized) package-list file. Have you got
any idea why ?
-- Guillaume Rousse <rousse@ccr.jussieu.fr>
GPG key http://lis.snv.jussieu.fr/~rousse/gpgkey.html
It would be nice if the rhino shell would accept a URL as the source
for javascript.
I've added this feature to my local copy so that I can launch rhino
with js scripts using JavaWebStart.
Below is a context diff of the changes I made to
toolsrc/org/mozilla/javascript/tools/shell/Main.java
Re: Rhino 1.5R2 release candidate
Date:
Fri, 13 Jul 2001 22:52:43 -0700
From:
Christopher Oliver <coliver@mminternet.com>
Organization:
Primary Interface LLC
To:
Norris Boyd <nboyd@atg.com>
References:
1
Hi Norris,
Attached are some (final?) changes to the debugger:
- Display NativeCall objects as "[object Call]" in this/locals tree-tables
- Fixed "Go to Function" to highlight the target function in the source
window
- Synchronized ContextListener implementation
- Added slightly more useful tooltips to the tool bar
Note I modified files from today's rhinoTip.zip. Hopefully they were
identical to those in the cvs release branch.
Chris
Rhino: deal with all Throwables in Interpreter.interpret
Date:
Thu, 12 Jul 2001 14:27:34 +0200
From:
Igor Bukanov <igor@icesoft.no>
Organization:
Wind River
To:
Norris Boyd <nboyd@atg.com>
The attached patch modifies the catch code in Interpreter.interpret to
catch general Throwable exceptions to allow cleanup after throwing an
Error instance from Context.observeInstructionCount.
===================
Subject:
Rhino: change of InterpreterData.itsLineNumberTable from Hahstable to
UintHash
Date:
Thu, 12 Jul 2001 15:51:38 +0200
From:
Igor Bukanov <igor@icesoft.no>
Organization:
Wind River
To:
Norris Boyd <nboyd@atg.com>
The patch linetable_patch changes InterpreterData.itsLineNumberTable
from Hahstable to UintHash and debug/DebuggableScript.java to return
int[] array instead of Enumeration. It was run produced via
diff -ru javascript.0 javascript
The patch debugger_patch contains update for
toolsrc/org/mozilla/javascript/tools/debugger/Main.java to reflect above
api changes.
===============================
Subject:
Rhino: patch not to store VariableTable in InterpreterData
Date:
Thu, 12 Jul 2001 16:34:18 +0200
From:
Igor Bukanov <igor@icesoft.no>
Organization:
Wind River
To:
Norris Boyd <nboyd@atg.com>
The patch removes the "VariableTable itsVariableTable" field from
InterpreterData so it would not be stored in
InterpretedFunction/InterpretedScript and could be garbage collected
after interpreter byte code generation is finished. The usage of
theData.itsVariableTable it Interpreter.interpret is replaced by
accessing argNames/argCount fields from the passed NativeFunction.
Bugfix to Rhino Debugger
Date:
Sat, 30 Jun 2001 06:09:44 -0700
From:
Christopher Oliver <coliver@mminternet.com>
Organization:
Primary Interface LLC
To:
nboyd@atg.com
Hi Norris,
Attached is a fix to a problem I encountered with the Rhino debugger.
Apparently some recent changes to the engine broke the debugger because
the debugger wasn't acquiring a Context before making certain engine
calls like ScriptableObject.getIds(). You can see this by stepping
through the "enum.js" example and expanding the variable "elements".
The below exception trace will be printed on the debugger console. The
attached file should fix this problem.
Chris
Subject:
Another fix to VariableModel.java
Date:
Sat, 30 Jun 2001 07:33:51 -0700
From:
Christopher Oliver <coliver@mminternet.com>
Organization:
Primary Interface LLC
To:
nboyd@atg.com
Hi Norris,
I modified this file to always call Context.toString() to display a
variable's value in the the tree table. Previously it only called it
for Scriptables and the toString() method of the object otherwise. This
caused for example JavaScript "2" to be displayed as "2.0".
Chris
Rhino: speed optimization in omj/Interpreter.java
Date:
Tue, 26 Jun 2001 21:06:56 +0200
From:
Igor Bukanov <igor@icesoft.no>
Organization:
Wind River
To:
Norris Boyd <nboyd@atg.com>
Hi, Norris!
The attached Interpreter_patch contains a speed optimization patch that
tries to avoid creation of Double objects by keeping a parallel stack
for double values: instead of putting Double to the stack, DBL_MRK is
put and the real value is put to double stack (sDbl). Then when reading
stack with DBL_MRK, the double value from the double stack is used
wrapped to Double object when necessary. In addition local and vars
arrays are merged to stack array.
The attached before.txt and after.txt contain results of typical runs of
mozilla/js/benchmarks/all_bench.js before and after optimization on my
PC: Athlon 650/Red Hat 7.0/JDK 1.3.0 from Sun .
In number of cases the optimization actually slow down the executionby
5-10% (I guess due to the checks for DBL_MRK), but mostly it is a nice
sped up often by factor of 2 ot more with overall optimization win: 267
versus 218 seconds.
I guess it is possible to apply the same optimization to the optimizer
package, but in our browser we use strictly interpreter mode. Also by
changing signature of call/construct methods in Scriptable it is
possible to avoid creation of almost all objects currently allocated
during method calls, but that is for far future.
Regards, Igor
1. Keyword search via Java Hahstable is replaced by explicit "switch"
code generated by idswitch tool. It not only speed up keyword search and
eliminates all Integer objects created to hold keyword tokens and
corresponding Hahstable structures, but it also reduces code size due to
very poor array initialization support in JVM.
2. It replaces the isXDigit method by xDigitToInt that either converts
its argument to 0..15 or returns -1 if it is not a hex digit and updates
the method usage accordingly The patch updates NativeGlobal.js_unescape
to reflect this usage change.
-----
The patch changes NativeCall to use IdScriptable. This is done mostly
for uniformity with other Native* classes plus it would allow to call
NativeCall.init directly and make NativeCall package private.
-----
The patch changes NativeScript to use id-based properties. Due to
inheritance from NativeFunction, id support requires to take into
account the fact that there are instance ids available from
BaseFunction. This is the reason to use "int prototypeIdShift" instead
of "boolean prototypeFlag" so it can store instance id offset.
The patch updates ScriptRuntime.callOrNewSpecial to check against
IdFunction and not FunctionObject for the Script exec method where it
also add finally clause to make sure that Context.exit would always be
called after Context.enter in the evalScript method.
-----
After converting NativeScript and NativeFunction to use IdScriptable,
they get scope argument directly as a parameter of execMethod call, so
cx.ctorScope is not used any more. The patch removes code to set/unset
cx.ctorScope.
-----
[This patch depends on conversion of NativeScript and NativeCall to use
IdScriptable and the patch to remove access of ctorScope from
FunctionObject]
The patch changes Context.initStandardObjects to call NativeCall.init
and NativeScript.init directly plus it unrolls the lazily initialization
loop. Due to rather poor support of an array initialization in Java byte
code, it actually decreases code size while eliminating are creation of
array object. The patch also removes ctorScope field as unused.
-----
The patch makes sure that ids used by NativeGlobal are visible only in
the object instance that initializes global scope and removes some junk
white space at line ends.
-----
To use the idswitch tool to generate map for strings that can not be
part of Id_ Java identifier like $*, I added code to the tool to look
for "// #string=...#" in the id definition line. The attached README
file also contains some documentation about the tool and should go to
idswitch directory.
The patch was made from toolsrc/org/mozilla/javascript/tools via:
cvs diff -u > idswitch_patch