Use textContent instead of innerHTML for extracting logs from headless browser tests

Easier to maintain fidelity and less likely to be sabotaged by XSS and
`<script>` tags.

Fixes #1232
This commit is contained in:
Nick Fitzgerald 2019-02-08 10:35:19 +01:00
parent 9d27bc2e8b
commit 11eeeb8fc8
4 changed files with 21 additions and 18 deletions

View File

@ -13,7 +13,7 @@
const orig = id => (...args) => { const orig = id => (...args) => {
const logs = document.getElementById(id); const logs = document.getElementById(id);
for (let msg of args) { for (let msg of args) {
logs.innerHTML += `${msg}\n`; logs.textContent += `${msg}\n`;
} }
}; };

View File

@ -30,7 +30,7 @@ pub fn spawn(
// Now that we've gotten to the point where JS is executing, update our // Now that we've gotten to the point where JS is executing, update our
// status text as at this point we should be asynchronously fetching the // status text as at this point we should be asynchronously fetching the
// wasm module. // wasm module.
document.getElementById('output').innerHTML = "Loading wasm module..."; document.getElementById('output').textContent = "Loading wasm module...";
async function main(test) {{ async function main(test) {{
// this is a facet of using wasm2es6js, a hack until browsers have // this is a facet of using wasm2es6js, a hack until browsers have

View File

@ -22,10 +22,10 @@ extern "C" {
fn getElementById(this: &HTMLDocument, id: &str) -> Element; fn getElementById(this: &HTMLDocument, id: &str) -> Element;
type Element; type Element;
#[wasm_bindgen(method, getter = innerHTML, structural)] #[wasm_bindgen(method, getter = textContent, structural)]
fn inner_html(this: &Element) -> String; fn text_content(this: &Element) -> String;
#[wasm_bindgen(method, setter = innerHTML, structural)] #[wasm_bindgen(method, setter = textContent, structural)]
fn set_inner_html(this: &Element, html: &str); fn set_text_content(this: &Element, text: &str);
type BrowserError; type BrowserError;
#[wasm_bindgen(method, getter, structural)] #[wasm_bindgen(method, getter, structural)]
@ -37,24 +37,16 @@ impl Browser {
/// (requires `Node::new()` to have return `None` first). /// (requires `Node::new()` to have return `None` first).
pub fn new() -> Browser { pub fn new() -> Browser {
let pre = document.getElementById("output"); let pre = document.getElementById("output");
pre.set_inner_html(""); pre.set_text_content("");
Browser { pre } Browser { pre }
} }
} }
impl super::Formatter for Browser { impl super::Formatter for Browser {
fn writeln(&self, line: &str) { fn writeln(&self, line: &str) {
let mut html = self.pre.inner_html(); let mut html = self.pre.text_content();
for c in line.chars() { html.extend(line.chars().chain(Some('\n')));
match c { self.pre.set_text_content(&html);
'<' => html.push_str("&lt;"),
'>' => html.push_str("&gt;"),
'&' => html.push_str("&amp;"),
c => html.push(c),
}
}
html.push_str("\n");
self.pre.set_inner_html(&html);
} }
fn log_test(&self, name: &str, result: &Result<(), JsValue>) { fn log_test(&self, name: &str, result: &Result<(), JsValue>) {

11
tests/headless.rs Normal file → Executable file
View File

@ -26,3 +26,14 @@ impl ConsumeRetString {
fn works() { fn works() {
ConsumeRetString.consume(); ConsumeRetString.consume();
} }
#[wasm_bindgen]
extern {
#[wasm_bindgen(js_namespace = console)]
pub fn log(s: &str);
}
#[wasm_bindgen_test]
fn can_log_html_strings() {
log("<script>alert('lol')</script>");
}