2007年 12月 14日

gerry++

2007年 12月 12日

JavaScript で Blosxom, Rhino

http://svn.coderepos.org/share/lang/javascript/blosxom.rhino/

Java との連動が結構たのしい。Java に足りない部分とかめんどうくさい部分と、JS にないシステムの部分とかをうまくくみあわせられてたのしい。

Java がよくわかんなくて文字化けしていたんだけど、結局 js.jar を叩くときの java コマンドに -Dfile.encoding=UTF-8 いれてうまくいった。ただこれって、プログラム側から設定しても反映されない? っぽくてよくわからない……

本体は完全に Rhino に依存してるけど、テンプレートエンジンは依存せずに書いてある

JS のテンプレートエンジンなんて腐るほどあるけど、自分で書いてみるのはやっぱ面白い。今回は new Function("stash", templatecode") みたいにして、ハッシュをわたすとテンプレートをプロセスする関数を動的に生成してみてる (toSource すればコンパイルされた結果をキャッシュできる)。new Function による eval はなんかなんともいえない楽しさがあるなぁと思った。

JS 1.6 相当の関数 (filter とか) ってほぼ必須だよなぁと思った……ないと書けない。

toSource と uneval の出力からわかる Object と Primitive

ためしてみるとすぐわかる違い。前提として、JavaScript では「全てオブジェクトというわけではない」ことを覚えておく必要があります (Ruby との違い)。

uneval("foo");
//=> "\"foo\""

"foo".toSource();
//=>  "(new String(\"foo\"))"

なぜこのような違いが生まれるか、というと 11.2.1 プロパティアクセス演算子 (Property Accessors) にある

生成規則 MemberExpression : MemberExpression [ Expression ] は次のように評価される:

  1. MemberExpression を評価。
  2. GetValue(Result(1)) を呼出す。
  3. Expression を評価。
  4. GetValue(Result(3)) を呼出す。
  5. ToObject(Result(2)) を呼出す。
  6. ToString(Result(4)) を呼出す。
  7. 基準オブジェクトが Result(5) でプロパティ名が Result(6) である Reference 型の値を返す。

の ToObject(Result(2)) がキモです。

JavaScript において

"foobar"

typeof "foobar" //=> "string"

は、typeof すればわかるように Primitive な String 型であって、String オブジェクトのインスタンス (Object 型) ではありません。プロパティアクセス演算子が使われると、そのつど String オブジェクトへ変換されます。

これは以下のようにすればすぐわかります。

String.prototype.returnThis = function () { return this };
typeof "foobar".returnThis(); //=> "object"

"foobar".returnThis() === "foobar".returnThis(); //=> false

レシーバは "foobar" にみえますが、上の結果と違っています。これはプロパティアクセス演算子の作用で ToObject された結果が this として渡されているからです。(ToObject は処理系の内部関数なので JS から直接はよべません)

ここでなんとなく気付くと思いますが、this は Object 型以外の型には絶対になりません。this を明示して渡せる call や apply でさえ this に対しては ToObject で変換がかかります。

そうなると、Object に変換されるまえの、Primitive な値がほしいときに (そんなケースあんまりありませんが)、ちょっと困るので、そういうときに valueOf() をつかいます。valueOf() って説明だけ読みとなにがしたいのがさっぱりわかりませんが、こいつを使ってやることで、本来のレシーバ (のようにみえる値) をとることができます。

"foobar".valueOf() //=> "foobar"

この valueOf() はどんなオブジェクトにも存在するので安心して本来のレシーバを取得することができます。(Primitive 値のラッパオブジェクトでは Primitive 値になるし、そうでなければ単に this をかえすだけです)

valueOf には Date オブジェクトみたいに this 以外をかえすのもあります。

JavaScript の型

前後しますが JavaScript には6個の型があります (処理系内部的/説明的には9個)。

  1. Undefined / undefined
  2. Null / null
  3. Boolean / true, false
  4. Number / 10, 0xff
  5. String / "foo", "fumino san love"
  6. Object / {foo: 123, bar: 456}

Object 型以外は Primitive であり、そう考えると Primitive vs Object の構造が想像できると思います。(リテラル undefined や null, 1, 2, "foo" とかは全部この型に対応しています) JavaScript における「オブジェクト」は Object 型の値のことで、Object 型以外は「プロパティ」や「メソッド」を持ったりはしていません。

プロパティアクセス演算子は Object 型へ必ず変換しますが、そのとき使われる ToObject は、undefined と null のときに TypeError をなげます。(この変換のおかげで Primitive 値の多くはオブジェクトのように扱うことができます)

割とよくみるであろう

TypeError: null has no properties
TypeError: undefined has no properties

は、この ToObject への変換時におきているものです (殆どないし全部)。もし JavaScript でも Ruby と同じように「全てがオブジェクト」であるならば、上のようなエラーは絶対に起きないはず (オブジェクトであれば no properties はありえない) ですし、Object に定義されているメソッドが null や undefined に対しても使えるはずです。

null.toString();
undefined.valueOf();

実行しなくてもわかるようにこのコードは TypeError がでます。JavaScript では「全てがオブジェクトというわけではない」ことは、この TypeError の背中が物語っています。

Tree Style Tab いい!

https://addons.mozilla.org/en-US/firefox/addon/5890 (SandBox にはいってる)

そろそろ Fx3 で縦おきタブデキナイカナーとおもってさまよってたら Tree Style Tab でできた……piroさん++

Mac のテーマだとタブの高さがちょっとたりなくてセレクトしたときに outline がはみだしてしまうので、Stylish で

@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);

