{"id":14967163,"url":"https://github.com/golemfactory/sp-wasm","last_synced_at":"2025-10-19T09:31:36.843Z","repository":{"id":57668344,"uuid":"173767212","full_name":"golemfactory/sp-wasm","owner":"golemfactory","description":"SpiderMonkey-based Wasm sandbox","archived":false,"fork":false,"pushed_at":"2020-05-29T16:58:39.000Z","size":338,"stargazers_count":21,"open_issues_count":1,"forks_count":4,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-04-14T23:45:17.566Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/golemfactory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-04T15:08:34.000Z","updated_at":"2022-10-27T05:59:34.000Z","dependencies_parsed_at":"2022-09-07T15:50:35.101Z","dependency_job_id":null,"html_url":"https://github.com/golemfactory/sp-wasm","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golemfactory%2Fsp-wasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golemfactory%2Fsp-wasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golemfactory%2Fsp-wasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/golemfactory%2Fsp-wasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/golemfactory","download_url":"https://codeload.github.com/golemfactory/sp-wasm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219869245,"owners_count":16555571,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T13:37:33.011Z","updated_at":"2025-10-19T09:31:36.323Z","avatar_url":"https://github.com/golemfactory.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SpiderMonkey-based WebAssembly Sandbox\n[![Build Status]][build]\n\n[Build Status]: https://github.com/golemfactory/sp-wasm/workflows/Continuous%20Integration/badge.svg\n[build]: https://github.com/golemfactory/sp-wasm/actions\n\nA WebAssembly sandbox using standalone SpiderMonkey engine. For `v8` version,\nsee [golemfactory/v8-wasm](https://github.com/golemfactory/v8-wasm).\n\nThis WebAssembly sandbox is used in current development version of\nGolem: [golem/apps/wasm](https://github.com/golemfactory/golem/tree/develop/apps/wasm).\nIf you would like to launch a gWASM task in Golem, see\n[here](https://docs.golem.network/#/About/Use-Cases?id=wasm).\n\n- [SpiderMonkey-based WebAssembly Sandbox](#spidermonkey-based-webassembly-sandbox)\n  - [Quick start guide](#quick-start-guide)\n    - [1. Create and cross-compile simple program](#1-create-and-cross-compile-simple-program)\n      - [1.1 C/C++](#11-cc)\n      - [1.2 Rust](#12-rust)\n    - [2. Create input and output dirs and files](#2-create-input-and-output-dirs-and-files)\n    - [3. Run!](#3-run)\n  - [Build instructions](#build-instructions)\n    - [Using Docker (recommended)](#using-docker-recommended)\n    - [Natively on Linux](#natively-on-linux)\n    - [Natively on other OSes](#natively-on-other-oses)\n  - [CLI arguments explained](#cli-arguments-explained)\n  - [Caveats](#caveats)\n  - [Wasm store](#wasm-store)\n  - [Contributing](#contributing)\n  - [License](#license)\n\n## Quick start guide\nThis guide assumes you have successfully built the `wasm-sandbox` binary; for build instructions, see section\n[Build instructions](#build-instructions) below. If you are running Linux, then you can also use the prebuilt\nbinaries from [here](https://github.com/golemfactory/sp-wasm/releases).\n\n### 1. Create and cross-compile simple program\nLet us create a simple `hello world` style program which will read in\nsome text from `in.txt` text file, read your name from the command line,\nand save the resultant text in `out.txt`. We'll demonstrate how to\ncross-compile apps to Wasm for use in Golem in two languages of choice:\nC and Rust.\n\n#### 1.1 C/C++\n```c\n#include \u003cstdio.h\u003e\n\nint main(int argc, char** argv) {\n  char* name = argc \u003e= 2 ? argv[1] : \"anonymous\";\n  size_t len = 0;\n  char* line = NULL;\n  ssize_t read;\n\n  FILE* f_in = fopen(\"in.txt\", \"r\");\n  FILE* f_out = fopen(\"out.txt\", \"w\");\n\n  while ((read = getline(\u0026line, \u0026len, f_in)) != -1)\n      fprintf(f_out, \"%s\\n\", line);\n\n  fprintf(f_out, \"%s\\n\", name);\n\n  fclose(f_out);\n  fclose(f_in);\n\n  return 0;\n}\n```\n\nThere is one important thing to notice here. The sandbox communicates\nthe results of computation by reading and writing to files. Thus, every\nWasm program is required to at the very least create an output file.\nIf your code does not include file manipulation in its main body,\nthen the Emscripten compiler, by default, will not initialise\nJavaScript `FS` library, and will trip the sandbox. This will also be true\nfor programs cross-compiled [from Rust](#12-rust).\n\nNow, we can try and compile the program with Emscripten.\nIn order to do that you need Emscripten SDK installed on your\nsystem. For instructions on how to do it, see\n[here](https://emscripten.org/docs/getting_started/downloads.html).\n\n```\n$ emcc -o simple.js simple.c\n```\n\nEmscripten will then produce two files: `simple.js` and `simple.wasm`.\nThe produced JavaScript file acts as glue code and sets up all of\nthe rudimentary syscalls in JavaScript such as `MemFS` (in-memory\nfilesystem), etc., while the `simple.wasm` is our C program\ncross-compiled to Wasm.\n\n#### 1.2 Rust\nWith Rust, firstly go ahead and create a new binary with `cargo`\n```\n$ cargo new --bin simple\n```\n\nThen go ahead and paste the following to `simple/src/main.rs`\nfile\n```rust\nuse std::env;\nuse std::fs;\nuse std::io::{self, Read, Write};\n\nfn main() -\u003e io::Result\u003c()\u003e {\n    let args = env::args().collect::\u003cVec\u003cString\u003e\u003e();\n    let name = args.get(1).map_or(\"anonymous\".to_owned(), |x| x.clone());\n\n    let mut in_file = fs::File::open(\"in.txt\")?;\n    let mut contents = String::new();\n    in_file.read_to_string(\u0026mut contents)?;\n\n    let mut out_file = fs::File::create(\"out.txt\")?;\n    out_file.write_all(\u0026contents.as_bytes())?;\n    out_file.write_all(\u0026name.as_bytes())?;\n\n    Ok(())\n}\n```\n\nAs was the case with [C program](#11-c/c++), it is important to notice\nhere that the sandbox communicates\nthe results of computation by reading and writing to files. Thus, every\nWasm program is required to at the very least create an output file.\nIf your code does not include file manipulation in its main body,\nthen the Emscripten compiler, by default, will not initialise\nJavaScript `FS` library, and will trip the sandbox.\n\nIn order to cross-compile Rust to Wasm compatible with Golem's\nsandbox, firstly we need to install rustc 1.38.0 toolchain which\nincludes fastcomp backend for `wasm32-unknown-emscripten` target\n\n```\n$ rustup toolchain add 1.38.0\n```\n\nThen, we need to install the required target which\nis `wasm32-unknown-emscripten`. The easiest way of doing so, as well\nas generally managing your Rust installations, is to use\n[rustup](https://rustup.rs/)\n```\n$ rustup target add wasm32-unknown-emscripten --toolchain 1.38.0\n```\n\nNote that cross-compiling Rust to this target still requires that you\nhave Emscripten SDK installed on your\nsystem. For instructions on how to do it, see\n[here](https://emscripten.org/docs/getting_started/downloads.html).\n\nNow, we can compile our Rust program to Wasm. Make sure you are in\nthe root of your Rust crate, i.e., at the top of `simple`\nif you didn't change the name of your crate, and run\n```\n$ cargo +1.38.0 build --target=wasm32-unknown-emscripten --release\n```\n\nIf everything went OK, you should now see two files:\n`simple.js` and `simple.wasm` in `simple/target/wasm32-unknown-emscripten/release`.\nJust like in [C program](#11-cc++)'s case, the produced JavaScript\nfile acts as glue code and sets up all of\nthe rudimentary syscalls in JavaScript such as `MemFS` (in-memory\nfilesystem), etc., while the `simple.wasm` is our Rust program\ncross-compiled to Wasm.\n\n### 2. Create input and output dirs and files\nThe sandbox will require us to specify input and output paths together\nwith output filenames to create, and any additional arguments (see\n[CLI arguments explained](#cli-arguments-explained) section below\nfor detailed specification\nof the required arguments). Suppose we have the following file\nstructure locally\n\n```\n  |-- in/\n  |    |\n  |    |-- in.txt\n  |\n  |-- out/\n```\n\nPaste the following text in the `in.txt` file\n\n```\n// in.txt\nYou are running Wasm!\n```\n\n### 3. Run!\nAfter you have successfully run all of the above steps up to now, you should have the following file structure locally\n\n```\n  |-- simple.js\n  |-- simple.wasm\n  |\n  |-- in/\n  |    |\n  |    |-- in.txt\n  |\n  |-- out/\n```\n\nWe can now run our Wasm binary inside the sandbox\n\n1. using Docker (if you've followed [Using Docker (recommended)](#using-docker-recommended)\n   build instructions)\n\n```\ndocker run --mount type=bind,source=$PWD,target=/workdir --workdir /workdir \\\n            wasm-sandbox:latest -I in/ -O out/ -j simple.js -w simple.wasm \\\n            -o out.txt -- \"\u003cyour_name\u003e\"\n```\n\n2. natively (if you're using the prebuilt binaries, or you've built natively following\n   [Natively on Linux](#natively-on-linux) build instructions)\n\n```\n$ wasm-sandbox -I in/ -O out/ -j simple.js -w simple.wasm \\\n               -o out.txt -- \"\u003cyour_name\u003e\"\n```\n\nHere, `-I` maps the input dir with *all* its contents (files and\nsubdirs) directly to the root `/` in `MemFS`. The output files,\non the other hand, will be saved in `out/` local dir. The names of\nthe expected output files have to match those specified with `-o`\nflags. Thus, in this case, our Wasm bin is expected to create an\noutput file `/out.txt` in `MemFS` which will then be saved in\n`out/out.txt` locally.\n\nAfter you execute Wasm bin in the sandbox, `out.txt` should be\ncreated in `out/` dir\n\n```\n  |-- simple.js\n  |-- simple.wasm\n  |\n  |-- in/\n  |    |\n  |    |-- in.txt\n  |\n  |-- out/\n  |    |\n  |    |-- out.txt\n```\n\nwith the contents similar to the following\n\n```\n// out.txt\nYou are running Wasm!\n\u003cyour_name\u003e\n```\n\n## Build instructions\n### Using Docker (recommended)\nTo build using Docker, simply run\n\n```\n$ ./build.sh\n```\n\nIf you are running Windows, then you can invoke the command in the shell script manually\nin the command line as follows\n\n```\ndocker build -t wasm-sandbox:latest .\n```\n\n### Natively on Linux\n**NOTE: Building the sandbox from source requires rustc 1.38.0 due to fastcomp backend\ncompability for `wasm32-unknown-emscripten` target, and other changes that are\nincompatible with SpiderMonkey Rust wrappers.**\n\nTo build natively on Linux, first install rustc `1.38.0` toolchain\n\n```\n$ rustup toolchain add 1.38.0\n```\n\nNext, you need to follow the installation instructions of\n[servo/rust-mozjs](https://github.com/servo/rust-mozjs) and\n[servo/mozjs](https://github.com/servo/mozjs). The latter is Mozilla's Servo's SpiderMonkey fork and low-level\nRust bindings, and as such, requires C/C++ compiler and Autoconf 2.13. See [servo/mozjs/README.md](https://github.com/servo/mozjs)\nfor detailed building instructions.\n\nAfter following the aforementioned instructions, to build the sandbox, run\n\n```\n$ cargo +1.38.0 build --release\n```\n\nIf you would like to build with SpiderMonkey's debug symbols and extensive logging, run instead\n\n```\n$ cargo +1.38.0 build --release --features \"debugmozjs\"\n```\n\n### Natively on other OSes\nWe currently do not offer any support for building the sandbox natively on other OSes.\n\n## CLI arguments explained\n```\nwasm-sandbox -I \u003cinput-dir\u003e -O \u003coutput-dir\u003e -j \u003cwasm-js\u003e -w \u003cwasm\u003e -o \u003coutput-file\u003e... -- \u003cargs\u003e...\n```\n\nwhere\n* `-I` path to the input dir\n* `-O` path to the output dir\n* `-j` path to the Emscripten JS glue script\n* `-w` path to the Emscripten WASM binary\n* `-o` paths to expected output files\n* `--` anything after this will be passed to the WASM binary as arguments\n\nBy default, basic logging is enabled. If you would like to enable more comprehensive logging, export\nthe following variable\n\n```\nRUST_LOG=debug\n```\n\n## Caveats\n* Building the sandbox from source requires rustc 1.38.0 due to fastcomp backend\n  compability for `wasm32-unknown-emscripten` target, and other changes that are\n  incompatible with SpiderMonkey Rust wrappers.\n* Sometimes, if the binary you are cross-compiling is of substantial\n  size, you might encounter a `asm2wasm` validation error stating\n  that there is not enough memory assigned to Wasm. In this case,\n  you can circumvent the problem by adding `-s TOTAL_MEMORY=value`\n  flag. The value has to be an integer multiple of 1 Wasm memory page\n  which is currently set at `65,536` bytes.\n* When running your Wasm binary you encounter an `OOM` error at\n  runtime, it usually means that the sandbox has run out-of-memory.\n  To alleviate the problem, recompile your program with\n  `-s ALLOW_MEMORY_GROWTH=1`.\n* Emscripten, by default, doesn't support `/dev/(u)random` emulation\n  targets different than either browser or `nodejs`. Therefore, we\n  have added basic emulation of the random device that is *fully*\n  deterministic. For details, see [#5](https://github.com/golemfactory/sp-wasm/pull/5).\n\n## Wasm store\nMore examples of precompiled Wasm binaries can be found in [golemfactory/wasm-store](https://github.com/golemfactory/wasm-store) repo.\n\n## Contributing\nAll contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for pointers.\n\n## License\nLicensed under [GNU General Public License v3.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgolemfactory%2Fsp-wasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgolemfactory%2Fsp-wasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgolemfactory%2Fsp-wasm/lists"}