diff --git a/oxygen/js-debugger/README.md b/oxygen/js-debugger/README.md new file mode 100644 index 0000000..bcc529c --- /dev/null +++ b/oxygen/js-debugger/README.md @@ -0,0 +1,101 @@ +# Opening a JavaScript debugger within Oxygen [JS Operations](https://www.oxygenxml.com/doc/versions/23.1/ug-editor/topics/dg-default-author-operations.html#dg-default-author-operations__jsoperation) + +Even though its authors state that this operation "[can be used to execute small pieces of Javascript code](https://github.com/oxygenxml/javascript-sample-operations)", +all the Oxygen and Java public APIs are exposed and this operation can be used for fairly complex tasks. + +The main limitation is then the lack of a debugger and relying on logs rapidly becomes very tedious to develop complex code. + +The good news is that Oxygen uses Mozilla's [Rhino JavaScript engine](https://en.wikipedia.org/wiki/Rhino_(JavaScript_engine)) and that this engine comes with a +[debugger](https://www-archive.mozilla.org/rhino/debugger.html). + +This rambling proposes a way to launch the debugger from a JS Operation. + +## Installation + +To do so, add this function to your commons.js file: + +```javascript +startDebugger = function () { + + var runnable = { + run: function () { + main.dispose(); + } + } + + + var context = Packages.org.mozilla.javascript.Context.getCurrentContext(); // Within the current context... + var contextFactory = context.getFactory(); + var scope = Packages.org.mozilla.javascript.tools.shell.Environment(runnable.__parent__); // and the scope of the runnable variable's parent ... + var main = Packages.org.mozilla.javascript.tools. debugger.Main.mainEmbedded(contextFactory, scope, 'Debugger'); // start a debugging session ... + main.setExitAction(java.lang.Runnable(runnable)); // , clean the resources at exit time... + main.setVisible(true); // and make it visible/ + +} +``` + +And use it in the script parameter of the JS operation: +```javascript +doOperation = startDebugger; +``` + +To call the action which uses this operation, you can attach it to a menu or tool icon or just define a shortkey and you're done ! + +Call this action and you'll pop up a nice vintage debugger : +![debugger.jpg](debugger.jpg) + +Use the File menu to open or run the file to debug (such as [test.js]): +![debugger2.jpg](debugger2.jpg) + +There are a few things to know before using it, though... + +## Limitations + +### Scope + +I haven't found a way to simply grab the current scope object in JavaScript and the closest method I have found is: +```javascript +Packages.org.mozilla.javascript.tools.shell.Environment(runnable.__parent__) +``` + +This creates a scope with everything in the runnable's parent's scope augmented with the environment variables with may not be present in the current scope. + + +All the other methods I have tried gave scopes which were, on the contrary, reduced compared to the current scope and lacking, for instance, the authorAcces object +without which you can't interact with Oxygen. + +### Functions seen as objects + +Just try it by yourself in the "evaluate" window: +```javascript +function a() {} + +b = function() {} +``` +"a" is seen as an object and not as a function, meaning that you can't call it. "b" is, correctly, seen as a function. + +### Strict behavior on instanciation. + +The word "new" is mandatory when instanciating a "class" (which is not the case when a JS operation script is run out of the debugger): + +```javascript +aclass = function () { + this.setFoo(1); + return this; +} + +aclass.prototype.setFoo = function (v) { + this.foo = v; +} + +anObject = new aclass() ; // works as expected + +anobject = aclass(); // fails with a message saying that there is no setFoo function in the object + +``` + +# Framework + +This directory includes the Oxygen sample framework on which ou can test the debugger but it should work on any framework. + + diff --git a/oxygen/js-debugger/commons.js b/oxygen/js-debugger/commons.js index e0753fa..be71a9a 100644 --- a/oxygen/js-debugger/commons.js +++ b/oxygen/js-debugger/commons.js @@ -7,11 +7,11 @@ startDebugger = function () { } - var context = Packages.org.mozilla.javascript.Context.getCurrentContext(); + var context = Packages.org.mozilla.javascript.Context.getCurrentContext(); // Within the current context... var contextFactory = context.getFactory(); - var scope = Packages.org.mozilla.javascript.tools.shell.Environment(runnable.__parent__); - var main = Packages.org.mozilla.javascript.tools. debugger.Main.mainEmbedded(contextFactory, scope, 'Debugger'); - main.setExitAction(java.lang.Runnable(runnable)); - main.setVisible(true); + var scope = Packages.org.mozilla.javascript.tools.shell.Environment(runnable.__parent__); // and the scope of the runnable variable's parent ... + var main = Packages.org.mozilla.javascript.tools. debugger.Main.mainEmbedded(contextFactory, scope, 'Debugger'); // start a debugging session ... + main.setExitAction(java.lang.Runnable(runnable)); // , clean the resources at exit time... + main.setVisible(true); // and make it visible/ } \ No newline at end of file diff --git a/oxygen/js-debugger/debugger.jpg b/oxygen/js-debugger/debugger.jpg new file mode 100644 index 0000000..0f93e89 Binary files /dev/null and b/oxygen/js-debugger/debugger.jpg differ diff --git a/oxygen/js-debugger/debugger2.jpg b/oxygen/js-debugger/debugger2.jpg new file mode 100644 index 0000000..c737a37 Binary files /dev/null and b/oxygen/js-debugger/debugger2.jpg differ diff --git a/oxygen/js-debugger/test.js b/oxygen/js-debugger/test.js index 1e8e017..007a76e 100644 --- a/oxygen/js-debugger/test.js +++ b/oxygen/js-debugger/test.js @@ -1,14 +1,17 @@ - +/* + * Unexpected things happen here... + */ function a() {} b = function() {} -typeof a; -typeof b; +// Notice the weird behavior : + +typeof a; // object +typeof b; // function aclass = function () { - // this.foo = 1; this.setFoo(1); return this; } @@ -25,6 +28,7 @@ anObject.setFoo(2); anObject.foo; +// Also worth mentionning, you ***must*** use new and this doesn't work : +// // anobject = aclass(); -// anobject.setFoo(3); \ No newline at end of file