作成者別アーカイブ: shohei909

NanoTestがマクロ環境以外のテストでのバグも、コンパイラ警告として出力できるようになりました

前回のNanoTestの記事 : テストで検出したバグをコンパイラ警告として出力してくれるHaxeライブラリ、NanoTestを公開しました

このNanoTest、バージョン1.0に更新しました!

これまでのNanoTest

Haxeのマクロ上でテストを実行して、検出したエラーをコンパイラ警告として出力すれば、IDEのコンパイルエラー表示機能を使って表示できるよ。コンパイルエラーと同じように扱われるから、FlashDevelopでもIntelliJ IDEAでも、エラー行の強調とか、エラー行へのジャンプ機能とかが使えるよ。

マクロでテストをすることの重大な欠点

Haxeには出力する言語特有バグとか、挙動の違いとかがあるよ。
あと、各プラットフォーム依存のライブラリとかを使うとマクロを使ってのテストができないよ。

新しいNanoTest

新しいNanoTestではマクロ以外で実行したテストの結果をIDE上に出力することができるようになりました。これで、プラットフォーム依存な内容のテストも簡単にできるようになります。

NanoTestOnFlashDevelopNanoTestOnIntelliJIDEA

しくみ

  1. ターゲットのプラットフォームへコンパイルする
  2. ターゲットのプラットフォーム上でテスト実行して結果をテキストファイルに出力する
  3. マクロでファイルを読み込んで、エラーの情報があれば、コンパイラ警告として出力する

これだけです。とってもシンプル。だけど強力。

これにより、出力対象がNekoだろうと、C++だろうと、C#だろうと、Javaだろうと、JavaScriptだろうと、FlashだろうとIDE上でテストのデバッグができるようになります。

インストール方法

以下のコマンドを入力

haxelib install nanotest

使い方

Githubのsampleフォルダに、FlashDevelop用、Intellij IDEA用のサンプルプロジェクトがあるので、それをみればどうやって使えばいいかはわかると思います。

Nanotest | Github

一応、簡単に解説。

NanoTestRunner.readResult

バージョン1.0で新たに追加されたNanoTestRunner.readResultをマクロから呼び出すことでテキストファイルの内容にしたがって、IDE上でのデバッグが可能になります。

具体的には、hxmlで以下のような指定を行います。

-lib nanotest
--macro nanotest.NanoTestRunner.readResult(テスト結果ファイルのパス, ソースのパスの配列, ラベル)

“テスト結果ファイル”というのは、テストのときに標準出力される内容をファイルにリダイレクトしたものです。NanoTest, haxe.unit, MUnitのNeko出力の出力形式に対応しています。

“ソースのパスの配列”は、テストのコンパイル時に-cpで指定したディレクトリを配列で指定してください。

“ラベル”は任意の文字列です。プラットフォーム名などをラベルにしておくと失敗の警告にラベルが表示されるので、IDE上で表示する際にどのプラットフォームで失敗したのかわかり安くなります。

Haxe/JavaScriptの場合

# test_js.hxml

#1. JSターゲットでコンパイル
-main sample.TestSample
-js bin/test.js
-lib nanotest
-cp src
-cp test
-debug

#2. node.jsで実行して、結果をファイルに出力
--next
-cmd node "bin/test.js" 1>bin/report_js.txt

#3. 出力したファイルをマクロで読み込んで、テストの情報を読み取る
--next
-lib nanotest
--macro nanotest.NanoTestRunner.readResult('bin/report_js.txt', ['test', 'src'], 'JS')

Haxe/Flashの場合

Flashのデバッグをする場合は、flashlog.txtを使用しますので、Flashのデバッグプレーヤーが必要になります。

# test_swf.hxml

#1. SWFに出力
-main sample.TestSample
-swf bin/test.swf
-lib nanotest
-cp src
-cp test
-debug
-D fdb

#2. Flashを起動して、flashlog.txtのテスト結果をコピー。
--next
-cmd swf_debug bin/test.swf bin/report_swf.txt

#3. flashlogのコピーから結果を読み取り
--next
-lib nanotest
--macro nanotest.NanoTestRunner.readResult('bin/report_swf.txt', ['test', 'src'], 'Flash')

Windows用のFlashを起動するバッチファイル(swf_debug.bat)。test_swfと同じ階層に置く。

:: swf_debug.bat

"C:\Program Files (x86)\FlashDevelop\Tools\flexlibs\runtimes\player\11.9\win\FlashPlayerDebugger.exe" %1 
cp "%APPDATA%\Macromedia\Flash Player\Logs\flashlog.txt" %2

