Jsdom: MutationObserverのサポートを追加

作成日 2013年06月08日  ·  53コメント  ·  ソース: jsdom/jsdom

最も参考になるコメント

全てのコメント53件

私もこれが必要です。 誰かが私を正しい方向に向けることができれば、私はこれに対するプルリクエストに喜んで取り組みます。

@ SegFaultx64この問題に関する最初の投稿でschettino72によって提供されたURLは、「正しい方向」です。

十分に公平なことですが、これほど大規模なプロジェクトにオブザーバーをどのように登録するかさえわかりません。 そのようなものが保管されている場所はありますか?

@ SegFaultx64 jsdomのその部分を見ていないので、最善の方法が何であるかは私には

@lddubeauわかりました、ポインタをありがとう。 私は実際にMutationObserverhttps ://github.com/megawac/MutationObserver.js/blob/master/MutationObserver.jsの見栄えの良いシムを見つけました

私の唯一のアドバイスは、 https: //dom.spec.whatwg.org/を熟読し、ミューテーションレコードがキューに入れられている場所の詳細を調べることです。 まだ新しいDOM標準に移行しているため、jsdomで適切な対応物を見つけるのは難しいかもしれませんが、少なくとも仕様では、何を実装する必要があるかについてのガイダンスが提供されます。

これに関する更新はありますか?

@kresliプルリクエストを歓迎します!

どうすればいいのかわからないのですが、実験をすることにしました。 最悪の場合私は少し学びます、私が貢献できるかもしれない最良の場合。

私は現在、jsdomがどのように構成され、webidlがどのように機能しているか(そしてjsdomで使用されているか)を理解しようとしています。

MutationObserverでこのwebidlから離れることは可能でしょうか: https ://dxr.mozilla.org/mozilla-central/source/dom/webidl/MutationObserver.webidl ~~~

私はそれをもう少しよく理解しています-使用するインターフェースはここで説明されているものでなければなりません: https ://dom.spec.whatwg.org/#interface -mutationobserver-そうですか?

@henrikkorsgaard正解です! jsdomで機能させるには、いくつかのことから始める必要があります。

  • 適切なMutationObserver.idlをhttps://github.com/tmpvar/jsdom/tree/master/lib/jsdom/living/nodesに追加し
  • MutationObserver-impl.jsファイルもそのフォルダーに追加します。 ここで実際の実装作業が行われます。 たとえば、仕様には「各MutationObserverオブジェクトにはこれらの関連する概念があります」と記載されています。 それらはおそらくimpl(=実装)クラスのインスタンス変数になります。

次に、observ、disconnect、takeRecordsメソッドに加えて、コンストラクターをimplクラスに実装する必要があります。 一般的には、可能な限り仕様に従うようにしてください。 ( @Sebmaster 、コンストラクターの実行方法を説明できますか?)

この場合、CharacterDataのような単純なものとは異なり、多くの変更では、他のjsdomimplファイルを変更する必要があります。 たとえば、仕様には「各ノードには登録されたオブザーバーのリストが関連付けられています」と記載されています。 これには、Nodeimplにインスタンス変数を追加する必要があります。

仕様には、「関連する類似オリジンブラウジングコンテキストの各ユニットには、最初は設定されていないミューテーションオブザーバー複合マイクロタスクキューフラグと、最初は空のMutationObserverオブジェクトの関連リストがあります」とも記載されています。 「関連する類似した起源のブラウジングコンテキストのユニット」はjsdomでは明らかではないため、これは少し注意が必要です。 これに対して私がすることは、それらをWindowオブジェクトに配置することから始めることです。 ウィンドウオブジェクトはまだIDLを使用していないため、Window.jsにアンダースコアのプレフィックスが付いたプロパティを追加するだけです。 将来的には、複数のウィンドウで物事が追跡されるようにすることを心配するように試みることができます(つまり、iframeの世話をします)。 しかし今のところ、ウィンドウはそれらを置くのに良い場所です。

