# 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.