********************************************************************** この文書は、 XTF: An eXtensible Tag Framework http://lxr.mozilla.org/seamonkey/source/content/xtf/readme.txt を nanto_vi が翻訳したものです。 ********************************************************************** XTF: An eXtensible Tag Framework ================================ XTF: 拡張可能なタグフレームワーク ================================= XTF allows you to extend Mozilla by implementing new XML elements in XPCOM modules. It is not a C++-version of XBL: XTF elements can be written in any XPCOM-compatible language. I myself tend to write most elements in JavaScript. XTF を使えば XPCOM モジュールを用いて新しい XML 要素を実装することによ り Mozilla を拡張できます。これは XBL の C++ 版ではありません。XTF 要 素はどんな XPCOM 互換の言語でも書けます。私自身ほとんどの要素を JavaScript で書くことが多いです。 XTF support needs to be explicitly switched on for Mozilla builds by specifying the configure option '--enable-xtf' (add "ac_add_options --enabl-xtf" to your .mozconfig). XTF サポートは Mozilla のビルドのために --enable-xtf コンフィギュアオ プションを指定することにより明示的にオンにさせる必要があります (あなた の .mozconfig に "ac_add_options --enable-xtf" を加えてください) 【訳注: 現在ではデフォルトで XTF がサポートされています】。 To serve a particular namespace "urn:mycompany:mynamespace" with your own XTF elements, create an XPCOM component that implements the interface nsIXTFElementFactory, and register it with the component manager under the contract id "@mozilla.org/xtf/element-factory;1?namespace=urn:mycompany:mynamespace". Whenever Mozilla encounters a tag in your namespace it will call your factory's 'createElement()' function. This function should either return a new xtf element (an object implementing 'nsIXTFElement' and some other interfaces, depending on type and required features), or 'null'. In the later case, the implementation will build a generic XML element. 特定の名前空間 "urn:mycompany:mynamespace" にあなた自身の XTF 要素を提 供するためには、nsIXTFElementFactory インターフェースを実装する XPCOM コンポーネントを作って、それをコンポーネントマネージャにコントラクト ID "@mozilla.org/xtf/element-factory;1?namespace=urn:mycompany:mynamespace" を用いて登録してください。Mozilla があなたの名前空間のタグに出会ったと きはいつでもあなたのファクトリの createElement() 関数を呼び出します。 この関数は新しい XTF 要素 (nsIXTFElement と、型と要求される機能によっ てはほかのインターフェースとを実装するオブジェクト) か null のどちらか 一方を返すべきです。後者の場合、実装は一般的な XML 要素を作るでしょう。 All interfaces relevant to XTF factory modules and XTF elements can be found in mozilla/content/xtf/public/. The implementation code itself is mainly spread over the directories mozilla/content/xtf/ and mozilla/layout/xtf/. XTF ファクトリモジュールと XTF 要素に関係のある全てのインターフェース は mozilla/content/xtf/public/ で見つけることができます。実装コード自 体は主に mozilla/content/xtf/ と mozilla/layout/xtf/ ディレクトリに分 散しています。 Binding outermost elements (document elements) ============================================== 最外部の要素 (文書要素) を結びつける ==================================== Binding of outermost elements is not (yet) supported. Depending on what you use xtf elements for, this might or might not be a problem. If you use xtf to implement a whole new language, rather than just widgets that will get used in html, xul, or svg docs, then you'll probably want to wrap up your documents in an xml element for which you provide some style (e.g. via a ua style sheet), so that things get displayed instead of pretty printed. This outermost element can be in your xtf-served namespace, as long as your xtf factory returns a failure for this element's tagname. The implementation will then generate a generic XML element for this element. 最外部の要素の結びつけは (まだ) サポートされていません。あなたが XTF 要素を何に使うかによって、これは問題になるかもしれないしならないかもし れません。もしあなたが XTF をただ HTML 、XUL 、SVG 文書で使われるだけ のウィジェットではなく、まったく新しい言語の実装に使うのなら、あなたは おそらく、それらがプリティープリント【訳注: スタイルが結び付けられてい ない XML 文書をツリー表示する機能のことか】ではなくきちんと表示される ために、あなたの文書をあなたが (例えば UA スタイルシートによって) 何ら かのスタイルを提供する XML 要素の中に包みたくなるでしょう。この最外部 の要素は、あなたの XTF ファクトリがこの要素のタグ名に対して失敗を返す 限りは、あなたの XTF が提供する名前空間の中にあってもかまいません。そ の場合、実装はこの要素のために一般的な XML 要素を生成するでしょう。 XTF and XUL =========== XTF と XUL ========== When using XTF elements in XUL documents, note that the owner document (both wrapper.ownerDocument & wrapper.elementNode.ownerDocument) will be null at the time of the onCreated() call. (For XML and SVG documents, at least wrapper.ownerDocument should be non-null.) This is unfortunate, since it is often advantageous to build the visual content tree at the time of the onCreated() call and not wait until the visual content is explicitly requested, so that attributes set on the xtf element can be mapped directly to elements in the visual content tree. It is possible to build the content tree using a different document than the ultimate target document, but this in turn leads to some subtleties with XBL-bound content - see below. XUL 文書の中で XTF 要素を使うときは、所有文書 (wrapper.ownerDocument 【訳注: 実際には wrapper (nsIXTFElementWrapper インターフェース) に ownerDocument プロパティは存在しない】と wrapper.elementNode.ownerDocument の両方) が onCreated() の呼び出しの 時点では null であるだろうことに注意してください。(XML と SVG 文書につ いては、少なくとも wrapper.ownerDocument は null でないはずです。) こ れは不幸なことです。なぜなら、ビジュアル内容が明示的に要求されるまで待 たずに、ビジュアル内容ツリーを onCreated() の呼び出しの時点で構築する ことは、XTF 要素に指定された属性をビジュアル内容ツリー内の要素に直接マ ッピングするためにはしばしば都合がいいからです。最終目標となる文書とは 異なる文書を用いて内容ツリーを構築することは可能ですが、そうすると今度 は XBL に結び付けられた内容との微妙な競合を生み出します。このことにつ いては以下を参照してください。 XTF and XBL =========== XTF と XBL ========== XTF elements generally behave well in conjunction with XBL. There are a few issues when using XBL-bound elements in an XTFVisual's visualContent that arise from the fact that XBL bindings are attached to elements at layout-time rather than content-tree contruction time: Accessing an XBL-bound element's interfaces or JS object before layout-time usually doesn't yield the expected result. E.g. a listbox won't have the members 'appendItem', 'clearSelection', etc. before layout-time, even if QI'ed for nsIDOMXULMenuListElement. Worse, if the visual content has been constructed in a different document (because the target doc wasn't available at the time of content tree construction time - see above), then the JS object obtained before layout time will be different to the one that will ultimately receive the bound implementation, i.e. even QI'ing at a later stage will fail. To work around these issues, XBL-bound content should a) either be build as late as possible (i.e. when requested by the wrapper with a call to nsIXTFVisual::GetVisualContent()) or b) if this is not a possibility (e.g. because you would like to map attributes directly into the visual content tree), all JS object references to the element should be re-resolved at the time of the first layout (listen in to DidLayout() notifications). XTF 要素は一般的に XBL とうまく連携して動きます。XTFVisual の visualContent の中で XBL に結び付けられた要素を使うときには少しばかり 問題があります。それらの問題は、XBL の結びつけは内容ツリーの構築時では なくレイアウト時に要素に付加されるという事実から起こるものです。レイア ウト時の前に XBL に結び付けられた要素のインターフェースや JS オブジェ クトにアクセスすることは、たいてい期待する結果をもたらしません。例えば、 リストボックスはレイアウト時の前には、例え nsIDOMXULMenuListElement に QI されても、appendItem や clearSelection といったメンバーを持たないで しょう。さらに悪いことに、もしビジュアル内容が異なった文書の中で構築さ れていたら (なぜなら上で述べたように対象となる文書は内容ツリーの構築時 には利用できないから) 、レイアウト時の前に取得された JS オブジェクトは 最終的に結び付けられた実装を受け取るものとは異なったものになるでしょう。 すなわち、後の段階で QI することすら失敗するのです。この問題に対処する ために、XBL に結び付けられた内容は次の a) か b) のうちどちらかを行うべ きです。a) 可能な限り遅く (すなわち、ラッパーにより nsIXTFVisual::GetVisualContent() の呼び出しが要求されたとき【訳注: JavaScript の場合は visualContent プロパティのゲッタが呼び出されたとき か】) 作成されるようにするか、または b) もしこのことが現実的でないのな らば (例えばビジュアル内容ツリーに直接属性をマッピングしたいときなど) 、 要素の JS オブジェクトへの参照は全て最初のレイアウト時 (DidLayout() の 通知に耳を傾けてください) に再度解決されるべきです。 Bugs ==== バグ ==== 1. For xtf elements written in JS (and possibly C++ as well), constructing a visual's visualContent using the same document as the visual's leads to some nasty reference cycle which prevents the wrapper, inner xtf element, anonymous content and possibly the whole document from ever getting destroyed. A workaround is to construct the visualContent in a different document (e.g. setting the document in nsXMLContentBuilder to null, or not setting the document at all, will lead to new content being build in a new temporary document). 1. JS で書かれた XTF 要素 (あるいは C++ で書かれたものも同様に) に関して、 ビジュアルと同じ文書を使ってビジュアルの visualContent を構築すること は、ラッパー、内部の XTF 要素、匿名内容、そしてあるいは文書全体までが 破棄されるのをずっと妨げる汚い循環参照を引き起こします。回避策は異なっ た文書 (例えば、nsXMLContentBuilder の中で文書を null にセットしたり、 または文書をまったくセットしないことで、新しい内容が新しい一時的な文書 の中で作成されるようになります) の中で visualContent を構築することで す。 2. XBL-bound elements behave strangely if *any* XUL content underneath them is accessed from JS too early. Example: 2. もし XBL に結び付けられた要素の下にある XUL 内容が「それがどんなもので あれ」JS からあまりにも早くアクセスされると、その要素は奇妙な振る舞い をします。 例: If the JS-implemented xtf element 'foo' accesses any xul content before it receives the 'didLayout' notification, the groupbox will not be properly build (it will not contain the label text). 'Accessing xul content' includes any operation that leads to a js wrapper being constructed for a xul element. E.g. if the xtf element listens in to parentChanged-notifications, a wrapper will be build for the notification's 'parent' parameter and groupbox construction mysteriously fails. もし JS で実装された XTF 要素 foo が、didLayout 通知を受け取る前に何ら かの XUL 内容にアクセスすると、groupbox は適切には作成されない (ラベル テキストを含まない) でしょう。「XUL 内容へのアクセス」とは、XUL 要素の ために JS ラッパーを構築させるどのような操作をも含みます。例えば、もし XTF 要素が parentChanged 通知に耳を傾けていたら、その通知の parent パ ラメータのためにラッパーが作成され、groupbox の構築は不可解にも失敗す るでしょう。 3. Some XUL interfaces can't be used via XPCOM and thus might not work as expected. E.g. menulist's nsIDOMXULSelectControlElement::insertItemAt() is supposed to return an element of type nsIDOMXULSelectControlItemElement. However, since menulist's XBL implementation of insertItemAt creates a xul element which will only be bound when the next asynchronous layout occurs, QI'ing to nsIDOMXULSelectControlItemElement fails. The result is that the method call always fails when invoked through XPCOM. A pragmatic solution would be to change the XUL interface signatures to return nsIDOMXULElement instead of nsIDOMXULSelectControlItemElement. 3. いくつかの XUL インターフェースは XPCOM から使用できないので、期待した ようには動かないかもしれません。例えば、メニューリストの nsIDOMXULSelectControlElement::insertItemAt() は nsIDOMXULSelectControlItemElement 型の要素を返すことを前提としています。 しかしながら、メニューリストの insertItemAt の XBL 実装は、次の非同期 レイアウトが起こるときのみに結び付けられる XUL 要素を作成するので、 nsIDOMXULSelectControlItemElement へ QI しても失敗します。結果として、 XPCOM を通じて呼び出されたときのメソッドの呼び出しは常に失敗します。実 用的な解決策は、nsIDOMXULSelectControlItemElement ではなく nsIDOMXULElement を返すように XUL インターフェースのシグネチャを変更す ることでしょう。 4. QI'ing a JS-implemented xtf element's wrapper from JS as in JS で実装された XTF 要素のラッパーに対して以下のように JS から QI する ことは、 element.QueryInterface(Components.interface.nsIXTFPrivate); occasionally hits the assertion ときに以下のようなアサーションを ###!!! ASSERTION: tearoff not empty in dtor: '!(GetInterface()||GetNative()||GetJSObject())', file /home/alex/devel/mozilla/js/src/xpconnect/src/xpcinlines.h, line 627 with the result that the QI succeeds (i.e. doesn't throw an exception) but the interface methods/properties aren't available on the element after the QI, even though element implements the given interface. QI が成功した (すなわち、例外が投げられなかった) という結果とともに引 き起こします。しかし、例え要素が指定されたインターフェースを実装してい ても、QI のあとにインターフェースのメソッド / プロパティは要素上で利用 できません。 This seems to happen if GC kicks in *afer* the xtf element is being queried for its interface ( resulting in the creation of an nsXTFInterfaceAggregator) but *before* the nsXTFInterfaceAggregator has been wrapped for JS use by XPCConvert::NativeData2JS(). このことは、XTF 要素がそのインターフェースを問い合わされている (nsXTFInterfaceAggregator の作成をもたらす)「後」、かつ XPCConvert::NativeData2JS() による JS の利用のために nsXTFInterfaceAggregator がラッピングされる「前」に GC が作動したら起 こると思われます。 The workaround is to a) either expose the interface via getScriptingInterfaces (in which case it will be available to JS callers automatically), or b) call QI until the interface is correctly installed, e.g.: 回避策は a) インターフェースを getScriptingInterfaces より公開する (こ の場合そのインターフェースは JS の呼び出し元にとって自動的に利用可能に なるでしょう) か、b) インターフェースが正しくインストールされるまで QI する (下の例を参照) かのどちらかです。 while (!element.inner) element.QueryInterface(Components.interface.nsIXTFPrivate); With this code the QI should succeed in the first or second iteration. このコードでは、QI は最初か 2 回目の繰り返しで成功するでしょう。 07. October 2004 Alex Fritze 翻訳: nanto_vi (TOYAMA Nao), 2005-12-07