最後に、実装の多くは、「ミューテーションレコードをキューに入れる」ための適切な場所を見つけることによって処理されます。 https://dom.spec.whatwg.org/#queue -a-mutation-recordにhttps://github.com/tmpvar/jsdom/blob/master/lib/jsdom/living/attributes.jsにも、全体に「TODOミューテーションオブザーバーのもの」があります。

お役に立てば幸いです。

素晴らしい :)

繰り返しになりますが、私はwebidlやより大きなコードベースの経験はあまりありません。 私もいくつかの締め切りに少し群がっています;)

私は最善を尽くし、次の数週間にわたってそれを試してみます。 また、テストケースを1つか2つ作ってみます。

Ok、

これまでにidlとImplを作成し、それをwindow.jsに要求しました。

今、私はそれのためのテストファイルを作成しようとしています、そして私はウィンドウプレフィックスで新しいMutationObserver()を呼び出すことができます。

const window = jsdom("<html><body><div id='mutation'></div></body></html>").defaultView;

let observer = new window.MutationObserver(function(mutations){
      console.log(mutations);
});

ここでいくつかのトリックが欠けているのでしょうか、それとも、MutationObserverをグローバルオブジェクト(ウィンドウオブジェクトで呼び出さずに呼び出される)として公開する必要がある場所がありますか。

Window.jsに次の行を追加しました

const MutationObserver = require("../living/generated/MutationObserver");

このすべての質問について申し訳ありません。 テストを開始してjsdomアーキテクチャ/パターンに従うことができるように、いくつかのエントリポイントを確立しようとしています。

あ、すみません、その部分を忘れてしまいました。 https://github.com/tmpvar/jsdom/blob/28f00b30236d540df1777ca6c2c0ee9e5e19fe5b/lib/jsdom/living/index.js#L28のような行を追加する必要があり

ミューテーションタスクのキューイングに関連する質問があり@domenicのアイデアは機能すると思います( webkitはミューテーションレコードを専用のスレッド/キューに追加します)。 ただし、これには、何らかの形式のキューに入れられたもの、さらに重要なことに、キューにあるものを実行するロジックも必要になります。 これは私に2つの質問につながります:

そのようなキューの恩恵を受ける可能性のあるjsdomの他のコンポーネントはありますか? アーキテクチャと(将来の)統合に関して、ここで考慮すべきことがありますか?

タイマーに基づいて(jsdomにグローバルティックがありますか?)、または単にpromise / doneコールバック構造に基づいてキュー内のタスクを実行するのが最も賢明ですか?

私は、非常に基本的な実装を実行してから、将来の実装をガイドするための広範なテストケースを作成することに重点を置いています。

したがって、マイクロタスクは基本的にprocess.nextTick(fn)です。 これは、複合マイクロタスクビジネスと「複合マイクロタスクサブタスクの実行」のため、ミューテーションオブザーバーにとっては少し注意が必要です。 私はあなたがほとんどそれを無視することができると_思います_。 jsdomは、設定する内容について心配する必要はありません。

したがって、仕様に「ミューテーションオブザーバーに通知するために複合マイクロタスクをキューに入れる」と記載されている場合は、 process.nextTick(notifyMutationObservers)ます。 次に、 notifyMutationObservers 、ステップ3は、サブステップを同期的に実行するミューテーションオブザーバーのループにすぎないと思います。

テストについては、 https://github.com/tmpvar/jsdom/blob/master/Contributing.mdを確認して

これは質問するのに適切な場所ではないかもしれませんが、implファイル間でwebidlスキームオブジェクト(例:/generated/MutationRecord.js)をやり取りする方法を理解するのに問題があります(Node-impl-> MutationObserver-Impl) 。

オブジェクトをMutationRecordsのスキーマをミラーリングする純粋なJSONオブジェクトとして構築し、ミューテーションが発生したときにそれをNode-implからMutationObserverに渡すだけの誘惑に駆られます。 これは、仕様に記載されているように、MutationObserversのすべての側面を実装するという野心を壊すだろうと思います。

