Skip to content

Conversation

@ratmice
Copy link
Collaborator

@ratmice ratmice commented Mar 17, 2025

This adds a poly-fill crate to fix #461

I don't really know anything about wasm etc, but web_time is a complete drop in replacement for std::time,
On platforms where std::time is available, it is simply just a re-export of std::time as shown in the link.

@stephanemagnenat Curious if you are still interested in testing whether this fixes things for you?

@ltratt
Copy link
Member

ltratt commented Mar 17, 2025

This works for me. I do take @stephanemagnenat's point about the dangers of using a timeout: alas, the "perfect" alternative would be to track memory usage and bork if it gets too high, but that's probably tricky for other reasons. It would be good to revisit that at some point, though, because we might be able to do something that's a little less sucky than the current timeout.

@ltratt ltratt self-assigned this Mar 17, 2025
vob.workspace = true
syn.workspace = true
prettyplease.workspace = true
web-time = "1.1.0"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory we could also make this an optional dependency, and only conditionally depend on it if a feature is enabled.

That duplicates the conditional compilation in the crate, but I get that some people might want to minimize dependencies.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must admit, I was thinking exactly the same. Personally I do have a mild preference for only compiling it on wasm targets, because then non-wasm users don't have to think about it as something they need to audit. But I appreciate that's extra work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I was thinking was slightly different actually than compiling it conditionally per-platform
But using a feature like the following.

#[cfg(feature = "webpolyfills")]
use web_time::{Instant, Duration}

#[cfg(not(feature = "webpolyfills"))]
use std::{Instant, Duration};

While the name doesn't imply it you could enable webpolyfills on non-web platforms.
Then you could use the same build options to target either web/non-web.

I think we need this kind of feature anyways, just to enable the library from cargo.toml.
At the very least, I don't know about using target specific cfg options that involve dependencies,
that may very well be a thing though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can say something like:

[target.'cfg(target_arch = "wasm32")'.dependencies]
web-time = "0.1.0"

and then:

#[cfg(target_arch = "wasm32")]
use web_time::{...};

But I haven't thought about whether that's nicer than a feature detected in build.rs or not TBH. I'm easy either way.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose making it work by default without feature flags does seem convenient

@ratmice ratmice marked this pull request as draft March 17, 2025 14:51
@ratmice
Copy link
Collaborator Author

ratmice commented Mar 17, 2025

I'm going to mark this one as draft, until I figure out how to test it.

because just doing the naive thing and installing wasmtime and trying to wasmtime run the .wasm files
does end up giving a bindgen error.

I think the actual main requires some bindgen attributes, and it may well be that more is needed than just this minimal patch. I don't know.

@stephanemagnenat
Copy link

@ratmice thank you for looking into this. I am currently not using grmtools any more, as I switched to lalrpop in the mean time.

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 19, 2025

Nevermind.. I seem to have figured out the problem with my testing....

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 20, 2025

So, I'm pretty uncertain about the .buildbot.sh changes, in particular that it is actually going to install everything
that is needed, and isn't just picking up necessary dependencies that I have installed already.

The example is very much not pretty, but from what I can tell it does actually work.
It could probably use some tlc from someone more familiar with who knows anything about the web.

But I'm going to mark as ready for review because it seems like it's working as intended.

@ratmice ratmice marked this pull request as ready for review March 20, 2025 01:00
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wasm-pack is pretty adamant that LICENSE files exist.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we really have to do this, we'll need to add the LICENSE-MIT too. But is there any way to shut wasm-pack up on this? Or, maybe, we just symlink back to the top-level files, to at least avoid bloating the repository?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd thought about symlinks, but IIRC git doesn't do symlinks well on windows.
I forget what it does exactly (either it puts the destination path of the symlink in the contents, or just bloats the repository how we'd be trying to avoid anyways) but I don't think it had a helpful behavior.

I'll look and see if I can't somehow get wasm-pack to pipe down.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't seem to be any workaround, there has been issues for 6 years, and PRs for at least 3.
I'll look and see though if there is anything I can do that is more similar to what we did with wasmtime,
setting a runner, so we can just avoid wasm-pack all together, as we aren't really using it for it's pack into a tarball for distribution behavior (where checking licenses makes sense).

I'm not certain this is going to be doable, e.g. the trunkrs project implements a lot of wasm-pack's packing behavior, but still doesn't seem to have it's own testing strategy afaict.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strangely and unexpectedly this appears to have been fixed by moving it into cttests in c5a4efd.

There must be something different about the Cargo.toml that makes it not run the check or maybe being one directory closer to the ../Cargo.toml instead of ../../Cargo.toml, I would guess that is it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did manage to get rid of wasm-pack fully in da72a4d

}

