Merge pull request #471 from mnaza/fix/treewalker-movers-469
fix(js): descend on FILTER_SKIP in TreeWalker child/sibling movers (#469)
This commit is contained in:
3 files changed
+423
-26
No files matched your search
@@ -0,0 +1,283 @@
|
|||||||
|
Compiling proc-macro2 v1.0.106
|
||||||
|
Compiling quote v1.0.45
|
||||||
|
Compiling unicode-ident v1.0.24
|
||||||
|
Compiling libc v0.2.186
|
||||||
|
Compiling cfg-if v1.0.4
|
||||||
|
Compiling parking_lot_core v0.9.12
|
||||||
|
Compiling serde_core v1.0.228
|
||||||
|
Compiling serde v1.0.228
|
||||||
|
Compiling smallvec v1.15.2
|
||||||
|
Compiling icu_properties_data v2.2.0
|
||||||
|
Compiling icu_normalizer_data v2.2.0
|
||||||
|
Compiling stable_deref_trait v1.2.1
|
||||||
|
Compiling pin-project-lite v0.2.17
|
||||||
|
Compiling version_check v0.9.5
|
||||||
|
Compiling scopeguard v1.2.0
|
||||||
|
Compiling itoa v1.0.18
|
||||||
|
Compiling memchr v2.8.2
|
||||||
|
Compiling typenum v1.20.1
|
||||||
|
Compiling lock_api v0.4.14
|
||||||
|
Compiling bytes v1.11.1
|
||||||
|
Compiling crc32fast v1.5.0
|
||||||
|
Compiling zmij v1.0.21
|
||||||
|
Compiling generic-array v0.14.7
|
||||||
|
Compiling rand_core v0.6.4
|
||||||
|
Compiling thiserror v2.0.18
|
||||||
|
Compiling rand v0.8.6
|
||||||
|
Compiling serde_json v1.0.150
|
||||||
|
Compiling subtle v2.6.1
|
||||||
|
Compiling futures-core v0.3.32
|
||||||
|
Compiling syn v2.0.117
|
||||||
|
Compiling glob v0.3.3
|
||||||
|
Compiling litemap v0.8.2
|
||||||
|
Compiling writeable v0.6.3
|
||||||
|
Compiling utf8_iter v1.0.4
|
||||||
|
Compiling prettyplease v0.2.37
|
||||||
|
Compiling clang-sys v1.8.1
|
||||||
|
Compiling siphasher v1.0.3
|
||||||
|
Compiling getrandom v0.2.17
|
||||||
|
Compiling errno v0.3.14
|
||||||
|
Compiling mio v1.2.1
|
||||||
|
Compiling socket2 v0.6.4
|
||||||
|
Compiling signal-hook-registry v1.4.8
|
||||||
|
Compiling autocfg v1.5.1
|
||||||
|
Compiling parking_lot v0.12.5
|
||||||
|
Compiling futures-sink v0.3.32
|
||||||
|
Compiling phf_shared v0.11.3
|
||||||
|
Compiling crypto-common v0.1.7
|
||||||
|
Compiling rustix v0.38.44
|
||||||
|
Compiling regex-syntax v0.8.11
|
||||||
|
Compiling percent-encoding v2.3.2
|
||||||
|
Compiling num-traits v0.2.19
|
||||||
|
Compiling either v1.16.0
|
||||||
|
Compiling bitflags v2.13.0
|
||||||
|
Compiling minimal-lexical v0.2.1
|
||||||
|
Compiling phf_generator v0.11.3
|
||||||
|
Compiling futures-channel v0.3.32
|
||||||
|
Compiling nom v7.1.3
|
||||||
|
Compiling libloading v0.8.9
|
||||||
|
Compiling linux-raw-sys v0.4.15
|
||||||
|
Compiling bindgen v0.71.1
|
||||||
|
Compiling rustc-hash v2.1.2
|
||||||
|
Compiling itertools v0.13.0
|
||||||
|
Compiling log v0.4.32
|
||||||
|
Compiling futures-io v0.3.32
|
||||||
|
Compiling shlex v1.3.0
|
||||||
|
Compiling adler2 v2.0.1
|
||||||
|
Compiling home v0.5.12
|
||||||
|
Compiling once_cell v1.21.4
|
||||||
|
Compiling hashbrown v0.17.1
|
||||||
|
Compiling regex-automata v0.4.14
|
||||||
|
Compiling equivalent v1.0.2
|
||||||
|
Compiling radium v0.7.0
|
||||||
|
Compiling slab v0.4.12
|
||||||
|
Compiling futures-task v0.3.32
|
||||||
|
Compiling indexmap v2.14.0
|
||||||
|
Compiling cexpr v0.6.0
|
||||||
|
Compiling miniz_oxide v0.8.9
|
||||||
|
Compiling gzip-header v1.1.0
|
||||||
|
Compiling form_urlencoded v1.2.2
|
||||||
|
Compiling fslock v0.2.1
|
||||||
|
Compiling find-msvc-tools v0.1.9
|
||||||
|
Compiling shlex v2.0.1
|
||||||
|
Compiling cc v1.2.64
|
||||||
|
Compiling which v6.0.3
|
||||||
|
Compiling http v1.4.2
|
||||||
|
Compiling paste v1.0.15
|
||||||
|
Compiling synstructure v0.13.2
|
||||||
|
Compiling regex v1.12.4
|
||||||
|
Compiling heck v0.5.0
|
||||||
|
Compiling httparse v1.10.1
|
||||||
|
Compiling ring v0.17.14
|
||||||
|
Compiling tracing-core v0.1.36
|
||||||
|
Compiling phf_codegen v0.11.3
|
||||||
|
Compiling block-buffer v0.10.4
|
||||||
|
Compiling alloc-no-stdlib v2.0.4
|
||||||
|
Compiling zerofrom-derive v0.1.7
|
||||||
|
Compiling yoke-derive v0.8.2
|
||||||
|
Compiling zerovec-derive v0.11.3
|
||||||
|
Compiling displaydoc v0.2.6
|
||||||
|
Compiling serde_derive v1.0.228
|
||||||
|
Compiling tokio-macros v2.7.0
|
||||||
|
Compiling futures-macro v0.3.32
|
||||||
|
Compiling thiserror-impl v2.0.18
|
||||||
|
Compiling deno_error_macro v0.6.1
|
||||||
|
Compiling sys_traits_macros v0.1.0
|
||||||
|
Compiling zerofrom v0.1.8
|
||||||
|
Compiling yoke v0.8.3
|
||||||
|
Compiling tokio v1.52.3
|
||||||
|
Compiling zerotrie v0.2.4
|
||||||
|
Compiling zerovec v0.11.6
|
||||||
|
Compiling futures-util v0.3.32
|
||||||
|
Compiling tinystr v0.8.3
|
||||||
|
Compiling potential_utf v0.1.5
|
||||||
|
Compiling icu_locale_core v2.2.0
|
||||||
|
Compiling icu_collections v2.2.0
|
||||||
|
Compiling cpufeatures v0.2.17
|
||||||
|
Compiling zeroize v1.9.0
|
||||||
|
Compiling anyhow v1.0.102
|
||||||
|
Compiling icu_provider v2.2.0
|
||||||
|
Compiling getrandom v0.4.2
|
||||||
|
Compiling icu_properties v2.2.0
|
||||||
|
Compiling icu_normalizer v2.2.0
|
||||||
|
Compiling idna_adapter v1.2.2
|
||||||
|
Compiling idna v1.1.0
|
||||||
|
Compiling rustls-pki-types v1.14.1
|
||||||
|
Compiling url v2.5.8
|
||||||
|
Compiling v8 v137.3.0
|
||||||
|
Compiling alloc-stdlib v0.2.2
|
||||||
|
Compiling tracing-attributes v0.1.31
|
||||||
|
Compiling digest v0.10.7
|
||||||
|
Compiling http-body v1.0.1
|
||||||
|
Compiling new_debug_unreachable v1.0.6
|
||||||
|
Compiling simd-adler32 v0.3.9
|
||||||
|
Compiling untrusted v0.9.0
|
||||||
|
Compiling proc-macro-rules-macros v0.4.0
|
||||||
|
Compiling tracing v0.1.44
|
||||||
|
Compiling deno_error v0.6.1
|
||||||
|
Compiling brotli-decompressor v5.0.1
|
||||||
|
Compiling phf_macros v0.11.3
|
||||||
|
Compiling strum_macros v0.27.2
|
||||||
|
Compiling capacity_builder_macros v0.3.0
|
||||||
|
Compiling pin-project-internal v1.1.13
|
||||||
|
Compiling block-padding v0.3.3
|
||||||
|
Compiling tap v1.0.1
|
||||||
|
Compiling rustls v0.23.40
|
||||||
|
Compiling tower-service v0.3.3
|
||||||
|
Compiling try-lock v0.2.5
|
||||||
|
Compiling utf-8 v0.7.6
|
||||||
|
Compiling wyz v0.5.1
|
||||||
|
Compiling want v0.3.1
|
||||||
|
Compiling brotli v8.0.3
|
||||||
|
Compiling inout v0.1.4
|
||||||
|
Compiling phf v0.11.3
|
||||||
|
Compiling num-integer v0.1.46
|
||||||
|
Compiling flate2 v1.1.9
|
||||||
|
Compiling rustls-webpki v0.103.13
|
||||||
|
Compiling proc-macro-rules v0.4.0
|
||||||
|
Compiling string_cache_codegen v0.5.4
|
||||||
|
Compiling stringcase v0.4.0
|
||||||
|
Compiling funty v2.0.0
|
||||||
|
Compiling compression-core v0.4.32
|
||||||
|
Compiling uuid v1.23.3
|
||||||
|
Compiling atomic-waker v1.1.2
|
||||||
|
Compiling mac v0.1.1
|
||||||
|
Compiling outref v0.5.2
|
||||||
|
Compiling precomputed-hash v0.1.1
|
||||||
|
Compiling vsimd v0.8.0
|
||||||
|
Compiling futf v0.1.5
|
||||||
|
Compiling hyper v1.10.1
|
||||||
|
Compiling debugid v0.8.0
|
||||||
|
Compiling bitvec v1.0.1
|
||||||
|
Compiling markup5ever v0.14.1
|
||||||
|
Compiling strum v0.27.2
|
||||||
|
Compiling base64-simd v0.8.0
|
||||||
|
Compiling deno_ops v0.226.0
|
||||||
|
Compiling futures-executor v0.3.32
|
||||||
|
Compiling compression-codecs v0.4.38
|
||||||
|
Compiling num-bigint v0.4.6
|
||||||
|
Compiling cipher v0.4.4
|
||||||
|
Compiling sys_traits v0.1.28
|
||||||
|
Compiling sync_wrapper v1.0.2
|
||||||
|
Compiling tower-layer v0.3.3
|
||||||
|
Compiling ipnet v2.12.0
|
||||||
|
Compiling dtoa v1.0.11
|
||||||
|
Compiling unicode-id-start v1.4.0
|
||||||
|
Compiling data-encoding v2.11.0
|
||||||
|
Compiling bit-vec v0.8.0
|
||||||
|
Compiling base64 v0.22.1
|
||||||
|
Compiling if_chain v1.0.3
|
||||||
|
Compiling zerocopy v0.8.52
|
||||||
|
Compiling rustix v1.1.4
|
||||||
|
Compiling getrandom v0.3.4
|
||||||
|
Compiling serde_v8 v0.259.0
|
||||||
|
Compiling hyper-util v0.1.20
|
||||||
|
Compiling bit-set v0.8.0
|
||||||
|
Compiling sourcemap v9.3.2
|
||||||
|
Compiling dtoa-short v0.3.5
|
||||||
|
Compiling tower v0.5.3
|
||||||
|
Compiling deno_path_util v0.4.0
|
||||||
|
Compiling tokio-rustls v0.26.4
|
||||||
|
Compiling async-compression v0.4.42
|
||||||
|
Compiling futures v0.3.32
|
||||||
|
Compiling tendril v0.4.3
|
||||||
|
Compiling string_cache v0.8.9
|
||||||
|
Compiling deno_unsync v0.4.4
|
||||||
|
Compiling pin-project v1.1.13
|
||||||
|
Compiling capacity_builder v0.5.0
|
||||||
|
Compiling wasm_dep_analyzer v0.3.0
|
||||||
|
Compiling tokio-util v0.7.18
|
||||||
|
Compiling http-body-util v0.1.3
|
||||||
|
Compiling webpki-roots v1.0.7
|
||||||
|
Compiling bincode v1.3.3
|
||||||
|
Compiling cssparser-macros v0.6.1
|
||||||
|
Compiling selectors v0.26.0
|
||||||
|
Compiling universal-hash v0.5.1
|
||||||
|
Compiling byteorder v1.5.0
|
||||||
|
Compiling deno_core_icudata v0.74.0
|
||||||
|
Compiling ryu v1.0.23
|
||||||
|
Compiling cooked-waker v5.0.0
|
||||||
|
Compiling opaque-debug v0.3.1
|
||||||
|
Compiling az v1.3.0
|
||||||
|
Compiling static_assertions v1.1.0
|
||||||
|
Compiling linux-raw-sys v0.12.1
|
||||||
|
Compiling serde_urlencoded v0.7.1
|
||||||
|
Compiling polyval v0.6.2
|
||||||
|
Compiling fxhash v0.2.1
|
||||||
|
Compiling cssparser v0.34.0
|
||||||
|
Compiling tower-http v0.6.11
|
||||||
|
Compiling hyper-rustls v0.27.9
|
||||||
|
Compiling hmac v0.12.1
|
||||||
|
Compiling sha1 v0.10.6
|
||||||
|
Compiling deno_core v0.350.0
|
||||||
|
Compiling derive_more v0.99.20
|
||||||
|
Compiling match_token v0.1.0
|
||||||
|
Compiling servo_arc v0.4.3
|
||||||
|
Compiling fastrand v2.4.1
|
||||||
|
Compiling tempfile v3.27.0
|
||||||
|
Compiling html5ever v0.29.1
|
||||||
|
Compiling rand_core v0.9.5
|
||||||
|
Compiling reqwest v0.12.28
|
||||||
|
Compiling ghash v0.5.1
|
||||||
|
Compiling ctr v0.9.2
|
||||||
|
Compiling aes v0.8.4
|
||||||
|
Compiling async-trait v0.1.89
|
||||||
|
Compiling aead v0.5.2
|
||||||
|
Compiling encoding_rs v0.8.35
|
||||||
|
Compiling aes-gcm v0.10.3
|
||||||
|
Compiling ppv-lite86 v0.2.21
|
||||||
|
Compiling obscura-dom v0.1.0 (/root/obscura2/merge471/crates/obscura-dom)
|
||||||
|
Compiling hkdf v0.12.4
|
||||||
|
Compiling pbkdf2 v0.12.2
|
||||||
|
Compiling cbc v0.1.2
|
||||||
|
Compiling sha2 v0.10.9
|
||||||
|
Compiling rand_chacha v0.9.0
|
||||||
|
Compiling utf8parse v0.2.2
|
||||||
|
Compiling anstyle-parse v1.0.0
|
||||||
|
Compiling rand v0.9.4
|
||||||
|
Compiling obscura-net v0.1.0 (/root/obscura2/merge471/crates/obscura-net)
|
||||||
|
Compiling colorchoice v1.0.5
|
||||||
|
Compiling anstyle v1.0.14
|
||||||
|
Compiling anstyle-query v1.1.5
|
||||||
|
Compiling is_terminal_polyfill v1.70.2
|
||||||
|
Compiling anstream v1.0.0
|
||||||
|
Compiling tungstenite v0.26.2
|
||||||
|
Compiling strsim v0.11.1
|
||||||
|
Compiling lazy_static v1.5.0
|
||||||
|
Compiling clap_lex v1.1.0
|
||||||
|
Compiling obscura-js v0.1.0 (/root/obscura2/merge471/crates/obscura-js)
|
||||||
|
Compiling clap_builder v4.6.0
|
||||||
|
Compiling sharded-slab v0.1.7
|
||||||
|
Compiling tokio-tungstenite v0.26.2
|
||||||
|
Compiling tracing-log v0.2.0
|
||||||
|
Compiling clap_derive v4.6.1
|
||||||
|
Compiling thread_local v1.1.9
|
||||||
|
Compiling nu-ansi-term v0.50.3
|
||||||
|
Compiling obscura-cli v0.1.0 (/root/obscura2/merge471/crates/obscura-cli)
|
||||||
|
Compiling matchers v0.2.0
|
||||||
|
Compiling tracing-subscriber v0.3.23
|
||||||
|
Compiling clap v4.6.1
|
||||||
|
Compiling obscura-browser v0.1.0 (/root/obscura2/merge471/crates/obscura-browser)
|
||||||
|
Compiling obscura-cdp v0.1.0 (/root/obscura2/merge471/crates/obscura-cdp)
|
||||||
|
Compiling obscura-mcp v0.1.0 (/root/obscura2/merge471/crates/obscura-mcp)
|
||||||
|
Finished `release` profile [optimized] target(s) in 1m 52s
|
||||||
Vendored
+47
-26
@@ -2710,42 +2710,63 @@ class Document extends Node {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
firstChild() {
|
// DOM 6.1 "traverse children" (issue #469). The movers used to step
|
||||||
let child = this.currentNode.firstChild;
|
// straight to the next sibling when a node was not accepted, so a
|
||||||
while (child) {
|
// FILTER_SKIP node hid its children instead of exposing them. `edge` and
|
||||||
if (this._accept(child)) { this.currentNode = child; return child; }
|
// `step` pick the direction: first/next for forward, last/previous for
|
||||||
child = child.nextSibling;
|
// backward.
|
||||||
|
_traverseChildren(edge, step) {
|
||||||
|
let node = this.currentNode[edge];
|
||||||
|
while (node) {
|
||||||
|
const verdict = this._filter(node);
|
||||||
|
if (verdict === 1) { this.currentNode = node; return node; }
|
||||||
|
// Only SKIP leaves the children eligible; REJECT prunes the subtree.
|
||||||
|
if (verdict === 3) {
|
||||||
|
const child = node[edge];
|
||||||
|
if (child) { node = child; continue; }
|
||||||
|
}
|
||||||
|
// Subtree exhausted: step sideways, climbing out without passing
|
||||||
|
// root or the node the walk started from.
|
||||||
|
while (node) {
|
||||||
|
const sibling = node[step];
|
||||||
|
if (sibling) { node = sibling; break; }
|
||||||
|
const parent = node.parentNode;
|
||||||
|
if (!parent || parent === this.root || parent === this.currentNode) return null;
|
||||||
|
node = parent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
lastChild() {
|
// DOM 6.1 "traverse siblings" (issue #469).
|
||||||
let child = this.currentNode.lastChild;
|
_traverseSiblings(edge, step) {
|
||||||
while (child) {
|
let node = this.currentNode;
|
||||||
if (this._accept(child)) { this.currentNode = child; return child; }
|
if (node === this.root) return null;
|
||||||
child = child.previousSibling;
|
for (;;) {
|
||||||
}
|
let sibling = node[step];
|
||||||
return null;
|
|
||||||
},
|
|
||||||
nextSibling() {
|
|
||||||
let sibling = this.currentNode.nextSibling;
|
|
||||||
while (sibling) {
|
while (sibling) {
|
||||||
if (this._accept(sibling)) { this.currentNode = sibling; return sibling; }
|
node = sibling;
|
||||||
sibling = sibling.nextSibling;
|
const verdict = this._filter(node);
|
||||||
|
if (verdict === 1) { this.currentNode = node; return node; }
|
||||||
|
// Descend into a skipped sibling's subtree; a rejected one is
|
||||||
|
// off-limits, and a childless one has nothing to descend into.
|
||||||
|
sibling = node[edge];
|
||||||
|
if (verdict === 2 || !sibling) sibling = node[step];
|
||||||
}
|
}
|
||||||
return null;
|
node = node.parentNode;
|
||||||
},
|
if (!node || node === this.root) return null;
|
||||||
previousSibling() {
|
// An accepted parent is where the walk would go next, so there is no
|
||||||
let sibling = this.currentNode.previousSibling;
|
// sibling to return.
|
||||||
while (sibling) {
|
if (this._filter(node) === 1) return null;
|
||||||
if (this._accept(sibling)) { this.currentNode = sibling; return sibling; }
|
|
||||||
sibling = sibling.previousSibling;
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
firstChild() { return this._traverseChildren('firstChild', 'nextSibling'); },
|
||||||
|
lastChild() { return this._traverseChildren('lastChild', 'previousSibling'); },
|
||||||
|
nextSibling() { return this._traverseSiblings('firstChild', 'nextSibling'); },
|
||||||
|
previousSibling() { return this._traverseSiblings('lastChild', 'previousSibling'); },
|
||||||
// DOM 6.1 "parentNode" (issue #475). The old version looked only at the
|
// DOM 6.1 "parentNode" (issue #475). The old version looked only at the
|
||||||
// immediate parent, so it couldn't climb past a skipped ancestor; it also
|
// immediate parent, so it couldn't climb past a skipped ancestor; it also
|
||||||
// excluded `root` as a result yet stepped to root's own parent when
|
// excluded `root` as a result yet stepped to root's own parent when
|
||||||
// currentNode was root — returning a node OUTSIDE the walker's subtree.
|
// currentNode was root, returning a node OUTSIDE the walker's subtree.
|
||||||
// The loop's `node !== this.root` guard is what keeps the walk inside
|
// The loop's `node !== this.root` guard is what keeps the walk inside
|
||||||
// root while still allowing root itself to be returned.
|
// root while still allowing root itself to be returned.
|
||||||
parentNode() {
|
parentNode() {
|
||||||
|
|||||||
@@ -1920,6 +1920,99 @@ mod tests {
|
|||||||
assert_eq!(result.value.unwrap(), serde_json::json!([1, 1, 400]));
|
assert_eq!(result.value.unwrap(), serde_json::json!([1, 1, 400]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Issue #469: FILTER_SKIP leaves a skipped node's children eligible, so
|
||||||
|
/// firstChild()/lastChild() must descend into them. FILTER_REJECT must not.
|
||||||
|
#[test]
|
||||||
|
fn tree_walker_child_movers_descend_on_skip_but_not_on_reject() {
|
||||||
|
let mut rt = setup_runtime(
|
||||||
|
r#"<div id="root"><section><a></a><b></b></section></div>"#,
|
||||||
|
);
|
||||||
|
let result = rt
|
||||||
|
.evaluate(
|
||||||
|
r#"
|
||||||
|
const root = document.getElementById('root');
|
||||||
|
function mover(verdict, method) {
|
||||||
|
const w = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
|
||||||
|
acceptNode(node) {
|
||||||
|
return node.tagName === 'SECTION' ? verdict : NodeFilter.FILTER_ACCEPT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const found = w[method]();
|
||||||
|
return found ? found.tagName : null;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
mover(NodeFilter.FILTER_SKIP, 'firstChild'),
|
||||||
|
mover(NodeFilter.FILTER_SKIP, 'lastChild'),
|
||||||
|
mover(NodeFilter.FILTER_REJECT, 'firstChild'),
|
||||||
|
mover(NodeFilter.FILTER_REJECT, 'lastChild'),
|
||||||
|
];
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
// SKIP descends into <section>; REJECT prunes it and finds nothing else.
|
||||||
|
assert_eq!(result, serde_json::json!(["A", "B", null, null]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Issue #469: nextSibling()/previousSibling() must descend into a skipped
|
||||||
|
/// sibling's subtree rather than stepping straight over it.
|
||||||
|
#[test]
|
||||||
|
fn tree_walker_sibling_movers_descend_into_skipped_siblings() {
|
||||||
|
let mut rt = setup_runtime(
|
||||||
|
r#"<div id="root"><p id="start"></p><section><a></a></section><q></q></div>"#,
|
||||||
|
);
|
||||||
|
let result = rt
|
||||||
|
.evaluate(
|
||||||
|
r#"
|
||||||
|
const root = document.getElementById('root');
|
||||||
|
function mover(verdict, method, from) {
|
||||||
|
const w = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
|
||||||
|
acceptNode(node) {
|
||||||
|
return node.tagName === 'SECTION' ? verdict : NodeFilter.FILTER_ACCEPT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
w.currentNode = document.getElementById(from);
|
||||||
|
const found = w[method]();
|
||||||
|
return found ? found.tagName : null;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
// <section> is skipped, so its child <a> is the next sibling.
|
||||||
|
mover(NodeFilter.FILTER_SKIP, 'nextSibling', 'start'),
|
||||||
|
// Rejected: the subtree is off-limits, so skip past to <q>.
|
||||||
|
mover(NodeFilter.FILTER_REJECT, 'nextSibling', 'start'),
|
||||||
|
];
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(result, serde_json::json!(["A", "Q"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Issue #469: the backward sibling mover descends to *last* children.
|
||||||
|
#[test]
|
||||||
|
fn tree_walker_previous_sibling_descends_to_last_child() {
|
||||||
|
let mut rt = setup_runtime(
|
||||||
|
r#"<div id="root"><section><a></a><b></b></section><p id="start"></p></div>"#,
|
||||||
|
);
|
||||||
|
let result = rt
|
||||||
|
.evaluate(
|
||||||
|
r#"
|
||||||
|
const root = document.getElementById('root');
|
||||||
|
const w = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {
|
||||||
|
acceptNode(node) {
|
||||||
|
return node.tagName === 'SECTION'
|
||||||
|
? NodeFilter.FILTER_SKIP
|
||||||
|
: NodeFilter.FILTER_ACCEPT;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
w.currentNode = document.getElementById('start');
|
||||||
|
const found = w.previousSibling();
|
||||||
|
return found ? found.tagName : null;
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
// Reverse order descends to <section>'s last child, not its first.
|
||||||
|
assert_eq!(result, serde_json::json!("B"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn append_child_flattens_document_fragment() {
|
fn append_child_flattens_document_fragment() {
|
||||||
let mut rt = setup_runtime(r#"<main id="host"></main>"#);
|
let mut rt = setup_runtime(r#"<main id="host"></main>"#);
|
||||||
|
|||||||
Reference in new issue
Block a user