これは、私がjsdomwebidlアーキテクチャ/オブジェクトモデル/インターフェイスに精通していないためだと思います。 コード内の例は、implファイル内の/ generate /オブジェクトの操作を理解するのにも役立ちます。

おそらくどこかでこれを文書化する必要がありますが、ここに行きます:

一般に、生成されたAPIを通過する引数はすべて自動的にボックス化解除/再ボックス化されるため、生成されたオブジェクトを気にする必要はありません。重要なのは実装オブジェクトだけです。 を除いて-実際にはそうではありません。 これは、_すべて_がすでにIDLベースに切り替えられている場合に当てはまりますが、そうではありません。 引数と戻り値は機能しますが、IDL以外のクラス(Windowなど)を操作するたびに、引数を自分で指定するときに、ボックス化解除/再ボックス化を行う必要があります(たとえば、 https:// githubを参照)。 com / tmpvar / jsdom / blob / master / lib / jsdom / living / events / EventTarget-impl.js#L103 、ここでは、Windowはまだidlされていないため、Windowをアンラップする必要がありますが、EventTarget(Windowはその継承します) from)is)。 この手動ボクシングは、必要に応じてidlUtils.wrapperForImpl / idlUtils.implForWrapperて行います。

したがって、一般的には、Implオブジェクトを作成する必要があります。 これを行うには、生成されたファイルが必要であり、そのエクスポートでcreateImplを呼び出します。 argsの配列(public-constructor引数用)とprivate argsのオブジェクト(両方ともimplクラスに提供されます)を取ります。 その例については、 https://github.com/tmpvar/jsdom/blob/9dd9069354e36c077032f4cbcb1616a7d9e6f0c4/lib/jsdom/living/nodes/Document-impl.js#L549を参照して

これは全体を把握するのに十分なほど詳細ではないことを理解しています(私は思う)ので、もっと具体的なことがあれば、もっと説明させていただきます。

@Sebmasterに感謝します、それは大いに役立ちました。

はい、API /オブジェクトを統合して使用する方法に関するいくつかの例を使用してこれを文書化すると役立ちますが、次のいくつかの手順については十分に理解していると思います。

クイックアップデート!
MutationRecordが仕様に従っている場合、 W3Cテストは失敗します(私は思います)。 私は彼らのリポジトリにコメントをしました。

私は自分の目的のためにそれらをローカルで更新しますが、これらをW3C / jsdomにコミットするかどうかはわかりません。 つまり、私にもそのタスクを完了する時間がない限り。

しかし、属性の突然変異は現在ほとんどのテストに合格しており、週末または来週の初めにプルリクエストを行います。

それは超エキサイティングです! 問題が何であるかをもう少し詳しく説明できますか? https://github.com/w3c/web-platform-tests/issues/2482を完全にフォローすることができなかったので、おそらく、MutationRecordのどのプロパティ値がテストで期待され、仕様に何が必要だと思いますか。 ?

問題は、テストで比較する完全なmutationRecordが指定されていないことです。 したがって、最初のテストケースでは、テストによってid値が変更され、その結果、返されるミューテーションレコードに古い値のプロパティが含まれます。 oldValueプロパティが予期されるオブジェクトで定義されていないため、テストは失敗します。 私が理解しているように、ミューテーションレコードには、nullの場合でも、常にすべてのプロパティが含まれている必要があります。 その場合、それらはDOMStringnullである必要があります。 テストケースにプロパティが設定されていない場合、テストはnull(オブジェクトのタイプ)とnull(文字列のタイプ)を比較して失敗します。

テストは遅延して構築されます。たとえば、未定義のフィールドは自動的にnull(オブジェクト)に設定されます。 これにより、a)mutationRecordが期待されるレコードオブジェクトに設定されていないプロパティ(oldValueなど)を返し、b)ミューテーションレコードプロパティがDOMstring null(attributeNamespaceなど)の場合にテストが失敗します。

意味がありますか?

