Как разделить IIFE, чтобы вписаться в ограничение байт-кода Java JVM / Rhino 64k - PullRequest
1 голос
/ 20 марта 2012

Я хотел бы разрешить скрипты на стороне сервера через 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);

в функциональные куски.

Все, что нужно, - это разделить части функции на вызываемый код, который будет иметь те же функциональные возможности после выполнения.

Ответы [ 3 ]

1 голос
/ 22 марта 2012

Нет необходимости разбивать jQuery, он работает с env.js 1.2 (http://www.envjs.com/), Rhino 1.7R2 и jQuery 1.7.1, если выполнить следующие шаги.

  1. Скачать env.js source и запустите 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();
      }
    

При этом просто загрузите скриптиспользует функциональные возможности RRe Rative Reader:

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 превысить ограничение в 64 Кбайт-кода. Как только env.js загружен в модуликак и выше (порядок важен!), оригинальный код jQuery просто работает.

Если вы используете $ .ajax или другие вызовы jQuery XHR, будьте внимательны, чтобы jQuery + env.js следовал той же политике домена, поэтому серверв запросе XHR должно совпадать window.location.

1 голос
/ 30 января 2014

Даже после того, как вы разбили свой Javascript на функции <64k, все еще существует глобальный предел, который вы можете достичь из-за внутренних компонентов Rhino.Еще одно ограничение, с которым я столкнулся, заключалось в том, что слишком большое количество функций, переменных и т. Д. JavaScript сталкивалось с ограничением Rhino, поскольку оно строило таблицу функций переключения на основе символов в программе. </p>

Мы исправили Rhino 1.7.4 для обходаэто здесьhttps://github.com/TMCBonds/rhino/tree/Rhino1_7R4_RELEASE_64KPLUS

Мы успешно запустили Env.js вместе с большим количеством JS-кода поверх этого.

1 голос
/ 21 марта 2012

Вы можете попробовать ветку Rhino_1_8, расположенную здесь:

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

Цитата Ханнеса:

Эта ветвь может разбить очень длинные объектные литералы на несколько методов Java, чтобы обойти ограничение размера метода Java 64 КБ. Я реализовал это для Coffeescript, который имел ту же проблему, и теперь работает в скомпилированном режиме на Rhino_1_8.

Конечно, он все еще может потерпеть неудачу, если у вас действительно объектный литерал (по сравнению с тем, который состоит из нескольких вложенных литералы объекта / массива). Если вы попробуете, пожалуйста, дайте мне знать, если это работает!

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

...