fix(js): remove runtime selector traversal
Replace runtime querySelector/closest/matches traversal with explicit element walks and generated-id predicates, preserving existing runtime convention coverage. req: runtime/001 req: target_policy/001 req: target_policy/002
This commit is contained in:
+18
-11
@@ -26,9 +26,11 @@ fn runtime_targets_generated_resources_not_response_selectors() {
|
||||
let source = slhx_js::RUNTIME_JS;
|
||||
|
||||
assert!(source.contains("function targetFor(scope, ref)"));
|
||||
assert!(source.contains("return scope.querySelector(`[data-sid=\"${ref.resource.id}\"], [data-slot-id=\"${ref.resource.id}\"]`)"));
|
||||
assert!(source.contains("return scope.querySelector(`[data-sid=\"${id}\"][data-key=\"${escapedKey}\"], [data-sid=\"${id}\"] [data-key=\"${escapedKey}\"], [data-slot-id=\"${id}\"][data-key=\"${escapedKey}\"], [data-slot-id=\"${id}\"] [data-key=\"${escapedKey}\"]`)"));
|
||||
assert!(source.contains("doc.querySelectorAll(\"[data-sid], [data-slot-id]\")"));
|
||||
assert!(source.contains("return generatedTarget(scope, ref.resource.id)"));
|
||||
assert!(source.contains("function firstElement(scope, predicate)"));
|
||||
assert!(source.contains("function generatedResource(el, id)"));
|
||||
assert!(source.contains("return firstElement(scope, (el) => attrEquals(el, \"data-key\", key) && withinGeneratedResource(el, scope, id))"));
|
||||
assert!(source.contains("const target = generatedTarget(scope, id)"));
|
||||
assert!(source.contains("if (!target) return missing(scope, op.target)"));
|
||||
assert!(!source.contains("data-slhx-target"));
|
||||
assert!(!source.contains("data-slhx-select"));
|
||||
@@ -39,8 +41,9 @@ fn runtime_interval_dispatch_avoids_duplicate_timers() {
|
||||
// req: convention/005
|
||||
let source = slhx_js::RUNTIME_JS;
|
||||
|
||||
assert!(source.contains("root.querySelectorAll(\"[data-slhx-every]\")"));
|
||||
assert!(source.contains("if (timers.has(el)) return"));
|
||||
assert!(source.contains("forEachElement(root, (el) =>"));
|
||||
assert!(source.contains("!el.hasAttribute(\"data-slhx-every\") || timers.has(el)"));
|
||||
assert!(source.contains("if (!el.hasAttribute(\"data-slhx-every\") || timers.has(el)) return"));
|
||||
assert!(source.contains("setInterval(() => document.contains(el) ? send(el, \"every\")"));
|
||||
assert!(source.contains("clearInterval(timers.get(el))"));
|
||||
}
|
||||
@@ -53,9 +56,11 @@ fn runtime_toggles_pending_conventions_around_requests() {
|
||||
assert!(source.contains("function showPending(el, on)"));
|
||||
assert!(source.contains("el.getAttribute(\"data-slhx-pending-class\")"));
|
||||
assert!(source.contains("el.classList.toggle(klass, on)"));
|
||||
assert!(source.contains("root.querySelectorAll(\"[data-slhx-indicator]\")"));
|
||||
assert!(source.contains("forEachElement(root, (i) => { if (i.hasAttribute(\"data-slhx-indicator\")) i.hidden = !on; })"));
|
||||
assert!(source.contains("i.hidden = !on"));
|
||||
assert!(source.contains("el.hasAttribute(\"data-slhx-disable-while-pending\")"));
|
||||
assert!(source.contains("if (isDisableControl(el)) controls.push(el)"));
|
||||
assert!(source.contains("forEachElement(el, (child) => { if (isDisableControl(child)) controls.push(child); })"));
|
||||
assert!(source.contains("c.disabled = on"));
|
||||
assert!(source.contains("showPending(target, true)"));
|
||||
assert!(source.contains("showPending(target, false)"));
|
||||
@@ -95,8 +100,9 @@ fn runtime_clicking_submitter_schedules_form_submit() {
|
||||
assert!(source.contains("function formOwner(el)"));
|
||||
assert!(source.contains("function formHandleId(form)"));
|
||||
assert!(source.contains("document.getElementById(el.getAttribute(\"form\"))"));
|
||||
assert!(source.contains("const direct = closestInRoot(event.target, root, `[${HID}]`)"));
|
||||
assert!(source.contains("button[type=submit], input[type=submit], button:not([type])"));
|
||||
assert!(source.contains("const direct = closestInRoot(event.target, root, (el) => el.hasAttribute(HID))"));
|
||||
assert!(source.contains("const submitter = closestInRoot(event.target, root, (el) =>"));
|
||||
assert!(source.contains("el.tagName === \"BUTTON\" && (!el.hasAttribute(\"type\") || el.getAttribute(\"type\") === \"submit\")"));
|
||||
assert!(source.contains("form.reportValidity && !form.reportValidity()"));
|
||||
assert!(source.contains("schedule(form, \"submit\")"));
|
||||
}
|
||||
@@ -187,7 +193,8 @@ fn runtime_page_swaps_lowered_slot_ids() {
|
||||
let source = slhx_js::RUNTIME_JS;
|
||||
|
||||
assert!(source.contains("function replaceLoweredSlots(scope, doc)"));
|
||||
assert!(source.contains("doc.querySelectorAll(\"[data-sid], [data-slot-id]\")"));
|
||||
assert!(source.contains("forEachElement(doc.body || doc, (source)"));
|
||||
assert!(source.contains("const target = generatedTarget(scope, id)"));
|
||||
assert!(source.contains("target.innerHTML = source.innerHTML"));
|
||||
}
|
||||
|
||||
@@ -196,9 +203,9 @@ fn runtime_keeps_form_field_targets_separate_from_error_targets() {
|
||||
let source = slhx_js::RUNTIME_JS;
|
||||
|
||||
assert!(source.contains("function fieldTarget(scope, id, field)"));
|
||||
assert!(source.contains("[data-fid=\"${id}\"] [name=\"${escapedField}\"]"));
|
||||
assert!(source.contains("attrEquals(el, \"name\", field) && withinGeneratedForm(el, scope, id)"));
|
||||
assert!(source.contains("function formErrorTarget(scope, id, field)"));
|
||||
assert!(source.contains("[data-slhx-error-for=\"${escapedField}\"]"));
|
||||
assert!(source.contains("attrEquals(el, \"data-slhx-error-for\", field) && withinGeneratedForm(el, scope, id)"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user