0

Вот что я ищу:Есть ли способ сообщить компилятору Google Closure о том, что * NOT * не встроил мои локальные функции?

  • Я хочу использовать замечательные свойства SIMPLE режима минификации при отключении только одна особенности (отключить локальную функцию инлайн).


  • UPDATE: Ответ НЕТ, это не возможно, учитывая мои настройки. Но для меня есть обходное решение, когда я использую Grails.
  • Как пояснил @Chad ниже: «Это нарушает основные предположения компилятора». Дополнительную информацию см. В моем UPDATE3 ниже.



В ФОРМЕ ВОПРОС:

  • Я использую CompilationLevel.SIMPLE_OPTIMIZATIONS, который делает все, что нужно, за исключением того, что это встраивание мои локальные функции.
  • Есть ли способ обойти это? Например, есть ли параметр, который я могу разместить в своих JS-файлах, чтобы сообщить Google Closure не включать мои локальные функции?

Было бы здорово иметь некоторые директивы в верхней части моего файла JavaScript, таких как:

// This is a JS comment... 
// google.closure.compiler = [inlineLocalFunctions: false] 

Я занимаюсь разработкой приложения Grails и используя Grails asset-pipeline плагин, который использует Google Closure Compiler (в дальнейшем, компилятор). Плагин поддерживает различные уровни минимизации, которые поддерживает компилятор через конфигурацию Grails grails.assets.minifyOptions. Это позволяет использовать «ПРОСТО», «РАСШИРЕННЫЙ», «WHITESPACE_ONLY».

AssetCompiler.groovy (актив-конвейерный плагин) вызывает ClosureCompilerProcessor.process()

Это в конечном итоге присваивает SIMPLE_OPTIMIZATIONS на объект в CompilerOptions. И при этом CompilerOptions.inlineLocalFunctions = true как побочный продукт (это жестко закодированное поведение в компиляторе). Если бы я использовал WHITESPACE_ONLY, результат был бы inlineLocalFunctions=false.

Таким образом, используя настройку «ПРОСТОЙ» в Asset Pipeline, локальные функции вставляются, что вызывает у меня проблемы. Пример: ExtJS ext-all-debug.js, который использует множество локальных функций.

SO post Is it possible to make Google Closure compiler *not* inline certain functions? оказывает некоторую помощь. Я могу использовать его трюк window['dontBlowMeAway'] = dontBlowMeAway, чтобы мои функции не вставлялись. Однако у меня много функций, и я не собираюсь вручную делать это для каждого; и я не хочу писать сценарий, чтобы сделать это для меня. Создание JS-модели и попытка идентифицировать локальные функции не звучат безопасно, весело и быстро.

Предыдущий SO сообщение направляет читателю https://developers.google.com/closure/compiler/docs/api-tutorial3#removal, где объясняется трюк window['bla'], и он работает.

Wow спасибо, что прочитали этот длинный.

Помощь? :-)


Update1:

Хорошо. Приложив все усилия для написания этого вопроса, у меня может получиться трюк, который мог бы сработать. Grails использует Groovy. Groovy упрощает процедуру перехвата вызова метода, используя свой MetaClass API.

Я собираюсь попробовать перехватить вызов:

com.google.javascript.jscomp.Compiler.compile(
    List<T1> externs, List<T2> inputs, CompilerOptions options) 

Мой перехватывать метод будет выглядеть так:

options.inlineLocalFunctions=false 
// Then delegate call to the real compile() method 

Пора кровать, так что я должен попробовать это позже. Тем не менее, было бы неплохо решить эту проблему без взлома.



UPDATE2: Отклик в аналогичной должности (Is it possible to make Google Closure compiler *not* inline certain functions?) не решает мою проблему из-за большого количества функций, мне нужно встраиваемыми. Я уже объяснил это.

