# Preview2 Shim

WASI Preview2 implementations for Node.js & browsers.

Node.js support is fully tested and conformant against the Wasmtime test suite.

Browser support is considered experimental, and not currently suitable for production applications.

# Features

## WASI Shim object for easy instantiation

An default instantiation object can be used via the `WASIShim` class in `@bytecodealliance/preview2-shim/instantiation`:

```typescript
import { WASIShim } from '@bytecodealliance/preview2-shim/instantiation';
import type {
    VersionedWASIImportObject,
    WASIImportObject,
} from '@bytecodealliance/preview2-shim/instantiation';

const shim = new WASIShim();

const unversioned: WASIImportObject = shim.getImportObject();
// console.log('unversioned', unversioned);
unversioned satisfies WASIImportObject;
unversioned satisfies VersionedWASIImportObject<''>;

const versioned: VersionedWASIImportObject<'0.2.3'> = shim.getImportObject({
    asVersion: '0.2.3',
});
//console.log('versioned', versioned);
versioned satisfies VersionedWASIImportObject<'0.2.3'>;
```

The import object generated by `getImportObject` can be easily used in `instantiate()` calls
produced by [`jco transpile`][jco] (with `--instantiation=async`):

```js
import { WASIShim } from '@bytecodealliance/preview2-shim/instantiation';

// The code below assumes that you have output your transpiled WebAssembly component to `dist/transpiled`
import { instantiate } from './dist/transpiled/component.js';

const loader = async (path: string) => {
    const buf = await readFile(`./dist/transpiled/${path}`);
    return await WebAssembly.compile(buf.buffer as ArrayBuffer);
};
const component = await instantiate(loader, new WASIShim().getImportObject());

// TODO: Code that uses your component's exports goes here.
```

## Sandboxing

By default, the preview2-shim provides full access to the host filesystem, environment variables,
and network - matching the default behavior of Node.js libraries. However, you can configure
sandboxing to restrict what guests can access.

### Using WASIShim for sandboxing

The `WASIShim` class accepts a `sandbox` configuration option to control access:

```js
import { WASIShim } from '@bytecodealliance/preview2-shim/instantiation';

// Fully sandboxed - no filesystem, network, or env access
const sandboxedShim = new WASIShim({
  sandbox: {
    preopens: {},           // No filesystem access
    env: {},                // No environment variables
    args: ['arg1'],         // Custom arguments
    enableNetwork: false,   // Disable network access
  }
});

// Limited filesystem access - map virtual paths to host paths
const limitedShim = new WASIShim({
  sandbox: {
    preopens: {
      '/data': '/tmp/guest-data',  // Guest sees /data, maps to /tmp/guest-data
      '/config': '/etc/app'        // Guest sees /config, maps to /etc/app
    },
    env: { 'ENV1': '42' },           // Only expose specific env vars
  }
});

const component = await instantiate(loader, sandboxedShim.getImportObject());
```

### Notes on sandboxing

- By default (when no options are passed), the shim is providing full access to match typical
  Node.js library behavior.
- Each `WASIShim` instance has its own isolated preopens, environment variables, and arguments.
  Multiple instances with different configurations will not affect each other.
- The direct preopen functions (`_setPreopens`, `_clearPreopens`, etc.) modify global state and
  affect all components not using `WASIShim` with explicit configuration. For isolation, prefer
  using `WASIShim` with the `sandbox` option containing `preopens` and `env`.
- When `sandbox.enableNetwork: false`, all socket and HTTP operations will throw "access-denied" errors.

[jco]: https://www.npmjs.com/package/@bytecodealliance/jco

# License

This project is licensed under the Apache 2.0 license with the LLVM exception.
See [LICENSE](LICENSE) for more details.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be licensed as above, without any additional terms or conditions.