MUnitとの連携

NanoTest v1.0のしくみなら、テスト情報の含まれるテキストファイルさえあればコンパイラ警告として出力が可能です。つまり、実際のテストを行うライブラリがNanoTestでなくても構わないわけです。NanoTest v1.0では、MUnitのテスト時に標準出力される失敗行の情報から、コンパイラ警告を出力する機能がついてます(Neko出力にのみ対応)

1. 標準出力をテキストファイルにリダイレクトするようにMUnit実行。

haxelib run munit run 1>bin\test_result.txt

.munitはこんな感じ↓

version=2.1.0
src=test
bin=bin
report=report
hxml=munit.hxml
classPaths=src
resources=resources
templates=null
coveragePackages=null
coverageIgnoredClasses=null

2. 出力されたテキストをNanoTestで読み込み

以下のような、hxmlを実行する。

# nanotest.hxml

-lib nanotest
--macro nanotest.NanoTestRunner.readResult('bin/test_result.txt', ['src','test'], "MUnit")

これで、MUnitでのテスト内容を、IDE上でデバッグできます。

そのほかの変更

パッケージの変更

パッケージ名が変わりました。

shohei909.nanotest.* -> nanotest.*

メソッドチェーンで、テスト失敗時に詳細情報を出力できるように

class SampleCase extends NanoTestCase {
    public function testBasic() {
        var a = [1, 2, 3, 5];
        var b = [2, 2, 3, 3];
        for (i in 0...a.length) {
            assertEquals(a[i], b[i]).label(i);
        }
    }
}

assertから始まるメソッドから、.label()にメソッドチェーンでつなぐと、追加の情報が出力されます。

上の例では、以下のような出力がされるので、失敗したのが配列の0番目と3番目の要素だったことを知ることができます。

Test failed : expected 1 but was 2 [0]
Test failed : expected 5 but was 3 [3]

-D result_exit_code

出力ファイルをNanoTestでreadResultする際に、result_exit_codeのフラグをつけると、テスト失敗時に返り値1でプログラムが終了します。

脆弱性の歴史からみるWindows XPのウイルス感染過程

もうみなさんご存じでしょうが、2014年4月8日をもってWindows XPのサポートは終了しました。
先週、先々週あたりはXPから早くアップデートしろだの、XPは窓から投げ捨てろだの騒がしくなってましたね。

ニコニコ動画には、Windows XPサポート切れをあつかった自主制作アニメまで上がっていました。

ざっくりまとめてしまうと、社内のXPで怪しいソフトをインストールしてしまって大変なことに…。みたいなお話。XPユーザーはドキッとしてしまうような内容ですね。

でも、なんか違うんだよなー。

だって、怪しいソフトをインストールしちゃいけないのは、Windows8だろうと、Linuxだろうと変わらないじゃないですか。(いわゆるトロイの木馬ですね)

Windows XPが危ないって伝わったひとでも、実際のところどう危ないのかってことまではわかってないひとは多いんじゃないでしょうか。Windows XPを脅かす“脆弱性”とはどういうものなのか?これまでの脆弱性を振り返ることで見ていきたいと思います。

ここ半年のWindowsのセキュリティ情報をながめる

Windowsには毎月のように脆弱性が発見されています。これは、XPだけでなくVista, 7, 8でも同じことです。XPサポート終了が問題になるのは、この毎月のように発見されている脆弱性が修正されなくなるからです。

では、脆弱性というのはいったいどういうものなのでしょう?

脆弱性がどういうことものなのかを理解するのに手っ取り早いのは、これまでにあった脆弱性を知ることです。Windowsの修正ずみの脆弱性についてはマイクロソフトのサイトで公開されています。

マイクロソフト セキュリティ情報

以下に、2013年9月から2014年3月までに公表された脆弱性のうち深刻度「緊急」のものの一部を挙げていきます。

ぱっと眺めてみただけで、やばさはわかると思います。特に注目すべきことは以下のことです

  • 脆弱性のあるソフトウェアでは、ウェブページを閲覧したり、画像を閲覧したり、フォントを閲覧したり、メールを閲覧したりするだけで、ウイルスに感染させることが可能だということ
  • これらに、怪しいソフトウェアをインストールしたり、怪しいメールの添付ファイルを開くなどの危険とされる操作は必要ないということ
  • 脆弱性のうちいくつかは修正より前に公開されてしまって、だれでも攻撃ができる状態になってしまうこと
  • Windows8, 7, Vista, XPに共通する脆弱性は多いということ
  • Windows8, 7, Vistaの脆弱性にこれからも修正や情報公開をしていくが、XPの脆弱性は修正されないということ。つまり、Windows8, 7, Vistaの更新内容から、XPの持っている脆弱性がある程度推測できるということ

