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 です。宜しくお願い致します。