クロムブリンクコアの概要

クロムブリンクコア Outline_51CTO博客_switchyomega_chromium.crx

マルチプロセス アーキテクチャ。1 つのブラウザー プロセスと N サンドボックス レンダラー プロセスがあり、Blink はサンドボックス レンダリングで実行されます。ブラウザーのタブと iframe は、同じレンダラー プロセスを共有できます。

サンドボックス操作: サンドボックスでは、リソース (ファイル アクセス、ネットワーク、オーディオとビデオの再生、ユーザー構成ファイルの読み取り (Cookie、パスワード) など) をスケジュールおよび使用するために、親ブラウザー プロセスを使用する必要があります。Blink は、ブラウザー プロセスをグループに抽象化します。サービス、Mojo を使用して、サービスおよびブラウザー プロセスと対話します。

レンダリング プロセスのスレッド

1 つのメイン スレッド: JavaScript、DOM、CSS、スタイル、レイアウト計算を実行
N 個のワーカー スレッド: Web Worker、ServiceWorker、Worklet を実行内部スレッド: Blink と V8 は、Web オーディオ、データベース、GC などのクロススレッド通信
を処理するための複数のスレッドを作成しますなど
: メッセージングを使用するには、PostTask API を使用する必要があります。共有メモリ プログラミングは、パフォーマンス上の理由で必要な場所がいくつかない限り、推奨されません。これが、Blink コードベースで多くの MutexLock が見られない理由です。

Page、Frame、Document、ExecutionContext、および DOMWindow は、次の概念です。

ページ: ページは、タブの概念に対応します (以下で説明する OOPIF が有効になっていない場合)。各レンダラー プロセスには、複数のタブが含まれる場合があります。
フレーム: フレームは、フレーム (メイン フレームまたは iframe) の概念に対応します。各ページには、ツリー階層に配置された 1 つまたは複数のフレームを含めることができます。1:n
DOMWindow は、JavaScript の windows オブジェクトに対応します。各 Frame には DOMWindow が 1 つだけあります。1:1
Document は、JavaScript の window.document オブジェクトに対応します。各 iframe には Document が 1 つだけあります。1:1
ExecutionContext は、Document (メイン スレッド用) と WorkerGlobalScope (ワーカー スレッド用) を抽象化する概念です。


Renderer process : Page = 1 : N 単一プロセスの場合、複数プロセスの場合、モードによって区別する必要があります。

ページ : フレーム = 1 : M

Frame : DOMWindow : Document (または ExecutionContext) = 1 : 1 : 1

page は、クロム拡張機能のタブまたは背景ページです。

実行コンテキスト ExecutionContext は JS の実行コンテキストです。ページは複数に対応します: 各フレームが DOM にアタッチされた後、暗黙的な実行コンテキストが存在します; 拡張機能には別の実行コンテキストがあります。​​​​

DOMWindow (js windows object) と Document (js window.document) (または ExecutionContext) は、JS でのインタラクティブな制御に使用されます。

レンダラー プロセスにローカルなフレームは LocalFrame で表され、レンダラー プロセスにローカルでないフレームは RemoteFrame で表されます。

メイン フレームから見ると、メイン フレームは LocalFrame であり、<iframe> は RemoteFrame です。<iframe> から見ると、メイン フレームは RemoteFrame であり、<iframe> は LocalFrame です。

LocalFrame と RemoteFrame (異なるレンダラー プロセスに存在する可能性があります) の間の通信は、ブラウザー プロセスを介して処理されます。

V8 API のコードを記述する際には、Isolate、Context、および World の概念を理解することが非常に重要です。コードベースでは、それぞれ v8::Isolate、v8::Context、DOMWrapperWorld で表されます。

Isolate は物理スレッドに対応します。Isolate : Blink の物理スレッド = 1 : 1。メインスレッドには独自の分離があります。ワーカー スレッドには独自の分離があります。

V8 のインスタンスは Isolate と呼ばれ、各 Isolate には GC 用の独自のスタック スペースがあります。これは、ある Isolate の JavaScript オブジェクトが、別の Isolate のオブジェクトに直接アクセスできないことを意味します。

Chrome では、各レンダリング プロセスに V8 Isolate があり、同じレンダリング プロセスで処理されるサイトのすべての JavaScript コードは同じ Isolate で実行されます。しかし、Web ワーカーの場合、各ワーカーには独自の Isolate があります。

