or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcore-runtime.mderrors.mdfunctions.mdindex.mdlinking.mdmemory.mdtypes.mdutilities.mdwasi.md

wasi.mddocs/

0

# WASI Integration

1

2

Complete WebAssembly System Interface implementation providing filesystem access, environment variables, command-line arguments, I/O redirection, and comprehensive permission controls for secure WebAssembly execution in system environments.

3

4

## Capabilities

5

6

### WASI Configuration

7

8

Configuration system for WebAssembly System Interface providing fine-grained control over system resource access, I/O redirection, filesystem permissions, and process environment setup.

9

10

```python { .api }

11

class WasiConfig:

12

def __init__(self):

13

"""Create a new WASI configuration with default settings"""

14

15

# Command line arguments

16

def argv(self, argv: List[str]) -> None:

17

"""

18

Set command line arguments for the WebAssembly program.

19

20

Parameters:

21

- argv: List of command line arguments (first element is program name)

22

"""

23

24

def inherit_argv(self) -> None:

25

"""Inherit command line arguments from the current Python process"""

26

27

# Environment variables

28

def env(self, env: List[Tuple[str, str]]) -> None:

29

"""

30

Set environment variables for the WebAssembly program.

31

32

Parameters:

33

- env: List of (name, value) tuples for environment variables

34

"""

35

36

def inherit_env(self) -> None:

37

"""Inherit environment variables from the current Python process"""

38

39

# Standard I/O redirection

40

def stdin_file(self, path: str) -> None:

41

"""

42

Redirect stdin from a file.

43

44

Parameters:

45

- path: Path to file for stdin input

46

"""

47

48

def stdout_file(self, path: str) -> None:

49

"""

50

Redirect stdout to a file.

51

52

Parameters:

53

- path: Path to file for stdout output

54

"""

55

56

def stderr_file(self, path: str) -> None:

57

"""

58

Redirect stderr to a file.

59

60

Parameters:

61

- path: Path to file for stderr output

62

"""

63

64

def inherit_stdin(self) -> None:

65

"""Inherit stdin from the current Python process"""

66

67

def inherit_stdout(self) -> None:

68

"""Inherit stdout from the current Python process"""

69

70

def inherit_stderr(self) -> None:

71

"""Inherit stderr from the current Python process"""

72

73

# Filesystem access

74

def preopen_dir(self, path: str, guest_path: str, perms: DirPerms) -> None:

75

"""

76

Preopen a directory for WebAssembly filesystem access.

77

78

Parameters:

79

- path: Host filesystem path to directory

80

- guest_path: Path as seen by WebAssembly program

81

- perms: Directory access permissions

82

"""

83

```

84

85

### Directory Permissions

86

87

Permission enumeration controlling directory access rights for preopened directories, providing read-only, write-only, and read-write access control.

88

89

```python { .api }

90

class DirPerms:

91

READ_ONLY: 'DirPerms' # Read-only directory access

92

WRITE_ONLY: 'DirPerms' # Write-only directory access

93

READ_WRITE: 'DirPerms' # Read and write directory access

94

```

95

96

### File Permissions

97

98

Permission enumeration controlling file access rights within preopened directories, providing granular control over file operations and security boundaries.

99

100

```python { .api }

101

class FilePerms:

102

READ_ONLY: 'FilePerms' # Read-only file access

103

WRITE_ONLY: 'FilePerms' # Write-only file access

104

READ_WRITE: 'FilePerms' # Read and write file access

105

```

106

107

## Usage Examples

108

109

### Basic WASI Setup

110

111

```python

112

import wasmtime

113

import sys

114

import os

115

116

# Create WASI configuration

117

wasi_config = wasmtime.WasiConfig()

118

119

# Configure command line arguments

120

wasi_config.argv(["my_program", "arg1", "arg2", "--flag"])

121

122

# Configure environment variables

123

wasi_config.env([

124

("HOME", "/home/wasm"),

125

("PATH", "/usr/bin:/bin"),

126

("CUSTOM_VAR", "custom_value")

127

])

128

129

# Inherit standard I/O

130

wasi_config.inherit_stdin()

131

wasi_config.inherit_stdout()

132

wasi_config.inherit_stderr()

133

134

# Create engine and linker

135

engine = wasmtime.Engine()

136

linker = wasmtime.Linker(engine)

137

store = wasmtime.Store(engine)

138

139

# Define WASI imports

140

linker.define_wasi(store, wasi_config)

141

142

# Load and instantiate WASI-enabled WebAssembly module

143

module = wasmtime.Module.from_file(engine, "wasi_program.wasm")

144

instance = linker.instantiate(store, module)

145

146

# Call main function if it exists

147

try:

148

start_func = instance.get_export(store, "_start")

149

if start_func:

150

start_func(store)

151

except wasmtime.ExitTrap as exit_trap:

152

print(f"Program exited with code: {exit_trap.code}")

153

```