#[cfg(test)]
mod test {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think i've ever actually used a test folder but I don't see any way to specify a crate type for them.
Because of how wasm32-unknown-unknown works, this seems to need to be a cdylib crate.

the #[cfg(test)] module is used for wasm32-wasip2 and native targets,
while the other section is used only for wasm32-unknown-unknown.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed by moving it into cttests in c5a4efd

* wasm32-unknown-unknown using wasm-bindgen
* wasm32-wasip2 without wasm-bindgen
* native targets.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably give instructions, and requirements.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed in bfe3346

),
wasm_bindgen
)]
pub fn calculate(l: &str) -> Result<u64, String> {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A big reason this is as ugly as it is is that on wasm32-unknown-unknown the Err variant must be able to be converted into a JsonValue, hence the String error.

Uncertain about wasm32-wasip2.

test
))]
mod wasm_bindgen_test {
use super::calculate;
Copy link
Collaborator Author

@ratmice ratmice Mar 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making these separate modules seemed more clear than the alternative of:

#[cfg(any(all(target_arch = "wasm32", target_os = "unknown", target_vendor = "unknown", test), test))]
mod test {
then

#[cfg_attr(not(all(...)),test)]
#[cfg_attr(all(...), wasm_bindgen_test])
fn test() {...}

wasm_bindgen here kind of wants to take over #[wasm_bindgen_test(unsupported=test)] for tests that should also run on other targets.

But that means bringing in wasm_bindgen as a dependency even for targets where it is unnecessary.
I guess it is worth trying to clean this up via a dev-dependency on cfg_aliases, it is an absolutely tiny macro_rules only crate which seems to be about the same compilation speed as an empty build.rs from my testing.

It seems worth attempting anyways.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up with cfg_aliases in 2a6e491, I personally think the dep pulls it's weight.
considering the duplication of either modules or attributes that we'd otherwise have.

@ltratt
Copy link
Member

ltratt commented Mar 20, 2025

I have a very dumb question: what is calc_wasm aiming to show? My very limited experience of wasm, mostly, is that it's just a backend target and, mostly, I don't need to know anything about. The calc_wasm target, though, seems to be doing various special things that don't fit that mental model. I'm sure I'm missing something obvious!

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 20, 2025

It isn't a dumb question at all,

The thing it is really trying to show is that bug #461 is actually fixed, i.e. it is more of a #[test] than an example.
however wasm32-unknown-unknown has a ton of limitations, in that it requires you to use a specific crate type, it only seems to support crate-type = ["cdylib"], and requires you to annotate anything that would invoke javascript or be invoked by javascript with special function annotations. Running as a normal #[test] can't just change the crate type, so I added it as an example so it could.

So yeah the entirety of wasm32-unknown-unknown is a ton of various special things if I understand correctly, because it is also dealing with lots of javascript nonsense.

wasm32-wasip2 however is much more normal fitting the mental model of how you would expect. Like it I believe that it is able to use a bin target and normal main function. (I don't have a start function here, but in order to add one you have to annotation #[wasm_bindgen(start)]. That is because the host environment isn't reliant on javascript shims.

So you are not wrong, it just seems to be the madness of wasm32-unknown-unknown.
I'm certain that someone who actually knows javascript and browsers and understands it better could
seriously improve what I've done, but I feel it has achieved the goal of testing #461 since it does panic with the appropriate errors if run on the master branch :)

@ltratt
Copy link
Member

ltratt commented Mar 20, 2025

it is more of a #[test] than an example.

Ah, I see! Right, I think I now understand your comment about a tests directory earlier. I think it would be better to dump it in such a directory so that people don't look at the examples repo, see "wasm" and then go "gosh, grmtools requires all sorts of weird hoops" if that makes sense?

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 20, 2025

I'll try to see if I can get it working by putting it in lrpar/cttests/src/lib.rs.
Or maybe it'd be better to just have it e.g. lrpar/wasmtests/

Edit:
The specific problem with tests/ is that cargo tests/ folder support doesn't actually seem to support crate-type for those.
The other issue is the lack of nested workspaces.

lrpar/cttests/ seems to work around those, so If I can I'll use that.

.buildbot.sh Outdated
touch .fake_profile
export WASMTIME_HOME="`pwd`/.wasmtime"
rustup target add wasm32-wasip2
PROFILE=.fake_profile curl https://wasmtime.dev/install.sh -sSf | bash
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one doesn't seem to check whether the current install is sufficient before
downloading/going through the install process, so it redownloads wasmtime every time.

I guess we could just check which wasmtime and if we ever need specific versions we can start comparing the output of wasmtime -v

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of a hack, but 99cfb93 checks the PATH for wasmtime before install.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If/when an appropriate wasmtime is available on Debian, we can edit the docker file in the repo (which buildbot uses). I guess it's either not present or too old?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it is worth trying, there are versions of rust-wasm and nodejs on debian.
I don't know where this docker file is however.

I'm actually not certain which versions are required, but since wasm-pack has been around and stable for a long time, I would hope the version of nodejs installed there is sufficient.
I don't know what the necessary wasmtime version is, because I've only ever run with the latest version.

https://packages.debian.org/search?searchon=sourcenames&keywords=rust-wasmtime
https://packages.debian.org/search?searchon=sourcenames&keywords=nodejs

There doesn't appear to be a package for wasm-pack.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docker file is .buildbot_dockerfile_debian. You'd need to add the appropriate package(s) to the apt-get -y install line. I suggest we give it a go, remove the wasmtime manual installation stuff, and only add that back in if we find we have to. If the version in Debian is good enough, it'll save us some long term maintenance (it also makes CI a bit quicker!).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I don't see a .buildbot_dockerfile_debian could it be just not checked into the repo?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooooops! PR up which adds one.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks if it's alright, I'll rebase onto master once that goes through,
There are some other ci changes like the license check on master which will also help.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, if that PR goes in first, it should make this PR easier (I hope).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use debian packages in c679aec and 52be2ee

ARG CI_UID
RUN useradd -m -u ${CI_UID} ci
RUN apt-get update && \
apt-get -y install build-essential curl procps file
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to end this line with \ and remove apt-get -y install from the following line. [I remember this format being fussy, and I think that's what works.]

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doh, I see it now.

should be fixed in 949e713

.buildbot.sh Outdated
wasm-pack test --node
cargo test --target wasm32-unknown-unknown
cargo test --target wasm32-wasip2
cargo test
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These would ideally run cargo test --target ... just from the root rather than within this subdir.
However that doesn't seem to work, building the tempfile crate needed for lrpar::ctbuilder.

I don't have a complete understanding of what is going on but it seems like that tries to run the codegen process from within wasi on wasip2, and that runs into some issue with nightly features in the std library.

Thus currently we can only build the targets at top-level but only test them on this cttests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was improved in 96f24cb

By disabling those tests that required tempfile.

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 21, 2025

Alright, well I think this now ticks all the boxes for me, assuming the debian packaged versions work out.

Edit: I guess one thing is that 96f24cb adds a .cargo/config.toml, and the .buildbot.sh installs rustup into .cargo/ In my experience these don't overlap, but that doesn't mean they couldn't.

Perhaps it would be better to move the rustup install away from .cargo to something like .cargo_install?
Did that in cc6da91

}

CTLexerBuilder::new()
.rust_edition(lrlex::RustEdition::Rust2021)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thought is that I don't see any reason we can't move this build.rs, calc_wasm.l, and calc_wasm.y into a calc_wasm.test file.

Copy link
Collaborator Author

@ratmice ratmice Mar 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6615a93 & 1d94a4d

@ltratt
Copy link
Member

ltratt commented Mar 21, 2025

Please squash.

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 21, 2025

Squashed.

@ltratt ltratt added this pull request to the merge queue Mar 21, 2025
Merged via the queue into softdevteam:master with commit 0927c33 Mar 21, 2025
2 checks passed
@ratmice
Copy link
Collaborator Author

ratmice commented Mar 21, 2025

I think the debian packages didn't actually work, but somehow it still succeeded.
Maybe the docker script is missing something equivalet to set -e for bash?

10:12:30 #7 ERROR: process "/bin/sh -c apt-get update && apt-get -y install build-essential curl procps file rust-wasmtime nodejs" did not complete successfully: exit code: 100

Eventually producing the message:

10:12:30 4.113 E: Unable to locate package rust-wasmtime

Looking at the output here:
https://ci.soft-dev.org/#/builders/3/builds/3180/steps/3/logs/stdio

Now that I'm looking at that, I see that the debian packages rust-wasmtime is only available on trixie and sid.
So I think we do need to add the wasmtime install phase to .buildbot.sh.
https://packages.debian.org/search?searchon=sourcenames&keywords=rust-wasmtime

Edit: Curiously I'm not familiar with the rest of the output of the .buildbot.sh script that seemed to have run

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 21, 2025

Also, i'm assuming that because trixie isn't released we actually want to do the install via .buildbot.sh locally

@ltratt
Copy link
Member

ltratt commented Mar 21, 2025

Since .buildbot.sh does set -e, presumably that part of things worked OK?

@ratmice
Copy link
Collaborator Author

ratmice commented Mar 21, 2025

That is part of the weird part though, I don't actually see the output of that,
instead, it ran some lang_tests as though it were running the wrong .buildbot.sh, because I'm not actually familiar with seeing that output anywhere in the normal .buildbot.sh run.
I'm pretty confused!

10:30:49 Finished `test` profile [unoptimized + debuginfo] target(s) in 4.78s
10:30:49 Running run.rs (target/debug/deps/lang_tests-eec52b86122b5dd4)
10:30:49 Running tests with interpreter binary: bf_base
10:30:49
10:30:49 running 7 tests
10:30:49 test lang_tests::hello.bf ... ok
10:30:49 test lang_tests::hashes.bf ... ok
10:30:49 test lang_tests::numwarp.bf ... ok
10:30:51 test lang_tests::interp.bf ... ok
10:30:54 test lang_tests::hanoi-opt.bf ... ok
10:31:15 test lang_tests::bench.bf ... ok
10:31:15 test lang_tests::hanoi.bf ... ok
10:31:15
10:31:15 test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
10:31:15
10:31:15 Running tests with interpreter binary: bf_simple2_yk
10:31:15
10:31:15 running 7 tests
10:31:15 test lang_tests::bench.bf ... ignored
10:31:15 test lang_tests::hello.bf ... ignored
10:31:15 test lang_tests::hanoi.bf ... ignored
10:31:15 test lang_tests::numwarp.bf ... ignored
10:31:15 test lang_tests::interp.bf ... ignored
10:31:40 test lang_tests::hashes.bf ... ok
10:31:40 test lang_tests::hanoi-opt.bf ... ok
10:31:40
10:31:40 test result: ok. 7 passed; 0 failed; 5 ignored; 0 measured; 0 filtered out
10:31:40
10:31:40 Running tests with interpreter binary: bf_simple_yk
10:31:40
10:31:40 running 7 tests
10:31:40 test lang_tests::bench.bf ... ignored
10:31:40 test lang_tests::interp.bf ... ignored
10:31:40 test lang_tests::hello.bf ... ignored
10:31:40 test lang_tests::hanoi.bf ... ignored
10:31:40 test lang_tests::numwarp.bf ... ignored
10:32:08 test lang_tests::hashes.bf ... ok
10:32:08 test lang_tests::hanoi-opt.bf ... ok
10:32:08
10:32:08 test result: ok. 7 passed; 0 failed; 5 ignored; 0 measured; 0 filtered out
10:32:08 

@ratmice ratmice mentioned this pull request Mar 23, 2025
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

Successfully merging this pull request may close these issues.

Make generated parsers usable on the web

3 participants