fix(js,dom): scope element queries, real timers, form/prepend/equal (#180)
- Element.querySelector / querySelectorAll scope to the receiver subtree via a new query_selector_scoped Rust op, not always document root. Same for DocumentFragment. - setTimeout respects its delay argument via a new async op_sleep. setInterval is a real repeating timer instead of an alias to setTimeout. - document.forms / images / links return live querySelectorAll results instead of hardcoded []. - HTMLFormElement subclasses Element with .elements / .length, and form nodes are wrapped as HTMLFormElement so instanceof works. submit() stays on Element.prototype to preserve the existing submit-event dispatch and form-data navigation path. - Element.prepend has a real implementation. - Node.isEqualNode does a structural compare (nodeType, nodeName, nodeValue, attributes, recursive children) instead of nid identity. - Fix long-standing insert_before arg-order bug: bootstrap.js was passing (parent, new, ref) but _dom only forwards two args, so ref was silently dropped. Pass (new, ref) directly. Same fix in replaceChild. Adds 3 selector unit tests and 6 runtime regression tests covering the JS shim fixes. Closes #105.
This commit is contained in:
1 parent
d4d749d850
commit
71b9b4fbab
4 files changed
+264
-31
No files matched your search
@@ -120,6 +120,17 @@ fn op_dom(state: &OpState, #[string] cmd: String, #[string] arg1: String, #[stri
|
||||
.map(|ids| ids.iter().map(|id| id.index() as i32).collect()).unwrap_or_default();
|
||||
serde_json::to_string(&ids).unwrap_or("[]".into())
|
||||
}
|
||||
"query_selector_scoped" => {
|
||||
let root_nid = arg1.parse::<u32>().unwrap_or(0);
|
||||
dom.query_selector_from(NodeId::new(root_nid), &arg2).ok().flatten()
|
||||
.map(|id| id.index().to_string()).unwrap_or("-1".into())
|
||||
}
|
||||
"query_selector_all_scoped" => {
|
||||
let root_nid = arg1.parse::<u32>().unwrap_or(0);
|
||||
let ids: Vec<i32> = dom.query_selector_all_from(NodeId::new(root_nid), &arg2).ok()
|
||||
.map(|ids| ids.iter().map(|id| id.index() as i32).collect()).unwrap_or_default();
|
||||
serde_json::to_string(&ids).unwrap_or("[]".into())
|
||||
}
|
||||
"node_type" => {
|
||||
let nid = arg1.parse::<u32>().unwrap_or(0);
|
||||
dom.get_node(NodeId::new(nid)).map(|n| match &n.data {
|
||||
@@ -742,6 +753,11 @@ fn op_navigate(state: &OpState, #[string] url: &str, #[string] method: &str, #[s
|
||||
gs.pending_navigation = Some((url.to_string(), method.to_string(), body.to_string()));
|
||||
}
|
||||
|
||||
#[op2(async)]
|
||||
async fn op_sleep(#[number] millis: u64) {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(millis)).await;
|
||||
}
|
||||
|
||||
pub fn build_extension() -> Extension {
|
||||
Extension {
|
||||
name: "obscura_dom",
|
||||
@@ -752,6 +768,7 @@ pub fn build_extension() -> Extension {
|
||||
op_get_cookies(),
|
||||
op_set_cookie(),
|
||||
op_navigate(),
|
||||
op_sleep(),
|
||||
]),
|
||||
..Default::default()
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user