Возьмите файл ExtJS, который я привел выше, в качестве примера того, почему приведенный выше similar SO post не разрешает мою проблему. Посмотрите на необработанный код для ext-all-debug.js. Найдите функцию byAttribute(). Затем продолжайте искать строку «byAttribute», и вы увидите, что она является частью строк, которые определяются. Я не знаком с этим кодом, но я предполагаю, что эти строковые значения byAttribute позже передаются на выполнение функции JS's eval(). Компилятор не изменяет эти значения byAttribute, когда это часть строки. После того, как function byAttribute встроен, попытки вызова функции больше невозможны.



Update3: Я пытался две стратегии, чтобы решить эту проблему, и оба оказались безуспешными. Однако я успешно реализовал обходной путь. Мои неудачные попытки:

  1. Использование перехвата метода Groovy (Протокол метаобъектов, aka MOP) для перехвата com.google.javascript.jscomp.Compiler.compile().
  2. Закройте заглушку-compiler.jar (сделайте мою собственную копию) и измените com.google.javascript.jscomp.applySafeCompilationOptions(), установив options.setInlineFunctions(Reach.NONE); вместо LOCAL.

метод перехват не работает, потому что Compiler.compile() является классом Java, который вызывается с помощью Groovy класса, помеченного как @CompileStatic. Это означает, что ССМ Groovy не используется, когда process() называет Compiler.compile() Google. Даже ClosureCompilerProcessor.translateMinifyOptions() (код Groovy) нельзя перехватить, потому что класс @CompileStatic. Единственный метод, который можно перехватить, - ClosureCompilerProcessor.process().

Викинг Google-compiler.jar был моим последним уродливым курортом. Но так же, как @Chad сказал ниже, просто вставка options.setInlineFunctions(Reach.NONE) в нужное место не воскресила мои встроенные имена функций JS. Я попытался переключить другие параметры, такие как setRemoveDeadCode=false безрезультатно. Я понял, что сказал Чад. Я бы закончил переворачивать настройки и, возможно, уничтожил работу миниатюры.

Мое решение: Я предварительно скомпилировал ext-all-debug.js с помощью UglifyJS и добавил их в свой проект. Я мог бы назвать файлы ext-all-debug.min.js, чтобы сделать это более чисто, но я этого не сделал. Ниже приведены настройки, которые я установил в своем Grails Config.groovy:

grails.assets.minifyOptions = [ 
    optimizationLevel: 'SIMPLE' // WHITESPACE_ONLY, SIMPLE or ADVANCED 
] 

grails.assets.minifyOptions.excludes = [ 
    '**ext-all-debug.js', 
    '**ext-theme-neptune.js' 
] 

Выполнено. Задача решена.




Ключевые слова: преуменьшать, минификация, уродовать, UglifyJS, UglifyJS2

+0

Можете ли вы объяснить ** почему ** локальная функция встраивания вызывает проблемы? Существует несколько методов предотвращения этого, но мне нужно знать основные причины, чтобы предложить его. –

+0

Возможный дубликат [Возможно ли сделать компилятор Google Closure \ * not \ * встроенными определенные функции?] (Http://stackoverflow.com/questions/4297685/is-it-possible-to-make-google-closure- compiler-not-inline-certain-functions) –

+0

Спасибо @ChadKillingsworth. Я добавил «UPDATE2» к моему вопросу как ответ на ваш вопрос. В самом деле, я просил вас прокомментировать «возможный дубликат», если вы прочтете мой первоначальный вопрос, который вы, вероятно, сделали в любом случае. Мир брата. –

ответ

2

В этом случае вы либо должны сделать собственную сборку компилятора или использовать API Java.

Однако для обеспечения безопасности это невозможно. Выявление проблем с переименованием и удалением кода также вызовет проблемы. Это нарушает основные предположения компилятора. Эта локальная функция ТОЛЬКО ссылается из строк.

Этот код является безопасным только для режима компилятора WHITESPACE_ONLY.

+0

Вы были правы. Подробные сведения см. В разделе UPDATE3 и мое успешное обходное решение. Спасибо Chad =) –

Смежные вопросы