Submit Search
Upload
GeckoのDOMイベント処理の実装
•
15 likes
•
6,909 views
Masayuki Nakano
Follow
DOMイベントと、その発火のGeckoにおける実装の解説。
Read less
Read more
Technology
Report
Share
Report
Share
1 of 65
Download now
Download to read offline
Recommended
GeckoのDOMイベント処理の実装 (Gecko Inside ver.)
GeckoのDOMイベント処理の実装 (Gecko Inside ver.)
Masayuki Nakano
DOMイベントの基礎から深淵まで
DOMイベントの基礎から深淵まで
Masayuki Nakano
0621 ndk game
0621 ndk game
cat kaotaro
【ツクールMV】ゲーム開始~Scene_Title呼び出しまでの流れ(一人輪読会)
【ツクールMV】ゲーム開始~Scene_Title呼び出しまでの流れ(一人輪読会)
りんね ぐりっど
サーバレスモードRTMFP
サーバレスモードRTMFP
itoz itoz
Client Side Cache
Client Side Cache
Toru Yamaguchi
実践 NestJS
実践 NestJS
Ayumi Goto
Windows スクリプトセミナー WMI編 VBScript&WMI
Windows スクリプトセミナー WMI編 VBScript&WMI
junichi anno
Recommended
GeckoのDOMイベント処理の実装 (Gecko Inside ver.)
GeckoのDOMイベント処理の実装 (Gecko Inside ver.)
Masayuki Nakano
DOMイベントの基礎から深淵まで
DOMイベントの基礎から深淵まで
Masayuki Nakano
0621 ndk game
0621 ndk game
cat kaotaro
【ツクールMV】ゲーム開始~Scene_Title呼び出しまでの流れ(一人輪読会)
【ツクールMV】ゲーム開始~Scene_Title呼び出しまでの流れ(一人輪読会)
りんね ぐりっど
サーバレスモードRTMFP
サーバレスモードRTMFP
itoz itoz
Client Side Cache
Client Side Cache
Toru Yamaguchi
実践 NestJS
実践 NestJS
Ayumi Goto
Windows スクリプトセミナー WMI編 VBScript&WMI
Windows スクリプトセミナー WMI編 VBScript&WMI
junichi anno
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
Makoto Setoh
2時間で学ぶjQuery
2時間で学ぶjQuery
Shumpei Shiraishi
OSC京都2011
OSC京都2011
haganemetal
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
Jumpei Ogawa
20080524
20080524
小野 修司
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
Gosuke Miyashita
人狼知能セミナー資料2017(案)0.4.5対応版
人狼知能セミナー資料2017(案)0.4.5対応版
Fujio Toriumi
Ssaw08 1028
Ssaw08 1028
Atsushi Tadokoro
Gruntでjava script前作業の自動化!
Gruntでjava script前作業の自動化!
Tanaka Yuichi
wxPython入門(大阪Pythonユーザの集まり2014/03)
wxPython入門(大阪Pythonユーザの集まり2014/03)
泰 増田
分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4
AdvancedTechNight
Node.jsでブラウザメッセンジャー
Node.jsでブラウザメッセンジャー
Yahoo!デベロッパーネットワーク
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋
Mori Shingo
Web Component概要
Web Component概要
Shumpei Shiraishi
SystemV IPC
SystemV IPC
Masami Ichikawa
マイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorp
Masahito Zembutsu
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
Yuki Higuchi
Html5 Web Applications
Html5 Web Applications
totty jp
Interact 2018:PowerShell of Microsoft SDN v2 101
Interact 2018:PowerShell of Microsoft SDN v2 101
wind06106
NoSQL and JavaScript 2013-02-09
NoSQL and JavaScript 2013-02-09
WakandaJA
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
Hiroki Ichikura
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Yuma Ohgami
More Related Content
Similar to GeckoのDOMイベント処理の実装
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
Makoto Setoh
2時間で学ぶjQuery
2時間で学ぶjQuery
Shumpei Shiraishi
OSC京都2011
OSC京都2011
haganemetal
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
Jumpei Ogawa
20080524
20080524
小野 修司
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
Gosuke Miyashita
人狼知能セミナー資料2017(案)0.4.5対応版
人狼知能セミナー資料2017(案)0.4.5対応版
Fujio Toriumi
Ssaw08 1028
Ssaw08 1028
Atsushi Tadokoro
Gruntでjava script前作業の自動化!
Gruntでjava script前作業の自動化!
Tanaka Yuichi
wxPython入門(大阪Pythonユーザの集まり2014/03)
wxPython入門(大阪Pythonユーザの集まり2014/03)
泰 増田
分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4
AdvancedTechNight
Node.jsでブラウザメッセンジャー
Node.jsでブラウザメッセンジャー
Yahoo!デベロッパーネットワーク
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋
Mori Shingo
Web Component概要
Web Component概要
Shumpei Shiraishi
SystemV IPC
SystemV IPC
Masami Ichikawa
マイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorp
Masahito Zembutsu
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
Yuki Higuchi
Html5 Web Applications
Html5 Web Applications
totty jp
Interact 2018:PowerShell of Microsoft SDN v2 101
Interact 2018:PowerShell of Microsoft SDN v2 101
wind06106
NoSQL and JavaScript 2013-02-09
NoSQL and JavaScript 2013-02-09
WakandaJA
Similar to GeckoのDOMイベント処理の実装
(20)
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
軽量EvernoteクライアントSmartEverにおけるアプリ高速化の工夫と課題
2時間で学ぶjQuery
2時間で学ぶjQuery
OSC京都2011
OSC京都2011
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
20080524
20080524
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
人狼知能セミナー資料2017(案)0.4.5対応版
人狼知能セミナー資料2017(案)0.4.5対応版
Ssaw08 1028
Ssaw08 1028
Gruntでjava script前作業の自動化!
Gruntでjava script前作業の自動化!
wxPython入門(大阪Pythonユーザの集まり2014/03)
wxPython入門(大阪Pythonユーザの集まり2014/03)
分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4
Node.jsでブラウザメッセンジャー
Node.jsでブラウザメッセンジャー
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋
Web Component概要
Web Component概要
SystemV IPC
SystemV IPC
マイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorp
Android Lecture #01 @PRO&BSC Inc.
Android Lecture #01 @PRO&BSC Inc.
Html5 Web Applications
Html5 Web Applications
Interact 2018:PowerShell of Microsoft SDN v2 101
Interact 2018:PowerShell of Microsoft SDN v2 101
NoSQL and JavaScript 2013-02-09
NoSQL and JavaScript 2013-02-09
Recently uploaded
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
Hiroki Ichikura
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Yuma Ohgami
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
iPride Co., Ltd.
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
Toru Tamaki
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
danielhu54
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
Toru Tamaki
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
sugiuralab
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
taisei2219
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
Toru Tamaki
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
Ryo Sasaki
Recently uploaded
(10)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
GeckoのDOMイベント処理の実装
1.
2.
Text GeckoのDOMイベント処理の実装
3.
中野雅之 •肩書き •正式:
Mozilla Japan 国際化担当マネージャ •非公式: Mozilla Japan 大阪支部長 •大阪の自宅で、自宅警備しながら仕事してます
4.
中野雅之 •色んなアカウント •メールアドレス:
masayuki@d-toybox.com •Skype: masayuki-nakano •Twitter: @d_toybox •Blog: 「もずはっく日記」で検索
5.
アジェンダ •DOMイベントの基礎知識 •Geckoのイベント処理の実装
•パフォーマンスを悪くしないためのヒント
6.
DOM イベントの基礎 •フェイズと、プロパゲーション
•イベントを捕まえる •イベントの伝播を抑制する •ブラウザのイベント処理を妨害する
7.
capturing フェイズ •最初は
window •次に document •root から target の親 •target の決定は、イ ベント依存 •フォーカス •発生位置 •……等々
8.
target フェイズ •target
フェイズは、 capturing フェイズの 一部でもあり、 bubbling フェイズの 一部でもある。 •window や document が target の場合も
9.
bubbling フェイズ •target
の親から root •次に document •最後に window •Event.bubbles が false の場合、 bubbling は発生しな い
10.
イベントを捕まえる •書式: •EventTarget.addEventListener(
イベント名, ハンドラ, Capture?); •EventTarget.removeEventListener( イベント名, ハンドラ, Capture?); •イベント名: イベントの名前 "click" とか、 "keydown" •ハンドラ: function foo(aEvent) { /* something */ } がお手軽で十分 •Capture?: true なら、capturing フェイズと、target フェイズ、false なら、target フェイズと、bubbling フェイズ
11.
イベントを捕まえる •単純な例1: •全ての要素で発生するkeydownイベントを知りたい
•イベントターゲットより先に知りたい •removeする必要はない document.addEventListener("keydown", function (aEvent) { /* something */ }, true);
12.
イベントを捕まえる •単純な例2: •全ての要素で発生するkeydownイベントを知りたい
•イベントターゲットより後に知りたい •removeする必要がある function keydownHandler(aEvent) { /* something */ } document.addEventListener("keydown", keydownHandler, false); … document.removeEventListener("keydown", keydownHandler, false);
13.
イベントの伝播を抑制する •複数のイベントリスナを登録している場合、あるイベント ハンドラで処理済みのイベントを他のイベントハンドラで
は無視したい場合が考えられる •Event.stopPropagation() か、 Event.stopImmediatePropagation() を呼ぶと、それ以 降のイベント発生を中止できる •Event.stopPropagation() では、次の EventTarget 以 降でのイベントハンドラの実行を中止できる •Event.stopImmediatePropagation() では、同じ EventTarget に登録されている未処理のイベントハンド ラも含めて、イベントハンドラの実行を中止できる
14.
ブラウザのイベント処理を妨害する •ブラウザにデフォルトの動作(default action)を実行して
もらいたくない場合が考えられる •Event.preventDefault()を呼び出すと、 Event.defaultPrevented属性値がtrueになる •defaultPrevented属性がtrueなら、ブラウザは default action を実行しない(ただし、タブの切替等、 セキュリティ上、無視することはある) •Web アプリは Event.defaultPrevented の値を、処理 前に確認することで、Event.stopPropagation()の代 用としても使える
15.
Geckoのイベント処理の実装 •OS ネイティブなイベントを
DOM イベントとして Web アプリに通知するケースを解説 •図にすると、次のように……
16.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
17.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
18.
EventListenerManager •イベントターゲットで、最初にイベントリスナが登録さ れた時に、インスタンスが生成され、そのノードに保存
される •そのノードに登録された全てのイベントリスナを管理 する •HandleEvent() が呼び出されると、イベントの名前と フェーズ、イベントリスナのグループがマッチするもの を探し、マッチした場合に登録されているハンドラを実 行する •stopImmediatePropagation() が呼び出されたら、中 断する
19.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
20.
モジュール間の処理の流れの例 1.widget/ は、各
OS のネイティブイベントをハンドリ ングするモジュール。ネイティブイベントが発生した ら、内部イベントである、Widget*Event クラスのイ ンスタンスをスタックに作成し、その値を設定する 2.PresShell にイベントを送信、PresShell が target を決定する
21.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
22.
モジュール間の処理の流れの例 3.EventStateManager::PreHandleEvent() が前処
理を行う •詳しくは後ほど
23.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
24.
モジュール間の処理の流れの例 4.PresShell が
EventDispatcher::Dispatch() を呼び 出す 5.EventDispatcher::CreateEvent() で Widget*Event のクラスに対応した、dom::*Event クラスを選択し、そのインスタンスをヒープに作成す る 6.EventListenerManager を列挙した配列を用意し、 EventTargetChainItem::HandleEventTargetChain()を 呼び出す
25.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
26.
モジュール間の処理の流れ 7.EventTargetChainItem::HandleEventTargetChain() で、
受け取った、各 EventListenerManager の HandleEvent() を実行していく 8.EventListenerManager::HandleEvent() は、その ノードに登録されたイベントリスナを順に実行してい く 9.EventTargetChainItem::HandleEventTargetChain() が自身をもう一度呼び出し、デフォルトア クションの実行のため、System Event Group に登 録されたリスナを実行する。
27.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
28.
モジュール間の処理の流れ 10.EventStateManager::PostHandleEvent() で、デフォルト
アクションを実行したり、関連するイベントを生成したりする
29.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
30.
Widget*Event、Internal*Event •WidgetEvent クラスが全てのイベントクラスの基底ク
ラス •WidgetMouseEvent や、InternalFocusEvent といっ た派生クラスが、イベントごとに定義・実装されている •各クラスは、ほぼ構造体であり、メンバのカプセル化 はほとんど行われず、メンバにダイレクトにアクセスす る (読み書き問わず) •widget から生成されるイベントは、Widget*Event、そ れ以外の場合は、DOM イベントのデータを保存する ためだけのものは、Internal*Event と命名されている
31.
Widget*Event、Internal*Event •widget/ •widget/BasicEvents.h
•widget/ContentEvents.h •widget/MiscEvents.h •widget/MouseEvents.h •widget/TextEvents.h •widget/TouchEvents.h •dom/events/ •dom/events/InternalMutationEvent.h
32.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
33.
PresShell •PresShell は、
Presentation Shell の略で、 nsPresShell.cpp で実装され、 nsIPresShell.h で定 義されている nsIPresShell インターフェースを持つ •ドキュメントに対し、一つ生成される (正確なところは 不明) •イベントの複雑な処理は EventStateManager、表示 に関わる部分は nsPresContext に分離されている •イベント処理では widget で生成されたイベントを受け 取り、target の決定と、発火処理を行う •PresShell::HandleEvent() や、関連メソッドを参照
34.
EventStateManager::PreHandleEvent() •PresShell がイベントを発火する直前に呼び出す
•マウスの操作によって変化する hover や、active とい った要素の状態設定を行う •マウスのクリックカウント等、状態の保存や、その値の Widget*Event のメンバへの書き出しを行う •ホイールの速度等、設定でカスタマイズできる項目を、 Widget*Event のメンバの値を書き換えることで実現 してる
35.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
36.
EventDispatcher::CreateEvent() •Widget*Event クラスのインスタンスや、
Internal*Event クラスのインスタンスから、DOM イベ ントの実装クラスを選択し、インスタンスを生成する •Javascript の document.createEvent() の実装でも ある •EventListenerManager::HandleEventInternal() が 最初のイベントリスナを見つけた時点で呼び出される
37.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
38.
dom::Event •DOM イベントの実装クラスは、名前空間
“mozilla::dom“ に、標準仕様と同じ名前で定義 •dom::KeyboardEvent、dom::WheelEvent 等 •nsIDOMEvent インターフェースを必ず継承している •dom::Event は、WidgetEvent へのポインタを持ち、 イベントの属性値はここに保存している •DOM イベントクラスは、Widget*Event や Internal*Event へ、DOM からアクセスするためのラ ッパクラス
39.
dom::Event •古くから実装されている DOM
イベントクラスは、固有 の、nsIDOM*Event インターフェースも継承している •新規作成時にはほとんど定義されない •データにアクセスするだけなら、内部イベントクラス にアクセスする方が高速で、実装も単純化される •nsIDOM*Event のメソッドは全て、virtual call にな るためパフォーマンスが悪い
40.
dom::Event •内部イベントクラスを定義・実装する必要が無い、シン プルなイベントを実装する際は、webidlで定義したイ
ベントから、実装コードを自動生成することも可能 •自動生成の定義は dom/webidl/moz.build で定義 •dom/bindings/Codegen.py によって、ビルド時に cpp ファイルが自動的に生成される
41.
dom::Event •実装例 •dom/events/
•dom/events/Event.cpp •dom/events/UIEvent.cpp •dom/events/WheelEvent.cpp •content/svg/content/src/ •content/svg/content/src/SVGZoomEvent.cpp
42.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
43.
EventDispatcher::Dispatch() •PresShell から呼び出される
•最初に、 target の PreHandleEvent() を実行する •window から target ノードまで辿り、作成されている全 ての EventListenerManager を列挙し、配列に格納 •EventTargetChainItem::HandleEventTargetChain() にその配列を渡す •その後、 target の PostHandleEvent() を実行する •発火が終了しても、DOM イベントが JS の変数等か ら参照されている場合、内部イベントをヒープにコピ ーする •発火処理後、スタックにある内部イベントは破棄さ れるため
44.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
45.
EventTargetChainItem::HandleEventTargetChain() •EventDispatcher::Dispatch() に呼び出される
•列挙されている、window から target の親ノードまで の EventListenerManager の、HandleEvent() を実 行していく (capturing フェーズ) •Event.stopPropagation() が HandleEvent() 実行 中に呼び出されていたら、ループを中断する
46.
EventTargetChainItem::HandleEventTargetChain() •次に、target の
EventListenerManager の HandleEvent() を呼び出す (target フェーズ) •Event.stopPropagation() か、 Event.stopImmediatePropagation() が既に呼び出 されていた場合、実行しない •Event.stopPropagation()が HandleEvent() 実行中 に呼び出されていたら、ループを中断する
47.
EventTargetChainItem::HandleEventTargetChain() •次に、列挙された、target の親から、
window までの EventListenerManager の、HandleEvent() を実行し ていく (bubbling フェーズ) •Event.bubbles が false なら実行しない •Event.stopPropagation() か、 Event.stopImmediatePropagation() が既に呼び出 されていた場合、実行しない •Event.stopPropagation() が HandleEvent() 実行 中に呼び出されていたら、ループを中断する
48.
EventTargetChainItem::HandleEventTargetChain() •次に、イベントターゲットが生成した、CSS box
を実装 している、nsIFrame::HandleEvent() を呼び出す • PresShell が EventDispatcher::Dispatch() に渡し た callback クラス経由で呼び出し •default action の実装に利用可能
49.
EventTargetChainItem::HandleEventTargetChain() •最後に、System Event
Group のイベントリスナが登録 されている場合、capturing、target、bubbling フェーズ を再度、処理する •通常の Web コンテンツからは登録不可 •Web コンテンツに Event.stopPropagation() 等を呼 び出されていても実行される •default action の実装に利用可能 •System Event Group 内のリスナで、 stopPropagation() 等を呼ぶと中断される
50.
Geckoのイベント処理の実装 nsDocument PresShell
widget EventDispatcher EventStateManager Widget*Event dom::*Event PreHandleEvent() PostHandleEvent() Dispatch() CreateEvent() 2 3 4 5 6 EventTargetChainItem nsINode EventListenerManager HandleEvent() handler2 handler1 nsINode EventListenerManager HandleEvent() handler2 handler1 7 8 10 1 9
51.
EventStateManager::PostHandleEvent() •PresShell が最後に呼び出す
•イベントの後処理や、default action を実行 •マウスホイールによるスクロール処理やズーム処理 •mouseup から click イベントや、dblclick イベントの 生成 •mousemove から、 mouseover、mouseout、 mouseenter、mouseleave イベントの生成
52.
パフォーマンスを悪くしないためのヒント •イベントリスナを必要以上に登録しない •登録するノードが増える程、EventListenerManager
のインスタンスの数が増える •登録するハンドラが増える程、全てのイベントの発生時 に、マッチするイベントを探すループの処理回数が増え る •stopPropagation()や、stopImmediatePropagation() を効果的に利用するとループを中断させることができる
53.
パフォーマンスを悪くしないためのヒント •発火回数が多いイベントや、発火のコストが高いイベント はリスナを登録しないようにする
•EventListenerManager と、nsDocument は、一部の イベントリスナが登録されたかどうかをフラグで保存し ており、これらが false の場合、イベントそのものを発 火しないようにしている •各フラグは、RemoveEventListener() でリセットされな い。これは、RemoveEventListener() のパフォーマン スを悪くしないため •発生コストが高いイベントは、一度登録したが最後、 document が unload されるまで、その document では発生し続ける
54.
パフォーマンスを悪くしないためのヒント •mMayHaveCapturingListeners •全てのイベントリスナが、bubbling
フェーズのイベント のリスナであれば、false •これが false なら、capturing フェーズのループは丸ご とスキップされる •target フェーズのイベントは、bubbling フェーズのイベ ントリスナで取得できるので、target フェーズでイベント を処理したい場合は、bubbling フェーズとして登録す る方が良い
55.
パフォーマンスを悪くしないためのヒント •mMayHavePaintEventListener •“MozAfterPaint”
•描画する度に発生するので、発生回数が莫大
56.
パフォーマンスを悪くしないためのヒント •mMayHaveMutationListeners •“DOMAttrModified”
•“DOMCharacterDataModified” •“DOMNodeInserted” •“DOMNodeInserted” •“DOMNodeInsertedIntoDocument” •“DOMNodeRemovedFromDocument” •“DOMSubtreeModified” •MutationObserver を利用するべき
57.
パフォーマンスを悪くしないためのヒント •mMayHavePointerEnterLeaveEventListener •“pointerdown”
•“pointermove” •“pointerup” •“pointercancel” •“pointerover” •“pointerout” •“pointerenter” •“pointerleave” •“gotpointercapture” •“lostpointercapture”
58.
パフォーマンスを悪くしないためのヒント •mMayHaveTouchEventListener •“touchstart”
•“touchend” •“touchmove” •“touchcancel” •タッチデバイスを直接サポートする場合はやむを 得ない •利用しても他ほどパフォーマンスは落ちない(は ず)
59.
パフォーマンスを悪くしないためのヒント •mMayHaveMouseEnterLeaveEventListener •“mouseenter”
•“mouseleave” •“mouseover” や “mouseout” 発生時に、祖先要 素全てで発生すべきか確認する必要があり、多 数の要素上で、同時にイベントが発生する可能性 もある •“mouseover” や ”mouseout” で代用可能か、 熟慮した上で判断を
60.
パフォーマンスを悪くしないためのヒント •他にも細かい、イベント単位での最適化があるので、 EventListenerManager::AddEventListenerInternal()のコー
ドを参照
61.
パフォーマンスを悪くしないためのヒント •極端な話をすると、 •全てのイベントリスナを
window に登録 •bubbling フェーズで登録 •Event.target を自前で確認 •Event.stopImmediatePropagation()で伝播を中断 •こうすると、イベントリスナを呼び出すコストは最小限に 抑えられる •もちろん、綺麗なコードになるわけではないので、やら ない方が良い
62.
パフォーマンスを悪くしないためのヒント 最適化はほどほどに!
63.
パフォーマンスを悪くしないためのヒント 読みやすいコードで、 バグの少ないアプリを!
64.
知っておいた方が良い用語・略語 •D3E •DOM
Level 3 Events •ESM •EventStateManager •dispatch、fire •(イベントを)発火する •consumed •preventDefault() が呼び出され、default action がキ ャンセルされている状態
65.
その他の資料 •DOM Level
3 Events 仕様書 (Working Draft) •Event developer guide (MDN) •Adding a new event (MDN) •dom/events (mxr)
Download now