FIREFOX HACKS' (4)
日課の散歩をしていたら、たんぼのあぜ道を、トコトコと散歩してるカモに出くわしました。 ヨウご同輩、あんた達も散歩ですかい? じっと見ていたら、田んぼの中へと移動してゆきました。 今度は、食事の時間なのでしょうか? しきりに水の中に首をつっこみ、何やらやっていましたよ。
もう大分前に終わっちゃったけど、この地は「ダッシュ村」になりうる場所だなあ。せいぜい、 たんぼを掻き回し、虫を食べて、糞をばらまいて、大きくなっておくれ。頑張れ、カモ夫婦。
コードを読む前に
前回は、javascript のコード見始めた。けれども、難航が予想されるので、先にコードが どんな生成物を出しているか見ておく事にする。久しぶりに、完全なUTF-8環境である Debian 上に移行し、変な事に気を回さなくても良いようにする。
FreeBSDの環境をそのまま持ってきたけど、やはり Jsonのデータをparseするとエラーになって しまった。生のJSONデータは、最密の一本糞であるから始末が悪い。何とか見やすくならないか? 10秒考えて、いい事を思いついた。ちょいとJSONデータを加工して、ruby風味にしちゃうのだ。
sakae@debian:~/json$ sed -e 's/:/=>/g' -e 's/null/nil/g' Bookmarks_2009-06-09.json >forruby
rubyでは、Hashのキーと値の区切りは => でしょ。nullの変わりは nil にしとくか。 こうして出来た、ruby用のデータを、下記スクリプトに食わせて、整形しちゃいます。(rubyでも、 read,eval,print ですよ。嗚呼、禁断のeval使っちゃった!)
require 'pp'
str = File.read('forruby')
h = eval( str )
PP.pp h
スクリプトの結果は、美容整形の高須じゃなく output とか適当なファイルにリダイレクトします。 以下は、整形結果の冒頭と最後の部分です。
{"title"=>"",
"id"=>1,
"dateAdded"=>1244456288889743,
"lastModified"=>1244456310537030,
"type"=>"text/x-moz-place-container",
"root"=>"placesRoot",
"children"=>
[{"title"=>"Bookmarks Menu",
"id"=>2,
"parent"=>1,
"dateAdded"=>1244456288891942,
"lastModified"=>1244505218280884,
"type"=>"text/x-moz-place-container",
"root"=>"bookmarksMenuFolder",
"children"=>
[{"title"=>"Windows",
.................
{"index"=>2,
"title"=>"Tags",
"id"=>4,
"parent"=>1,
"dateAdded"=>1244456288894095,
"lastModified"=>1244456288898880,
"type"=>"text/x-moz-place-container",
"root"=>"tagsFolder",
"children"=>[]},
{"index"=>3,
"title"=>"Unsorted Bookmarks",
"id"=>5,
"parent"=>1,
"dateAdded"=>1244456288895191,
"lastModified"=>1244456288898429,
"type"=>"text/x-moz-place-container",
"root"=>"unfiledBookmarksFolder",
"children"=>[]}]}
木が生えてます。大きな木です。(葉は273枚ありました)
sakae@debian:~/json$ grep root output
"root"=>"placesRoot",
"root"=>"bookmarksMenuFolder",
"root"=>"toolbarFolder",
"root"=>"tagsFolder",
"root"=>"unfiledBookmarksFolder",
sakae@debian:~/json$ grep parent output
"parent"=>1,
"parent"=>2,
"parent"=>61,
"parent"=>61,
..................
"parent"=>1,
"parent"=>3,
"parent"=>3,
"parent"=>3,
"parent"=>1,
"parent"=>1,
index及びid番号は、1がオリジンになってます。(js流?)
それにしても、Jsonのパーサーが2種類共エラーになる中、上記のような簡単(いんちき)な 変換で、ruby上に展開出来ちゃうって、どういう事?
utils.js を嫁
utilis.jsをemacsで開いてみたのですが、C++モードになっていました。jsモードって、無い んでしょうか? それはさておき、キーワードに従って、色がつくのは有難いのですが、途中から 文字列扱いの色に化けてしまいます。その部分を良く見たら、" のバランスが崩れていて、 次の行も文字列と思っているようです。ちょいと気持ちが悪いので、応急処置しました。
var escJSONStringRegExp = /(["\\])/g; // For emacs "
もっと、インテリジェントにしてくださいよ。> rms
restoreBookmarksFromJSONString:
function PU_restoreBookmarksFromJSONString(aString, aReplace, aExcludeItems) \
{
// convert string to JSON
var nodes = this.unwrapNodes(aString, this.TYPE_X_MOZ_PLACE_CONTAINER);
まず、nodesを取り出している。下記のように、[] で、包んでいるので、配列になって 返ってくる。
unwrapNodes: function PU_unwrapNodes(blob, type) {
// We split on "\n" because the transferable system converts "\r\n" to "\n\
"
var nodes = [];
switch(type) {
case this.TYPE_X_MOZ_PLACE:
case this.TYPE_X_MOZ_PLACE_SEPARATOR:
case this.TYPE_X_MOZ_PLACE_CONTAINER:
var JSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
nodes = JSON.decode("[" + blob + "]");
break;
restoreBookmarksFromJSONString の続きを読んで行くと、確かに木の処理をしてるし、先のデータ 中に出てきたキーワード等も参照されているので、調べている場所としては間違いなさそうだ。 そうすると、後は JSON.decode が、どう定義されてるか見ればいいんだな。
[sakae@fb ~/mozilla]$ find . -type f | xargs grep JSON.decode
./toolkit/components/places/src/utils.js: nodes = JSON.decode("[" + blob + "]");
./dom/src/json/test/unit/test_long_input.js:var z = nativeJSON.decode(y);
./dom/src/json/test/unit/test_decode.js: var x = nativeJSON.decode("{}");
.....
./dom/src/json/test/unit/test_decode.js: var x = nativeJSON.decodeFromStream(istream, istream.available());
どうも、JSON.decode を定義してる所は見つからない。悔し紛れに、test_decode.js(名前と場所から 多分、試験機だろうけど)をちょいと覗いてみます。
// nesting
x = nativeJSON.decode('{"foo":[{}]}');
do_check_eq(x.foo.constructor, Array);
do_check_eq(x.foo.length, 1);
do_check_eq(typeof x.foo[0], "object");
x = nativeJSON.decode('{"foo":[{"foo":[{"foo":{}}]}]}');
do_check_eq(x.foo[0].foo[0].foo.constructor, Object);
x = nativeJSON.decode('{"foo":[{"foo":[{"foo":[]}]}]}');
do_check_eq(x.foo[0].foo[0].foo.constructor, Array);
// strings
x = nativeJSON.decode('{"foo":"bar"}');
do_check_eq(x.foo, "bar");
x = nativeJSON.decode('["foo", "bar", "baz"]');
do_check_eq(x[0], "foo");
do_check_eq(x[1], "bar");
do_check_eq(x[2], "baz");
こんなのがずっと続いているだけでした。本当の JSON.decodeは何処に? どなたか、ここ見ろワンワン がありましたら、教えてください。なお、探っていたソースは、 firefox-3.0.10-source.tar.bz2 です。宜しくお願い致します。