cfx to jpm #3

wasavi も 0.6.580 から jpm でビルドするようにした。ただこれらのツールは、ビルド時だけではなく実行時にも影響を及ぼす。大昔は Add on SDK のライブラリは個々の拡張に同梱されていたが(このため wasavi でも Firefox 版だけやたらサイズがでかくなるという問題がかつてあった)最近は SDK のライブラリは Firefox 自身が保持するようになっている。困ったことにこのライブラリが、cfx でビルドされたかあるいは jpm かで微妙に動作を変える。

たとえば cfx の [cci]require()[/cci] に比べて jpm のそれはより commonjs に準拠しているようになっていて、cfx では基準のディレクトリが常に lib なのだが(正確には、エントリポイントスクリプトの dirname かもしれない。未確認)、jpm では require() を実行したソースが位置するパスが基準になるのである。つまり lib/foo とか lib/bar とかだったりと可変なのだ。

これで何が困るのかといえば、wasavi や akahukuplus はソースの共通化のために require() の polyfill を定義しているのだが、ある関数を呼び出した際にその呼び出し元のソースファイルのパスを得るという標準的な方法がないことだ。

標準的な方法がないということは、標準的ではない方法を使わざるを得ないということで、具体的には [cci](new Error).stack[/cci] が返す文字列を取得して解析するしかない。しかしこれは非常に脆弱で、各ブラウザベンダがこのプロパティが返す文字列の内容をちょっとでも変えたら即破綻する。文字列ではなく、もっと構造化されたオブジェクトでスタックフレーム情報を返してくれればもうちょっとましなのだけど…。

さて、cfx から jpm への移行で最後に残ったのは赤福プラスだ。これも移行してみた。また、最近は絵文字が unicode のコードポイントにやたら導入されている状況を鑑みたり鑑みなかったりしつつ、コメント中の絵文字は twitter のそれと同様の画像で置き換えるようにしてみた。

akahukuplus-emoji

wasavi/0.6.580 released

リリースした。

Chrome: https://chrome.google.com/webstore/detail/wasavi/dgogifpkoilgiofhhhodbodcfgomelhe

Opera: https://addons.opera.com/ja/extensions/details/wasavi/

Firefox: https://github.com/akahuku/wasavi/raw/master/dist/wasavi.xpi

* * *

w/W/b/B コマンドがある。これらは vi 内の独自の文字の分類に従ってカーソルを移動させる。これ、Unicode における単語境界の仕様に準拠してもいいんじゃないかなあという気になりつつある。

cfx to jpm #2

などといいつつ、jpm の動作をいろいろ見ている。

cfx と同様、[cci]jpm xpi[/cci] とすることで xpi を生成することができる。ただし、[cci]–pkgdir[/cci] オプションや [cci]–update-link[/cci] オプションがどういう訳か削除されている。前者は、xpi をアーカイブする際のベースディレクトリを指定する。これがないということになっても、単に [cci]cd && jpm xpi[/cci] などとすればよいのでそれほど問題ではない。しかし後者が問題だ。

[cci]cfx xpi[/cci] においては以下のオプションが有効で:

  • –update-link: 拡張を自動更新する際の最新の xpi ファイルの場所を指定する。このオプションを指定すると、cfx は update.rdf を生成する
  • –update-url: 拡張を自動更新する際の更新情報を示す RDF ファイルの場所を指定する。この情報は xpi 内の install.rdf に埋め込まれる

この違いはとてもわかりにくい。前者は [cci]–location-of-latest-xpi[/cci]、後者は [cci]–location-of-update-manifest-rdf[/cci] などと脳内で変換する必要がある。

で。jpm では前述の通り [cci]–update-link[/cci] オプションが削除されている。従って、jpm は update.rdf を一切生成しない。そのため jpm ベースの開発サイクルでは update.rdf を自前で生成しなければならなくなっている。なぜこのような仕様変更が行われたのかはよく分からないが、自前で update.rdf を制御する場面というのは、つまり拡張を AMO 以外の場所で配布する状況ということだ。AMO に載せるのなら気にする必要はない。つまり update.rdf の生成機能が取り除かれているのは野良拡張の配布をやめろという暗黙的な圧力なのかもしれない。

この手の悪意に満ちた嫌がらせはこれだけではない。拡張に自前で署名を施すためのツールとして McCoy というものがあるのだが、これもあからさまに使いにくい。そして、「使いにくいけど将来的には直すので期待してね!」なんつったりしちゃったりしてるのだが、もちろん今現在になっても使いやすくなってはいない。

一方で Mozilla は

インストールを Mozilla の配布チャンネルに限定することは余計な制約であると私たちは考えます

とかなんとか言っている。なーんか、言ってることとやってることが全然違いますね。こんなことばかりやってると、加速度的に信用を失うと思うんですけど。