脆弱性があるということは「ちょっとした過失でウイルスに感染しうる」ことだと思っているひとは多いかもしれません。脆弱性があるということは「何の過失がなくてもウイルスに感染しうる」ということです。むしろ、「脆弱性の放置されたPCを使い続けること自体が、過失である」とも言えます。

攻撃者はどうやって悪意あるWebページを閲覧させるか

Windows XPの脆弱性をねらう攻撃としてありそうなものは、閲覧するだけでウイルスに感染するようなメールを送りつけることや、閲覧するだけでウイルスに感染するようなWebページに誘導するなどがあります。

ここでは、攻撃者が悪意あるWebページを閲覧させる方法を掘り下げてみます。怪しいWebページになんて見なければいいんだろうと思う人もいるかもしれませんが、そう簡単ではありません。

泥棒はスーツを着ている

空き巣にもっともポピュラーな服装はスーツであるという話があります。悪意ある人間と同じように、悪意あるサイトもいたって健全そうな見た目をしていることはよくあります。

ある攻撃サイトは、GoogleやYahoo検索の上位に上がるようなサイトをつくることで、ページの閲覧者を増やします。ある攻撃サイトは中古のドメインを利用して、例えばもともと映画の公式サイトがあったURLにサイトをつくります。FC2や、はてなブログ、Tumblrのようなフリーのブログサービスなどを攻撃に使うことも可能です。こういった手法をつかわれると、リンクをみて怪しいサイトかどうかを判断するのはほとんど不可能です。

それだけではありません。もっとメジャーなSNSから攻撃されることもありえます。

クロスサイトスクリプティングでTwitterやYoutubeから攻撃をする

不特定多数のユーザーに対してWebページを閲覧させる方法の1つは、XSS(クロスサイトスクリプティング)を使う方法です。このXSSに対する脆弱性というのは、いままでTwitter、YouTube、Facebook、Yahoo知恵袋にも見つかった脆弱性です。

XSS脆弱性があるユーザー投稿型のサービスでは、特定のテキストを投稿するとそのテキストを閲覧した人に対してJavaScriptを実行させることが可能になります。

例えば、SNSなどのユーザー名やタイトルに

<script>document.location = "http://google.com"</script>

というテキストを含めた投稿を行うと、タイトルやユーザーが表示されるはずの場所で、

document.location = "http://google.com"

というテキストがJavaScriptとして解釈されて、閲覧者は、Googleのトップページに飛ばせる場合があります。わかりやすいのが、Yahoo知恵袋の例です。

<script>alert("xss");</script> これであなたもおしまいです。 – Yahoo知恵袋

ただ、タイトルに <script>alert("xss");</script> という文字が含まれているだけの質問ですが、当時はこのページの閲覧後に他の質問を閲覧すると、画面上に”xss”というポップアップが表示されるようになっていました(現在は修正ずみ)。

上の質問では、ただ文字を表示するだけでしたが、alert(“xss”)の代わりに別のJavaScriptが使えば、悪意あるWebページを表示したり、アカウントのログインに必要な情報を盗んだりすることも可能な状態になっていました。

とても単純な脆弱性ですが、このような脆弱性はめずらしいものではなく多くの有名なWebサービスでも見つかっています。

XSS脆弱性があったサービス

その他の悪意あるWebページを閲覧させる方法

  • 審査の甘い広告サービスを利用した広告枠からの攻撃(マルバタイジング)
  • 中間者攻撃
    • 例えば、無料Wifiスポットに偽装したWifiスポットで、偽のWebページを閲覧させる。
  • DNSキャッシュポイズニング
    • google.comやyahoo.co.jpなどのドメイン名がどこのサーバーを指しているのかを解決するサーバー(DNSサーバー)の脆弱性を狙った攻撃。成功すれば、例えばhttp://www.yahoo.co.jpを閲覧しようとしている人に対して、偽のページを表示させることができる。

悪意あるWebページを表示させる手法はいろいろあります。

結論

Google検索しか使わなくても、Twitterしか使わなくても、Youtubeしか使わなくても、Facebookしか使わなくても、悪質なWebページを閲覧する危険性がある。

Windowsだから危険なのか?

