sycamore-rs / sycamore

A library for creating reactive web apps in Rust and WebAssembly
https://sycamore-rs.netlify.app
MIT License
2.79k stars 148 forks source link

Invalid HTML from view! #621

Closed smessmer closed 1 year ago

smessmer commented 1 year ago

Describe the bug This input:

    view! {cx,
        input(
            type="checkbox",
        ) {
            label { "Rounded" }
        }
    }

fails with:

Error: failed to minify html (you can disable the `minify` flag to avoid this; this is very likely a Sycamore bug, unless you've provided invalid custom HTML)

Caused by:
    FriendlyError {
        position: 73,
        message: "Unexpected closing tag.",
        code_context: "1|<input data-hk=2.0 type=checkbox><label data-hk=2.1>Rounded</label>label></input>\n>|                                                                         ^ \n",
    }

Environment

lukechu10 commented 1 year ago

This is quite puzzling. I'll look more into this.

gbj commented 1 year ago

This is because <input> can’t have children, no? The position of the label and the input are reversed.

arctic-hen7 commented 1 year ago

For reference, that error emanates from Perseus, and there's extensive documentation about it in our FAQs. This sort of HTML will be happily parsed by most browsers, but it's strictly invalid according to the spec. Having Sycamore prevent this is probably not the best idea, because sometimes you want spec-invalid HTML to do particularly wacky things (like links inside links, which do rarely have their uses if accessibility is properly handled).

smessmer commented 1 year ago

I don't mind whether Perseus/sycamore allows nesting labels inside of inputs or throws an error. But the current implementation does neither and instead seems to mangle the HTML. This looks like a buffer overflow or out-of-bounds write.

lukechu10 commented 1 year ago

This is not a memory related error but is instead the minifier choking on invalid HTML. Given the following code:

view! { cx,
    input {
        label {
            "Foo"
        }
    }
}

Sycamore returns the following SSRed string:

<input data-hk="0.0"><label data-hk="0.1">Foo</label></input>

Perseus's minifier assumes that the only html it can receive is semantically valid HTML as described by the spec, allowing it to further shrink the resulting HTML. However, Sycamore allows arbitrary nesting of HTML elements, including invalid ones such as a label inside an input, which thereby causes problems such as these.

I'm going to close this issue now since it is not a Sycamore bug and I'm not even sure if it should even be considered as a Perseus bug since there is not much we can do about it besides disabling the minifier altogether.

arctic-hen7 commented 1 year ago

I agree with @lukechu10, but I'll also add that the Perseus minifier does mangle the output HTML deliberately, doing things like removing closing tags, because browsers can still interpret this, it just lessens the number of bytes needing to be transferred over the network. It's odd behaviour I agree, but it's intended. I would recommend disabling the minifier by turning off default features if you'd like to use technically invalid HTML like this.