No problem. I had fun discovering how to make it work. I like the macro idea btw.
Cheers Greg On 22 Aug 2010 14:03, "Jacob Beard" <jbea...@cs.mcgill.ca> wrote: > Hi Greg, > > I'll bring it up on the developer's list. > > I've created a macro that sets up the rhino environment, so right now > this seems like a good enough solution for me: > > <macrodef name="rhinoscript"> > > <text name="text"/> > > <sequential> > > <script language="javascript" manager="bsf"> > > <classpath> > > <fileset dir="../../../lib/java/" includes="js.jar"/> > > <fileset dir="../../../lib/build-java/" includes="*.jar"></fileset> > > </classpath><![CDATA[ > > importPackage(java.lang, java.util, java.io); > > //System.out.println("Hello from JavaScript!!"); > > //create shell, execute something and grab global > > var shell = org.mozilla.javascript.tools.shell.Main; > > var args = ["-e","var a='STRING';"]; > > shell.exec(args); > > var shellGlobal = shell.global; > > //grab functions from shell global and place in current global > > var load=shellGlobal.load; > > var print=shellGlobal.print; > > var defineClass=shellGlobal.defineClass; > > var deserialize=shellGlobal.deserialize; > > var doctest=shellGlobal.doctest; > > var gc=shellGlobal.gc; > > var help=shellGlobal.help; > > var loadClass=shellGlobal.loadClass; > > var quit=shellGlobal.quit; > > var readFile=shellGlobal.readFile; > > var readUrl=shellGlobal.readUrl; > > var runCommand=shellGlobal.runCommand; > > var seal=shellGlobal.seal; > > var serialize=shellGlobal.serialize; > > var spawn=shellGlobal.spawn; > > var sync=shellGlobal.sync; > > var toint32=shellGlobal.toint32; > > var version=shellGlobal.version; > > var environment=shellGlobal.environment; > > > > @{text} > > ]]></script> > > </sequential> > > </macrodef> > > > > <target name="hello"> > > <rhinoscript> > > print("Hello World!") > > </rhinoscript> > > </target> > > > Thanks again for your help with this, > > Jake > > On 10-08-22 04:12 AM, Greg Roodt wrote: >> Hi >> >> Glad it worked. >> >> I agree with you. I think it would be much easier and more useful if these >> functions from the Rhino shell were made available. It is not something that >> the<script /> task is going out of its way to remove though, the problem is >> actually Rhino/javascript itself (not a problem, more a strictness). The >> javascript language spec does not specify these functions, therefore they >> are not made available in the interpreter and JSR 223. >> >> All that the<script /> task essentially does is the following: >> 1. Determine which script engine to use. >> 2. Fire up the script engine. >> 3. Inject Ant objects (project, tasks etc.) into the Context of the script. >> This is to help make it possible to use scripting languages to write Ant >> scripts, remember this task is not meant to be a general purpose script >> runner, but a way to make it simpler to script Ant tasks. >> >> The Rhino Shell then confuses people, by providing all these wonderful >> functions that arent available in a standard embedded context which is a bit >> frustrating. Other languages like python do indeed have much more useful >> things baked directly into the language which makes them easier to use. >> >> I think you should bring this up on the dev list and see what they think. It >> might be that the Global stuff can be made available which will then make >> javascript and the<script /> tag much more powerful. Or they might suggest >> creating a new Ant task<rhinoshell /> or something. >> >> Cheers >> Greg >> >> >> >> >> >> >> >> >> On Sat, Aug 21, 2010 at 11:44 PM, Jacob Beard<jbea...@cs.mcgill.ca> wrote: >> >> >>> Hi Greg, >>> >>> Thanks a lot for this! This does exactly what I want. >>> >>> I had actually just about given up, as I realized that the load function I >>> was attempting to define would have the shortcoming of essentially capturing >>> any local variables eval'ed within it. This mean that while dojo worked >>> because it was declared in the global scope, RequireJS would not load >>> because its top-level argument ("require") was declared using var. >>> >>> I'm mentioning this now only because it's amusing, but to work around this, >>> I tried imagining a way to exit the load function to eval the string to be >>> loaded, thus allowing local variables declared within the string to be >>> declared in the global scope; then returning from the global scope to the >>> call site of the load function. The only way I could think to do this was >>> with continuations. Converting to the continuation-passing style was not an >>> option, because passing in a callback to load would break the API. >>> Fortunately, Rhino exposes a native Continuation. After some playing around, >>> I found that this code had the desired effect: >>> >>> /* >>> >>> this file is to test a technique for creating a load function in Rhino >>> >>> */ >>> >>> (function(){ >>> >>> myLoadLocal = function(str){ >>> >>> eval(str); >>> >>> } >>> >>> function call_with_current_continuation() { >>> >>> var kont = new Continuation(); >>> >>> return kont; >>> >>> } >>> >>> var evalString = null, afterEval = null; >>> >>> var beforeEval = call_with_current_continuation(); >>> >>> if(evalString){ >>> >>> eval(evalString); >>> >>> evalString=null; >>> >>> afterEval(null); >>> >>> } >>> >>> myLoadContinuation = function(str){ >>> >>> evalString = str; >>> >>> afterEval = call_with_current_continuation(); >>> >>> if(afterEval instanceof Continuation){ >>> >>> beforeEval(beforeEval); >>> >>> }else{ >>> >>> return; >>> >>> } >>> >>> } >>> >>> myLoadLocal("var foo=1;"); >>> >>> print(typeof foo); //should be undefined >>> >>> myLoadContinuation("var bar=2;"); >>> >>> print(typeof bar); //should be number >>> >>> print(bar); //should be 2 >>> >>> //see if it works again >>> >>> myLoadContinuation("var bat=3;"); >>> >>> print(typeof bat); //should be number >>> >>> print(bat); //should be 3 >>> >>> })() >>> >>> >>> I think there's probably a more elegant way to use continuations to do >>> this, but this was the first thing I got working. One caveat to this, >>> however, is that Continuations in Rhino only work when run in interpreted >>> mode, without optimizations (-opt -1). Otherwise it fails with the following >>> error: >>> >>> js: Direct call is not supported >>> >>> When I brought this back into the Ant script context, it failed with this >>> error as well, so it appears that this technique would not work in Ant for >>> this reason. >>> >>> >>> I wonder if its worth discussing whether removing the global functions >>> normally found in Rhino is a desirable behaviour for Ant. Other scripting >>> languages include facilities for importing code as part of their core syntax >>> (e.g. Jython's import statement), so this cannot be easily removed for them, >>> but for Rhino, the load function is simply part of the global object, and >>> can be easily removed from the embedding context. But I'm not sure if this >>> is actually a good thing to do. Certainly it reduces the utility of the Ant >>> script context, and increases its verbosity for situations where external >>> scripts must be loaded via a module loader, such as Dojo or RequireJS. Do >>> you think this is something that would be worth bringing up on the >>> developer's list? Would it be useful to file a bug report or feature >>> request? >>> >>> Let me know what you think. Thanks, >>> >>> Jake >>> >>> >>> >>> On 10-08-21 05:37 PM, Greg Roodt wrote: >>> >>> >>>> This might work for you: >>>> >>>> <project default="hello" name="helloworld" basedir="."> >>>> <target name="hello"> >>>> <script language="javascript" manager="bsf"> >>>> <classpath> >>>> <fileset dir="rhino-lib" includes="*.jar"></fileset> >>>> </classpath><![CDATA[ >>>> importPackage(java.lang, java.util, java.io); >>>> System.out.println("Hello from JavaScript!!"); >>>> //create shell, execute something and grab global >>>> var shell = org.mozilla.javascript.tools.shell.Main; >>>> var args = ["-e","var a='STRING';"]; >>>> shell.exec(args); >>>> var shellGlobal = shell.global; >>>> >>>> //grab functions from shell global and place in current global >>>> var load=shellGlobal.load; >>>> var print=shellGlobal.print; >>>> var defineClass=shellGlobal.defineClass; >>>> var deserialize=shellGlobal.deserialize; >>>> var doctest=shellGlobal.doctest; >>>> var gc=shellGlobal.gc; >>>> var help=shellGlobal.help; >>>> var loadClass=shellGlobal.loadClass; >>>> var quit=shellGlobal.quit; >>>> var readFile=shellGlobal.readFile; >>>> var readUrl=shellGlobal.readUrl; >>>> var runCommand=shellGlobal.runCommand; >>>> var seal=shellGlobal.seal; >>>> var serialize=shellGlobal.serialize; >>>> var spawn=shellGlobal.spawn; >>>> var sync=shellGlobal.sync; >>>> var toint32=shellGlobal.toint32; >>>> var version=shellGlobal.version; >>>> var environment=shellGlobal.environment; >>>> >>>> //test your bad self >>>> load("test.js"); >>>> >>>> ]]></script> >>>> </target> >>>> </project> >>>> >>>> test.js: >>>> var a = function() { >>>> print("test"); >>>> help(); >>>> var scriptContents = readFile("test.js"); >>>> print(scriptContents); >>>> var ver = version(); >>>> print("version:"+ver); >>>> print(this); >>>> for(var prop in this){ >>>> print(prop); >>>> } >>>> } >>>> a(); >>>> >>>> >>>> >>>> On Sat, Aug 21, 2010 at 7:03 PM, Jacob Beard<jbea...@cs.mcgill.ca> >>>> wrote: >>>> >>>> >>>> >>>> >>>>> Hi Greg, >>>>> >>>>> Thanks for your response. Replies below: >>>>> >>>>> >>>>> On 10-08-21 01:41 PM, Greg Roodt wrote: >>>>> >>>>> >>>>> >>>>> >>>>>> I believe load() is part of Rhino Shell. I think all that the<script /> >>>>>> task runs when using JavaScript is the interpreter. It would only have >>>>>> the >>>>>> pure Javascript standard language features (and a few bits and pieces to >>>>>> interact with Java and the execution context). >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> load() is normally exposed as part of the global object when running >>>>> Rhino, >>>>> in the shell or the interpreter. All the js module loaders that support >>>>> Rhino that I've encountered, including RequireJS and dojo, make use of >>>>> load() to load JavaScript modules. >>>>> >>>>> It might be easier to run the shell for each test? Like so: >>>>> >>>>> >>>>> >>>>>> java org.mozilla.javascript.tools.shell.Main [options] >>>>>> script-filename-or-url [script-arguments] >>>>>> https://developer.mozilla.org/en/Rhino_Shell#Invoking_the_Shell >>>>>> >>>>>> Or like John Resig does with env.js: >>>>>> http://ejohn.org/blog/bringing-the-browser-to-the-server/ >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> I'm using that technique for other parts of my code, but it would be much >>>>> easier to simply hook into Ant's ResourceSet data structures for this >>>>> part, >>>>> as it's possible to register a number of unit tests with dojo before >>>>> running >>>>> them. >>>>> >>>>> >>>>> Or maybe, define your own global load() function inside the<script /> >>>>> >>>>> >>>>> >>>>>> tag? >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> That's what I'm working on. This seems to work, but I still need to test >>>>> it >>>>> with the dojo module loader: >>>>> >>>>> <script language="javascript" manager="bsf"> >>>>> >>>>> <classpath> >>>>> >>>>> <fileset dir="../../../lib/java/" includes="js.jar"/> >>>>> >>>>> <fileset dir="../../../lib/build-java/" >>>>> includes="*.jar"></fileset> >>>>> >>>>> </classpath><![CDATA[ >>>>> >>>>> //define load in global scope >>>>> >>>>> function readFile(path){ >>>>> >>>>> stream = new java.io.FileInputStream(new >>>>> java.io.File(path)); >>>>> >>>>> fc = stream.getChannel(); >>>>> >>>>> bb = >>>>> fc.map(java.nio.channels.FileChannel.MapMode.READ_ONLY, >>>>> 0, fc.size()); >>>>> >>>>> return >>>>> java.nio.charset.Charset.defaultCharset().decode(bb).toString(); >>>>> >>>>> } >>>>> >>>>> load = function(path){ >>>>> >>>>> eval(String(readFile(path))) >>>>> >>>>> } >>>>> >>>>> echo = helloworld.createTask("echo"); >>>>> >>>>> var contents = readFile('hello.js') >>>>> >>>>> echo.setMessage(contents); >>>>> >>>>> echo.perform(); >>>>> >>>>> load('hello.js') >>>>> >>>>> echo.perform(); >>>>> >>>>> ]]></script> >>>>> >>>>> hello.js: >>>>> >>>>> echo.setMessage("hello world!"); >>>>> >>>>> >>>>> Outputs: >>>>> >>>>> hello: >>>>> >>>>> [echo] echo.setMessage("hello world!"); >>>>> >>>>> [echo] hello world! >>>>> >>>>> >>>>> >>>>> Thanks, >>>>> >>>>> Jake >>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: user-unsubscr...@ant.apache.org >>>>> For additional commands, e-mail: user-h...@ant.apache.org >>>>> >>>>> >>>>> >>>>> >>>>> >>>> >>>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: user-unsubscr...@ant.apache.org >>> For additional commands, e-mail: user-h...@ant.apache.org >>> >>> >>> >> > > --------------------------------------------------------------------- > To unsubscribe, e-mail: user-unsubscr...@ant.apache.org > For additional commands, e-mail: user-h...@ant.apache.org >