Windowsの脆弱性についてばかり取り上げていますが、これは決してWindowsが他のOSに比べて脆弱性が多いという意味ではありません。例えば、Linuxなどにも同じように脆弱性は存在しています。

Linuxの安全性を語るときによくいわれるのは「オープンソースなので脆弱性が少ない」ということです。しかし、オープンソースであっても、ごく単純な脆弱性が発見されることなく放置されていた例というのはいくつもあります。

オープンソースのバグで記憶に新しいのはOpenSSLの、HeartBleedです。重大な脆弱性ですが、2年間も存在していました。長いものでは、X Windowの22年間放置されていたユーザーが昇格できる脆弱性というのもあります。

これらのバグを生んだソースコードは誰でも閲覧可能だったわけです。ソースを公開していないWindowsの脆弱性よりも、はるかに見つけやすかったはずです。オープンソースであることは、かえって攻撃しやすい原因にすらなります。

Linuxに対するウイルスは確かに、Windowsに対するものより少ないです。ただし、これはデスクトップPCのLinuxユーザーが少ないからという理由につきると思っています。スマートフォンのシェアの半数以上を握るAndroidは攻撃の的になっていますしね。

まとめ

サポート期限切れのソフトだと、メールをただ閲覧しただけ、いつものSNSやWebサイトを閲覧してるだけで、ウイルスに感染するよ!

ユーザーとしてできること

ソフトウェアを使う側としてできることって、当たり前なことを当たり前にやるってことぐらいしか思い浮かばないです。Linux、Windowsだの、Internet Explorer、Chromeだの関係なく以下のようなことはやっときましょう

  • OSはちゃんとアップデートしましょう
  • ブラウザやメールクライアントなどのソフトもアップデートしましょう
  • セキュリティソフトを使いましょう

脆弱性の話ばかりしたので、インターネットを利用することが怖く感じる人もいるかもしれません。ですが必要以上にインターネット自体を恐ろしく感じる必要は無いです。

悪意ある攻撃の話ばかりしてきましたが、実際のインターネットには善意があります。マイクロソフトのセキュリティ情報の謝辞の欄をみてください。ここには非公開の脆弱性をマイクロソフトに連絡してくれた方の名前がずらりと並んでいます。OSやブラウザの脆弱性を見つけるのは悪質なクラッカーだと思っている人は多いかもしれません。しかし実際には、善意をもった人たちが開発元への報告をしてくれたことで発見される脆弱性がほとんどです。

Internet ExplorerやWindows、Chromeなどの脆弱性は非公開で報告すれば多額の賞金が与えられます。大きな名誉も得られます。脆弱性を見つけたからといって、リスクを冒してそれを攻撃するメリットは大きくありません。

しかし、サポートの終了したソフトウェアは違います。公開されてしまった脆弱性で攻撃をすることができますし、それから守ってくれる人もいません。これが、サポートの終了したXPが危険な理由です。

開発者としてできること

じつは本当に言いたいことは、開発者に対しての話だったりします。安全なソフトウェアをつくるためにどうすべきかの話です。

Windowsのセキュリティ情報を読んでいると、「メモリ破壊による脆弱性」というものが多く出てきます。

メモリ破壊というのは、開発者が意図しないメモリへの書き込みが行われる脆弱性です。以下のバッファオーバーランなどがその代表例です。

IPA ISEC | バッファオーバーラン ~その1・こうして起こる~

メモリ破壊が不可能なことをメモリ安全であるといい、CやC++のような言語はメモリ安全でありません。メモリ安全でない言語では、ほんのちょっとした不注意によって非常に深刻な脆弱性が生まれてしまいます。

そして、C/C++のようなメモリ安全でない言語が、多数の脆弱性を生んできたというのは歴史的な事実です。

では、どうすればメモリ破壊による脆弱性を作らないことができるのか?これには単純で明快な解決策があります。

「メモリ安全な言語を使う」ということです。

ブラウザ、コーデック、メールクライアント、Webサーバー、バーチャルマシン、エディタ、動画・音楽プレーヤー、オフィスソフト。これらのソフトウェアは今でも多くがC/C++で作られていますが、これまでの脆弱性の歴史を考えればC/C++はこれらをつくるのに向いていません。

メモリ安全な言語を使用していればJPEG画像の閲覧などのプログラムで、任意のコードが実行可能な脆弱性の入り込む余地がありません。

C/C++と同様にネイティブコードを出力する言語であっても、D言語やGoはほとんどメモリ安全な言語です。