Isolate には、1 つ以上の JavaScript コンテキスト (JavaScript コンテンツ) があります。Chrome は iframe ごとに JavaScript 環境を作成します。また、各 Chrome 拡張機能には、iframe 用の独自の JavaScript 環境があります。Blink は通常、ScriptState オブジェクトを JavaScript 環境への参照として使用し、blink::ScriptState は v8::Context と 1:1 の関係にあります。(参考:https://zhuanlan.zhihu.com/p/279920830)

Context は、グローバル オブジェクトに対応します (Frame の場合は、Frame のウィンドウ オブジェクトです)。各フレームには独自のウィンドウ オブジェクトがあるため、レンダラー プロセスには複数のコンテキストがあります。V8 API を呼び出すときは、正しいコンテキストにいることを確認する必要があります。そうしないと、v8::Isolate::GetCurrentContext() が間違ったコンテキストを返し、最悪の場合、オブジェクトがリークしてセキュリティの問題が発生します。

World は、Chrome 拡張コンテンツ スクリプトをサポートする概念です。世界は Web 標準の何にも対応していません。コンテンツ スクリプトは Web ページと DOM を共有したいと考えていますが、セキュリティ上の理由から、コンテンツ スクリプトの JavaScript オブジェクトは Web ページの JavaScript ヒープから分離する必要があります。(別のコンテンツ スクリプトの JavaScript ヒープは、別のコンテンツ スクリプトの JavaScript ヒープから分離する必要があります。) 分離を実現するために、メイン スレッドは Web ページのメイン ワールドと、各コンテンツ スクリプトの分離されたワールドを作成します。メイン ワールドと分離されたワールドは同じ C++ DOM オブジェクトにアクセスできますが、それらの JavaScript オブジェクトは分離されています。この分離は、1 つの C++ DOM オブジェクトに対して複数の V8 ラッパーを作成することによって実現されます。つまり、ワールドごとに 1 つの V8 ラッパーです。

Context、World、Frame の関係は?

メインライン上に N 個のワールドがあると想像してください (1 つのメイン ワールド + (N - 1) の孤立したワールド)。次に、フレームには N 個のウィンドウ オブジェクトが必要であり、各ウィンドウ オブジェクトは 1 つのワールドに対応します。コンテキストは、ウィンドウ オブジェクトに対応する概念です。これは、M 個のフレームと N 個の世界がある場合、M * N 個のコンテキストがあることを意味します (ただし、コンテキストは遅延して作成されます)。

ワーカーには、1 つのワールドと 1 つのグローバル オブジェクトしかありません。したがって、コンテキストは 1 つだけです。

また、V8 API を使用する場合は、正しいコンテキストを使用するように細心の注意を払う必要があります。そうしないと、孤立した世界の間で JavaScript オブジェクトが漏洩し、セキュリティ災害を引き起こすことになります (たとえば、A.com の拡張機能が B.com の拡張機能を操作できるなど)。

ジェフ・モニー

リンク: https://www.jianshu.com/p/2a2424bdc057

ソース: Jianshu

著作権は作者に帰属します。商用転載の場合は著者に連絡して許可を得てください。非商用転載の場合は出典を示してください。

ブラウザのレンダリング処理はマルチスレッド化されています(これがわからない場合は、プロセスとスレッドの違いをもう一度確認してください)

やっと糸の概念にたどり着いた????、とても親切。次に、含まれているスレッドを見てみましょう (主な常駐スレッドをいくつか挙げてください)。

1. GUI レンダリング スレッド

ブラウザー インターフェースのレンダリング、HTML、CSS の解析、DOM ツリーと RenderObject ツリーの構築、レイアウトと描画などを担当します。

インターフェイスを再描画する必要がある場合 (Repaint)、または何らかの操作によってリフロー (reflow) がトリガーされると、スレッドが実行されます。

GUI レンダリング スレッドと JS エンジン スレッドは相互に排他的であることに注意してください. JS エンジンが実行されると、GUI スレッドは中断され (フリーズするのと同じです)、GUI の更新はキューに保存され、JS が実行されるとすぐに実行されます。エンジンはアイドリングです。

2.JS エンジンスレッド

JS カーネルとも呼ばれ、Javascript スクリプト プログラムの処理を担当します。(例:V8エンジン)

JS エンジン スレッドは、Javascript スクリプトの解析とコードの実行を担当します。

JS エンジンは、タスク キューでタスクの到着を待ってから処理を行っていましたが、タブ ページ (レンダラー プロセス) で JS プログラムを実行している JS スレッドは常に 1 つだけです。

また、GUI レンダリング スレッドと JS エンジン スレッドは相互に排他的であるため、JS の実行時間が長すぎると、ページのレンダリングが一貫性を失い、ページのレンダリングと読み込みがブロックされることに注意してください。

3. イベントトリガースレッド

JS エンジンではなくブラウザに属し、イベント ループを制御するために使用されます (JS エンジン自体がビジー状態であり、ブラウザが支援のために別のスレッドを開く必要があることは理解できます)。

JS エンジンが setTimeOut などのコード ブロック (またはマウス クリック、AJAX 非同期要求など、ブラウザー カーネルからの他のスレッド) を実行すると、対応するタスクがイベント スレッドに追加されます。

対応するイベントがトリガー条件を満たしてトリガーされると、スレッドはそのイベントを処理対象のキューの最後に追加し、JS エンジンの処理を待ちます。

JS のシングルスレッド関係により、これらの保留中のキュー内のイベントは、JS エンジンによる処理のためにキューに入れる必要があることに注意してください (これらは、JS エンジンがアイドル状態のときに実行されます)。

4.タイミングトリガースレッド

伝説的な setInterval と setTimeout があるスレッド

ブラウザーのタイミング カウンターは JavaScript エンジンによってカウントされません (JavaScript エンジンはシングル スレッドであるため、ブロックされたスレッド状態にあると、タイミングの精度に影響します)。

そのため、別のスレッドを使用してタイミングを計り、タイミングをトリガーします (タイミングが終了したら、イベント キューに追加し、JS エンジンがアイドル状態になるのを待って実行します)。

W3C では、setTimeout で 4 ミリ秒未満の時間間隔は 4 ミリ秒としてカウントする必要があると HTML 標準で規定しています。

5. 非同期 HTTP リクエスト スレッド

XMLHttpRequest が接続された後、ブラウザーを介して新しいスレッド リクエストが開かれます。

状態変化が検出されると、コールバック関数が設定されている場合、非同期スレッドは状態変化イベントを生成し、このコールバックをイベント キューに入れます。その後、JavaScript エンジンによって実行されます。

GUI レンダリング スレッドと JS エンジン スレッドは排他的です.
JavaScript は DOM を操作できるため、これらの要素のプロパティを変更しながらインターフェイスをレンダリングすると (つまり、JS スレッドと UI スレッドが同時に実行されます)、レンダリング スレッドの前後で取得される要素データが一致しない場合があります。

そのため、予期しないレンダリング結果を防ぐために、ブラウザーは GUI レンダリング スレッドと JS エンジンを相互に排他的な関係に設定し、JS エンジンが実行されると、GUI スレッドは中断されます。

GUI の更新はキューに保存され、JS エンジン スレッドがアイドル状態になるとすぐに実行されます。

JS がページの読み込みをブロックする
上記の相互排他関係から、JS の実行時間が長すぎるとページがブロックされると推測できます。

例えば、JS エンジンが膨大な計算を行っているとすると、この時点で GUI が更新されてもキューに保存され、JS エンジンがアイドル状態になってから実行されます。

すると、計算量が膨大なため、JS エンジンが長時間アイドル状態になる可能性が高く、巨大なカードが非常に大きいと自然に感じます。

したがって、JS の実行時間が長くなりすぎないようにしてください。これにより、ページの一貫性のないレンダリングが発生し、ページのレンダリングと読み込みのブロックの感覚が生じます。

WebWorker、JS のマルチスレッド?
前回の記事でも触れたように、JSエンジンはシングルスレッドであり、JSの実行時間が長すぎるとページをブロックしてしまうので、CPUを集中的に使用する計算にはJSは本当に役に立たないのでしょうか?

そのため、Web Worker は後に HTML5 でサポートされました。

MDN の公式説明は次のとおりです。

Web ワーカーは、Web コンテンツがバックグラウンド スレッドでスクリプトを実行するための簡単な方法を提供します。スレッドは、ユーザー インターフェースに干渉することなくタスクを実行できます. ワーカーは、指定された JavaScript ファイルを実行するコンストラクタ (Worker() など) を使用して作成されたオブジェクトです. このファイルには、ワーカー スレッドで実行されるコードが含まれています. ワーカーは別のスレッドで実行されます. global The context is different from current window. したがって、window ショートカットを使用して現在のグローバル スコープを取得すると (self ではなく)、Worker 内でエラーが返されます。

このように理解しました:

Workerを作成する際、JSエンジンがブラウザにサブスレッドを開くように働きかけます(サブスレッドはブラウザによって開かれ、メインスレッドによって完全に制御され、DOMを操作することはできません)。

JS エンジン スレッドは、特定の方法でワーカー スレッドと通信します (postMessage API は、特定のデータのスレッドとやり取りするためにオブジェクトをシリアル化する必要があります)。

そのため、非常に手間のかかる作業を行う場合は、Worker スレッドを別に開いて、どんなに大騒ぎしても JS エンジンのメイン スレッドに影響を与えないようにしてください。

結果を計算したら、結果をメイン スレッドに伝えます。

また、JS エンジンはシングルスレッドであり、その本質は変わっていません. Worker は JS エンジン用のブラウザーによって開かれ、それらの大量の計算問題を解決するために特別に使用されていることが理解できます。

なお、Worker の詳細な説明はこの記事の範囲を超えているため、ここでは繰り返しません。

WebWorker と SharedWorkerの両方が
ここにあるので、SharedWorker についてもう一度説明しましょう (後でこれら 2 つの概念を混同しないようにするため)。

WebWorker は特定のページにのみ属し、他のページの Render プロセス (ブラウザー カーネル プロセス) とは共有されません。

そのため、Chrome は Render プロセス (各タブ ページはレンダリング プロセス) で新しいスレッドを作成し、Worker で JavaScript プログラムを実行します。

SharedWorker はブラウザーのすべてのページで共有され、Worker と同じ方法で実装することはできません。これは、Render プロセスに属しておらず、複数の Render プロセスで共有できるためです。

そのため、Chrome ブラウザは、SharedWorker が JavaScript プログラムを実行するための別のプロセスを作成します.何回作成されても、ブラウザ内の同一の JavaScript ごとに 1 つの SharedWorker プロセスしかありません.

これを見ると、本質的にプロセスとスレッドの違いであることが容易に理解できるはずです。SharedWorker は独立したプロセスによって管理され、WebWorker はレンダリング プロセスの下の単なるスレッドです。

著者: Jony0114

リンク: https://www.jianshu.com/p/f1e5ad3b4afb

ソース: Jianshu

著作権は作者に帰属します。商用転載の場合は著者に連絡して許可を得てください。非商用転載の場合は出典を示してください。

Frame と WebFrame
Frame と WebFrame は 1 対 1 で対応しており、Frame は client を介して WebFrame を見つけることができ、WebFrame も Client を介して Frame を見つけることができます。

他の Web** カプセル化クラスはこれを参照できます

 IFrame、ウィンドウ、ドキュメントが相互に取得

LocalFrame* frame = node_->GetDocument().GetFrame();
  if (frame && frame->DomWindow())// フレーム内の domwindow を取得
    eventTiming = EventTiming::Create(frame->DomWindow(), *event_);
  event_->GetEventPath().EnsureWindowEventContext(); //イベントからdomWindow送信イベントを取得

//コンテキストからイベントを送信
auto* window = To<LocalDOMWindow>(GetExecutionContext());
window->DispatchEvent(*Event::Create(event_name));

フレーム内の domwindow を取得 イベントを送信 
    frame_? frame_->DomWindow()
    frame_->DomWindow() is null??
   frame_->DomWindow()->DispatchEvent(unload_event, this);

フレーム    
1 を取得、現在のフレームを取得
LocalFrame* ドキュメント: :ExecutingFrame() {   LocalDOMWindow* window = ExecutingWindow();   if (!window)     return nullptr;   return window->GetFrame(); }




2. 一番上のフレームを探します。フレームにはウィンドウとドキュメントの js オブジェクトがあります
Frame& top = GetFrame()->Tree().Top();
  KURL top_document_url;
  auto* top_local_frame = DynamicTo<LocalFrame>(&top);

3. domwindow からフレームを取得します
1.
LocalDOMWindow* execution_window = ExecutingWindow();
1.
LocalFrame* フレーム = execution_window->GetFrame();

フレーム内のドキュメント js オブジェクト
frame_->GetDocument()を取得します
 


 

localDomWindow がイベントを送信、プロトタイプ: DispatchEventResult LocalDOMWindow::DispatchEvent(Event& event,EventTarget* target)

 DispatchEvent(*Event::Create(event_type_names::kLanguagechange));

DispatchEvent(*PageTransitionEvent::Create(event_type_names::kPageshow,false /* 持続 */),document_.Get());

 
-----------------------------------
クロムブリンクコア概要
https://blog.51cto.com/u_15057855 /4536130

おすすめ

転載: blog.csdn.net/juruiyuan111/article/details/128427393