Skip to main content

DomBridge

Struct DomBridge 

Source
pub struct DomBridge {
Show 18 fields pub nodes: Vec<DomNode>, pub listeners: Vec<Listener>, pub dirty: bool, pub built: bool, pub rects: BTreeMap<usize, (i32, i32, i32, i32)>, pub border_widths: BTreeMap<usize, (i32, i32, i32, i32)>, pub computed_styles: BTreeMap<usize, BTreeMap<String, String>>, pub scroll_tops: BTreeMap<usize, i32>, pub scroll_heights: BTreeMap<usize, i32>, pub next_listener_id: u64, pub mut_observers: Vec<MutObsReg>, pub mut_records: Vec<(u32, MutRec)>, pub next_mut_obs_id: u32, pub pointer_captures: BTreeSet<(usize, i32)>, pub focused_idx: Option<usize>, pub pending_scroll_abs_y: Option<i32>, pub pending_scroll_by_y: Option<i32>, pub on_handlers: BTreeMap<(usize, String), Value>,
}
Expand description

DOM ブリッジ本体。JsRuntimeRc<RefCell<>> で保持し、レンダラと共有する。

Fields§

§nodes: Vec<DomNode>§listeners: Vec<Listener>§dirty: bool

JS が DOM を変更したフラグ。ホストはこれを見て再レイアウトする。

§built: bool

構築済みかどうか(未構築なら getElementById 等は空を返す)。

§rects: BTreeMap<usize, (i32, i32, i32, i32)>

レイアウト後の要素矩形 (x, y, w, h)(ページ座標)。getBoundingClientRect / offsetWidth 等が参照。レンダラが flatten 後に populate する。

§border_widths: BTreeMap<usize, (i32, i32, i32, i32)>

レイアウト後の各要素のborder幅 (top, right, bottom, left)。

§computed_styles: BTreeMap<usize, BTreeMap<String, String>>

算出スタイル(カスケード後の specified_values、kebab-case キー)。 getComputedStyle が参照。レンダラがスタイル適用後に populate する。

§scroll_tops: BTreeMap<usize, i32>

サブスクロールコンテナの現在 scrollTop (node_idx → px)。 JS が el.scrollTop = N で書き込み、レンダラが再レイアウト後に同期する。

§scroll_heights: BTreeMap<usize, i32>

サブスクロールコンテナの scrollHeight (node_idx → px)。 レンダラが parse_and_layout 後に populate する(コンテナ高 + scroll_max_y)。

§next_listener_id: u64

リスナ ID の発番カウンタ(once / removeEventListener 照合用)。

§mut_observers: Vec<MutObsReg>

登録済み MutationObserver。

§mut_records: Vec<(u32, MutRec)>

DOM 変更時に積まれるレコードキュー(observer_id, record)。

§next_mut_obs_id: u32

MutationObserver の ID 発番カウンタ。

§pointer_captures: BTreeSet<(usize, i32)>

setPointerCapture/releasePointerCapture/hasPointerCapture (Pointer Events。丸ごと未対応だった)が捕捉中の (node_idx, pointerId) 集合。 この処理系のイベント配信はヒットテストベースのため、実際にその後の pointer イベントをこの要素へ強制配送するところまでは配線しない (hasPointerCapture が仕様どおりの真偽を返せるようにする状態管理のみの 簡略実装。inert 属性のポインタ操作抑制のみ実装と同種の部分対応)。

§focused_idx: Option<usize>

document.activeElement/element.focus()/.blur()(HTML5。丸ごと 未対応だった)。現在フォーカス中のノード index。WebEngine::focused_id (レンダラ側の文字列キー版フォーカス状態)とは別に、JS 側から直接 読み書きできる node index ベースの状態としてここに持つ。レンダラの 実クリック/autofocus によるフォーカス変更も同期される(詳細は layout.rs/render.rsfocused_id 代入箇所を参照)。id/name 属性を 持たない要素へのレンダラ起点フォーカスは同期対象外(レンダラ自身の 既存の制約と同じ)。

§pending_scroll_abs_y: Option<i32>

window.scrollTo(x, y)/window.scroll(x, y)(丸ごと未対応だった。 実装はあったが SCROLL_Y という孤立した static へ書き込むのみで、 window.scrollY/実際のレンダラ描画位置のどちらにも一切反映されない 死んだ経路だった。2026-07-16 発見)。JS→レンダラの片方向同期用の 「保留中の絶対スクロール先」。focused_idxと同じ「レンダラが毎フレーム 消費する」設計だが、フォーカスと違い同一フレーム内での即時反映が 不要(次の描画で反映されれば十分)なため、render.rsdraw()冒頭 1箇所でのみ消費すればよく、.focus()のような10箇所以上への配線は 不要(改修規模がずっと小さい)。