.tabbrowser-tab {
    height: 2.2em !important;
}

.tabbrowser-tab label {
    font-size: 90% !important;
}

こんなん書いた。

なんか Opera と同じようなレイアウトにしたら (Opera は左にタブ縦置きにしてる) Fx がはやくなったように感じるプラセボ

それにしてもツリーが思ったより便利><

>

Windows 再インストール

たいして使ってないのに再インストール…… Windows Update でエラーでて (なんか証明書関係のエラーで、対策もひとおりしてみたんだけどだめだった。)

http://subtech.g.hatena.ne.jp/cho45/20070927/1190891651

  • Chipset Driver Windows 2000 用のやつ (from SC440 付属CD)
  • reboot
  • イーサネットコントローラ (ドライバの更新で CD を検索させる)
  • reboot
  • nVidia GeForce 6 系のドライバをインストール (via Internet)
  • reboot
  • WPCRSET 自動起動 ( Bus=0 Device=28 Function=0 Register=05h Data=00h )
  • Windows Update (再起動しまくり)
  • Avast インストール
  • US Keyboard http://subtech.g.hatena.ne.jp/cho45/20070928/1190965320
  • Firefox 3b1
  • Lhaplus
  • mayu
  • SKKIME http://subtech.g.hatena.ne.jp/cho45/20070929/1191020138
  • ~/fonts/* を %fonts% へコピー
  • foobar2000
    • Columns UI
    • ~/foobar.fcs からインポート
    • Last.fm インストール
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters]
"LayerDriver JPN"="KBD101.DLL"
"OverrideKeyboardIdentifier"="PCAT_101KEY"
"OverrideKeyboardType"=dword:00000007
"OverrideKeyboardSubtype"=dword:00000000
"LayerDriver KOR"="KBD101A.DLL"
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,1d,00,3a,00,00,00,00,00
2007年 12月 11日

JSDeferred

そういえば、あらかじめデータは取得しておきたいけど、表示自体は遅延したい、みたいな場合 (ホバーツールチップみたいなやつ) にもめっさつかえるなぁねむい。

var d = null;

anElement.addEventListener("mouseover", function (e) {
    if (d) d.cancel();
    // http.get はおこなわれるが、少なくとも 1 秒遅延してから表示する
    d = parallel({
        wait:  wait(1),
        value: http.get("foobar")
    }).next(function (o) {
        show(e.pageX, e.pageY, o.value); // show はどっかで定義
    });
}, false);

anElement.addEventListener("mouseout", function (e) {
    if (d) d.cancel();
}, false);

これだとまだまずいけど (mouseover が発生しまくるから//http.get をキャッシュつきにラップすればスマートかも) wait(1) してからロードしにいくみたいにするより、これだと同時によみこむから待ち時間がへる (その変わりリクエストが必ずとんでサーバに負荷かかる)

2007年 12月 10日

Trac で特定のコミッタの timeline フィード

http://mk-colors.org/scrap/2007/12/075208 みたいにあるとおり標準でそのまんまなのはできないっぽい。

けど http://dev.ariel-networks.com/column/tech/tracreport-tips/ よんでて、あーそっかーとおもったので report つかってフィード生成してみた。

SELECT
    "../changeset/" || rev AS ticket,
    rev || ": " || message AS summary,
    time AS _changetime,
    time AS created,
    author AS _reporter,
    message AS _description
    FROM revision WHERE author = '$AUTHOR' ORDER BY rev+0 DESC LIMIT 50;

こんなん。ticket がフィードのリンクにつかわれるみたい。ticket/#{ticket} にリンクされるので相対パスつかって changeset にしてる。詳細は TracReports にいろいろ書いてあった。

2007年 12月 09日

  • よりよい Ruby 用のドキュメント記法
    • doctest
  • よりよい JavaScript 用のドキュメント記法
    • ソースコードとの分離
    • doctest
2007年 12月 08日

Deferred チェインのときの setTimeout

http://coderepos.org/share/browser/lang/javascript/jsdeferred/trunk/jsdeferred.js?rev=2761#L119

の setTimeout について、スタックを消費するからこうしている、と書いたのは、next の問題で無駄な Deferred を生成していたせい ( http://subtech.g.hatena.ne.jp/cho45/20071202/1196571302 ) で、Stack over flow がでたことがあったからなんだけど、next の問題は解決したので、あらためて必要かどうか考えたらいらない気がした。

でもって http://coderepos.org/share/changeset/2817 はずしてみた。Safari はスタックサイズがかなりちっちゃくて、600?くらいの再帰でオーバーフローするからテストでは loop(1000 を実行してちゃんと戻ってくるかをテストしてる (loop は内部で next と call よんでる)。

この修正で、チェイン間ではブラウザへ処理がもどらなくなる。もどしたいなら wait(0) を return すればもどせる。