さらに、MozillaはC/C++を代替するためのメモリ安全な言語「Rust」の開発をしています。Mozillaはこの言語を使って、次世代のブラウザレンダリングエンジン「Servo」の開発にも取り掛かっています。

C/C++はもはや代替されるべき言語です。


ある程度の知識がある開発者がWindows XPを使用している人を見れば、「危険だ」「今すぐ新しいOSに変えた方がいい」「人にも迷惑がかかることだから自己責任では済まない」くらいのことは思うはずです。

しかし、メモリ安全でないCやC++でソフトウェアを作っている人を見て、「危険だ」「今すぐ新しい言語に変えた方がいい」「人にも迷惑がかかることだから自己責任では済まない」という人は、ほとんどいません。

不思議なことです。

メモリ安全でないCやC++を使い続ける人たちは、「気を付けて使えば大丈夫」「新しいことを覚えるのは大変なことだから」「コストがかかることだからそう簡単にはできない」と考えるのでしょうか。

でも、それってXPを使い続ける言い訳と何も変わらないように思えます。

2014/04/23: コメントより「メモリ安全」に関する記述を修正

テストで検出したバグをコンパイラ警告として出力してくれるHaxeライブラリ、NanoTestを公開しました

FlashDevelopcapture-20140201-150704


GUIを使ってテストのデバッグがしたい

Haxeには標準で、haxe.unitというテスト用のライブラリがあります。とてもシンプルなライブラリです。低い敷居でテストを導入できて良いのですが、もの足りないなーと思うところもあります。

何がもの足りないのか?

足りないのはGUIです。グラフィカルなユーザーインタフェースです。黒い画面上に表示されたメッセージを眺めて、ファイルを探して、失敗した行を探して、1つ1つバグを潰していくのは、なんとも骨が折れます。

「ずらっとならんだメッセージをクリックしたら、テスト失敗した行にすぐ飛べる!」とか「失敗行を赤線で示してくれる!」とかそういうGUIがあればもっと楽に、簡単にテストができるわけです。コンパイルエラーでは、エラー行へジャンプする機能も、エラー行をハイライトしてくれる機能もIDEについています。コンパイルエラーと同じように、テストの失敗も表示してくれればデバッグもはかどるわけです。

うれしいことにHaxeのコンパイラはそれを実現できる機能があります。Haxeには、コンパイル前にコードを実行して、その際にコンパイルエラーやコンパイラ警告を出力することができる機能があります。

それが、これ、Compiler Configuration with Macros。いわゆるマクロです。コンパイル中ではなく、コンパイル前に動作するマクロなので、自分はコンパイル前マクロと呼んでいます。今回は、このコンパイル前マクロでつかうテスト用のライブラリNanoTestを作りました。


NanoTest(ナノテスト)

ソースコード:https://github.com/shohei909/NanoTest
ライセンス:MIT Lisence

NanoTest(ナノテスト)の特徴は以下のとおり

  • テストの書き方はhaxe.unitとほぼ同じ。すでにhaxe.unit用に記述したコードがあるならばTestRunnerをNanoTestRunnerに、TestCaseを、NanoTestCaseに置き換えれば、同じように動作します。シンプルなので学習コストも低いです。
  • NanoTestをマクロとして実行することで、テストの失敗をコンパイラ警告やコンパイルエラーとして出力することができます。FlashDevelopだろうとIntelliJ IDEAだろうと、いつもと同じUIでテスト失敗が警告されるので、快適にデバッグをすることができます。

インストール

haxelibをつかってインストールすることが可能です。コンソール上で以下のコマンドを打ち込んでください。

haxelib install nanotest

使い方

基本的な、テストの書き方はHaxeマニュアルのWriting Unit Testsとほぼ同じです。

NanoTestの場合、以下のようなファイルをsample/TestSample.hxとして保存します。

package sample;
import shohei909.nanotest.NanoTestRunner;
import shohei909.nanotest.NanoTestCase;
 
class TestSample {   
    static function main(){
        var r = new NanoTestRunner();
        r.add(new TestFoo());
        r.run();
    }
}
 
class SampleCase extends NanoTestCase {
    public function testBasic(){
        assertEquals( "A", "A" );
    }   
}

これを、以下のようなhxmlファイルでコンパイルして実行すれば、haxe.unitと同じようにテストが出来ます。

-neko testSample.n 
-main TestSample
-lib nanotest

上記のテストをマクロとして実行したい場合、hxmlを以下のように書き変えます。

--no-output
--macro sample.TestSample.main()
-lib nanotest

