That is pretty awesome!. Peter
On Tue, Aug 24, 2010 at 1:53 AM, Jacob Beard <jbea...@cs.mcgill.ca> wrote: > And here is what it looks like now: > > https://svn.apache.org/repos/asf/commons/sandbox/gsoc/2010/scxml-js/trunk/build.xml > > Most interesting parts are target run-unit-tests-with-rhino target and macro > run-unit-tests-with-selenium-macro. I'm pretty happy with this result, as it > has allowed me to integrate javac compilation with testing of my JavaScript > modules, and to reuse code from my original build script written in > JavaScript. > > Jake > > On 10-08-23 01:56 PM, Greg Roodt wrote: >> >> 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 >>> >>> >> >> > > --------------------------------------------------------------------- > 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