それはさておき、update.rdf のテンプレートから任意の箇所を package.json の値で置換するような適当な javascript のスクリプトを書いた。javascript で書いたのは、jpm 自体が node.js で動かすスクリプトなのでそれに合わせて。

テンプレートとしてこういうものを用意して






  • {{version}}


    {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
    {{engines.firefox.minVersion}}
    {{engines.firefox.maxVersion}}
    https://example.org/example.xpi






  • package.json とテンプレートを両方読んで、プレースホルダ({{〜}} の部分)を package.json の該当する値で埋める。package.json に値が存在しなければ、プレースホルダを含む要素自体を空に置き換えるようにした。

    とりあえず webliopane fx40fixed を jpm でビルドするようにしてみた。

    cfx to jpm

    Firefox の拡張を Add on SDK ベースで作る際、cfx というツールを使うことになる。これは python で書かれたスクリプトだ。このツールが、拡張の基本的なディレクトリ構成を作成したり、テストしたり、xpi をビルドするといった開発のサイクルをサポートしてくれる。

    しかし、Mozilla 的にはこの cfx は既に deprecated である。この後継は jpm というツールになっている。jpm とは Node.js で動かす javascript のスクリプトだ。たぶん JetPackManager ということなのだろう。じゃあ cfx は何の略なんだろ。CuddleFisheXtension?

    ところでなぜ cfx がダメで、jpm に移行しなければならないかという理由はよく分からない。jpm だと npm ベースなので更新が簡単だとか、activate/deactivate する必要がないとか細々した理由はあるようだけど、しかしそれらは別に技術的に cfx で実現不可能なものとは思えない。技術的な理由じゃないとすると、Mozilla 内の政治的な理由なのかもしれない。

    ともあれ基本的には両者とも jetpack の仕組みに準じたツールであるので、移行したとしてもそれほど開発サイクルに変更はない。両者の違いはせいぜい 1 ページに収まる程度のものだ。

    しかしながらじゃあすぐ移行しようという気にはなぜかならない。どういうわけか jpm で作った拡張は AMO に載せてもらえないとかいう期間が長かったからかもしれない(長かったというか、今もそうなのだと思う)。この措置は本当に意味が分からないが、企業や団体や組織の行動のうち、外部から見て何の意味があるのかよく分からないものはやはり政治的な理由が根底にあったりするものなので、まあそういうことなんだろう。

    ここまでつらつらと書いてきて、なんだか Mozilla という団体がまともなブラウザも作れず、シェアも右肩下がりなくせして、内部の政治闘争だけは一生懸命なろくでもない奴らに思えてきたが、たぶん、きっと、おそらく、そんなことはないのです。

    a critical bug

    wasavi をリリースしたばかりなのだが、Chrome 上のとある条件下でフリーズするという致命的なバグを直したので今月末辺りにまたリリースするかもしれない。フリーズと言ってもプロセッサのリソースを食いつぶすとかそういう類ではない。

    これは 2 つのあまり関係なさそうな事柄が関係している。

    まず、wasavi が保持するバッファは、各行の末尾に [cci]\n[/cci] の内容を持つテキストノードを保持している。これは、編集後に textarea に代入するために wasavi のバッファから単一の文字列を得る際、単にバッファの div 要素の textContent プロパティを参照するだけで済むようにするためだ。

    次に、wasavi の input モードは div 要素の contentEditable 属性をオンにすることで実現している。

    この 2 つの事柄が Chrome 上で絡みあうと不思議なことが起きる。IME を通した仮入力が最終的に空文字になり、かつカーソル行の div 要素の内容も空になった場合(たとえば空行で仮入力を開始したが、結局全部 backspace で消して仮入力を抜けた時…など)、前述の改行要素が Chrome によって勝手に削除されてしまうようなのだ。

    wasavi のあらゆる編集機能はこの改行要素が存在することを前提としているので、ないとなるとあらゆるところでエラーが発生して満足に動かなくなる。

    weblioPane fixed

    Firefox の拡張に weblioPane というのがあって便利に使っていたのだが、最近になって(おそらく Firefox 40 のリリース以降)使用できなくなって困っていた。しかしなかなか新しいバージョンに更新される気配もないので勝手に直してみた。

    https://github.com/akahuku/webliopane-fx40fixed

    この拡張が参照している weblio の API についてのドキュメントが欲しいのだけど、見つからなかった。

    WebExtensions…?

    何やら物議をかもしている例の件。自作の拡張にはどういう影響があるのか考えてみる。

    Firefox 版の wasavi や赤福プラスは Addon SDK ベースで作っているのだが、SDK の提供するモジュールをそのまま使っているのではない。抽象的なラッパーを挟んでいる。ラッパーが Chrome と Presto Opera と Firefox の差異を吸収して、アプリケーション内にはブラウザ固有のコードはほとんどない。

    したがって、仮に WebExension ベースに移行するとしても、変更する必要があるのは Firefox 版のラッパーだけだ。そもそも WebExtensions が Chrome の拡張ベースだし、ラッパーも Chrome の拡張をベースにしたインターフェースにしてあるので、変更によりむしろコード量は少なくなるかもしれない。

    一方で、SDK ベースのままにするという選択肢もある。ただ、SDK 自体は廃止は免れるということなのだけれど、それは [cci]require(‘chrome’)[/cci] していないものに限られるという。

    ラッパーはもちろんこれを使っている。

    • XMLHttpRequest – SDK が提供するそれは upload プロパティをサポートしていない
    • FormData – SDK はこれを提供していない
    • Blob – SDK はこれを提供していない

    つまるところ、なぜ [cci]require(‘chrome’)[/cci] を使っているのかといえば、SDK が提供する API が全般的に中途半端だからなのだ。それなのに Cu/Ci の使用を今さら咎められても困るのだが、この辺を何とかしないといけない。

    width of character

    wasavi のステータス行にはカーソル位置の桁・行位置を表示しているのだけど、その桁位置とはなんぞやというと、これはカーソル位置の内部的な行頭からのオフセットをそのまま指しているわけではない。つまり内部的な桁位置と表示上の桁位置は違う。

    まず内部で charWidth という変数があり、これは大元の textarea のフォント関連のスタイリングに基づく、[cci]0[/cci] の文字幅だ。技術的には span 要素に [cci]0[/cci] を入れた際の offsetWidth の値だ。

    それを踏まえて表示上の桁位置を算出するには、span 要素に行頭からカーソルの物理位置までの文字列を入れ、その offsetWidth を出し、charWidth で割る。表示しているフォントが固定幅であればこれで特に問題ない。

    ところが困ったことに、固定幅フォントでさえ、文字列全体の offsetWidth が charWidth の整数倍にならないことが多々あるのであった。つまりこれは、cssom では offsetWidth の型は long だ。しかし実際には、それは小数で保持されているのが原因なんだと思う。そういうわけで正しい表示上の桁位置が得られない。

    うーんどうしよう。

     * * *

    charWidth を算出する際に、100 個並べた [cci]0[/cci] の offsetWidth を 100 で割るようにした。つまり charWidth の精度を上げた。

    wasavi/0.6.559 released

    リリースした。

    Chrome: https://chrome.google.com/webstore/detail/wasavi/dgogifpkoilgiofhhhodbodcfgomelhe

    Opera: https://addons.opera.com/ja/extensions/details/wasavi/

    Firefox 版は AMO へのアップを諦めた。その代わり github 上の開発版は署名済みになっているので Firefox41+ でもインストール時に警告されることはない: https://github.com/akahuku/wasavi/raw/master/dist/wasavi.xpi

     * * *

    wasavi が各ブラウザ上でアップグレードされた時、http://appsweets.net/wasavi/ を開くようになっている。ここで実質的なユーザー数をカウントすることができるので、そうなっている。先頭のテキスト “wasavi は Chrome、Opera、Firefox 用のエクステンションです。” の文句のそれぞれのブラウザ名にカーソルを合わせるとユーザー数を表示する。Opera に関しては Presto Opera と Blink Opera を分けてカウントする。

    現在のところ、

    • Chrome: 1615
    • Presto Opera: 0
    • Blink Opera: 57
    • Firefox: 29

    とのこと。Chrome では Web Store での表示が 3500 人とかそんな感じなので、まあ数日でその辺りに達するのだと思う。それにしても偏りがすごい。Opera に関してはブラウザ自体のシェア比からこんなもんなのかなという気はするが、Firefox 版ユーザーが妙に少ない。

    Presto Opera でのユーザーが 0 というのはとてもいいことだ。これはもはや Presto Opera を考慮して開発する必要が全くないということだ。

    Everything becomes Blink

    Microsoft Edge が Chrome と Firefox の両方の拡張をサポートするかもしれない? という噂について、そんなことができるのかなと訝しんだ記事を以前書いた。

    実際のところは、こういうことのようだ。
    http://rockridge.hatenablog.com/entry/2015/08/16/234729
    https://wiki.mozilla.org/WebExtensions

    なるほど。つまり Firefox 側で Blink の拡張のインターフェース互換のフレームワークを構築すると…。しかしそうすると Addon SDK の存在意義が根底から揺らいでしまう気が。それから、Mozilla 自身が XUL を捨てたがっているというもある。しかし、Firefox 本体や既存の拡張のシステムって相当 XUL と絡み合っているわけで、そちらの存在意義も揺らいでくるような。

    もしかしたら、レンダリングエンジンを servo にスイッチするタイミングでそれらも一気にグレートリセットされるのかもしれない。いやー Firefox 向けに拡張を書く人は大変だなー(他人事)。