“–macro”で指定した関数が、コンパイル前に実行させれて、そこでテストの失敗があればコンパイラ警告としてそれが出力されます。

このhxmlを使ってIDEがコンパイルするように設定すれば、IDEがコンパイラ警告としてテスト失敗を出力してくれるので、コンパイルエラーをとりのぞくのと同じようにテストのデバッグを行うことが出来ます。

※ FlashDevelopでhxmlを利用する方法は、ActionScript入門Wiki – FlashDevelopでHaxeプロジェクトを作成するで詳しく紹介されています。

より高度な使い方

テスト失敗を、コンパイル警告ではなくコンパイルエラーとして出力する

NanoTestRunnerのコンストラクタの引数に、NanoTestRunner.error関数を渡しましょう。

こんな風に

var r = new NanoTestRunner(NanoTestRunner.error);

コンパイル警告ではなくコンパイルエラーを出力する設定は、nightlyビルドのような自動ビルドをしたい場合に役に立ちます。つまり、テスト失敗時にコンパイルエラーになるようにしとけば、まちがってユーザーにバグを含むビルドを配布することを防げるので、安心して自動ビルドができます。

unit.haxe.TestCaseには無い関数について

NanoTestCaseは、unit.haxe.TestCaseと同じように使用することが出来ますがunit.haxe.TestCaseにはない追加の関数をもっています。

assertThrows( func:Void->Void, ?isSuccess:Dynamic->Bool, ?p : PosInfos )
funcを実行した場合に例外が投げられることをテストします。さらにisSuccessを設定した場合には、投げられた例外が正しいかどうかを、catchしたオブジェクトをisSuccess関数に渡してテストします。
globalSetup()
テストケースのクラスが複数持っているテスト用のメソッド(“test”ではじまるメソッド)の内、一番最初のメソッドが呼び出される前に呼び出されるメソッド。overrideして使う。
globalTearDown()
テストケースのクラスが複数持っているテスト用のメソッドの内、一番最後のメソッドが呼び出された後に呼び出されるメソッド。overrideして使う。
success( ?p:PosInfos )
テスト成功を出力します。
fail( message:String, ?p:PosInfos )
テスト失敗を出力します。
error( d:Dynamic )
テスト中に発生した例外を出力します。

またTestCaseとは異なり、assertEquals関数がEnumの比較をサポートしています。

注意点

マクロを使ったテストは、あくまでNekoに出力した場合のプログラムをテストしていることになります。FlashやJavaScriptなどその他のターゲットを使用している場合、そのターゲットに依存したコードについてはマクロではテスト出来ません。NanoTestでは、haxe.unit同様、実際にそのターゲットに出力した上で実行してテストするのも可能なので、ターゲット依存のコードについてはマクロを使わずにテストするようにしてください。

更新情報

v0.1.2(2014/02/02 17:29)
swf上で動作させた場合に上手く動かないバグがあったので修正。
v0.1.3(2014/02/02 22:05)
run関数を呼び出す前にassertできるようになりました。これにより非同期のテストが、書きやすくなりました。

Haxe3の新機能まとめ

本日2013/05/25、プログラミング言語Haxeのバージョン3が正式にリリースされました!
Haxe3のダウンロード:http://haxe.org/download

ということで、Haxe3がこれまでのHaxe2.10とどうが違うのかを徹底的に紹介していきます!


新機能

Java, C#ターゲットのサポート

これまで、Flash(AIRも)、JavaScript、C++、PHP、Nekoへの出力がサポートされていましたが、これらに新たにJava、C#が追加されました。

‘シングルクオテーション内での、変数展開

Haxe3から、「’」と「”」の扱いが変わります。

var x = 10;
trace( 'x is $x' )	//x is 10
trace( "x is $x" )	//x is $x

これまでのString.Format()関数の代替です。
「’」内で$変数名や${式}と記述した場合に、その変数や式が文字列内に組み込まれます。

新しいハッシュテーブルのクラス(Map)

クロスプラットフォームの辞書(ハッシュテーブル)のクラスが文法レベルでサポートされました。

var price:Map <String , Int > = [
	"カレー"        => 420,
	"カツカレー"    => 550,
	"ラーメン"      => 380
];

price.set("カレー",400);
trace( price.get( "カレー" ) ); //400

さらに、配列の演算子を使って値を参照することができます。

price["カレー"] += 30;

さらに、enumをカギに使うことも可能です。

配列内包表記

for文や、while文を使った配列の初期化がサポートされました。