154

155

### Filesystem Access with Permissions

156

157

```python

158

import wasmtime

159

import tempfile

160

import os

161

162

# Create temporary directories for demo

163

with tempfile.TemporaryDirectory() as temp_dir:

164

# Create some test directories

165

input_dir = os.path.join(temp_dir, "input")

166

output_dir = os.path.join(temp_dir, "output")

167

config_dir = os.path.join(temp_dir, "config")

168

169

os.makedirs(input_dir)

170

os.makedirs(output_dir)

171

os.makedirs(config_dir)

172

173

# Create test files

174

with open(os.path.join(input_dir, "data.txt"), "w") as f:

175

f.write("Input data for processing")

176

177

with open(os.path.join(config_dir, "settings.json"), "w") as f:

178

f.write('{"debug": true, "max_items": 100}')

179

180

# Configure WASI with different directory permissions

181

wasi_config = wasmtime.WasiConfig()

182

183

# Read-only input directory

184

wasi_config.preopen_dir(input_dir, "/input", wasmtime.DirPerms.READ_ONLY)

185

186

# Read-write output directory

187

wasi_config.preopen_dir(output_dir, "/output", wasmtime.DirPerms.READ_WRITE)

188

189

# Read-only config directory

190

wasi_config.preopen_dir(config_dir, "/config", wasmtime.DirPerms.READ_ONLY)

191

192

# Setup WebAssembly execution

193

engine = wasmtime.Engine()

194

store = wasmtime.Store(engine)

195

linker = wasmtime.Linker(engine)

196

linker.define_wasi(store, wasi_config)

197

198

# The WebAssembly program can now:

199

# - Read files from /input and /config

200

# - Write files to /output

201

# - Cannot write to /input or /config

202

203

print("WASI filesystem access configured:")

204

print(f" /input -> {input_dir} (read-only)")

205

print(f" /output -> {output_dir} (read-write)")

206

print(f" /config -> {config_dir} (read-only)")

207

```

208

209

### I/O Redirection

210

211

```python

212

import wasmtime

213

import tempfile

214

import os

215

216

# Create temporary files for I/O redirection

217

with tempfile.NamedTemporaryFile(mode='w', delete=False) as input_file:

218

input_file.write("Hello from input file!\n")

219

input_file.write("Second line of input\n")

220

input_file_path = input_file.name

221

222

with tempfile.NamedTemporaryFile(mode='w', delete=False) as output_file:

223

output_file_path = output_file.name

224

225

with tempfile.NamedTemporaryFile(mode='w', delete=False) as error_file:

226

error_file_path = error_file.name

227

228

try:

229

# Configure WASI with I/O redirection

230

wasi_config = wasmtime.WasiConfig()

231

232

# Redirect stdin from file

233

wasi_config.stdin_file(input_file_path)

234

235

# Redirect stdout to file

236

wasi_config.stdout_file(output_file_path)

237

238

# Redirect stderr to file

239

wasi_config.stderr_file(error_file_path)

240

241

# Set up command line arguments

242

wasi_config.argv(["io_test", "--echo"])

243

244

# Set up environment

245

wasi_config.env([("TEST_MODE", "redirect")])

246

247

# Create WebAssembly execution environment

248

engine = wasmtime.Engine()

249

store = wasmtime.Store(engine)

250

linker = wasmtime.Linker(engine)

251

linker.define_wasi(store, wasi_config)

252

253

# Load and run WebAssembly program

254

# (This would be a WASI program that reads stdin and writes to stdout/stderr)

255

# module = wasmtime.Module.from_file(engine, "io_program.wasm")

256

# instance = linker.instantiate(store, module)

257

# start_func = instance.get_export(store, "_start")

258

# start_func(store)

259

260

print("I/O redirection configured:")

261

print(f" stdin <- {input_file_path}")

262

print(f" stdout -> {output_file_path}")

263

print(f" stderr -> {error_file_path}")

264

265

# After execution, read the output files

266

# with open(output_file_path, 'r') as f:

267

# print(f"Program output: {f.read()}")

268

269

finally:

270

# Clean up temporary files

271

for path in [input_file_path, output_file_path, error_file_path]:

272

try:

273

os.unlink(path)

274

except OSError:

275

pass

276

```

