Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use spaces directly in a class string #121

Closed
ndarilek opened this issue Jan 24, 2018 · 18 comments
Closed

Can't use spaces directly in a class string #121

ndarilek opened this issue Jan 24, 2018 · 18 comments

Comments

@ndarilek
Copy link

ndarilek commented Jan 24, 2018

If in my render function, I have:

    fn view(&self) -> Html<Context, Self> {
        html! {
            <div class="container-fluid",>
                <div class="row",>
                    <div class="col",>
                    </div>
                </div>
                <main class="row",>
                    <div class="col",>
                    </div>
                </main>
            </div>
        }
    }

my code runs fine, without errors.

If I change to:

    fn view(&self) -> Html<Context, Self> {
        html! {
            <div class="container-fluid",>
                <div class="row",>
                    <div class="col",>
                        <nav class="navbar navbar-expand-lg navbar-light bg-light",>
                        </nav>
                    </div>
                </div>
                <main class="row",>
                    <div class="col",>
                    </div>
                </main>
            </div>
        }
    }

I get the following error:

exception thrown: InvalidCharacterError: String contains an invalid character,ASM_CONSTS<@http://localhost:8000/js/app.js:1707:80
_emscripten_asm_const_iii@http://localhost:8000/js/app.js:1729:10
__ZN6stdweb6webapi10token_list9TokenList3add17hbcd64a3dc4ae18fcE@http://localhost:8000/js/app.js:772025:1
dynCall_viii@http://localhost:8000/js/app.js:4750617:1
Module.dynCall_viii@http://localhost:8000/js/app.js:8323:66
invoke_viii@http://localhost:8000/js/app.js:8038:5
__ZN95__LT_yew__virtual_dom__vtag__VTag_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hbed485f8d5184751E@http://localhost:8000/js/app.js:327193:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN97__LT_yew__virtual_dom__vnode__VNode_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hfca50f400ff0a51fE@http://localhost:8000/js/app.js:388499:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN95__LT_yew__virtual_dom__vtag__VTag_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hbed485f8d5184751E@http://localhost:8000/js/app.js:334714:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN97__LT_yew__virtual_dom__vnode__VNode_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hfca50f400ff0a51fE@http://localhost:8000/js/app.js:388499:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN95__LT_yew__virtual_dom__vtag__VTag_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hbed485f8d5184751E@http://localhost:8000/js/app.js:334714:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN97__LT_yew__virtual_dom__vnode__VNode_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hfca50f400ff0a51fE@http://localhost:8000/js/app.js:388499:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN95__LT_yew__virtual_dom__vtag__VTag_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hbed485f8d5184751E@http://localhost:8000/js/app.js:334714:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN97__LT_yew__virtual_dom__vnode__VNode_LT_CTX_C__u20_COMP_GT__u20_as_u20_yew__virtual_dom__VDiff_GT_5apply17hfca50f400ff0a51fE@http://localhost:8000/js/app.js:388499:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN48__LT_yew__html__Scope_LT_CTX_C__u20_COMP_GT__GT_14mount_in_place17h89d4b08b69a16c7fE@http://localhost:8000/js/app.js:541259:1
dynCall_viiii@http://localhost:8000/js/app.js:4750692:1
Module.dynCall_viiii@http://localhost:8000/js/app.js:8326:68
invoke_viiii@http://localhost:8000/js/app.js:8065:5
__ZN48__LT_yew__html__Scope_LT_CTX_C__u20_COMP_GT__GT_5mount17hb6ed45d1713922caE@http://localhost:8000/js/app.js:540050:1
dynCall_vii@http://localhost:8000/js/app.js:4750494:1
Module.dynCall_vii@http://localhost:8000/js/app.js:8318:64
invoke_vii@http://localhost:8000/js/app.js:7993:5
__ZN48__LT_yew__html__Scope_LT_CTX_C__u20_COMP_GT__GT_13mount_to_body17heac8c16e9144cb0fE@http://localhost:8000/js/app.js:539586:1
__ZN6hermes3web4main17h387d3e4fbc1bd385E@http://localhost:8000/js/app.js:404925:1
__ZN6hermes4main17hf85a49bbb4aa5bf3E@http://localhost:8000/js/app.js:317312:1
__ZN3std2rt10lang_start28__u7b__u7b_closure_u7d__u7d_17h1c74e3c4f7fb0654E@http://localhost:8000/js/app.js:297327:1
__ZN3std10sys_common9backtrace28__rust_begin_short_backtrace17h7a30486027a5b027E@http://localhost:8000/js/app.js:984250:1
__ZN3std9panicking3try7do_call17h0b1cf60168c8dd57E@http://localhost:8000/js/app.js:963626:1
dynCall_vi@http://localhost:8000/js/app.js:4750386:1
Module.dynCall_vi@http://localhost:8000/js/app.js:8313:62
invoke_vi@http://localhost:8000/js/app.js:7948:5
___rust_maybe_catch_panic@http://localhost:8000/js/app.js:1010073:1
__ZN3std2rt19lang_start_internal17h2834043e12814a8eE@http://localhost:8000/js/app.js:963175:1
__ZN3std2rt10lang_start17hf551b0ba7b832818E@http://localhost:8000/js/app.js:297268:1
_main@http://localhost:8000/js/app.js:317306:1
Module._main@http://localhost:8000/js/app.js:8220:52
callMain@http://localhost:8000/js/app.js:8456:15
doRun@http://localhost:8000/js/app.js:8516:42
run@http://localhost:8000/js/app.js:8530:5
runCaller@http://localhost:8000/js/app.js:8435:29
removeRunDependency@http://localhost:8000/js/app.js:1381:7
receiveInstance@http://localhost:8000/js/app.js:1549:7
receiveInstantiatedSource@http://localhost:8000/js/app.js:1568:7
promise callback*doNativeWasm@http://localhost:8000/js/app.js:1583:7
integrateWasmJS/Module.asm@http://localhost:8000/js/app.js:1672:15
@http://localhost:8000/js/app.js:8202:10
app.js:196:7
wasm streaming compile failed: InvalidCharacterError: String contains an invalid character
app.js:196:7
falling back to ArrayBuffer instantiation
app.js:196:7