私が正しければ、修正するのはかなり簡単ですが、すべてのケースを1つずつ確認する必要があります。 これは、jsdomとw3cの両方のテストの部外者としては少し難しいかもしれません:)

すみません、簡単にできますか? 私は次の形式で答えたいと思います。テストではoldValueがnullまたは未定義であると想定されていますが、仕様では値「null」が示されています。 または類似。

上で参照したテストでは、oldValueがnullであることが暗黙的に想定されています。 「n」である必要があります

そのファイル内のすべてのテストケースは、attributeNamespaceがnull(オブジェクト)であると想定しています。仕様によれば、それらはDOMStringnullである必要があります。

attributeNamespaceのタイプはDOMString?であるため、nullにすることができます(「null」ではなく、nullのみ)。

oldValueのケースを明確にしていただきありがとうございます:)。

わかりました。明確にしていただきありがとうございます。仕様の重要な側面を見逃したと思います。

フォークにブランチ

既知の理由/問題(範囲サポート#317がないなど)で合格しなかったテストはどこに文書化すればよいですか?

Webプラットフォームテスト用にそれらをindex.jsファイルに追加しますが、その理由についてコメントを付けてコメントアウトします。 たとえば、テンプレートに対して行うことを参照

これは確定にはほど遠いですか?

突然変異イベントは8.5で削除されたようです。 8.5に戻ってポリフィルに依存せずに、カスタム要素(Mutation Observersが必要)をテストする方法はありますか? DOMParserは8.5では実装されていませんでした。ShadowDOMポリフィルにはそれが必要なので、現時点ではJSDOMでテストを実行できるためにブロックされています。 ここでは、ガイダンスが役立ちます。 残念ながら、現時点では、これを試して実装を支援する能力がありません。

私はそうする方法を知りません、ごめんなさい:(。

これを動かすのを手伝ってもらえますか? ここでいくつかの作業が開始されたようです: https

しかし、これを動かすためにまだ何が必要かはわかりません。 MutationObserverが基本的にどこでもサポートされていることを考えると、これが存在しないことには大きなギャップがあるように感じます: http

webcomponentsjsポリフィルを活用できますか? https://github.com/webcomponents/webcomponentsjs

プルリクエストはいつでも大歓迎です。 @henrikkorsgaardの仕事は間違いなく始めるのに良い場所です。 しかし、ポリフィルは意味がないと思います。

私の知る限り、パフォーマンスを考慮してミューテーションイベントが削除されました。 MutationObserverがブラウザによって指定および実装されたのと同じ理由。 ただし、ブラウザは、少なくともMOサポートが実装されるまでその機能を維持していました。 ここでの実用的なアプローチは、そのサポートを再度追加することかもしれません。そうすれば、少なくとも、これが実装されるまでMOをポリフィルすることができます。 JSDOMのメンテナンスには理想的ではなく、それ以来コードベースが分岐している可能性があることを認識しています。 そうは言っても、検討する価値があると思います。 これにより、特にWebコンポーネントが本番アプリの実行可能なソリューションであり、MOをポリフィルする必要があるこの段階では、大きなギャップが残ります。 JSDOMでテストを実行できると便利です。

それが役立つ場合; 私はMOオントップjsdomをポリフィルしました。 ここここ。 私はそのA良いソリューションを言わないだろうが、それが動作し、あまりにもタイマーなし。

4年前、まだ進行中ですか? この問題は、バージョン9.0.0以降の変更ログに記載されています。 これについて何かニュースはありますか?

@MeirionHughesファイルはスムーズに機能しました。ありがとうございます。

この問題に関する更新はありますか?

@domenicのリンクの
@MeirionHughesが提案したファイルを入れてみてください。これまでのところうまくいきました。

@mtrabelsi @MeirionHughesこんにちは、Jestで動作させることができませんでした。このエラーが発生しましたhttps://stackoverflow.com/questions/43190171/jsdom-cannot-read-property-location-of-null
JSDOMでMOをどのように使用したか説明していただけますか?

編集:
わかりました、それを機能させることができたようですhttps://gist.github.com/romuleald/1b9272fce11d344e257d0bdfd3a984b0

@romuleald要点にエラーがあります。this.expandothis.counterしていますが、静的にアクセスしています。 これにより、 _findMutations重大な問題が発生します。 変換しようとしたtypescriptファイルでは、両方のプロパティが静的であったことに注意してください(ES6では不可能です)。 Utilクラスの下に次の行を追加することをお勧めします。

Util.counter = 1;
Util.expando = 'mo_id';

そして、コンストラクターを完全に取り除くことができます(とにかくクラスがインスタンス化されることはありません)。

過去1日半の間、これによって引き起こされた問題をデバッグしていたので、これを見つけるのに恥ずかしいほど長い時間がかかりました。

さらに、シムのベースとなったソースは、 CharacterDataノードの.dataプロパティへの変更をサポートしていません。 簡単な修正については、このコメントの上にある私のリンクされた問題を見ることができます。

とりあえずhttps://github.com/megawac/MutationObserver.jspolyfillを使ってこれをテストすることができました。

私はAVAを使用しています。 そして、「m」は、MutationObserverを含む私のモジュールです。

import test from 'ava';
import delay from 'delay';
import jsdom from 'jsdom';
import m from '.';

const dom = new jsdom.JSDOM();
global.window = dom.window;
global.document = dom.window.document;

require('mutationobserver-shim');

global.MutationObserver = window.MutationObserver;

test('MutationObserver test', async t => {
    delay(500).then(() => {
        const el = document.createElement('div');
        el.id = 'late';
        document.body.appendChild(el);
    });

    const checkEl = await m('#late');
    t.is(checkEl.id, 'late');
});

ポリフィルであるため、標準のインターフェースとは異なる点がいくつかあります。 しかし、この問題は進展していないようですので、1つの選択肢として参照してください。

jsdomとjestを使用してポリフィルとして使用する別の方法は、シムをスクリプトとして手動でロードすることです。

npm install mutationobserver-shim

たとえば、beforeAll関数の内部:

const mo = fs.readFileSync(
  path.resolve('node_modules', 'mutationobserver-shim', 'dist', 'mutationobserver.min.js'),
  { encoding: 'utf-8' },
);
const moScript = win.document.createElement('script');
moScript.textContent = mo;

win.document.body.appendChild(moScript);

この「ハック」は私にとって、おそらく他の人にとってもうまくいきます;)

IIRC JestのsetupFilesの一部として、shim(pal-nodejsからのコードの微調整バージョンを使用しました。上記のnpmパッケージが何に基づいているかはわかりません)をロードするとうまく機能することがわかりました。 誰かが興味を持っているなら、私が他のラップトップに着いたら、より具体的な情報を与えることができます。

それで、これはほぼ5年間開いています、ステータスの更新はありますか?

@mendrikのモックは私のために働いたhttps://github.com/benitogf/corsarial/blob/master/test/specs/utils.js#L29そして上記のようにポリフィルソリューションもあります、良い一日を:)

ここに部分的な実装があります: https

@benitogf私はそれを試しましたが、どういうわけかレコードは私のために
@treshugartどうすればそれを使用できますか? :)

テストで@mendrik 、これをインポートしますhttps://github.com/aurelia/pal-nodejs/blob/master/src/polyfills/mutation-observer.ts
そしてそれをグローバル変数に設定します。 それでおしまい!

JSDOMhttps://github.com/skatejs/skatejs/tree/master/packages/ssr#usageをオプトアウトする場合は@mendrik そうでない場合は、そのファイルを直接インポートして、エクスポート(https://github.com/skatejs/skatejs/blob/master/packages/ssr/register/MutationObserver.js#L109)をグローバルに追加できます。

これは、react-quillを拡張するコンポーネントをテストしようとしたときにこの問題を修正するのに十分でした。

import 'mutationobserver-shim';

document.getSelection = () => null;
このページは役に立ちましたか?
0 / 5 - 0 評価