プロジェクト起動処理

発端はここしばらく取り組んでいるワークショップコンテンツ作成の作業でした。
いくつかあるカリキュラムのプロジェクトファイルを順次ダブルクリックしてNihongo7で開いて作業していると、特定のファイルでエラーになり、プロジェクトを開けないことがわかりました。取り扱っているファイルにはNihongo4aなど古いバージョンで作成したものが含まれているため、最初はそういう互換性問題だと思っていました。(そのように関係者にメールしてしまった。。。)しかし、少し調べてみると不思議なことがわかりました。

  • 元プロジェクト作成元のSqueakのバージョンは関係なさそうである。
  • ダブルクリックでは開けないが、起動したSqueakにドロップインするなら、ちゃんと開ける
  • ファイル名をASCII文字だけに変更するとうまく開ける。しかし日本語を使っていても開けるものと開けないものがある。
  • 参考までと思い、Squeakland05版でテストしたところ、日本語が使われているとまったく開けない。(Nihongo7で開けるものであっても)

それで調べ始めたところ、ずぶずぶと泥沼にはまってしまったのでした。

コマンドラインからのプロジェクト起動機能

プラグイン(Nihongo7, 本家Squeakland版)をインストールすると、ファイルタイプ *.pr に対して、アプリケーション(squeak.exe)起動のコマンドが登録され、プロジェクトファイルをダブルクリックすれば、Squeakが起動されてプロジェクトが開かれるようになります。Windowsの場合レジストリの以下の箇所に登録されています。
(Nihongo7の場合)

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\pr_auto_file\shell\open\command]
(デフォルト値)"C:\Program Files\Squeak\SqueakNihongo7\Squeak.exe" "C:\Program Files\Squeak\SqueakNihongo7\SqueakPlugin.image" "%1"

開こうとしている*.prファイル名がコマンドライン引数に渡されるわけです。

プロジェクト起動処理の流れ

  • ProjectLauncher>>startupAfterLogin あたりから始まります。コマンドラインに渡されたプロジェクトファイル名を以下の箇所
scriptName ←(SmalltalkImage current getSystemAttribute: 2) ifNil:[''].

で受け取りますが、これはSqueakの内部表現(unicode) ではなくOSの文字コードのまま渡されています。

  • 同じメソッドの少し後で、プロジェクトファイルからソースコードを読む処理が実行されます。
loader ←CodeLoader new.
loader loadSourceFiles: (Array with: scriptName).

どうやら、エラーになるのはこの中でのロード処理がうまくいっていないためのようです。

ソースコードのロード要求

主要な処理は、CodeLoader>>createRequestFor:name:in: の中で行われています。

  • HTTPLoader (class)>>httpRequestClass で、「リソースダウンロード要求」を表現する適切なクラスを選択する。ブラウザプラグインとして起動されていなければ、これはHTTPDownloadRequestである。
  • HTTPDownloadRequest>>for:in: 中で、 HTTPDownloadRequest>>httpEncodeSafelyにより、ロードすべきプロジェクトファイル名を処理し、Asciiで表現できない文字については%##%## のような数値実体参照形式に変換して覚えておく。ここでの表現は、"file:パス名"形式のURLです。

ソースコードのロードの実処理

真の読み込み処理は、HTTPDownloadRequest>>startRetrievalの中で行われています。

  • "file:パス名"形式の文字列を String>>asUrl で FileUrlに変換する。
  • FileUrl>>retrieveContents がロード処理の核です。FileUrl>>pathForFile で、"file:パス名" をまた元のパス名に戻します。そして、そのファイルを普通に FileStreamで開いて読み込もうとします。

Squeakland05版での動作の問題点と、パッチの作成

以下2点の対応を行うことで、Squeakland05版では正しく日本語ファイル名のプロジェクトをダブルクリックで開けるようになりました。(関係者にパッチ送付レビュー依頼済み)

  • 最終的には、コマンドラインで指定されたファイル名が FileStreamでファイルを開く際に指定されますので、Shift-JISで渡されたファイル名は Squeakの内部表現に変換する必要があります。
  • Squeak3.8開発の際行われたMultiString→WideStringのリファクタリングの仮定で、URLのパーセントエンコード処理がまったく抜け落ちてしまっていたので、Squeakland05開発の中で encodeForHTTPWithTextEncoding:conditionBlock: などが新規に実装されました。このコードは、UTF8ベースでちゃんと数値実体参照エンコードを行うようになっています。

しかし、FileUrl>>pathForFile の奥底で呼ばれている String>>unescapePercents が古いコードのままで、UTF8ベースの数値実体参照文字列を正しく逆変換できるようになっていませんでした。これを修正。

プラグイン起動処理というのは、スプラッシュ画面の表示処理などの都合で、デバッガを使うのがとても面倒で、ここまでくるのもかなり苦労しましたが、一応動いて満足したのもつかの間、新たな難問を見つけてしまいました。

新たな問題:SuperSwiki上の日本語ファイル名

http://squeakland.jp/super など、日本で使われている SuperSwiki はオリジナルのものに蜂須賀さん他の皆さんが作成されたパッチがあてられていて、日本語ファイル名のプロジェクトも投稿することができます。そしてSqueakland.jpなどに蓄積されています。
実際にサーバー上に置かれているファイル名は、パーセントエンコードされているのですが、このコードがシフトJISになっているようなのです。
これに関係する問題と思われますが、前述のパッチをあてようがあてまいが、既にsqueakland.jpに投稿されている日本語ファイル名のプロジェクトを、Squeakland05版ブラウザプラグインは開くことができません。(いったんローカルファイルに落としたものを開くことはできます)

まだテストは行っていませんが、Squeakland05版でSuperSwikiに投稿した場合、理論どおりに実装が完了しているなら、UTF8ベースのパーセントエンコードされた名前になると思われます。

Nihongo7はどうするべきか?

Nihongo7では、数値実体参照関係の処理は、中途半端な状態で、シフトJISのコードをそのまま処理したりしています。(それが原因で、どこかでtransparentに変換できないところがあるように思われる)
最初は、Squeakland05版のパッチがうまくいったら、実体参照の処理含めてNihongo7にバックポートするつもりでした。しかしNihongo7から Squeakland.jp/super への投稿が非常に活発になっているおり、そのやりとりに影響するような修正は加えないほうがよさげに思えてきました。
最終的には、ローカルファイルのダブルクリック起動 vs Squeakland.jp接続機能 のどちらを優先するかというトレードオフ判断になるかもしれません。

こんなことにまで発展するとは思っていなかったので、疲れました。

SuperSwikiはどうするべきか?

アドホックな内容とはいえここまで使えてきたのですが、Squeakland05版がユニバーサルな国際化を実現しようとしていることには追随できていないと思われます。そろそろ次どうするかを考える時なのかもしれません。