277

278

### Environment Variable Inheritance and Customization

279

280

```python

281

import wasmtime

282

import os

283

284

# Get current environment

285

current_env = dict(os.environ)

286

287

# Create custom environment based on current environment

288

custom_env = []

289

for key, value in current_env.items():

290

# Filter out sensitive variables

291

if not key.startswith(('SECRET_', 'TOKEN_', 'PASSWORD_')):

292

custom_env.append((key, value))

293

294

# Add custom variables

295

custom_env.extend([

296

("WASM_MODE", "production"),

297

("MAX_MEMORY", "1073741824"), # 1GB

298

("DEBUG_LEVEL", "info"),

299

("ALLOWED_HOSTS", "api.example.com,cdn.example.com")

300

])

301

302

# Configure WASI

303

wasi_config = wasmtime.WasiConfig()

304

wasi_config.env(custom_env)

305

306

# Alternative: inherit everything and let WebAssembly filter

307

# wasi_config_simple = wasmtime.WasiConfig()

308

# wasi_config_simple.inherit_env()

309

310

print(f"Configured {len(custom_env)} environment variables for WebAssembly")

311

print("Custom variables:")

312

for key, value in custom_env:

313

if key.startswith(('WASM_', 'MAX_', 'DEBUG_', 'ALLOWED_')):

314

print(f" {key}={value}")

315

```

316

317

### Complete WASI Application Setup

318

319

