Haxe для JavaScript без загрязнения глобального пространства имен? - PullRequest
9 голосов
/ 30 сентября 2010

Этот вопрос относится только к версии Haxe <2.10 </strong>

Я знал о haxe некоторое время, но никогда не играл с ним до вчерашнего дня. Будучи любопытным, я решил портировать showdown.js , порт javascript markdown.pl , на haxe. Это было довольно просто, и генерируемый им javascript, кажется, работает нормально ( edit: Если вы хотите увидеть его в действии, посмотрите здесь ).

Однако я заметил, что сгенерированный код сбрасывает кучу вещей в глобальном пространстве имен ... и, что еще хуже, он делает это, присваивая значения необъявленным идентификаторам без использования ключевого слова var поэтому они глобальны, даже если вы закроете все это закрытием.

Например ...

if(typeof js=='undefined') js = {}
...
Hash = function(p) { if( p === $_ ) return; {
...
EReg = function(r,opt) { if( r === $_ ) return; {
...

Мне удалось вычистить большую часть всего этого с помощью sed, но меня тоже беспокоит такая вещь:

{
 String.prototype.__class__ = String;
 String.__name__ = ["String"];
 Array.prototype.__class__ = Array;
 Array.__name__ = ["Array"];
 Int = { __name__ : ["Int"]}
 Dynamic = { __name__ : ["Dynamic"]}
 Float = Number;
 Float.__name__ = ["Float"];
 Bool = { __ename__ : ["Bool"]}
 Class = { __name__ : ["Class"]}
 Enum = { }
 Void = { __ename__ : ["Void"]}
}
{
 Math.__name__ = ["Math"];
 Math.NaN = Number["NaN"];
 Math.NEGATIVE_INFINITY = Number["NEGATIVE_INFINITY"];
 Math.POSITIVE_INFINITY = Number["POSITIVE_INFINITY"];
 Math.isFinite = function(i) {
  return isFinite(i);
 }
 Math.isNaN = function(i) {
  return isNaN(i);
 }
}

Это довольно неприятный JavaScript.


Вопросы

Есть ли где-нибудь вилка или клон гекса, который не загрязняет глобалы? Стоит ли модифицировать источник haxe, чтобы получить то, что я хочу, или кто-то уже решил это? Погуглил мало что нашел. Я открыт для любых предложений. Тем временем мне не терпится увидеть, какой PHP-код будет производить эта штука ...: D


Ответы

Вот некоторые из идей, которые я попробовал:

постобработки

Вот мой скромный скрипт сборки; он делает довольно хорошую работу по удалению вещей, но не все ловит. Я не решаюсь удалить модификации встроенных прототипов конструктора; Я уверен, что это сломало бы вещи. Исправление всего может быть немного трудной задачей, и я не хочу начинать ее, если кто-то уже сделал работу ...

haxe -cp ~/Projects/wmd-new -main Markdown -js markdown.js

echo "this.Markdown=(function(){ var \$closure, Float;" > markdown.clean.js;

sed "s/^if(typeof js=='undefined') js = {}$/if(typeof js=='undefined') var js = {};/g ;
     s/^\([ \x09]*\)\([\$_a-zA-Z0-9]* = \({\|function\)\)/\1var \2/g ;
      /^[ \x09]*\(else \)\?null;$/d ;
     " markdown.js >> markdown.clean.js

echo "return Markdown}());" >> markdown.clean.js;

java -jar closure/compiler.jar --js markdown.clean.js \
--compilation_level SIMPLE_OPTIMIZATIONS \
> markdown.cc.js

- переключатель пространства имен js сохраняет день

Спасибо Дину Берджу за указание на переключатель пространства имен. Это в значительной степени решило мою проблему с небольшой помощью. Вот мой текущий скрипт сборки. Я думаю это ловит все глобальные переменные ...

NS=N\$

haxe -cp ~/Projects/wmd-new -main Markdown --js-namespace $NS -js markdown.js 

# export our function and declare some vars
echo "this.markdown=(function(){var \$_,\$Main,\$closure,\$estr,js,"$NS"" > markdown.clean.js;

# strip silly lines containing "null;" or "else null;"
sed "/^[ \x09]*\(else \)\?null;$/d ;" markdown.js >> markdown.clean.js

# finish the closure
echo "return "$NS".Markdown.makeHtml}());" >> markdown.clean.js;

Ответы [ 4 ]

7 голосов
/ 30 сентября 2010

Я использую переключатель пространства имен на компиляторе для очистки этих глобальных корневых типов.

3 голосов
/ 30 сентября 2010

Haxe не предназначен для написания изолированного многократно используемого компонента в веб-приложении javascript. Об этом свидетельствует тот факт, что компилятор генерирует стандартную библиотеку для каждой чёртовой компиляции. Наиболее оптимальное использование цели javascript - это написать приложение полностью на haxe и вызывать внешние компоненты, используя нетипизированные блоки, надеясь, что это ничего не сломает. Вы должны относиться к выводу haxe как к флеш-ролику, не обращая внимания на среду, в которой он работает, предполагая, что это единственное, что выполняется.

Или вы можете попробовать обернуть код блоком with ().

2 голосов
/ 30 сентября 2010

здесь есть компилятор имен (экспериментальный) haxe http://github.com/webr3/haxe

1 голос
/ 25 ноября 2010

Макрос генератора JSTM JavaScript оптимизирует вывод haxe несколькими способами:

  1. выходные данные javascript разделены на отдельные файлы по типу
  2. эти файлы оптимизированы
  3. скрипт загрузчика загружает требуемые типы асинхронно
  4. используется только одна глобальная переменная: jstm
  5. загружен только код, который фактически необходим для запуска вашего приложения
  6. новые типы могут быть загружены во время выполнения, что делает возможным масштабируемые приложения

проверить http://code.google.com/p/jstm/ для получения дополнительной информации.

...