Note that this change necessitates adding:

#![recursion_limit="128"]

to my crate. I'm wondering if that might be related? It doesn't seem to happen with less deeply-nested templates.


Workaround: use <tag class=("class-1", "class-2"),> syntax. See below for the details.

@anxiousmodernman
Copy link

anxiousmodernman commented Jan 26, 2018

I encountered this error, too. I think these are errors from emscripten, via the cargo-web subcommand. I do specify the recursion limit, but I still encountered this error.

A workaround is to compile with Rust's native WebAssembly features instead of emscripten. Try compiling like cargo web build --release --target=wasm32-unknown-unknown.

@ndarilek
Copy link
Author

ndarilek commented Jan 26, 2018 via email

@ndarilek
Copy link
Author

ndarilek commented Feb 6, 2018

Just wondering if anyone had any more insights on this one? Not sure what to do next. I don't see any Emscripten errors, but this code just doesn't work.

Not sure if it's possible to use wasm32-unknown-unknown and link against native libraries built via Emscripten, but I suspect it isn't.

Thanks.

@ndarilek
Copy link
Author

ndarilek commented Feb 9, 2018

I did a bit more digging, attempting to create a minimal example. I failed, but in ways that might be enlightening.

I speculated that perhaps this was being triggered by the depth of the HTML tree, particularly since I need to update the recursion limit. So I created a tree deeper than the one in my app, but I can't trigger the failures. Likewise, I'm never prompted to up the recursion limit.

So what this tells me is that the failure case here is tied to whatever prompts me to up the recursion limit. I am doing a scene-style match in my document body, similar to what happens in the CRM example. Could be that plus the deeper HTML tree. I aven't yet added that to this example.

I'll try adding that to my minimal example next, but I thought I'd ask here for guidance. Here's what I have so far. Again, this doesn't trigger the bug, but it does seem to rule out deep HTML trees:

#[macro_use]
extern crate yew;

use yew::prelude::*;

struct Model;

enum Msg {
    Increment,
}

type Context = ();

impl Component<Context> for Model {
    type Msg = Msg;
    type Properties = ();

    fn create(_: Self::Properties, _: &mut Env<Context, Self>) -> Self {
        Model
    }

    fn update(&mut self, _msg: Self::Msg, _context: &mut Env<Context, Self>) -> ShouldRender {
        true
    }
}

impl Renderable<Context, Model> for Model {
    fn view(&self) -> Html<Context, Self> {
        html! {
            <div class="foo bar",>
                <div class="foo",>
                    <div class="foo",>
                        <div class="foo",>
                            <div class="foo",>
                                <div class="foo",>
                                    <p>{ "Hello." }</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div>
                    <div>
                        <div>
                            <p>{ "Goodbye."} </p>
                        </div>
                    </div>
                </div>
            </div>
        }
    }
}

