maciejhirsz / kobold

Easy declarative web interfaces.
https://docs.rs/kobold/
Mozilla Public License 2.0
385 stars 7 forks source link

Unable to debug #47

Open ltfschoen opened 1 year ago

ltfschoen commented 1 year ago

I'm been trying to figure out how to setup debugging for introspection using breakpoints. I'm using VSCode. I pushed my attempts so far in this commit https://github.com/maciejhirsz/kobold/commit/d6b170d567b4b3c3bb8f9a226d64d92799d96141. I want to debug struct Table. If I run the code with RUST_LOG=debug (i.e. RUST_LOG=debug trunk serve --address=127.0.0.1) then it outputs more debugging logs in the terminal, but not the ones that i introduce in the code using gloo_console::debug or log::debug. I'm aware that i can use the following to use console.log in the browser https://rustwasm.github.io/wasm-bindgen/examples/console-log.html, but i want to debug the non-private parts of kobold.

I managed to get it to log to console in the browser by following this https://blog.urth.org/2022/02/14/frontend-rust-without-node/#just-use-trunkhttpstrunkrsdev where they suggested using wasm-logger, so it worked in this commit https://github.com/maciejhirsz/kobold/commit/dfc527f5a71c9119fc669a0406c8d1e911a7061a, but it only output main() and Editor(), but not the move and ## table logs

I found the info about how to try and debug from these sources.

maciejhirsz commented 1 year ago

So the problem is your logger drops at the end of main(). Ideally kobold::start should halt further execution and prevent drops, but I have yet to find a clean way to do it without just throwing an exception in JS.

If you don't care about clean console and want to use the log crate you can add a call to throw_str after kobold::start to prevent drops. You could also wrap the logger in ManuallyDrop to prevent it from being dropped.

Alternatively don't use a logger and use gloo_console or any other wasm binding that calls into any of the console methods.

ltfschoen commented 1 year ago

I found links that showed how to step-through wasm-bindgen Rust code in Chrome Canary or Chrome Dev and it seems to work. I just can't seem to step into where i want it to. For example I can get it to step through inside view functions like fn Head, fn Cell, fn EntryInput, fn QRExample but haven't figured out why it doesn't step through fn Editor(). e.g.

Screen Shot 2023-04-02 at 8 00 17 am Screen Shot 2023-04-02 at 8 04 55 am

It also steps through kobold files so you can get some information about the state variables

This is how I did it (note that most of what i've written is a mixed summary of what other people wrote about the current status, i've just organised it):

Screen Shot 2023-04-02 at 7 38 01 am Screen Shot 2023-04-02 at 7 36 20 am Screen Shot 2023-04-02 at 7 45 47 am
ltfschoen commented 1 year ago

Note: I was getting the following error in the browser caught (in promise) TypeError: Illegal invocation

Screen Shot 2023-04-02 at 9 40 50 am

To fix that I had to remove the data-reference-types in index.html file. i couldn't get it to work with data-reference-types={true} or data-reference-types={false}

That's probably what @71 meant here https://github.com/rustwasm/walrus/pull/231#issuecomment-1431438647 when they said 4. If I use --reference-types with wasm-bindgen, llvm-dwarfdump fails with "error: web.wasm: invalid function export", so I cannot use --reference-types. --weak-refs work fine, though.

So now the index.html has the following and it works:

    <link
      data-trunk rel="rust"
      data-keep-debug={true}
      data-type="main"
      data-typescript={false}
      data-wasm-opt="0"
      data-no-demangle={false}
      data-weak-refs={true}
    />

Also note: If you get errors in the browser like caught (in promise) LinkError: WebAssembly.instantiate(): Import #0 module="wbg" function="__wbg_e0366eabf37a397670_7f4bc47df50cbc28" error: function import requires a callable a even if you refresh the page, then use Google Chrome Canary in "Incognito mode", and make sure you right-click the "refresh" icon and click "Empty cache and hard reload"

ltfschoen commented 1 year ago

So the problem is your logger drops at the end of main(). Ideally kobold::start should halt further execution and prevent drops, but I have yet to find a clean way to do it without just throwing an exception in JS.

If you don't care about clean console and want to use the log crate you can add a call to throw_str after kobold::start to prevent drops. You could also wrap the logger in ManuallyDrop to prevent it from being dropped.

Alternatively don't use a logger and use gloo_console or any other wasm binding that calls into any of the console methods.

