I would like to allow server-side scripting via Rhino with a syntax as close to jQuery as possible. Ideally I would simply like to use jQuery on the server.

Currenly, Rhino + Env.js + jQuery works, but without optimization switched on (I have to do cx.setOptimizationLevel(-1); because of http://bugs.sun.com/view_bug.do?bug_id=4262078) Interpreted JS severely limits applicability of the tool I am writing.

Before I try to do it on my own, I would like to ask JavaScript gurus what would be the best way to break up nicely encapsulated core of jQuery (and some of my jQuery plugins written in the same style)? I.e. how to split a function like

(function( window, undefined ) {
...
var foo = function() { ... } 
...
foo.a = {...}
foo.bar = function() { }
...
foo.bar();
...
})(window);

into functional chunks.

All that is needed is to have parts of the function separated into callable code that will have the same functionality after it is executed.

有帮助吗?

解决方案 2

There is no need to split the jQuery, it works with env.js 1.2 (http://www.envjs.com/), Rhino 1.7R2 and jQuery 1.7.1 if one does the following steps.

  1. Download env.js sources and run ant in the root.
  2. From resulting ./dist, copy all files except env.js and env.rhino.js into a place where your code can access it (I called the folder 'env.js').
  3. Do the following, and you will have fast, jQuery-enabled context on the server:

      Context cx = ContextFactory.getGlobal().enterContext();
      try {
         Scriptable scope = cx.initStandardObjects();
         //global function print is needed to redirect console output. E.g.:
         cx.evaluateString(scope,
           "var print = function(v) {"+
                 " java.lang.System.out.println(v);"+
           " };",
           "print",1,null);
        //load env.js one by one
        loadScript(cx, scope, "env.js/platform/core.js");
        loadScript(cx, scope, "env.js/platform/rhino.js");            
        loadScript(cx, scope, "env.js/console.js");
        loadScript(cx, scope, "env.js/dom.js");
        loadScript(cx, scope, "env.js/event.js");
        loadScript(cx, scope, "env.js/html.js");
        loadScript(cx, scope, "env.js/css.js");
        loadScript(cx, scope, "env.js/parser.js");
        loadScript(cx, scope, "env.js/xhr.js");
        loadScript(cx, scope, "env.js/timer.js");
        loadScript(cx, scope, "env.js/window.js");
    
        //now everything is ready to load jquery
        loadScript(cx, scope, "jquery/jquery.js");
    
        //now you can do jQuery calls in this scope
        cx.evaluateString(scope, 
              "$.each([42, 1024], "+
              " function(index, value) { console.log(index+' -> '+value); });", 
              "example", 1, null);
      } finally {
        Context.exit();
      }
    

Whereby loadScript simply utilizes Rhino's evaluateReader functionality:

private void loadScript(Context cx, Scriptable scope, String name) {
        FileReader readerJQ = null;
        try {
            readerJQ = new FileReader(name);
            cx.evaluateReader(scope, readerJQ, name, 1, null);
            readerJQ.close();
        } catch (IOException e) {               
            throw new RuntimeException(e);
        }
    }

I guess it is a combination of env.js and jQuery both wrapped in IIFE that causes the Rhino to go over 64k byte code limit. Once env.js is loaded in modules like abvove (order is important!), original jQuery code just works.

If you try $.ajax or other XHR jQuery calls, be avare, that jQuery + env.js follow same domain policy, so the server in XHR request needs to match window.location.

其他提示

You could try the Rhino_1_8 branch located here:

https://github.com/mozilla/rhino/tree/rhino_1_8

Quoting Hannes:

That branch is able to split up very long object literals into multiple java methods to circumvent the 64k java method size limit. I've implemented this for coffeescript which had same problem and now works in compiled mode on rhino_1_8.

Of course it might still fail for you if you really have one huge object literal (versus one that is composed of multiple nested object/array literals). If you try please let me know if it works!

https://groups.google.com/d/msg/mozilla-rhino/N_O4Got4ED8/gqMnItFFzL8J

Even after you break up your Javascript into functions < 64k there is still a global limit that you can hit due to internals of Rhino. Another limitation I ran into was that having too many javascript functions, variables, etc. ran into Rhino limitation since it builds a switching function table based off symbols in the program.

We patched Rhino 1.7.4 to work around this here. https://github.com/TMCBonds/rhino/tree/Rhino1_7R4_RELEASE_64KPLUS

We successfully ran Env.js along with a large amount of JS Code on top of that.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top