fn main() {
    yew::initialize();
    let app: App<_, Model> = App::new(());
    app.mount_to_body();
    yew::run_loop();
}

@ndarilek
Copy link
Author

Here is the most minimal example I can produce.

Note that, in my testing, this example fails with both wasm32-unknown-emscripten and wasm32-unknown-unknown. So that suggests to me this isn't an Emscripten/cargo-web bug.

Would really appreciate some help with this one. :) Thanks!

@matprec
Copy link

matprec commented Mar 15, 2018

I've hit this too and have reduced it to spacebars in things which will get lowered by/into tokenlists, e.g. class names
<ul class="nav nav-tabs",></ul> errors, while <ul class="nav",></ul> doesn't

@matprec
Copy link

matprec commented Mar 15, 2018

I've found the solution, at least for me

Placing multiple class names into a class string is a syntax error, one has to write
<ul class=("nav", "nav-tabs"),></ul>

See macro code

@ndarilek
Copy link
Author

ndarilek commented Mar 15, 2018 via email

@matprec
Copy link

matprec commented Mar 15, 2018

I don't know, @deniskolodin might give more information on this

I just guesstimated based on the stacktrace and crawled though the source until i found the comment/solution

@therustmonk
Copy link
Member

therustmonk commented Mar 15, 2018

I've found that in https://dom.spec.whatwg.org/#interface-domtokenlist:

tokenlist . add(tokens…)
Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace.

When you try to use class parameter of macro it calls add directly: https://docs.rs/stdweb/*/src/stdweb/webapi/token_list.rs.html#26 and stumbles on this error.

We can fix this footgun in two ways:

  1. Try to split string before adding it to the list (impacts on performance)
  2. Use special type or or compilation check (need some research)

I will refocus the PR to fix this spacing problem. Thank you for the investigation tips 👍

@therustmonk therustmonk changed the title Wasm errors in html! macro Can't use spaces directly in a class string Mar 15, 2018
@vitiral
Copy link
Contributor

vitiral commented Apr 5, 2018

I actually think this syntax:

<ul class=("nav", "nav-tabs"),>

should be much preferred to

<ul class="nav nav-tabs",>

We should simply suggest the first syntax if we encounter the second IMO (the second should remain an error but with a better message).

I'm a little confused as to how it is even possible that both syntaxes pass the type checker?

@ndarilek
Copy link
Author

ndarilek commented Apr 5, 2018 via email

@vitiral
Copy link
Contributor

vitiral commented Apr 6, 2018

@ndarilek that was just personal preference as a js newbie. Definitely open to other suggestions.

I'm a bit confused about your concern though... isn't the deviation from "standard html" already significantly large that you can't simply copy/paste into a Vue.js app? Examples: Inline rust comments, inline rust code, etc?

@ndarilek
Copy link
Author

ndarilek commented Apr 6, 2018 via email

@vitiral
Copy link
Contributor

vitiral commented Apr 6, 2018

I guess there are two points there:

  • Could we get the html! macro "closer to plain html" in the future?
  • Even if we can, do we really want something html like?

I think there is definitely benefits for a macro here, at least until rust get's optional kwargs or something similar. The syntax doesn't really bother me at first glance (but I've only just started using it).

I guess a side-question would be to mimick jsx, which is much closer in spirit to the html! macro.

Edit: maybe change the html! macro to the jsx! macro instead?

@ndarilek
Copy link
Author

ndarilek commented Apr 6, 2018 via email

@vitiral
Copy link
Contributor

vitiral commented Apr 6, 2018

I almost think your feature, were it to be added, would be a plain_html! macro. I think the fact that it is inline "html" within a rust program alone makes it clear it isn't "plain HTML".

This is just my personal feeling. I am not overly confused that there is slightly special syntax within html!, although anything that reduced the "specialness" would be much appreciated 😄.

The major pain points so far for me:

  • Regular text not allowed inside of blocks, <p>This is some text</p> needs to be <p>{"This is some text"}</p>.
  • The commas after attributes.
<p class="foo",>{"foobar"}</p>
              ^
              Agggh, why?

That's about all I have.

@therustmonk
Copy link
Member

Fixed with #289

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants