nushell/crates/nu-std
Piepmatz 3d5f853b03
Start to Add WASM Support Again (#14418)
<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
The [nushell/demo](https://github.com/nushell/demo) project successfully
demonstrated running Nushell in the browser using WASM. However, the
current version of Nushell cannot be easily built for the
`wasm32-unknown-unknown` target, the default for `wasm-bindgen`.

This PR introduces initial support for the `wasm32-unknown-unknown`
target by disabling OS-dependent features such as filesystem access, IO,
and platform/system-specific functionality. This separation is achieved
using a new `os` feature in the following crates:

 - `nu-cmd-lang`
 - `nu-command`
 - `nu-engine`
 - `nu-protocol`

The `os` feature includes all functionality that interacts with an
operating system. It is enabled by default, but can be disabled using
`--no-default-features`. All crates that depend on these core crates now
use `--no-default-features` to allow compilation for WASM.

To demonstrate compatibility, the following script builds all crates
expected to work with WASM. Direct user interaction, running external
commands, working with plugins, and features requiring `openssl` are out
of scope for now due to their complexity or reliance on C libraries,
which are difficult to compile and link in a WASM environment.

```nushell
[ # compatible crates
	"nu-cmd-base",
	"nu-cmd-extra",
	"nu-cmd-lang",
	"nu-color-config",
	"nu-command",
	"nu-derive-value",
	"nu-engine",
	"nu-glob",
	"nu-json",
	"nu-parser",
	"nu-path",
	"nu-pretty-hex",
	"nu-protocol",
	"nu-std",
	"nu-system",
	"nu-table",
	"nu-term-grid",
	"nu-utils",
	"nuon"
] | each {cargo build -p $in --target wasm32-unknown-unknown --no-default-features}
```

## Caveats
This PR has a few caveats:
1. **`miette` and `terminal-size` Dependency Issue**
`miette` depends on `terminal-size`, which uses `rustix` when the target
is not Windows. However, `rustix` requires `std::os::unix`, which is
unavailable in WASM. To address this, I opened a
[PR](https://github.com/eminence/terminal-size/pull/68) for
`terminal-size` to conditionally compile `rustix` only when the target
is Unix. For now, the `Cargo.toml` includes patches to:
    - Use my forked version of `terminal-size`.
- ~~Use an unreleased version of `miette` that depends on
`terminal-size@0.4`.~~

These patches are temporary and can be removed once the upstream changes
are merged and released.

2. **Test Output Adjustments**
Due to the slight bump in the `miette` version, one test required
adjustments to accommodate minor formatting changes in the error output,
such as shifted newlines.

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->
This shouldn't break anything but allows using some crates for targeting
`wasm32-unknown-unknown` to revive the demo page eventually.

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

I did not add any extra tests, I just checked that compiling works, also
when using the host target but unselecting the `os` feature.

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
~~Breaking the wasm support can be easily done by adding some `use`s or
by adding a new dependency, we should definitely add some CI that also
at least builds against wasm to make sure that building for it keep
working.~~
I added a job to build wasm.

---------

Co-authored-by: Ian Manske <ian.manske@pm.me>
2024-11-30 07:57:11 -06:00
..
src Always load default env/config values (#14249) 2024-11-20 16:15:15 -06:00
std Deprecate date to-record and date to-table (#14319) 2024-11-29 23:06:26 +01:00
tests add from ndnuon and to ndnuon to stdlib (#14334) 2024-11-27 09:43:49 +08:00
Cargo.toml Start to Add WASM Support Again (#14418) 2024-11-30 07:57:11 -06:00
CONTRIBUTING.md Surprising symlink resolution for std path add (#13258) 2024-06-28 18:11:48 -05:00
LICENSE add LICENSE to nu-std (#8803) 2023-04-07 13:39:21 -07:00
README.md Change the usage misnomer to "description" (#13598) 2024-08-22 12:02:08 +02:00
testing.nu add multiple grouper support to group-by (#14337) 2024-11-15 06:40:49 -06:00

Welcome to the standard library of `nushell`!

The standard library is a pure-nushell collection of custom commands which provide interactive utilities and building blocks for users writing casual scripts or complex applications.

To see what's here:

> use std
> scope commands | select name description | where name =~ "std "
#┬───────────name────────────┬───────────────────description───────────────────
0│std assert                 │Universal assert command
1│std assert equal           │Assert $left == $right
2│std assert error           │Assert that executing the code generates an error
3│std assert greater         │Assert $left > $right
4│std assert greater or equal│Assert $left >= $right
             ...                                     ...
─┴───────────────────────────┴─────────────────────────────────────────────────

🧰 Using the standard library in the REPL or in scripts

All commands in the standard library must be "imported" into the running environment (the interactive read-execute-print-loop (REPL) or a .nu script) using the use command.

You can choose to import the whole module, but then must refer to individual commands with a std prefix, e.g:

use std

std log debug "Running now"
std assert (1 == 2)

Or you can enumerate the specific commands you want to import and invoke them without the std prefix.

use std ["log debug" assert]

log debug "Running again"
assert (2 == 1)

This is probably the form of import you'll want to add to your env.nu for interactive use.

✏️ contribute to the standard library

You're invited to contribute to the standard library! See CONTRIBUTING.md for details