§pending_scroll_by_y: Option<i32>

window.scrollBy(x, y)(丸ごと未対応だった。dom_noopのまま)。 複数回呼ばれた場合は加算し、次の描画で一括反映する。

§on_handlers: BTreeMap<(usize, String), Value>

element.onchange = fnのような GlobalEventHandlers IDL 属性(関数値)の 永続的な保管先。以前はObj::dom(idx)(呼び出す度に新規生成される使い捨ての ラッパーオブジェクト)自身の.propsへ書き込んでいたため、代入直後に そのRcが破棄されると値ごと消え、dispatchEvent側が同じObj::dom(idx)を 新規生成して読み直しても常に見つからない(=ハンドラが一切発火しない) 静かなバグだった。listeners(addEventListener系)と同じくDOM構造体側に 持たせることで、どのObj::dom(idx)インスタンス経由でも一貫して読み書き できるようにする。キーは(node_idx, "onchange"等のプロパティ名)

Implementations§

Source§

impl DomBridge

Source

pub fn new() -> Self

Source

pub fn set_on_handler(&mut self, node: usize, key: &str, val: Value)

element.onXXX = fn(関数値)の永続的な書き込み。

Source

pub fn get_on_handler(&self, node: usize, key: &str) -> Option<Value>

element.onXXXの読み出し。未設定ならNone

Source

pub fn set_pointer_capture(&mut self, idx: usize, pointer_id: i32)

element.setPointerCapture(pointerId)

Source

pub fn release_pointer_capture(&mut self, idx: usize, pointer_id: i32)

element.releasePointerCapture(pointerId)

Source

pub fn has_pointer_capture(&self, idx: usize, pointer_id: i32) -> bool

element.hasPointerCapture(pointerId)

Source

fn notify_child_list( &mut self, parent_idx: usize, added: Vec<usize>, removed: Vec<usize>, )

MutationObserver: childList 変化を記録するヘルパ。

Source

fn notify_attribute( &mut self, idx: usize, attr_name: &str, old_value: Option<&str>, )

MutationObserver: 属性変化を記録するヘルパ。attributeFilter が指定された 観察者はその一覧に無い属性名を無視し、attributeOldValue が指定された 観察者にのみ変更前の値をレコードへ積む(以前はどちらのオプションも 読み取られておらず、attributeFilter 指定時も無関係な属性の変化まで 全て通知され、oldValue は常に null 固定だった)。

Source

fn notify_character_data(&mut self, idx: usize, old_value: Option<&str>)

MutationObserver: テキストノードの内容変化を記録するヘルパ(丸ごと 未対応だった。notify_attributeと対になるcharacterData版。 idxは変化したテキストノード自身のインデックス〔仕様上 CharacterDataのmutationはテキストノード自身がtargetになる〕。 2026-07-17 発見・実装)。

Source

pub fn set_rect(&mut self, idx: usize, x: i32, y: i32, w: i32, h: i32)

レンダラがレイアウト後に要素矩形を登録する(getBoundingClientRect 等が参照)。

Source

pub fn get_rect(&self, idx: usize) -> Option<(i32, i32, i32, i32)>

Source

pub fn set_border_widths( &mut self, idx: usize, top: i32, right: i32, bottom: i32, left: i32, )

Source

pub fn get_border_widths(&self, idx: usize) -> (i32, i32, i32, i32)

Source

pub fn clear_rects(&mut self)

Source

pub fn set_computed_style(&mut self, idx: usize, prop: &str, val: &str)

算出スタイルを登録(kebab-case プロパティ→値)。

Source

pub fn get_computed(&self, idx: usize, prop: &str) -> String

算出スタイルを取得(無ければインライン style → 空)。

Source

pub fn clear_computed(&mut self)

Source

pub fn build_from(&mut self, root: &Node)

新しいページの DOM 木からブリッジを再構築する(リスナはクリア)。

Source

fn collect(node: &Node, parent: Option<usize>, out: &mut Vec<DomNode>) -> usize

木をドキュメント順(プリオーダ)に再帰収集。子インデックスを記録する。

Source

fn collect_text(&self, idx: usize) -> String

部分木のテキストを連結(textContent 相当)。現在値(override 優先)で集約。

Source

fn collect_text_into(&self, idx: usize, out: &mut String)

