fix(js): coerce non-string primitives in before/after/replaceWith
before(), after() and replaceWith() only converted string arguments to Text nodes; other primitives (numbers, booleans, null) were passed straight to insert_before with no _nid, corrupting the call. Route them through the shared _convertNodes helper (the same path append/prepend use), so every non-node argument becomes document.createTextNode(String(n)). Fixes #498
This commit is contained in:
1 parent
8078cc3070
commit
499a5ef983
2 files changed
+26
-12
No files matched your search
Vendored
+6
-12
@@ -4122,13 +4122,13 @@ if (typeof Response === 'undefined') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Element.prototype.replaceWith) {
|
if (!Element.prototype.replaceWith) {
|
||||||
|
// _convertNodes turns any non-node argument (numbers, booleans, null, …) into
|
||||||
|
// a Text node via String(n), matching the spec and append()/prepend(); the
|
||||||
|
// old `typeof n === 'string'` check corrupted insert_before for other types.
|
||||||
Element.prototype.replaceWith = function(...nodes) {
|
Element.prototype.replaceWith = function(...nodes) {
|
||||||
const parent = this.parentNode;
|
const parent = this.parentNode;
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
for (const n of nodes) {
|
for (const n of _convertNodes(nodes)) parent.insertBefore(n, this);
|
||||||
if (typeof n === 'string') parent.insertBefore(document.createTextNode(n), this);
|
|
||||||
else parent.insertBefore(n, this);
|
|
||||||
}
|
|
||||||
parent.removeChild(this);
|
parent.removeChild(this);
|
||||||
};
|
};
|
||||||
_markNative(Element.prototype.replaceWith);
|
_markNative(Element.prototype.replaceWith);
|
||||||
@@ -4137,10 +4137,7 @@ if (!Element.prototype.before) {
|
|||||||
Element.prototype.before = function(...nodes) {
|
Element.prototype.before = function(...nodes) {
|
||||||
const parent = this.parentNode;
|
const parent = this.parentNode;
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
for (const n of nodes) {
|
for (const n of _convertNodes(nodes)) parent.insertBefore(n, this);
|
||||||
if (typeof n === 'string') parent.insertBefore(document.createTextNode(n), this);
|
|
||||||
else parent.insertBefore(n, this);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
_markNative(Element.prototype.before);
|
_markNative(Element.prototype.before);
|
||||||
}
|
}
|
||||||
@@ -4149,10 +4146,7 @@ if (!Element.prototype.after) {
|
|||||||
const parent = this.parentNode;
|
const parent = this.parentNode;
|
||||||
if (!parent) return;
|
if (!parent) return;
|
||||||
const ref = this.nextSibling;
|
const ref = this.nextSibling;
|
||||||
for (const n of nodes) {
|
for (const n of _convertNodes(nodes)) parent.insertBefore(n, ref);
|
||||||
if (typeof n === 'string') parent.insertBefore(document.createTextNode(n), ref);
|
|
||||||
else parent.insertBefore(n, ref);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
_markNative(Element.prototype.after);
|
_markNative(Element.prototype.after);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1317,6 +1317,26 @@ mod tests {
|
|||||||
rt
|
rt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn childnode_helpers_coerce_non_string_primitives_to_text() {
|
||||||
|
let mut rt = setup_runtime(r#"<html><body><div id="p"><span id="t">x</span></div></body></html>"#);
|
||||||
|
let before = rt
|
||||||
|
.evaluate("(function(){var t=document.getElementById('t'); t.before(5); return t.previousSibling ? t.previousSibling.textContent : 'NULL';})()")
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(before, serde_json::json!("5"));
|
||||||
|
let after = rt
|
||||||
|
.evaluate("(function(){var t=document.getElementById('t'); t.after(true); return t.nextSibling ? t.nextSibling.textContent : 'NULL';})()")
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(after, serde_json::json!("true"));
|
||||||
|
let replaced = rt
|
||||||
|
.evaluate("(function(){var t=document.getElementById('t'); t.replaceWith(42); return document.getElementById('p').textContent;})()")
|
||||||
|
.unwrap();
|
||||||
|
assert!(
|
||||||
|
replaced.as_str().unwrap().contains("42"),
|
||||||
|
"replaceWith(42) should leave text '42': {replaced}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_document_title() {
|
fn test_document_title() {
|
||||||
let mut rt = setup_runtime("<html><head><title>Test</title></head><body></body></html>");
|
let mut rt = setup_runtime("<html><head><title>Test</title></head><body></body></html>");
|
||||||
|
|||||||
Reference in new issue
Block a user