//0~20の偶数の配列!
var evenArray = [for (i in 0...21) if (i & 1 == 0) i];

パターンマッチング

switch文を使ったパターンマッチングがサポートされました。
多機能なので、詳しくはhttp://haxe.org/manual/pattern_matchingを見てください。

パッケージをまとめてインポート

import my.pack.*;

のような書き方が出来るようになりました。

bind関数

callback構文の代替です。
より簡単に、関数の引数を束縛することができます。

function add(a:Int, b:Int) { trace( '$a,$b' ); }
var func1 = add.bind(3);
var func2 = add.bind(_, 4);

func1( 2 ); //add(3,2)と同じ
func2( 0 ); //add(0,4)と同じ

抽象型(abstract)

Haxe3では、新たに抽象型(abstract)が加わりました。
これは、JavaやC#の抽象クラスや抽象メソッドとは大きく異なるものです。

Haxeの抽象型は実行時には他の型として実行される型で、変換元となる型、変換先となる型、変換方法などを定義して使用します。
カスタム配列アクセス、演算子オーバーロードなどが使用出来ます。

NekoのIntが31bit整数から32bit整数に

Haxe2.10までのNeko出力では、

var argb = 0x66FFFFFF;

のように、31bitであらわせない数値が含まれているとコンパイルエラーになってました。
Haxe3では上記のコードは正常に動作します。

出力されるコードが綺麗に

Haxeには、未使用の関数や変数を自動で取り除くデッドコード削除という機能があります。
Haxe3では、この強さを3段階から選択することが出来ます。

