1

我想允许通过 Rhino 使用尽可能接近 jQuery 的语法进行服务器端脚本。理想情况下,我只想在服务器上使用 jQuery。

目前,Rhino + Env.js + jQuery 可以工作,但没有开启优化(我必须这样做, cx.setOptimizationLevel(-1);因为http://bugs.sun.com/view_bug.do?bug_id=4262078)解释的 JS 严重限制了我工具的适用性我在写。

在我尝试自己做之前,我想问一下 JavaScript 专家,什么是分解封装良好的 jQuery 核心(以及我的一些以相同风格编写的 jQuery 插件)的最佳方法?即如何拆分一个函数

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

成功能块。

所需要的只是将函数的某些部分分成可调用的代码,这些代码在执行后将具有相同的功能。

4

3 回答 3

1

您可以尝试位于此处的 Rhino_1_8 分支:

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

引用汉尼斯的话:

该分支能够将非常长的对象文字拆分为多个 java 方法,以规避 64k java 方法大小的限制。我已经为有同样问题的咖啡脚本实现了这个,现在在 rhino_1_8 上以编译模式工作。

当然,如果你真的有一个巨大的对象文字(相对于一个由多个嵌套对象/数组文字组成的),它可能仍然会失败。如果您尝试,请告诉我它是否有效!

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

于 2012-03-20T21:42:00.527 回答
1

无需拆分 jQuery,它适用于 env.js 1.2 (http://www.envjs.com/)、Rhino 1.7R2 和 jQuery 1.7.1,如果执行以下步骤。

  1. 下载 env.js 源代码并在根目录下运行 ant。
  2. 从生成的 ./dist 中,将除 env.js 和 env.rhino.js 之外的所有文件复制到您的代码可以访问它的位置(我将文件夹称为“env.js”)。
  3. 执行以下操作,您将在服务器上拥有快速、启用 jQuery 的上下文:

      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();
      }
    

其中 loadScript 简单地利用了 Rhino 的 evaluateReader 功能:

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);
        }
    }

我猜这是 env.js 和 jQuery 的组合,它们都包装在 IIFE 中,导致 Rhino 超过 64k 字节代码限制。一旦 env.js 被加载到像 abvove 这样的模块中(顺序很重要!),原始的 jQuery 代码就可以工作了。

如果您尝试 $.ajax 或其他 XHR jQuery 调用,请注意,jQuery + env.js 遵循相同的域策略,因此 XHR 请求中的服务器需要匹配window.location

于 2012-03-21T21:42:03.017 回答
1

即使您将 Javascript 分解为 < 64k 的函数,由于 Rhino 的内部结构,您仍然可以达到一个全局限制。我遇到的另一个限制是,有太多的 javascript 函数、变量等遇到了 Rhino 的限制,因为它基于程序中的符号构建了一个切换函数表。

我们修补了 Rhino 1.7.4 来解决这个问题。 https://github.com/TMCBonds/rhino/tree/Rhino1_7R4_RELEASE_64KPLUS

我们成功地运行了 Env.js 以及大量的 JS 代码。

于 2014-01-30T16:39:39.320 回答