Source

pub fn build_id_index(&self) -> BTreeMap<&str, usize>

id → ノード添字の対応表を 1 回で作る。

【2026-08-05】get_element_by_id は全ノードの線形走査で、 しかも各ノードで is_attached が親を辿る。 レイアウト後の矩形反映では要素 1 個ごとにこれを呼んでおり、 O(要素 × ノード × 深さ) になっていた(実測で要素・ノードとも約 369)。

走査 1 回で表を作れば、引く側は O(log N) で済む。 条件(テキストノードでない・id が空でない・ルートから到達可能)は get_element_by_id と揃えてある。同じ id が複数あれば先勝ち (find と同じ)。

計算量: O(N × D)(N はノード数、D は木の深さ)。

Source

pub fn get_element_by_id(&self, id: &str) -> Option<usize>

Source

pub fn is_attached(&self, idx: usize) -> bool

node[0](ルート)から到達可能か。createElement 直後や remove 済みは false。 node.isConnected(丸ごと未対応だった)向けに公開する。

Source

pub fn query(&self, selector: &str) -> Option<usize>

単純セレクタ(#id / .class / tag、先頭一致)にマッチする最初のノード。

Source

pub fn query_all(&self, selector: &str) -> Vec<usize>

セレクタにマッチする全ノード(ドキュメント順)。以前は node_matches と同じ 単純セレクタ限定の簡略実装が独立に重複しており、querySelectorAll('div.active') 等のコンパウンドセレクタが常に空になる同型のバグだった。node_matches と 共通の compound_matches/match_selector_chain に統一して解消する。

Source

pub fn query_all_scoped( &self, selector: &str, scope_root: Option<usize>, ) -> Vec<usize>

query_all:scope 対応版。element.querySelectorAll/querySelector の起点要素を scope_root として渡すと、セレクタ中の :scope 疑似クラス (Selectors Level 4。丸ごと未対応だった)がそのノードにのみ一致するように なる(詳細は node_matches_scoped 参照)。

Source

pub fn set_text_content(&mut self, idx: usize, val: &str)

要素の textContent を設定。子孫テキストノードがあれば最初に値を入れ残りを空に、 無ければ既存の子を捨てて単一テキスト子を作る(createElement したノード等)。

Source

pub fn normalize_node(&mut self, idx: usize)

node.normalize()(丸ごと未対応だった。DOM 標準メソッドで、連続する隣接テキスト ノードを1つに連結し、空のテキストノードを取り除く。textContent を何度も 部分的に書き換えた後などに呼ばれる定番の掃除用メソッド)。子孫を再帰的に処理する。

Source

fn text_of(&self, idx: usize) -> String

テキストノードの実効テキスト(text_override があればそれ、無ければ initial_text)。collect_text_into と同じ参照パターン。

Source

fn new_element_node(&mut self, tag: &str) -> usize

Source

fn new_text_node(&mut self, text: &str) -> usize

Source

pub fn create_element(&mut self, tag: &str) -> usize

document.createElement(tag)。デタッチ状態のノードを返す。

Source

pub fn create_text_node(&mut self, text: &str) -> usize

document.createTextNode(text)

Source

pub fn create_comment(&mut self, text: &str) -> usize

document.createComment(text)

Source

pub fn create_document_fragment(&mut self) -> usize

document.createDocumentFragment()(丸ごと未対応だった)。仕様どおり、 #fragment という特殊タグの要素として表現する。この要素自身は決して root から到達可能(is_attached)にならず、append_child/insert_before に渡されると自身ではなく子要素群がそのまま挿入先へ移動し、自身は空になる (実 DOM の DocumentFragment の「挿入すると中身だけが移動する」挙動を再現)。

Source

pub fn template_content(&mut self, idx: usize) -> usize

template.content<template> が丸ごと未対応だった)。仕様上 <template> の子は「不活性」で通常の DOM ツリーには存在せず、代わりに .contentDocumentFragment)経由でのみアクセスできる。この処理系は HTML パース時に template を特別扱いしないため子が普通にライブツリーへ入ってしまうが、 初回アクセス時にその子を #fragment ノードへ移し替え(内部専用属性 _content_frag にフラグメントの index をキャッシュ)、以後は同じフラグメントを 返すことで「以後 <template> 自身は空、.content だけが中身を持つ」という 仕様どおりの見た目に近づける。

Source

fn expand_fragment(&mut self, child: usize) -> Vec<usize>