```python

320

import wasmtime

321

import os

322

import sys

323

import tempfile

324

import shutil

325

326

def setup_wasi_application(wasm_path: str, work_dir: str = None):

327

"""

328

Complete setup for a WASI WebAssembly application.

329

330

Parameters:

331

- wasm_path: Path to the WebAssembly WASI binary

332

- work_dir: Working directory for the application (optional)

333

"""

334

335

# Create working directory if not provided

336

if work_dir is None:

337

work_dir = tempfile.mkdtemp(prefix="wasi_app_")

338

cleanup_work_dir = True

339

else:

340

cleanup_work_dir = False

341

342

try:

343

# Create application directory structure

344

app_dirs = {

345

"data": os.path.join(work_dir, "data"),

346

"config": os.path.join(work_dir, "config"),

347

"logs": os.path.join(work_dir, "logs"),

348

"temp": os.path.join(work_dir, "temp")

349

}

350

351

for dir_path in app_dirs.values():

352

os.makedirs(dir_path, exist_ok=True)

353

354

# Create sample configuration

355

config_content = '''

356

{

357

"app_name": "WASI Application",

358

"version": "1.0.0",

359

"max_memory": "512MB",

360

"log_level": "info"

361

}

362

'''

363

364

with open(os.path.join(app_dirs["config"], "app.json"), "w") as f:

365

f.write(config_content)

366

367

# Configure WASI

368

wasi_config = wasmtime.WasiConfig()

369

370

# Command line arguments

371

wasi_config.argv([

372

"wasi_app",

373

"--config", "/config/app.json",

374

"--data-dir", "/data",

375

"--log-dir", "/logs"

376

])

377

378

# Environment variables

379

wasi_config.env([

380

("HOME", "/app"),

381

("TMPDIR", "/temp"),

382

("LOG_LEVEL", "info"),

383

("APP_VERSION", "1.0.0")

384

])

385

386

# Filesystem access

387

wasi_config.preopen_dir(app_dirs["data"], "/data", wasmtime.DirPerms.READ_WRITE)

388

wasi_config.preopen_dir(app_dirs["config"], "/config", wasmtime.DirPerms.READ_ONLY)

389

wasi_config.preopen_dir(app_dirs["logs"], "/logs", wasmtime.DirPerms.READ_WRITE)

390

wasi_config.preopen_dir(app_dirs["temp"], "/temp", wasmtime.DirPerms.READ_WRITE)

391

392

# I/O configuration

393

wasi_config.inherit_stdin()

394

wasi_config.inherit_stdout()

395

wasi_config.inherit_stderr()

396

397

# Set up WebAssembly runtime

398

engine = wasmtime.Engine()

399

store = wasmtime.Store(engine)

400

linker = wasmtime.Linker(engine)

401

402

# Define WASI imports

403

linker.define_wasi(store, wasi_config)

404

405

# Load the WebAssembly module

406

module = wasmtime.Module.from_file(engine, wasm_path)

407

408

# Instantiate the module

409

instance = linker.instantiate(store, module)

410

411

print(f"WASI application setup complete:")

412

print(f" Work directory: {work_dir}")

413

print(f" WebAssembly module: {wasm_path}")

414

print(f" Directory mappings:")

415

for guest_path, host_path in [("/data", app_dirs["data"]),

416

("/config", app_dirs["config"]),

417

("/logs", app_dirs["logs"]),

418

("/temp", app_dirs["temp"])]:

419

print(f" {guest_path} -> {host_path}")

420

421

# Run the application

422

try:

423

start_func = instance.get_export(store, "_start")

424

if start_func:

425

print("Running WASI application...")

426

start_func(store)

427

print("Application completed successfully")

428

else:

429

print("No _start function found in WebAssembly module")

430

431

except wasmtime.ExitTrap as exit_trap:

432

exit_code = exit_trap.code

433

if exit_code == 0:

434

print("Application completed successfully")

435

else:

436

print(f"Application exited with code: {exit_code}")

437

438

except wasmtime.Trap as trap:

439

print(f"Application trapped: {trap.message}")

440

if trap.frames:

441

for frame in trap.frames:

442

print(f" at {frame.func_name or 'unknown'} in {frame.module_name or 'unknown'}")

443

444

return instance

445

446

finally:

447

if cleanup_work_dir and os.path.exists(work_dir):

448

shutil.rmtree(work_dir)

449

450

# Example usage:

451

# setup_wasi_application("my_wasi_app.wasm", "/path/to/work/directory")

452

```

453

454

### WASI Error Handling

455

456

```python

457

import wasmtime

458

459

def safe_wasi_execution(wasm_path: str):

460

"""Demonstrate proper error handling for WASI applications"""

461

462

try:

463

# Configure WASI

464

wasi_config = wasmtime.WasiConfig()

465

wasi_config.inherit_argv()

466

wasi_config.inherit_env()

467

wasi_config.inherit_stdin()

468

wasi_config.inherit_stdout()

469

wasi_config.inherit_stderr()

470

471

# Set up runtime

472

engine = wasmtime.Engine()

473

store = wasmtime.Store(engine)

474

linker = wasmtime.Linker(engine)

475

linker.define_wasi(store, wasi_config)

476

477

# Load module

478

module = wasmtime.Module.from_file(engine, wasm_path)

479

instance = linker.instantiate(store, module)

480

481

# Execute

482

start_func = instance.get_export(store, "_start")

483

if start_func:

484

start_func(store)

485

486

except FileNotFoundError:

487

print(f"Error: WebAssembly file '{wasm_path}' not found")

488

489

except wasmtime.WasmtimeError as e:

490

print(f"WebAssembly error: {e}")

491

492

except wasmtime.ExitTrap as exit_trap:

493

exit_code = exit_trap.code

494

if exit_code != 0:

495

print(f"Application exited with error code: {exit_code}")

496

return exit_code

497

498

except wasmtime.Trap as trap:

499

print(f"Runtime trap: {trap.message}")

500

print("Stack trace:")

501

for frame in trap.frames:

502

func_name = frame.func_name or f"func[{frame.func_index}]"

503

module_name = frame.module_name or "unknown"

504

print(f" {func_name} in {module_name} at offset {frame.module_offset}")

505

return 1

506

507

except Exception as e:

508

print(f"Unexpected error: {e}")

509

return 1

510

511

return 0

512

```