So the reason why i was only able to debug in main() and in fn Editor() -> impl View { stateful(State::mock, |state| {, but not in the block inside fn Editor() called move |e: Event<InputElement>| { and not in the block inside fn Editor() called spawn_local(async move {, was because i didn't observe that move |e: Event<InputElement>| { obviously only gets called when the UI has loaded and you click the "Choose file" button and upload a .csv file, since it only gets run when that event happens

Screen Shot 2023-04-02 at 10 02 47 am

So I debugging worked when i did stuff like

#[component]
fn Editor() -> impl View {
    stateful(State::mock, |state| {
        let onload = {
            log::debug!("Editor()");
            let my_struct1 = MyStruct {
                a: "abc".to_owned(),
                b: false,
            };
            let serialized = serde_json::to_string(&my_struct1).unwrap();
            let value = JsValue::from_serde(&serialized).unwrap();
            log::debug!("Editor() {:#?}", value);

            // debug option 1
            assert_eq!(&*serialized, "{\"a\":\"abc\",\"b\":false}");

            // debug option 2
            throw_str(&serialized);

            // debug option 3
            use std::mem::ManuallyDrop;
            let test = ManuallyDrop::new(throw_str(&serialized));

...
...
                spawn_local(async move {
                    log::debug!("spawn_local1");
                    if let Ok(table) = csv::read_file(file).await {
                        let serialized = serde_json::to_string(&table).unwrap();
                        let value = JsValue::from_serde(&serialized).unwrap();
                        console_dbg!("## table0 {:#?}", value);
                        info!("## table1 {:#?}", value);
                        log::debug!("## table2 {:#?}", value);
                        use std::mem::ManuallyDrop;
                        let test = ManuallyDrop::new(throw_str(&serialized));
                        // throw_str("testing1");
                        throw_str(&serialized);
...

I pushed the changes i made to get it to work here https://github.com/ltfschoen/kobold in branch 'luke/invoice-debug'

ltfschoen commented 1 year ago

But I still don't know how to:

1) Get breakpoints to trigger if i put them inside these specific blocks move |e: Event<InputElement>| { or spawn_local(async move {. For example if i add breakpoints in those blocks, and reload the page with breakpoints disabled and then activate breakpoints, and then in the UI click "Choose file" button and upload a .csv file, it outputs in the console all the log::debug! from in those blocks, but it doesn't trigger any of the breakpoints in those blocks. The breakpoints work outside of those blocks though.

2) On macOS, when i'm stepping-through the code debugging, sometimes it displays an error like one of the following, but it still seems to work:


Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/iter/adapters/map.rs (System error: net::ERR_FILE_NOT_FOUND)

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/iter/adapters/step_by.rs (System error: net::ERR_FILE_NOT_FOUND)

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/char/methods.rs (System error: net::ERR_FILE_NOT_FOUND

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/alloc/src/boxed.rs (System error: net::ERR_FILE_NOT_FOUND)

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/mem/manually_drop.rs (System error: net::ERR_FILE_NOT_FOUND)

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/ops/function.rs (System error: net::ERR_FILE_NOT_FOUND)

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/macros/mod.rs (System error: net::ERR_FILE_NOT_FOUND)

Could not load content for file:///rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/core/src/option.rs (System error: net::ERR_FILE_NOT_FOUND

Which is caused because as shown here

Screen Shot 2023-04-02 at 10 30 43 am

For some reason it's not able to find these folders in Chrome DevTools > Sources

I don't know what it's trying to use file:cargo/registry/src/github.com-1ecc6299db9ec823, which doesn't exist, when it is alraedy successfully got access to it here file:Users/luke/.cargo/registry/src/github.com-1ecc6299db9ec823

But meanwhile it can successfully find file:Users/luke, so it has access to the following folders to access Cargo dependencies required by the project

And it has access to the project folders itself

Screen Shot 2023-04-02 at 11 20 44 am

So i tried running it on Ubuntu with RUST_LOG=debug trunk serve --address=<PUBLIC_IP_ADDRESS>, and it gave the same error not being able to find those folders like /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0. Note: the 9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0 refers to the commit of the rustc release being used https://github.com/rust-lang/rust/commit/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0

rustc --version
rustc 1.68.2 (9eb3afe9e 2023-03-27)

I also did a search but couldn't find any rustc folders with a subdirectory called library when i did a search

$ find / -name rustc -type d
maciejhirsz commented 1 year ago

Thanks for doing all this, and documenting it!

There is still a ton of stuff that I want to tackle and this isn't necessarily top of my list right now, but it will be good to have all this researched when it is.

ltfschoen commented 1 year ago

2. On macOS, when i'm stepping-through the code debugging, sometimes it displays an error like one of the following, but it still seems to work:

So i resolved 2.

although, i think these errors may be as a result of from @71 trying to use source maps, but maybe the source maps aren't setup correctly yet.

but i just decided to manually copy the files it wants to the relevant folders as follows:

mkdir -p /Users/luke/code/temp/rustc mkdir -p /Users/luke/code/temp/cargo


* restart computer

* install dependencies that are shown in Chrome DevTools to also need to be in /cargo/registry for debugging 

* this might give error `Updating crates.io index   error: there is nothing to install ...` but it does install what we want. it was only showing that it was trying to find these files so these are the only ones i'll add
```bash
cargo install --version 0.2.3 dlmalloc
cargo install --version 0.1.21 rustc-demangle
cargo install --version 0.1.85 compiler-builtins

mkdir -p /Users/luke/code/temp/cargo/registry/src/github.com-1ecc6299db9ec823/dlmalloc-0.2.3
mkdir -p /Users/luke/code/temp/cargo/registry/src/github.com-1ecc6299db9ec823/rustc-demangle-0.1.21
mkdir -p /Users/luke/code/temp/cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.85

cp -r /Users/luke/.cargo/registry/src/github.com-1ecc6299db9ec823/dlmalloc-0.2.3/ /Users/luke/code/temp/cargo/registry/src/github.com-1ecc6299db9ec823/dlmalloc-0.2.3

cp -r /Users/luke/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-demangle-0.1.21/ /Users/luke/code/temp/cargo/registry/src/github.com-1ecc6299db9ec823/rustc-demangle-0.1.21

cp -r /Users/luke/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.85/ /Users/luke/code/temp/cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.85

mkdir -p /Users/luke/code/temp/rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library cp -r /Users/luke/code/github/rust-lang/rust/library/ /Users/luke/temp/code/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library


* note: i was unable to get it to work using a symlink with `
ln -s /Users/luke/code/github/rust-lang/rust/library /Users/luke/code/temp/rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0`, hence why recursively copied the whole folders instead

* now if you go to https://github.com/rust-lang/rust/tree/master/library:
  * the folder 'backtrace' is shown as 'backtrace @ 07872f2' since it links to https://github.com/rust-lang/backtrace-rs/tree/07872f28cd8a65c3c7428811548dc85f1f2fb05b
  * the folder 'stdarch' is shown as 'stdarch @ b655243' since it links to https://github.com/rust-lang/stdarch/tree/b655243782c18d3419439daa523782e0818ecf26

* clone and recursively copy those dependencies into subdirectories of the folder that we've linked to /rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0 on macOS
```bash
cd ~/code/github/rust-lang
git clone https://github.com/rust-lang/backtrace-rs
git fetch origin 07872f28cd8a65c3c7428811548dc85f1f2fb05b:07872f28cd8a65c3c7428811548dc85f1f2fb05b
git checkout 07872f28cd8a65c3c7428811548dc85f1f2fb05b
mkdir -p /Users/luke/code/temp/rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/backtrace
cp -r /Users/luke/code/github/rust-lang/backtrace-rs/ /Users/luke/code/temp/rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/backtrace

cd ~/code/github/rust-lang
git clone https://github.com/rust-lang/stdarch
git fetch origin b655243782c18d3419439daa523782e0818ecf26:b655243782c18d3419439daa523782e0818ecf26
git checkout b655243782c18d3419439daa523782e0818ecf26
mkdir -p /Users/luke/code/temp/rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/stdarch
cp -r /Users/luke/code/github/rust-lang/stdarch/ /Users/luke/code/temp/rustc/9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0/library/stdarch
ltfschoen commented 1 year ago

Note: For some reason after i restarted the computer when i went to debug again using Google Chrome Canary, even though I had breakpoints setup it wouldn't stop at them, and it would only debug the JS code instead of Rust code.

I resolved that by:

Screen Shot 2023-04-03 at 1 53 10 am Screen Shot 2023-04-03 at 1 52 52 am
ltfschoen commented 1 year ago

i just set this up so i could debug this PR where i am using CSS https://github.com/maciejhirsz/kobold/pull/57/files#diff-6f961f3fdf36b8574e58351c93169e1f148663d2d0b0aa58f7e839af517e8a12R16. it was necessary to update the index.html to be the following (note: the first has rel="css" and href="styles.css" but second has rel="rust" and does not have href="styles.css"

    <link
      data-trunk rel="css"
      data-keep-debug={true}
      data-type="main"
      data-typescript={false}
      data-wasm-opt="0"
      data-no-demangle={false}
      data-weak-refs={true}
      href="styles.css"
    />

    <link
      data-trunk rel="rust"
      data-keep-debug={true}
      data-type="main"
      data-typescript={false}
      data-wasm-opt="0"
      data-no-demangle={false}
      data-weak-refs={true}
    />

also i used Incognito mode.

if it crashed and it wouldn't show the files in "Source", i just disabled and re-enabled the "DWARF support feature" mentioned here https://github.com/maciejhirsz/kobold/issues/47#issuecomment-1493378395