child が DocumentFragment(#fragment タグ)なら、その子要素群を 親から切り離して返し、フラグメント自身は空にする。それ以外は [child] を そのまま返す(append_child/insert_before の共通前処理)。

Source

pub fn append_child(&mut self, parent: usize, child: usize)

parent.appendChild(child)。既存の親から外して付け替える。child が DocumentFragment の場合は仕様どおりその子要素群を代わりに追加する。

Source

pub fn remove_child(&mut self, parent: usize, child: usize)

parent.removeChild(child) / child.remove()

Source

pub fn remove_node(&mut self, idx: usize)

Source

pub fn insert_before( &mut self, parent: usize, new_child: usize, ref_child: Option<usize>, )

parent.insertBefore(new_child, ref_child)。ref が None/不在なら末尾に追加。 new_child が DocumentFragment の場合は仕様どおりその子要素群を代わりに挿入する。

Source

pub fn replace_child( &mut self, parent: usize, new_child: usize, old_child: usize, )

parent.replaceChild(new_child, old_child)。old を new で置換。

Source

pub fn clone_node(&mut self, idx: usize, deep: bool) -> usize

node.cloneNode(deep)。属性/テキストをコピーした新ノードを作る(親なし)。deep なら子も再帰。

Source

fn detach(&mut self, idx: usize)

親の children から idx を外す。

Source

pub fn insert_adjacent_node(&mut self, idx: usize, position: &str, node: usize)

単一ノードを基準ノード idx の相対位置へ挿入(insertAdjacent* 共通)。

Source

pub fn insert_adjacent_html(&mut self, idx: usize, position: &str, html: &str)

element.insertAdjacentHTML(position, html)。html をパースして相対位置へ挿入。

Source

pub fn set_inner_html(&mut self, idx: usize, html: &str)

element.innerHTML = html。フラグメントをパースして子を置換する。 appendChild/removeChild/insertBefore/replaceChild は全て notify_child_list 経由で MutationObserver に通知していたが、 innerHTML 代入だけがこの呼び出しを欠いており、最も頻繁に使われる DOM 書き換え手段にもかかわらず childList 変化が一切観察できなかった。

Source

pub fn set_outer_html(&mut self, idx: usize, html: &str)

element.outerHTML = html。自ノードを HTML パース結果のノード群で置き換える。

Source

fn import_node(&mut self, node: &Node) -> usize

dom::Node 部分木をブリッジへ取り込み、ルート idx を返す。

Source

pub fn to_dom_node(&self) -> Node

ブリッジツリー(node[0] をルート)を dom::Node へ変換する。 JS の変更(textContent/style/class/動的ノード)が反映された描画用ツリー。

Source

fn build_node(&self, idx: usize) -> Node

Source

pub fn get_text_content(&self, idx: usize) -> String

要素の textContent(現在値)を取得。

Source

fn descendant_text_nodes(&self, idx: usize) -> Vec<usize>

Source

fn descendant_text_into(&self, idx: usize, out: &mut Vec<usize>)

Source

pub fn set_style(&mut self, idx: usize, prop: &str, val: &str)

Source

pub fn get_style(&self, idx: usize, prop: &str) -> String

Source

pub fn get_style_priority(&self, idx: usize, prop: &str) -> String

element.style.getPropertyPriority(name)(丸ごと未対応だった。 2026-07-16 発見)。!important は生の値文字列末尾にそのまま保持 されている(set_style/css_prop_from_camel 参照)ため、 strip_style_priority で判定するだけで済む。

Source

pub fn get_css_text(&self, idx: usize) -> String

element.style.cssText の読み出し。以前は丸ごと未対応で、cssText を単なる 通常の CSS プロパティ名として扱う既存の汎用経路(get_style)に落ちてしまい、 常に空文字列を返していた(serialize_inline_style 自体は属性文字列の再構築で 既に使われていたが、JS からの読み出しには配線されていなかった)。

Source

pub fn set_css_text(&mut self, idx: usize, text: &str)

element.style.cssText = "..." の書き込み。単一プロパティとして扱われ常に 無視されていたのを、既存のスタイル属性パーサ(parse_inline_style)で丸ごと 置き換えるよう実装する。

Source

pub fn get_outer_html(&self, idx: usize) -> String

element.outerHTML(読み出し専用。書き込み側は要素の親子関係の組み替えが 必要で改修規模が大きいため今回は見送り)が丸ごと未対応だった。自身のタグ・属性 (id/class/style を含む)・子孫を再帰的に HTML 文字列へ直列化する。

Source

pub fn get_inner_html(&self, idx: usize) -> String

element.innerHTML の読み出しが、実際にはマークアップ(子要素タグ)を含めず textContent と同じ「全テキストを連結しただけ」の値を返してしまっていたバグ。 <div>a<b>bold</b></div>innerHTML が仕様どおりの "a<b>bold</b>" ではなく "abold" になっていた。自身のタグは含めず、子ノードだけを直列化する。

Source

fn serialize_node_html(&self, idx: usize, out: &mut String)

Source

pub fn class_add(&mut self, idx: usize, cls: &str)

Source

pub fn class_remove(&mut self, idx: usize, cls: &str)

Source

pub fn class_toggle(&mut self, idx: usize, cls: &str) -> bool

Source

pub fn class_contains(&self, idx: usize, cls: &str) -> bool

Source

fn collect_descendant_options(&self, idx: usize, out: &mut Vec<usize>)

<select>配下の<option>要素を全て集める(<optgroup>でグループ化 された<option>も含む再帰探索。丸ごと未対応だった。以前は直接の子 のみを見る実装だったため、``という非常によく使われる カテゴリ分けパターンで、``配下の`

Source

pub fn select_options(&self, idx: usize) -> Vec<usize>

<select> の option 子要素一覧(<optgroup>配下も含む)。select. options(丸ごと未対応だった。動的にドロップダウンを構築する定番 イディオムで使われる)向けに公開する。

Source

fn option_value(&self, opt_idx: usize) -> String

option 要素の実効値: value 属性があればそれ、無ければテキスト内容 (仕様どおり。collect_form_data の select フォールバックと同じ規則)。

Source

pub fn selected_option_indices(&self, idx: usize) -> Vec<usize>

select.selectedOptions<select multiple> で選択中の option 一覧を得る 定番イディオム。FormData の multi-select 対応と同じく selected 属性を 真実源とする)。単一選択の <select> でも仕様どおり動作する (selected が無ければ既定選択の最初の option を1件返す)。

Source

pub fn select_effective_value(&self, idx: usize) -> String

select.value(丸ごと未対応だった。<select> 自身に value 属性は無く、 選択状態は子の <option selected> が持つため、汎用の属性直結 getter では 常に空文字列になっていた)。selected な option を優先し、無ければ HTML の既定選択どおり最初の option にフォールバックする。

Source

pub fn effective_form_value(&self, idx: usize) -> String

フォーム系コントロールの「現在の実効値」を文字列で解決する。 checkValidity()/.validationMessage/.validityが素朴に get_attr(idx,"value")だけを見ており、value属性を持たない <select>(選択状態は子<option selected>が持つ)や、初期値が value属性ではなくテキストノードで表現される<textarea>では 常に空文字列として(=未入力として)誤って検証されてしまうバグの 共通修正用。.valueゲッター(dom_props.rs)と同じフォールバック 規則をここに一本化する。

Source

pub fn set_select_value(&mut self, idx: usize, val: &str)

select.value = v(丸ごと未対応だった)。value が一致する最初の option へ 選択を移す(他の option の selected は解除。仕様どおり単一選択)。

Source

pub fn select_selected_index(&self, idx: usize) -> i32

select.selectedIndex(丸ごと未対応だった)。selected な option の位置、 無ければ option が1つ以上あれば 0(既定選択)、無ければ -1

Source

pub fn set_select_selected_index(&mut self, idx: usize, n: i32)

select.selectedIndex = n

Source

pub fn set_select_length(&mut self, idx: usize, n: usize)

select.length = n(HTML5。select.options.lengthと同じ値を返す ゲッター兼、nより末尾のoptionを切り捨てる/不足分を空の<option>で 埋めるセッター。丸ごと未対応だった)。仕様どおり、新しい長さが現在より 小さければ末尾から削除、大きければ空の<option>を追加する。

Source

pub fn option_index(&self, idx: usize) -> i32

option.index(HTML5。自身が属する<select>内での0始まりの位置。 select.selectedIndexの対になる、<option>側のIDL属性だが丸ごと 未対応だった)。<select>祖先が無い場合は仕様どおり0(要素が 「optionのリスト」に属さない場合の既定値。<datalist>配下は 対象外の簡略実装)。

Source

pub fn get_attr(&self, idx: usize, name: &str) -> Option<String>

Source

pub fn set_attr(&mut self, idx: usize, name: &str, val: &str)

Source

pub fn has_attr(&self, idx: usize, name: &str) -> bool

属性が存在するか(空値の boolean 属性も存在として true。id/class は専用フィールド)。

Source

pub fn remove_attr(&mut self, idx: usize, name: &str)

属性を削除(id/class フィールドも同期)。

Source

pub fn close_details_group_siblings(&mut self, idx: usize) -> Vec<usize>

<input type="radio"> の排他選択(同じ name を持つグループ内で1つだけが checked になる、というラジオボタンの最も基本的な仕様上の挙動)。idx を checked にする際、同じ name を持つ他の radio 全ての checked 属性を外す。 フォーム所有者(<form> 単位のスコープ)は区別せず、同じ name を持つ document 内の全 radio を対象にする簡略実装。 <details name="...">(HTML5。同じnameを持つ<details>同士は ラジオボタングループのように排他的に開閉する——1つを開くと同じ グループの他の<details>は自動的に閉じる——仕様が丸ごと未対応 だった。uncheck_radio_group_siblingsと同じ「name属性が一致する 兄弟(ドキュメント全体、DOM上の兄弟関係は問わない)を探して状態を 揃える」パターンをそのまま適用する。2026-07-18 発見・実装)。

Source

pub fn uncheck_radio_group_siblings(&mut self, idx: usize)

Source

pub fn node_matches(&self, idx: usize, selector: &str) -> bool

単一ノードがセレクタ(コンパウンド + 結合子、カンマ区切りは OR)にマッチするか。 matches()/closest()/querySelector(All) 共通の実装本体。以前は #id/.class/ tag/* の単純セレクタしか認識せず、div.active(コンパウンド)や [data-x] (属性セレクタ)、.a > .b(結合子)を渡すと文字列全体を tag 名として比較する 分岐に落ち、常に false になる静かな破壊バグだった(:not()/:nth-child()/ :is()/:where() 等の疑似クラスは引き続き非対応。改修規模を絞るための 意図的な割り切り)。

Source

pub fn node_matches_scoped( &self, idx: usize, selector: &str, scope_root: Option<usize>, ) -> bool

node_matches:scope 対応版。scope_rootelement. querySelectorAll/matches/closest 等の起点ノードを渡すと、セレクタ中の :scope 疑似クラス(Selectors Level 4。丸ごと未対応だった)がそのノードに のみ一致するようになる。scope_rootNonedocument.querySelectorAll 等、起点を持たない文脈)の場合は :scope は常に不一致として扱う簡略実装。

Source

fn compound_matches( &self, idx: usize, c: &CompoundSel, scope_root: Option<usize>, ) -> bool

idx がコンパウンドセレクタ(タグ/#id/.class/[attr...])に一致するか。

Source

fn element_sibling_position(&self, idx: usize) -> (usize, usize)

idx の「要素兄弟のみを数えた」1始まりの位置と、要素兄弟の総数を返す (テキストノードは数えない。CSS の :nth-child() 等と同じ規則)。

Source

fn element_type_sibling_position(&self, idx: usize) -> (usize, usize)

element_sibling_position と同じだが、同じタグ名の兄弟のみを数える (:first-of-type/:last-of-type/:nth-of-type() 用)。

Source

fn match_selector_chain( &self, idx: usize, steps: &[SelStep], step_i: usize, scope_root: Option<usize>, ) -> bool

idxsteps[step_i] に既に一致した状態で呼ばれる。steps[0..step_i] を 結合子に従って祖先/兄弟方向へ再帰的に検証する。

Source

fn prev_element_sibling(&self, idx: usize) -> Option<usize>

idx の直前の要素兄弟(テキストノードは飛ばす)。

Source

fn preceding_element_siblings(&self, idx: usize) -> Vec<usize>

idx より前にある全ての要素兄弟(テキストノードは飛ばす、ドキュメント順)。

Source

pub fn is_ancestor_of(&self, anc: usize, idx: usize) -> bool

anc が idx の祖先か(idx 自身は含まない)。

Source

pub fn document_position(&self, this_idx: usize, other_idx: usize) -> u32

Node.compareDocumentPosition(other)(DOM標準)が丸ごと未対応だった。 this_idx(reference node)から見た other_idx の位置関係をビットマスクで返す (DOCUMENT_POSITION_* 定数は呼び出し側 builtins.rs で定義)。祖先/子孫関係は 既存の is_ancestor_of で判定し、それ以外(兄弟や別分岐)は両者の祖先鎖を根まで 辿って最も近い共通祖先(LCA)の子リスト内での順序を比較する。根が異なる (disconnected)場合、仕様上 PRECEDING/FOLLOWING の割当ては実装依存でよいため ノードindexの大小で決定的に決める。

Source

pub fn offset_parent(&self, idx: usize) -> Option<usize>

idx 自身を含め祖先方向へ、指定タグの最初の要素を返す(<form> 解決等)。 element.offsetParent(HTML5。丸ごと未対応だった)。祖先を遡り、算出 positionstatic 以外の最初の要素を返す。無ければ <body> (見つからなければ None = 仕様どおり null)。

Source

pub fn closest_tag(&self, idx: usize, tag: &str) -> Option<usize>

Source

pub fn associated_form(&self, idx: usize) -> Option<usize>

フォーム系コントロールが実際に属する<form>を解決する。HTML5仕様では form="formId"属性(<form>の子孫でなくても、そのidで明示的に関連付ける 「form owner」機構)が祖先探索より優先される。以前はclosest_tag(idx, "form")(祖先探索のみ)しか実装されておらず、<form id="f1">の外に置かれた <input form="f1">(フォーム外配置は<form>の視覚レイアウトを変えずに コントロールだけ離れた場所に置きたい場合の定番パターン)が element.formnullになり、<form>.checkValidity()/送信データ収集からも 漏れる、という兄弟ギャップだった。

Source

pub fn form_associated_controls( &self, form_idx: usize, tags: &[&str], ) -> Vec<usize>

<form id="f1">に属するtagsに含まれるタグの全フォームコントロールを 収集する。子孫に加えて、form="f1"属性でフォーム外から明示的に関連付けられた コントロール(associated_formと対になる「form owner」機構)も含む。 checkValidity()/FormData収集/form.elementsの各<form>祖先ループが フォーム外配置のコントロールを見落としていた兄弟ギャップの修正に使う (呼び出し側ごとに対象タグが異なる: checkValidity/FormDatainput/select/textareaのみ、form.elementsはそれにbuttonも含む)。

Source

pub fn first_by_tag(&self, tag: &str) -> Option<usize>

ドキュメント順で最初の指定タグ要素。

Source

pub fn element_children(&self, idx: usize) -> Vec<usize>

子のうち要素(非テキスト)ノードの index 一覧。

Source

pub fn descendants_by_tag_name(&self, root: usize, tag: &str) -> Vec<usize>

root 以下(自身は含まない)の子孫のうち、tag が tags のいずれかに一致するものを 文書順で収集する。フォーム配下の入力欄列挙(バリデーション)に使用。 element.getElementsByTagName(tag) 用の子孫走査。tag"*" なら全要素。

§なぜ文書全体の検索を使わないか

query_allis_attached文書に繋がっていないノードを除外する。 仕様では getElementsByTagName文書への接続に関係なく自分の子孫を 返すので、切り離した要素(createElement した直後など)では結果が 空になってしまう。

jQuery 1.8.2 の機能検出はまさにこれをやる: 切り離した <div>innerHTML を入れ、getElementsByTagName("a")[0]style を触る。空が返ると undefinedstyle を読んで落ち、 jQuery 全体が初期化できなくなっていた

なお is_attached は根(索引 0)まで遡る実装のため、空の DOM では 最初に作った要素自身が索引 0 になり偶然「接続済み」になる。 単体試験を空のランタイムで書くとこの不具合を再現できない (実際に 5 回取り逃がした)。試験は実ページの DOM で確かめること。

Source

pub fn descendants_by_tags(&self, root: usize, tags: &[&str]) -> Vec<usize>

Source

pub fn is_disabled(&self, idx: usize) -> bool

<fieldset disabled>の子孫コントロールは、自身にdisabled属性が無くても 暗黙に無効化される(HTML5仕様の「fieldset disabling」)。以前は要素自身の disabled属性の有無しか見ておらず、<fieldset disabled>配下の<input>.disabledが常にfalse、制約バリデーションも無効化されずに常に対象内の ままになっていた。祖先をparentで遡り<fieldset disabled>が1つでも あれば無効とみなす(<fieldset>の最初の子<legend>直下のコントロールは 無効化対象外という仕様上の例外は、この処理系のフォーム系テストでは実用上 ほぼ現れないため今回は簡略化して見送る)。

Source

pub fn validity_flags(&self, idx: usize, value: &str) -> ValidityFlags

ValidityState の各フラグを個別に計算する(validate_field は最初に見つかった 違反のメッセージ1件しか返さないため、.validity.patternMismatch のような特定 制約の狙い撃ちには使えなかった)。validate_field と同じ規則を、短絡させずに 全項目評価する。

Source

fn required_satisfied( &self, n: &DomNode, input_type: &str, trimmed_value: &str, ) -> bool

required制約が充足されているかを判定する。checkboxは自身のcheckedradioは同じnameグループ内のいずれかがcheckedであれば充足(HTML5 仕様どおり)。それ以外のinput/select/textareavalue(trim後)が 空でなければ充足。validate_field/validity_flagsの両方から共通で使う。

Source

pub fn validate_field(&self, idx: usize, value: &str) -> Option<String>

HTML5 制約バリデーション。フィールド要素 idx と現在値 value を検査し、 違反があればユーザー向けメッセージを返す(None = 妥当)。 対応: setCustomValidity(_custom_validity) / required / minlength / maxlength / pattern / type=email / type=url / type=number,range(min,max,step)。 disabled/readonly や type=submit/button/hidden は検証対象外。

Source

fn is_valid_email(s: &str) -> bool

簡易メールアドレス検証(完全な RFC ではなく実用的な近似)。

Source

fn is_valid_email_value(n: &DomNode, value: &str) -> bool

<input type="email" multiple>(HTML5。multiple属性がある email input は カンマ区切りで複数アドレスを入力できる仕様だが、以前はis_valid_email(value) を値全体にそのまま適用しており、2件目以降のアドレスやカンマ自体を含む文字列は 単一アドレスとして常に不正と誤判定されていた(逆にmultipleが無いのに カンマ区切りを入力した場合はこのメソッドを経由しないため今までどおり単一 アドレスとして正しく不正判定される)。空要素("a@b.com,"のような末尾カンマ) は仕様上不正。

Source

fn pattern_matches(pat: &str, val: &str) -> bool

<input pattern="...">(HTML Living Standard の制約検証。仕様上は値全体を ^(?:pattern)$ として完全一致させる)が、以前はメタ文字を含む複雑なパターンを 「誤検知で送信を妨げないため」全て無条件で通過させる簡易近似だった。この エンジンには既に本物の正規表現実装(js::regex::Regex)があるため、それを そのまま使えば近似ではなく正しく検証できる(\d/[...]/+/.* 等、 HTML pattern で使われる構文は通常の JS RegExp と同じ)。

Source

pub fn attr_names(&self, idx: usize) -> Vec<String>

属性名の一覧(id/class を先頭に、続いてその他属性)。

Source

pub fn add_listener(&mut self, node: usize, event: &str, func: Value)

Source

pub fn add_listener_opts( &mut self, node: usize, event: &str, func: Value, capture: bool, once: bool, ) -> u64

capture / once オプション付きでリスナを登録する。重複(同一 node+event+func+capture) は DOM 仕様どおり無視する。戻り値は発番した ID。

Source

pub fn add_listener_opts_signal( &mut self, node: usize, event: &str, func: Value, capture: bool, once: bool, signal: Option<Value>, ) -> u64

add_listener_opts{signal} 対応版。signal が既に abort 済みなら 仕様どおり登録自体を行わない。

Source

pub fn remove_listener( &mut self, node: usize, event: &str, func: &Value, capture: bool, )

removeEventListener: 同一 (node, event, func, capture) のリスナを削除する。

Source

pub fn remove_listener_by_id(&mut self, id: u64)

ID 指定でリスナを削除する(once 発火後の自動削除に使う)。

Source

pub fn has_listener(&self, event: &str) -> bool

指定イベント型のリスナがページ内に1つでも登録されているか(ホバー判定の省略用)。

Source

pub fn listeners_for(&self, node: usize, event: &str) -> Vec<Value>

指定ノードに登録された指定イベントのリスナ関数を返す(呼び出しは呼び元で)。 バブリングフェーズ用(capture=false のみ)。{signal} が abort 済みの リスナは除外する。

Source

pub fn listeners_phase( &self, node: usize, event: &str, want_capture: bool, ) -> Vec<(Value, bool, u64)>

指定ノード・イベントのリスナを (func, capture, once, id) 付きで返す。 want_capture でキャプチャ/バブルのどちらのフェーズかを絞り込む。 {signal} が abort 済みのリスナは除外する。

Source

pub fn has_listener_on(&self, node: usize, event: &str) -> bool

指定ノードに当該イベントのリスナ(フェーズ問わず)が在るか。

Source

pub fn apply_overrides(&self, root: &mut Node)

再パースした DOM 木へ JS の変更を焼き戻す。木はビルド時と同一ドキュメント順前提。

Source

fn apply_node(&self, node: &mut Node, counter: &mut usize)

Trait Implementations§

Source§

impl Default for DomBridge

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.