–dce no: デッドコード削除を行わない(Haxe2.10のデフォルト)
–dce std: 自分で書いたコードから呼び出していない、標準ライブラリ、外部ライブラリのコードを削除。(新機能、Haxe3のデフォルト)
–dce full: main関数から呼び出していないコードについて削除を行う。(Haxe2.10で–dead-code-eliminationを指定した場合と同じ

デフォルトでのデッドコード削除は強化されたため、基本的にHaxe3から出力されるコードは綺麗になります。

型パラメータ(ジェネリクス)の強化。

構造的部分型による、型パラメータの束縛。

static function test < T: {function clone():T} >( a:T ) {}

enum(列挙型)のコンストラクタに対する、型パラメータの設定。

enum EnumTest{
	 HOGE < T >(t:T);
}

など、型パラメータの機能が強化されました。

マクロ機能の改善

詳しくはhttp://haxe.org/manual/haxe3/features

その他

  • コンストラクタのインライン化が可能に
  • Flashで、swcをそのまま外部ライブラリとして利用可能に
  • traceに複数の値が指定可能に

新しい標準ライブラリ

標準ライブラリの詳細はhttp://haxe.org/apiに載っています。

クロスプラットフォームのZIP圧縮、解凍

パッケージ: haxe.zip.*;
Flash, JavaScript, C++, PHP, Neko, C#, Javaで動くzipライブラリです。

暗号ライブラリの強化

パッケージ: haxe.crypto.*;
もともとあったMd5,Sha1,BaseCodeに加えて、Crc32,Adler32が使えるようになりました。

データ構造の追加

パッケージ: Map, haxe.ds.*;
いままで標準で、
Array < T >(可変長配列),
List < T >(連結リスト),
Hash < T >(文字列が鍵のハッシュ表)をサポートしていたのですが、

Hashが無くなり、

あらたに、
Map < K, V >(汎用なハッシュ表)、
GenericStack < T >(スタック)、
Vector < T >(固定長配列)、
BalancedTree < T >
が加わりました

これらはすべてクロスプラットフォームです。
VectorはいくつかのターゲットではArrayより速く、すべてのターゲットでArrayと同等以上の速度が出ます。

Enumの補助クラス

パッケージ: haxe.EnumTools;

JavaScriptターゲットがHTML5に対応

パッケージ: js.html.*;

HTML5の機能が標準で利用できるようになりました。
svg,webglなどもサポートされます。

その他

  • Array.map、Array.filter

移動したライブラリ

cpp.Sys Sys
php.Sys Sys
neko.Sys Sys
Lib.print Sys.print
neko.db sys.db
php.db sys.db
cpp.net sys.net
php.net sys.net
neko.net sys.net
cpp.io sys.io
php.io sys.io
neko.io sys.io
neko.zip haxe.zip
cpp.Utf8 haxe.Utf8
php.Utf8 haxe.Utf8
neko.Utf8 haxe.Utf8
haxe.BaseCode haxe.crypto.BaseCode
haxe.SHA haxe.crypto.Sha1
haxe.MD5 haxe.crypto.Md5
js.Lib.window js.Browser.window
js.Lib.document js.Browser.document
IntIter IntIterator
tringTools.isEOF StringTools.isEof
haxe.Stack haxe.CallStack
EReg.customReplace EReg.map

新しいメタデータ

@:to, @:from
抽象型(abstract)で使用します。型の変換方法を定義します。
@:arrayAccess
抽象型(abstract)で使用します。カスタム配列アクセスを定義します。
@:op
抽象型(abstract)で使用します。演算子オーバーロードを定義します。
@:publicFields
クラスのデフォルトの可視性をpublicに変更します。
@:noCompletion
コンパイラの補完機能に反映されないようにします。
@:noUsing
usingした際に反映されないようにします
@:font
Flashのみです。フォントの埋め込みを行います。文字コードの範囲指定も可能です。

新しいコンパイラオプション

-dce [std|full|no]
デッドコード削除の強さを(no,std,full)から選択します。
-swf-lib-extern < file >
externのSWFファイルを指定する
-version
バージョンの確認
–help-defines
有効なコンパイラ定義(-D)のリストを表示
–help-metas
コンパイル時に使用されるメタデータを表示

置き換えられたもの

–dead-code-eliminationが-dce fullに
–js-modernがデフォルトに
これにより、JavaScript全体が(function(){“use strict”; })()に囲まれます。コンパイラオプション-D js-classicでこれを回避できます。さらに詳しくは、http://haxe.org/doc/js/modern
extendsとimplementsを同時に指定するときの書き方が変わりました。
haxe2:

... extends haxe.Template, implements InterfaceSyntax2 { }

haxe3:

... extends haxe.Template implements InterfaceSyntax2 { }
プロパティのgetter,setterの書き方が変わりました
詳しくは、http://haxe.org/manual/haxe3/migration#property-accessors

無くなったもの、出来なくなったもの

jQueryライブラリの自動的な埋め込み
Haxe2以前では、標準ライブラリに含まれるJQueryのライブラリを使った場合に出力されるjsにjQueryのコードが埋め込まれていました。
Haxe3では、このjQueryの埋め込みが無くなりました。
対策: コンパイル時に-D embed-jsのオプションを指定する(2013/07/15加筆 コメントで教えてもらいました) または、jQueryのjsファイルをダウンロードしてきてHaxeのjsより前に埋め込む。
Array < Dynamic > に対する型推論
対策: 明示的に型指定を行う
inline変数を参照型の値で初期化
対策: inline関数を使う
Int32
対策: Intを使う
String.format()
対策: ”(シングルクオテーション)を使う。
callback
対策: bind関数を使う
プロパティでget, setを両方指定した際の、デフォルト変数
対策: @:isVarを明示的に指定する
Hash, IntHashクラス
対策: Mapを使う
haxe.Publicインターフェース
対策: @:publicメタデータを使う
haxe.rtti.Genericインターフェース
対策: @:genericメタデータを使う
コンパイラオプション -as3-native

Haxe3での主な変更点は以上のとおりです!あれが足りない、ここが間違ってるなどあればコメントしていただけると嬉しいです。

2013/05/31_訂正:
@:noCompleteって書いてありましたが、正しくは@:noCompletionでした。
3.0RC出たあたりでwikiが変更されてたのを見逃してました。
http://haxe.org/manual/tips_and_tricks?version=15566

2013/08/21_追記:

C#,Javaの正式サポートって書いたんですが、よくよくいろんなところ見返してみたら、betaから、stableになりましたよっていう正式な発表が見つかれませんでした…

2.09リリース時点では、Haxe3.0でC#,Javaをサポートする予定(http://www.silexlabs.org/133720/the-blog/haxe-3-and-4-plans-for-world-domination/)で、2.10リリース時http://haxe.org/doc/release/2.10にも”their final implementation in Haxe 3.0″って書いてあったので、3.0でC#,Javaが正式サポートだと思ってたのですが、3.0公開後の発表ではそこらへんに触れてるものがなかったです

逆に3.0のJava,C#周りの記述でまだbetaだよ記述も無くて、あたらしいgithubレポジトリにはJavaやC#のターゲットのところにもbetaと書かれてないので、このままこっそりbetaの文字が消えてくような気もします。

とはいえ、もしかしたら、次のリリース以降でbetaじゃなくなりましたよって発表があるかもしれません。

ここらへんちゃんと知ってる人がいたら教えてほしいです。