├── .gitignore ├── package.json ├── packages ├── asm-webpack │ ├── index.html │ ├── package.json │ ├── src │ │ └── index.js │ └── wasm │ │ ├── fibonacci.js │ │ ├── fibonacci.wasm │ │ └── fibonacci.wast ├── clang-array │ ├── .gitignore │ ├── build.sh │ ├── index.html │ ├── readme.md │ └── src │ │ └── print_array.c ├── clang-simd │ ├── .gitignore │ ├── build.sh │ ├── index.html │ ├── lib.js │ ├── no-simd.html │ ├── readme.md │ ├── simd.html │ └── src │ │ ├── multiply_arrays.c │ │ └── multiply_arrays_simd.c ├── clang-thread │ ├── .gitignore │ ├── build.sh │ ├── index.html │ ├── readme.md │ └── src │ │ └── test.c ├── clang │ ├── index.html │ ├── package.json │ ├── readme.md │ ├── wasm-loader.js │ └── wasm │ │ ├── helloworld-dylib.c │ │ ├── helloworld-dylib.wasm │ │ ├── helloworld-std.c │ │ ├── helloworld-std.js │ │ └── helloworld-std.wasm ├── go │ ├── Makefile │ ├── index.html │ ├── readme.md │ ├── server │ ├── src │ │ ├── main.go │ │ └── server.go │ ├── wasm │ │ └── main.wasm │ └── wasm_exec.js ├── rust-parcel │ ├── index.html │ ├── package.json │ ├── readme.md │ ├── src │ │ └── index.js │ └── wasm │ │ ├── add.rs │ │ └── square.wasm ├── rust-thread │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.sh │ ├── index.html │ ├── readme.md │ ├── src │ │ ├── lib.rs │ │ └── thread.rs │ └── worker.js ├── rust-wasi-node │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── readme.md │ ├── runtime │ │ └── index.mjs │ └── src │ │ └── lib.rs ├── rust-wasm-bindgen │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── index.html │ ├── package.json │ ├── readme.md │ ├── src │ │ └── index.js │ ├── wasm │ │ └── alert.rs │ └── webpack.config.js ├── rust-wasm-pack │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.sh │ ├── index.html │ ├── readme.md │ └── src │ │ └── lib.rs ├── rust-webgl │ ├── .babelrc │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── index.html │ ├── package.json │ └── src │ │ ├── main.rs │ │ └── webgl.rs ├── rust │ ├── index.html │ ├── package.json │ ├── readme.md │ ├── wasm-loader.js │ └── wasm │ │ ├── math.rs │ │ └── math.wasm └── ts-assembly-script │ ├── index.html │ ├── package.json │ ├── readme.md │ ├── tsconfig.json │ ├── wasm-loader.js │ └── wasm │ ├── fibonacci.ts │ ├── fibonacci.wasm │ └── fibonacci.wasm.map └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | yarn.lock 4 | .cache -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world-wasm", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "devDependencies": { 6 | "http-server": "^0.11.1", 7 | "webpack": "^4.6.0", 8 | "webpack-cli": "^2.0.14" 9 | }, 10 | "dependencies": { 11 | "next": "^12.0.2", 12 | "react": "^17.0.2", 13 | "react-dom": "^17.0.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/asm-webpack/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/asm-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asm", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "start": "../node_modules/.bin/serve .", 6 | "build:webpack": "../node_modules/.bin/webpack --mode=development --output-public-path=/dist/", 7 | "build:wasm": "asm2wasm ./wasm/fibonacci.js | grep -v '(import \"env\"' > ./wasm/fibonacci.wast && wat2wasm ./wasm/fibonacci.wast -o ./wasm/fibonacci.wasm", 8 | "build": "npm run build:wasm && npm run build:webpack" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/asm-webpack/src/index.js: -------------------------------------------------------------------------------- 1 | import('../wasm/fibonacci.wasm').then(m => { 2 | document.write(m.fibonacci(5)) 3 | }) -------------------------------------------------------------------------------- /packages/asm-webpack/wasm/fibonacci.js: -------------------------------------------------------------------------------- 1 | function () { 2 | "use asm"; 3 | 4 | function fibonacci (n) { 5 | n = n | 0; 6 | if (n < 2) { 7 | return 1 8 | } 9 | return (fibonacci(n - 2) | 0) + (fibonacci(n - 1) | 0) | 0 10 | } 11 | 12 | return { 13 | fibonacci: fibonacci, 14 | } 15 | } -------------------------------------------------------------------------------- /packages/asm-webpack/wasm/fibonacci.wasm: -------------------------------------------------------------------------------- 1 | asm`  fibonacci 2 |  AH@A Ak Akj -------------------------------------------------------------------------------- /packages/asm-webpack/wasm/fibonacci.wast: -------------------------------------------------------------------------------- 1 | (module 2 | (export "fibonacci" (func $fibonacci)) 3 | (func $fibonacci (; 0 ;) (param $n i32) (result i32) 4 | (if 5 | (i32.lt_s 6 | (get_local $n) 7 | (i32.const 2) 8 | ) 9 | (return 10 | (i32.const 1) 11 | ) 12 | ) 13 | (return 14 | (i32.add 15 | (call $fibonacci 16 | (i32.sub 17 | (get_local $n) 18 | (i32.const 2) 19 | ) 20 | ) 21 | (call $fibonacci 22 | (i32.sub 23 | (get_local $n) 24 | (i32.const 1) 25 | ) 26 | ) 27 | ) 28 | ) 29 | ) 30 | ) 31 | -------------------------------------------------------------------------------- /packages/clang-array/.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | *.wasm -------------------------------------------------------------------------------- /packages/clang-array/build.sh: -------------------------------------------------------------------------------- 1 | emcc ./src/print_array.c -o print_array.js -O2 -s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' -s ALLOW_MEMORY_GROWTH=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -------------------------------------------------------------------------------- /packages/clang-array/index.html: -------------------------------------------------------------------------------- 1 | 2 | 39 | -------------------------------------------------------------------------------- /packages/clang-array/readme.md: -------------------------------------------------------------------------------- 1 | # Array manging example with Clang 2 | 3 | ## Build 4 | 5 | ``` 6 | sh ./build.sh 7 | ``` 8 | 9 | ## Run 10 | 11 | ``` 12 | python3 -m http.server 13 | ``` 14 | 15 | # License 16 | 17 | MIT @ Jimmy Moon -------------------------------------------------------------------------------- /packages/clang-array/src/print_array.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | EM_JS(void, iprint, (int n), { 4 | console.log(n); 5 | }); 6 | 7 | EM_JS(void, fprint, (float n), { 8 | console.log(n); 9 | }); 10 | 11 | EM_JS(void, dprint, (double n), { 12 | console.log(n); 13 | }); 14 | 15 | EMSCRIPTEN_KEEPALIVE 16 | void print_iarray(int* in, int size) { 17 | for (int i = 0; i < size; i++) { 18 | iprint(in[i]); 19 | } 20 | } 21 | 22 | EMSCRIPTEN_KEEPALIVE 23 | void print_farray(float* in, int size) { 24 | for (int i = 0; i < size; i++) { 25 | fprint(in[i]); 26 | } 27 | } 28 | 29 | EMSCRIPTEN_KEEPALIVE 30 | void print_darray(double* in, int size) { 31 | for (int i = 0; i < size; i++) { 32 | dprint(in[i]); 33 | } 34 | } -------------------------------------------------------------------------------- /packages/clang-simd/.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | !lib.js 3 | *.wasm -------------------------------------------------------------------------------- /packages/clang-simd/build.sh: -------------------------------------------------------------------------------- 1 | emcc ./src/multiply_arrays_simd.c -o multiply_arrays_simd.js -O2 -s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall"]' -s ALLOW_MEMORY_GROWTH=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -msimd128 2 | emcc ./src/multiply_arrays.c -o multiply_arrays.js -O2 -s WASM=1 -s NO_EXIT_RUNTIME=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall"]' -s ALLOW_MEMORY_GROWTH=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -------------------------------------------------------------------------------- /packages/clang-simd/index.html: -------------------------------------------------------------------------------- 1 | 7 |
8 | 9 |
10 |
11 | 12 |
13 | -------------------------------------------------------------------------------- /packages/clang-simd/lib.js: -------------------------------------------------------------------------------- 1 | function TypedArrayToHeap(arr) { 2 | const { name, BYTES_PER_ELEMENT } = arr.constructor; 3 | const prefix = name.charAt(0).replace(/I|B/, ''); 4 | const heap = Module[`HEAP${prefix}${BYTES_PER_ELEMENT << 3}`]; 5 | 6 | if (!heap) { 7 | throw new Error(`Unknow typed array ${heap}`); 8 | } 9 | 10 | const ptr = Module._malloc(arr.length * BYTES_PER_ELEMENT); 11 | heap.set(arr, ptr / BYTES_PER_ELEMENT); 12 | 13 | return ptr; 14 | } 15 | 16 | function runWasm(func, onload) { 17 | var script = document.createElement('script'); 18 | script.onload = onload; 19 | script.src = func + '.js'; 20 | document.body.appendChild(script); 21 | } 22 | 23 | function multiply(func, array, arr1, arr2, arr3) { 24 | const size = array.length; 25 | const time = [0, 0]; 26 | 27 | time[0] = performance.now(); 28 | 29 | Module.ccall( 30 | func, 31 | null, 32 | ['number', 'number', 'number', 'number'], 33 | [arr1, arr2, arr3, size] 34 | ); 35 | 36 | time[1] = performance.now(); 37 | 38 | return time[1] - time[0]; 39 | } 40 | 41 | function setRunResult(func, result) { 42 | const e = document.querySelector('#result'); 43 | e.setAttribute('style', 'white-space: pre;'); 44 | e.textContent += `${func}: ${result}\r\n`; 45 | } 46 | 47 | function getInt32Value(arr, index = 0) { 48 | const startPtr = arr / Int32Array.BYTES_PER_ELEMENT; 49 | return arr + index; 50 | } 51 | 52 | function subInt32Array(arr, begin = 0, end = undefined) { 53 | const startPtr = arr / Int32Array.BYTES_PER_ELEMENT; 54 | return new Int32Array(HEAP32.subarray(startPtr + begin, startPtr + (end ? end : arr.length))); 55 | } 56 | -------------------------------------------------------------------------------- /packages/clang-simd/no-simd.html: -------------------------------------------------------------------------------- 1 | 2 |

Multiply without SIMD

3 |
4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /packages/clang-simd/readme.md: -------------------------------------------------------------------------------- 1 | # SIMD example with Clang 2 | 3 | > Working SIMD example from https://v8.dev/features/simd 4 | 5 | ## Build 6 | 7 | ``` 8 | sh ./build.sh 9 | ``` 10 | 11 | ## Run 12 | 13 | ``` 14 | python3 -m http.server 15 | ``` 16 | 17 | # License 18 | 19 | MIT @ Jimmy Moon -------------------------------------------------------------------------------- /packages/clang-simd/simd.html: -------------------------------------------------------------------------------- 1 | 2 |

Multiply with SIMD

3 |
4 | 5 | 22 | 23 | -------------------------------------------------------------------------------- /packages/clang-simd/src/multiply_arrays.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | EMSCRIPTEN_KEEPALIVE 4 | void multiply_arrays(int* out, int* in_a, int* in_b, int size) { 5 | for (int i = 0; i < size; i++) { 6 | out[i] = in_a[i] * in_b[i]; 7 | } 8 | } -------------------------------------------------------------------------------- /packages/clang-simd/src/multiply_arrays_simd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | EMSCRIPTEN_KEEPALIVE 5 | void multiply_arrays_simd(int* out, int* in_a, int* in_b, int size) { 6 | for (int i = 0; i < size; i++) { 7 | out[i] = in_a[i] * in_b[i]; 8 | } 9 | } 10 | 11 | EMSCRIPTEN_KEEPALIVE 12 | void multiply_arrays_simd_intrinsics(int* out, int* in_a, int* in_b, int size) { 13 | for (int i = 0; i < size; i += 4) { 14 | v128_t a = wasm_v128_load(&in_a[i]); 15 | v128_t b = wasm_v128_load(&in_b[i]); 16 | v128_t prod = wasm_i32x4_mul(a, b); 17 | wasm_v128_store(&out[i], prod); 18 | } 19 | } -------------------------------------------------------------------------------- /packages/clang-thread/.gitignore: -------------------------------------------------------------------------------- 1 | pkg -------------------------------------------------------------------------------- /packages/clang-thread/build.sh: -------------------------------------------------------------------------------- 1 | mkdir -p pkg 2 | emcc -O2 -s -pthread -s PTHREAD_POOL_SIZE=4 ./src/test.c -o ./pkg/test.js 3 | python3 -m http.server -------------------------------------------------------------------------------- /packages/clang-thread/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Threads test 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/clang-thread/readme.md: -------------------------------------------------------------------------------- 1 | # Web Assembly Thread 2 | 3 | > Working sample for [WebAssembly Threads ready to try in Chrome 70](https://developers.google.com/web/updates/2018/10/wasm-threads) 4 | 5 | # Prerequisites 6 | 7 | - HTTP server which can serve some of static files like html, js. You might need to install `http-server` on your system, or just use your own simple http server to do 8 | - emscripten SDK, 1.38.11 or later. Please make sure `emcc` is being in your PATH 9 | 10 | # How to run 11 | 12 | ``` 13 | yarn build && yarn start 14 | ``` 15 | 16 | -------------------------------------------------------------------------------- /packages/clang-thread/src/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Calculate fibonacci numbers shared function 5 | int fibonacci(int iterations) { 6 | int val = 1; 7 | int last = 0; 8 | 9 | if (iterations == 0) { 10 | return 0; 11 | } 12 | for (int i = 1; i < iterations; i++) { 13 | int seq; 14 | 15 | seq = val + last; 16 | last = val; 17 | val = seq; 18 | } 19 | return val; 20 | } 21 | // Start function for the background thread 22 | void *bg_func(void *arg) { 23 | int *iter = (void *)arg; 24 | 25 | *iter = fibonacci(*iter); 26 | return arg; 27 | } 28 | // Foreground thread and main entry point 29 | int main(int argc, char *argv[]) { 30 | int fg_val = 54; 31 | int bg_val = 42; 32 | pthread_t bg_thread; 33 | 34 | // Create the background thread 35 | if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) { 36 | perror("Thread create failed"); 37 | return 1; 38 | } 39 | // Calculate on the foreground thread 40 | fg_val = fibonacci(fg_val); 41 | // Wait for background thread to finish 42 | if (pthread_join(bg_thread, NULL)) { 43 | perror("Thread join failed"); 44 | return 2; 45 | } 46 | // Show the result from background and foreground threads 47 | printf("Fib(42) is %d, Fib(6 * 9) is %d\n", bg_val, fg_val); 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /packages/clang/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 33 | 34 | 35 |
36 | 37 | -------------------------------------------------------------------------------- /packages/clang/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clang", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "start": "../node_modules/.bin/serve .", 6 | "build:dylib": "emcc ./wasm/helloworld-dylib.c -Os -s WASM=1 -s SIDE_MODULE=1 -o ./wasm/helloworld-dylib.wasm", 7 | "build:std": "emcc ./wasm/helloworld-std.c -Os -s WASM=1 -s ONLY_MY_CODE=1 -o ./wasm/helloworld-std.js", 8 | "build": "npm run build:dylib && npm run build:std" 9 | }, 10 | "devDependencies": { 11 | "serve": "^6.5.5" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/clang/readme.md: -------------------------------------------------------------------------------- 1 | # EMSCRIPTEN SDK ONLY 2 | 3 | ``` 4 | yarn intall 5 | 6 | yarn build 7 | 8 | yarn start 9 | ``` -------------------------------------------------------------------------------- /packages/clang/wasm-loader.js: -------------------------------------------------------------------------------- 1 | function setEnvironment({env = {}}) { 2 | if (!env.memory) { 3 | env.memory = new WebAssembly.Memory({ 4 | initial: 256, 5 | maximum: 256 6 | }) 7 | } 8 | 9 | if (!env.table) { 10 | env.table = new WebAssembly.Table({ 11 | initial: 0, 12 | maximum: 0, 13 | element: 'anyfunc' 14 | }) 15 | } 16 | 17 | return { 18 | ...{ 19 | tableBase: 0, 20 | memoryBase: 0, 21 | STACKTOP: 0, 22 | STACK_MAX: env.memory.buffer.byteLength, 23 | abortStackOverflow() {}, 24 | abort() {} 25 | }, 26 | ...env 27 | } 28 | } 29 | 30 | async function wasmInstantiate(req, importObject = {}) { 31 | const bytes = await window.fetch(req).then(x => x.arrayBuffer()) 32 | 33 | importObject = { 34 | global: {}, 35 | ...importObject, 36 | env: setEnvironment(importObject) 37 | } 38 | 39 | return { 40 | ...await WebAssembly.instantiate(bytes, importObject), 41 | ...importObject 42 | } 43 | } -------------------------------------------------------------------------------- /packages/clang/wasm/helloworld-dylib.c: -------------------------------------------------------------------------------- 1 | #define HELLO_WORLD "Hello World!" 2 | 3 | const char* str() { 4 | return HELLO_WORLD; 5 | } 6 | 7 | unsigned int len() { 8 | unsigned int len = 0; 9 | 10 | for (const char* p = HELLO_WORLD; *p != '\0'; p++) { 11 | len++; 12 | } 13 | 14 | return len; 15 | } -------------------------------------------------------------------------------- /packages/clang/wasm/helloworld-dylib.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ragingwind/wasm-helloworld/3b49e9f944cfb94191dd6312517b96c444544080/packages/clang/wasm/helloworld-dylib.wasm -------------------------------------------------------------------------------- /packages/clang/wasm/helloworld-std.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | EMSCRIPTEN_KEEPALIVE 4 | const char* HELLO_WORLD = "Hello World!"; 5 | 6 | EMSCRIPTEN_KEEPALIVE 7 | const char* str() { 8 | return HELLO_WORLD; 9 | } 10 | 11 | EMSCRIPTEN_KEEPALIVE 12 | unsigned int len() { 13 | unsigned int len = 0; 14 | 15 | for (const char* p = HELLO_WORLD; *p != '\0'; p++) { 16 | len++; 17 | } 18 | 19 | return len; 20 | } -------------------------------------------------------------------------------- /packages/clang/wasm/helloworld-std.js: -------------------------------------------------------------------------------- 1 | // The Module object: Our interface to the outside world. We import 2 | // and export values on it. There are various ways Module can be used: 3 | // 1. Not defined. We create it here 4 | // 2. A function parameter, function(Module) { ..generated code.. } 5 | // 3. pre-run appended it, var Module = {}; ..generated code.. 6 | // 4. External script tag defines var Module. 7 | // We need to check if Module already exists (e.g. case 3 above). 8 | // Substitution will be replaced with actual code on later stage of the build, 9 | // this way Closure Compiler will not mangle it (e.g. case 4. above). 10 | // Note that if you want to run closure, and also to use Module 11 | // after the generated code, you will need to define var Module = {}; 12 | // before the code. Then that object will be used in the code, and you 13 | // can continue to use Module afterwards as well. 14 | var Module = typeof Module !== 'undefined' ? Module : {}; 15 | 16 | // --pre-jses are emitted after the Module integration code, so that they can 17 | // refer to Module (if they choose; they can also define Module) 18 | // {{PRE_JSES}} 19 | 20 | // Sometimes an existing Module object exists with properties 21 | // meant to overwrite the default module functionality. Here 22 | // we collect those properties and reapply _after_ we configure 23 | // the current environment's defaults to avoid having to be so 24 | // defensive during initialization. 25 | var moduleOverrides = {}; 26 | var key; 27 | for (key in Module) { 28 | if (Module.hasOwnProperty(key)) { 29 | moduleOverrides[key] = Module[key]; 30 | } 31 | } 32 | 33 | Module['arguments'] = []; 34 | Module['thisProgram'] = './this.program'; 35 | Module['quit'] = function(status, toThrow) { 36 | throw toThrow; 37 | }; 38 | Module['preRun'] = []; 39 | Module['postRun'] = []; 40 | 41 | // The environment setup code below is customized to use Module. 42 | // *** Environment setup code *** 43 | var ENVIRONMENT_IS_WEB = false; 44 | var ENVIRONMENT_IS_WORKER = false; 45 | var ENVIRONMENT_IS_NODE = false; 46 | var ENVIRONMENT_IS_SHELL = false; 47 | 48 | // Three configurations we can be running in: 49 | // 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) 50 | // 2) We could be the application main() thread proxied to worker. (with Emscripten -s PROXY_TO_WORKER=1) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false) 51 | // 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) 52 | 53 | if (Module['ENVIRONMENT']) { 54 | if (Module['ENVIRONMENT'] === 'WEB') { 55 | ENVIRONMENT_IS_WEB = true; 56 | } else if (Module['ENVIRONMENT'] === 'WORKER') { 57 | ENVIRONMENT_IS_WORKER = true; 58 | } else if (Module['ENVIRONMENT'] === 'NODE') { 59 | ENVIRONMENT_IS_NODE = true; 60 | } else if (Module['ENVIRONMENT'] === 'SHELL') { 61 | ENVIRONMENT_IS_SHELL = true; 62 | } else { 63 | throw new Error('Module[\'ENVIRONMENT\'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.'); 64 | } 65 | } else { 66 | ENVIRONMENT_IS_WEB = typeof window === 'object'; 67 | ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; 68 | ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; 69 | ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; 70 | } 71 | 72 | 73 | if (ENVIRONMENT_IS_NODE) { 74 | // Expose functionality in the same simple way that the shells work 75 | // Note that we pollute the global namespace here, otherwise we break in node 76 | var nodeFS; 77 | var nodePath; 78 | 79 | Module['read'] = function shell_read(filename, binary) { 80 | var ret; 81 | if (!nodeFS) nodeFS = require('fs'); 82 | if (!nodePath) nodePath = require('path'); 83 | filename = nodePath['normalize'](filename); 84 | ret = nodeFS['readFileSync'](filename); 85 | return binary ? ret : ret.toString(); 86 | }; 87 | 88 | Module['readBinary'] = function readBinary(filename) { 89 | var ret = Module['read'](filename, true); 90 | if (!ret.buffer) { 91 | ret = new Uint8Array(ret); 92 | } 93 | assert(ret.buffer); 94 | return ret; 95 | }; 96 | 97 | if (process['argv'].length > 1) { 98 | Module['thisProgram'] = process['argv'][1].replace(/\\/g, '/'); 99 | } 100 | 101 | Module['arguments'] = process['argv'].slice(2); 102 | 103 | if (typeof module !== 'undefined') { 104 | module['exports'] = Module; 105 | } 106 | 107 | process['on']('uncaughtException', function(ex) { 108 | // suppress ExitStatus exceptions from showing an error 109 | if (!(ex instanceof ExitStatus)) { 110 | throw ex; 111 | } 112 | }); 113 | // Currently node will swallow unhandled rejections, but this behavior is 114 | // deprecated, and in the future it will exit with error status. 115 | process['on']('unhandledRejection', function(reason, p) { 116 | process['exit'](1); 117 | }); 118 | 119 | Module['inspect'] = function () { return '[Emscripten Module object]'; }; 120 | } 121 | else if (ENVIRONMENT_IS_SHELL) { 122 | if (typeof read != 'undefined') { 123 | Module['read'] = function shell_read(f) { 124 | return read(f); 125 | }; 126 | } 127 | 128 | Module['readBinary'] = function readBinary(f) { 129 | var data; 130 | if (typeof readbuffer === 'function') { 131 | return new Uint8Array(readbuffer(f)); 132 | } 133 | data = read(f, 'binary'); 134 | assert(typeof data === 'object'); 135 | return data; 136 | }; 137 | 138 | if (typeof scriptArgs != 'undefined') { 139 | Module['arguments'] = scriptArgs; 140 | } else if (typeof arguments != 'undefined') { 141 | Module['arguments'] = arguments; 142 | } 143 | 144 | if (typeof quit === 'function') { 145 | Module['quit'] = function(status, toThrow) { 146 | quit(status); 147 | } 148 | } 149 | } 150 | else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { 151 | Module['read'] = function shell_read(url) { 152 | var xhr = new XMLHttpRequest(); 153 | xhr.open('GET', url, false); 154 | xhr.send(null); 155 | return xhr.responseText; 156 | }; 157 | 158 | if (ENVIRONMENT_IS_WORKER) { 159 | Module['readBinary'] = function readBinary(url) { 160 | var xhr = new XMLHttpRequest(); 161 | xhr.open('GET', url, false); 162 | xhr.responseType = 'arraybuffer'; 163 | xhr.send(null); 164 | return new Uint8Array(xhr.response); 165 | }; 166 | } 167 | 168 | Module['readAsync'] = function readAsync(url, onload, onerror) { 169 | var xhr = new XMLHttpRequest(); 170 | xhr.open('GET', url, true); 171 | xhr.responseType = 'arraybuffer'; 172 | xhr.onload = function xhr_onload() { 173 | if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 174 | onload(xhr.response); 175 | return; 176 | } 177 | onerror(); 178 | }; 179 | xhr.onerror = onerror; 180 | xhr.send(null); 181 | }; 182 | 183 | Module['setWindowTitle'] = function(title) { document.title = title }; 184 | } 185 | 186 | // console.log is checked first, as 'print' on the web will open a print dialogue 187 | // printErr is preferable to console.warn (works better in shells) 188 | // bind(console) is necessary to fix IE/Edge closed dev tools panel behavior. 189 | Module['print'] = typeof console !== 'undefined' ? console.log.bind(console) : (typeof print !== 'undefined' ? print : null); 190 | Module['printErr'] = typeof printErr !== 'undefined' ? printErr : ((typeof console !== 'undefined' && console.warn.bind(console)) || Module['print']); 191 | 192 | // *** Environment setup code *** 193 | 194 | // Closure helpers 195 | Module.print = Module['print']; 196 | Module.printErr = Module['printErr']; 197 | 198 | // Merge back in the overrides 199 | for (key in moduleOverrides) { 200 | if (moduleOverrides.hasOwnProperty(key)) { 201 | Module[key] = moduleOverrides[key]; 202 | } 203 | } 204 | // Free the object hierarchy contained in the overrides, this lets the GC 205 | // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. 206 | moduleOverrides = undefined; 207 | 208 | 209 | 210 | // {{PREAMBLE_ADDITIONS}} 211 | 212 | var STACK_ALIGN = 16; 213 | 214 | 215 | function staticAlloc(size) { 216 | assert(!staticSealed); 217 | var ret = STATICTOP; 218 | STATICTOP = (STATICTOP + size + 15) & -16; 219 | return ret; 220 | } 221 | 222 | function dynamicAlloc(size) { 223 | assert(DYNAMICTOP_PTR); 224 | var ret = HEAP32[DYNAMICTOP_PTR>>2]; 225 | var end = (ret + size + 15) & -16; 226 | HEAP32[DYNAMICTOP_PTR>>2] = end; 227 | if (end >= TOTAL_MEMORY) { 228 | var success = enlargeMemory(); 229 | if (!success) { 230 | HEAP32[DYNAMICTOP_PTR>>2] = ret; 231 | return 0; 232 | } 233 | } 234 | return ret; 235 | } 236 | 237 | function alignMemory(size, factor) { 238 | if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default 239 | var ret = size = Math.ceil(size / factor) * factor; 240 | return ret; 241 | } 242 | 243 | function getNativeTypeSize(type) { 244 | switch (type) { 245 | case 'i1': case 'i8': return 1; 246 | case 'i16': return 2; 247 | case 'i32': return 4; 248 | case 'i64': return 8; 249 | case 'float': return 4; 250 | case 'double': return 8; 251 | default: { 252 | if (type[type.length-1] === '*') { 253 | return 4; // A pointer 254 | } else if (type[0] === 'i') { 255 | var bits = parseInt(type.substr(1)); 256 | assert(bits % 8 === 0); 257 | return bits / 8; 258 | } else { 259 | return 0; 260 | } 261 | } 262 | } 263 | } 264 | 265 | function warnOnce(text) { 266 | if (!warnOnce.shown) warnOnce.shown = {}; 267 | if (!warnOnce.shown[text]) { 268 | warnOnce.shown[text] = 1; 269 | Module.printErr(text); 270 | } 271 | } 272 | 273 | 274 | 275 | var jsCallStartIndex = 1; 276 | var functionPointers = new Array(0); 277 | 278 | // 'sig' parameter is only used on LLVM wasm backend 279 | function addFunction(func, sig) { 280 | var base = 0; 281 | for (var i = base; i < base + 0; i++) { 282 | if (!functionPointers[i]) { 283 | functionPointers[i] = func; 284 | return jsCallStartIndex + i; 285 | } 286 | } 287 | throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; 288 | } 289 | 290 | function removeFunction(index) { 291 | functionPointers[index-jsCallStartIndex] = null; 292 | } 293 | 294 | var funcWrappers = {}; 295 | 296 | function getFuncWrapper(func, sig) { 297 | if (!func) return; // on null pointer, return undefined 298 | assert(sig); 299 | if (!funcWrappers[sig]) { 300 | funcWrappers[sig] = {}; 301 | } 302 | var sigCache = funcWrappers[sig]; 303 | if (!sigCache[func]) { 304 | // optimize away arguments usage in common cases 305 | if (sig.length === 1) { 306 | sigCache[func] = function dynCall_wrapper() { 307 | return dynCall(sig, func); 308 | }; 309 | } else if (sig.length === 2) { 310 | sigCache[func] = function dynCall_wrapper(arg) { 311 | return dynCall(sig, func, [arg]); 312 | }; 313 | } else { 314 | // general case 315 | sigCache[func] = function dynCall_wrapper() { 316 | return dynCall(sig, func, Array.prototype.slice.call(arguments)); 317 | }; 318 | } 319 | } 320 | return sigCache[func]; 321 | } 322 | 323 | 324 | function makeBigInt(low, high, unsigned) { 325 | return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0)); 326 | } 327 | 328 | function dynCall(sig, ptr, args) { 329 | if (args && args.length) { 330 | return Module['dynCall_' + sig].apply(null, [ptr].concat(args)); 331 | } else { 332 | return Module['dynCall_' + sig].call(null, ptr); 333 | } 334 | } 335 | 336 | 337 | 338 | var Runtime = { 339 | // FIXME backwards compatibility layer for ports. Support some Runtime.* 340 | // for now, fix it there, then remove it from here. That way we 341 | // can minimize any period of breakage. 342 | dynCall: dynCall, // for SDL2 port 343 | }; 344 | 345 | // The address globals begin at. Very low in memory, for code size and optimization opportunities. 346 | // Above 0 is static memory, starting with globals. 347 | // Then the stack. 348 | // Then 'dynamic' memory for sbrk. 349 | var GLOBAL_BASE = 1024; 350 | 351 | 352 | 353 | // === Preamble library stuff === 354 | 355 | // Documentation for the public APIs defined in this file must be updated in: 356 | // site/source/docs/api_reference/preamble.js.rst 357 | // A prebuilt local version of the documentation is available at: 358 | // site/build/text/docs/api_reference/preamble.js.txt 359 | // You can also build docs locally as HTML or other formats in site/ 360 | // An online HTML version (which may be of a different version of Emscripten) 361 | // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html 362 | 363 | 364 | 365 | //======================================== 366 | // Runtime essentials 367 | //======================================== 368 | 369 | var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort() 370 | var EXITSTATUS = 0; 371 | 372 | /** @type {function(*, string=)} */ 373 | function assert(condition, text) { 374 | if (!condition) { 375 | abort('Assertion failed: ' + text); 376 | } 377 | } 378 | 379 | var globalScope = this; 380 | 381 | // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) 382 | function getCFunc(ident) { 383 | var func = Module['_' + ident]; // closure exported function 384 | assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); 385 | return func; 386 | } 387 | 388 | var JSfuncs = { 389 | // Helpers for cwrap -- it can't refer to Runtime directly because it might 390 | // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find 391 | // out what the minified function name is. 392 | 'stackSave': function() { 393 | stackSave() 394 | }, 395 | 'stackRestore': function() { 396 | stackRestore() 397 | }, 398 | // type conversion from js to c 399 | 'arrayToC' : function(arr) { 400 | var ret = stackAlloc(arr.length); 401 | writeArrayToMemory(arr, ret); 402 | return ret; 403 | }, 404 | 'stringToC' : function(str) { 405 | var ret = 0; 406 | if (str !== null && str !== undefined && str !== 0) { // null string 407 | // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' 408 | var len = (str.length << 2) + 1; 409 | ret = stackAlloc(len); 410 | stringToUTF8(str, ret, len); 411 | } 412 | return ret; 413 | } 414 | }; 415 | 416 | // For fast lookup of conversion functions 417 | var toC = { 418 | 'string': JSfuncs['stringToC'], 'array': JSfuncs['arrayToC'] 419 | }; 420 | 421 | // C calling interface. 422 | function ccall (ident, returnType, argTypes, args, opts) { 423 | var func = getCFunc(ident); 424 | var cArgs = []; 425 | var stack = 0; 426 | if (args) { 427 | for (var i = 0; i < args.length; i++) { 428 | var converter = toC[argTypes[i]]; 429 | if (converter) { 430 | if (stack === 0) stack = stackSave(); 431 | cArgs[i] = converter(args[i]); 432 | } else { 433 | cArgs[i] = args[i]; 434 | } 435 | } 436 | } 437 | var ret = func.apply(null, cArgs); 438 | if (returnType === 'string') ret = Pointer_stringify(ret); 439 | else if (returnType === 'boolean') ret = Boolean(ret); 440 | if (stack !== 0) { 441 | stackRestore(stack); 442 | } 443 | return ret; 444 | } 445 | 446 | function cwrap (ident, returnType, argTypes) { 447 | argTypes = argTypes || []; 448 | var cfunc = getCFunc(ident); 449 | // When the function takes numbers and returns a number, we can just return 450 | // the original function 451 | var numericArgs = argTypes.every(function(type){ return type === 'number'}); 452 | var numericRet = returnType !== 'string'; 453 | if (numericRet && numericArgs) { 454 | return cfunc; 455 | } 456 | return function() { 457 | return ccall(ident, returnType, argTypes, arguments); 458 | } 459 | } 460 | 461 | /** @type {function(number, number, string, boolean=)} */ 462 | function setValue(ptr, value, type, noSafe) { 463 | type = type || 'i8'; 464 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit 465 | switch(type) { 466 | case 'i1': HEAP8[((ptr)>>0)]=value; break; 467 | case 'i8': HEAP8[((ptr)>>0)]=value; break; 468 | case 'i16': HEAP16[((ptr)>>1)]=value; break; 469 | case 'i32': HEAP32[((ptr)>>2)]=value; break; 470 | case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; 471 | case 'float': HEAPF32[((ptr)>>2)]=value; break; 472 | case 'double': HEAPF64[((ptr)>>3)]=value; break; 473 | default: abort('invalid type for setValue: ' + type); 474 | } 475 | } 476 | 477 | /** @type {function(number, string, boolean=)} */ 478 | function getValue(ptr, type, noSafe) { 479 | type = type || 'i8'; 480 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit 481 | switch(type) { 482 | case 'i1': return HEAP8[((ptr)>>0)]; 483 | case 'i8': return HEAP8[((ptr)>>0)]; 484 | case 'i16': return HEAP16[((ptr)>>1)]; 485 | case 'i32': return HEAP32[((ptr)>>2)]; 486 | case 'i64': return HEAP32[((ptr)>>2)]; 487 | case 'float': return HEAPF32[((ptr)>>2)]; 488 | case 'double': return HEAPF64[((ptr)>>3)]; 489 | default: abort('invalid type for getValue: ' + type); 490 | } 491 | return null; 492 | } 493 | 494 | var ALLOC_NORMAL = 0; // Tries to use _malloc() 495 | var ALLOC_STACK = 1; // Lives for the duration of the current function call 496 | var ALLOC_STATIC = 2; // Cannot be freed 497 | var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk 498 | var ALLOC_NONE = 4; // Do not allocate 499 | 500 | // allocate(): This is for internal use. You can use it yourself as well, but the interface 501 | // is a little tricky (see docs right below). The reason is that it is optimized 502 | // for multiple syntaxes to save space in generated code. So you should 503 | // normally not use allocate(), and instead allocate memory using _malloc(), 504 | // initialize it with setValue(), and so forth. 505 | // @slab: An array of data, or a number. If a number, then the size of the block to allocate, 506 | // in *bytes* (note that this is sometimes confusing: the next parameter does not 507 | // affect this!) 508 | // @types: Either an array of types, one for each byte (or 0 if no type at that position), 509 | // or a single type which is used for the entire block. This only matters if there 510 | // is initial data - if @slab is a number, then this does not matter at all and is 511 | // ignored. 512 | // @allocator: How to allocate memory, see ALLOC_* 513 | /** @type {function((TypedArray|Array|number), string, number, number=)} */ 514 | function allocate(slab, types, allocator, ptr) { 515 | var zeroinit, size; 516 | if (typeof slab === 'number') { 517 | zeroinit = true; 518 | size = slab; 519 | } else { 520 | zeroinit = false; 521 | size = slab.length; 522 | } 523 | 524 | var singleType = typeof types === 'string' ? types : null; 525 | 526 | var ret; 527 | if (allocator == ALLOC_NONE) { 528 | ret = ptr; 529 | } else { 530 | ret = [typeof _malloc === 'function' ? _malloc : staticAlloc, stackAlloc, staticAlloc, dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); 531 | } 532 | 533 | if (zeroinit) { 534 | var stop; 535 | ptr = ret; 536 | assert((ret & 3) == 0); 537 | stop = ret + (size & ~3); 538 | for (; ptr < stop; ptr += 4) { 539 | HEAP32[((ptr)>>2)]=0; 540 | } 541 | stop = ret + size; 542 | while (ptr < stop) { 543 | HEAP8[((ptr++)>>0)]=0; 544 | } 545 | return ret; 546 | } 547 | 548 | if (singleType === 'i8') { 549 | if (slab.subarray || slab.slice) { 550 | HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret); 551 | } else { 552 | HEAPU8.set(new Uint8Array(slab), ret); 553 | } 554 | return ret; 555 | } 556 | 557 | var i = 0, type, typeSize, previousType; 558 | while (i < size) { 559 | var curr = slab[i]; 560 | 561 | type = singleType || types[i]; 562 | if (type === 0) { 563 | i++; 564 | continue; 565 | } 566 | 567 | if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later 568 | 569 | setValue(ret+i, curr, type); 570 | 571 | // no need to look up size unless type changes, so cache it 572 | if (previousType !== type) { 573 | typeSize = getNativeTypeSize(type); 574 | previousType = type; 575 | } 576 | i += typeSize; 577 | } 578 | 579 | return ret; 580 | } 581 | 582 | // Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready 583 | function getMemory(size) { 584 | if (!staticSealed) return staticAlloc(size); 585 | if (!runtimeInitialized) return dynamicAlloc(size); 586 | return _malloc(size); 587 | } 588 | 589 | /** @type {function(number, number=)} */ 590 | function Pointer_stringify(ptr, length) { 591 | if (length === 0 || !ptr) return ''; 592 | // TODO: use TextDecoder 593 | // Find the length, and check for UTF while doing so 594 | var hasUtf = 0; 595 | var t; 596 | var i = 0; 597 | while (1) { 598 | t = HEAPU8[(((ptr)+(i))>>0)]; 599 | hasUtf |= t; 600 | if (t == 0 && !length) break; 601 | i++; 602 | if (length && i == length) break; 603 | } 604 | if (!length) length = i; 605 | 606 | var ret = ''; 607 | 608 | if (hasUtf < 128) { 609 | var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack 610 | var curr; 611 | while (length > 0) { 612 | curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); 613 | ret = ret ? ret + curr : curr; 614 | ptr += MAX_CHUNK; 615 | length -= MAX_CHUNK; 616 | } 617 | return ret; 618 | } 619 | return UTF8ToString(ptr); 620 | } 621 | 622 | // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns 623 | // a copy of that string as a Javascript String object. 624 | 625 | function AsciiToString(ptr) { 626 | var str = ''; 627 | while (1) { 628 | var ch = HEAP8[((ptr++)>>0)]; 629 | if (!ch) return str; 630 | str += String.fromCharCode(ch); 631 | } 632 | } 633 | 634 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 635 | // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP. 636 | 637 | function stringToAscii(str, outPtr) { 638 | return writeAsciiToMemory(str, outPtr, false); 639 | } 640 | 641 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns 642 | // a copy of that string as a Javascript String object. 643 | 644 | var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined; 645 | function UTF8ArrayToString(u8Array, idx) { 646 | var endPtr = idx; 647 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 648 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 649 | while (u8Array[endPtr]) ++endPtr; 650 | 651 | if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { 652 | return UTF8Decoder.decode(u8Array.subarray(idx, endPtr)); 653 | } else { 654 | var u0, u1, u2, u3, u4, u5; 655 | 656 | var str = ''; 657 | while (1) { 658 | // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 659 | u0 = u8Array[idx++]; 660 | if (!u0) return str; 661 | if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } 662 | u1 = u8Array[idx++] & 63; 663 | if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } 664 | u2 = u8Array[idx++] & 63; 665 | if ((u0 & 0xF0) == 0xE0) { 666 | u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; 667 | } else { 668 | u3 = u8Array[idx++] & 63; 669 | if ((u0 & 0xF8) == 0xF0) { 670 | u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; 671 | } else { 672 | u4 = u8Array[idx++] & 63; 673 | if ((u0 & 0xFC) == 0xF8) { 674 | u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; 675 | } else { 676 | u5 = u8Array[idx++] & 63; 677 | u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; 678 | } 679 | } 680 | } 681 | if (u0 < 0x10000) { 682 | str += String.fromCharCode(u0); 683 | } else { 684 | var ch = u0 - 0x10000; 685 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 686 | } 687 | } 688 | } 689 | } 690 | 691 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns 692 | // a copy of that string as a Javascript String object. 693 | 694 | function UTF8ToString(ptr) { 695 | return UTF8ArrayToString(HEAPU8,ptr); 696 | } 697 | 698 | // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', 699 | // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP. 700 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 701 | // Parameters: 702 | // str: the Javascript string to copy. 703 | // outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element. 704 | // outIdx: The starting offset in the array to begin the copying. 705 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 706 | // terminator, i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else. 707 | // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator. 708 | // Returns the number of bytes written, EXCLUDING the null terminator. 709 | 710 | function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { 711 | if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. 712 | return 0; 713 | 714 | var startIdx = outIdx; 715 | var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. 716 | for (var i = 0; i < str.length; ++i) { 717 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 718 | // See http://unicode.org/faq/utf_bom.html#utf16-3 719 | // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 720 | var u = str.charCodeAt(i); // possibly a lead surrogate 721 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 722 | if (u <= 0x7F) { 723 | if (outIdx >= endIdx) break; 724 | outU8Array[outIdx++] = u; 725 | } else if (u <= 0x7FF) { 726 | if (outIdx + 1 >= endIdx) break; 727 | outU8Array[outIdx++] = 0xC0 | (u >> 6); 728 | outU8Array[outIdx++] = 0x80 | (u & 63); 729 | } else if (u <= 0xFFFF) { 730 | if (outIdx + 2 >= endIdx) break; 731 | outU8Array[outIdx++] = 0xE0 | (u >> 12); 732 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 733 | outU8Array[outIdx++] = 0x80 | (u & 63); 734 | } else if (u <= 0x1FFFFF) { 735 | if (outIdx + 3 >= endIdx) break; 736 | outU8Array[outIdx++] = 0xF0 | (u >> 18); 737 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 738 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 739 | outU8Array[outIdx++] = 0x80 | (u & 63); 740 | } else if (u <= 0x3FFFFFF) { 741 | if (outIdx + 4 >= endIdx) break; 742 | outU8Array[outIdx++] = 0xF8 | (u >> 24); 743 | outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); 744 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 745 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 746 | outU8Array[outIdx++] = 0x80 | (u & 63); 747 | } else { 748 | if (outIdx + 5 >= endIdx) break; 749 | outU8Array[outIdx++] = 0xFC | (u >> 30); 750 | outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63); 751 | outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); 752 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 753 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 754 | outU8Array[outIdx++] = 0x80 | (u & 63); 755 | } 756 | } 757 | // Null-terminate the pointer to the buffer. 758 | outU8Array[outIdx] = 0; 759 | return outIdx - startIdx; 760 | } 761 | 762 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 763 | // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP. 764 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 765 | // Returns the number of bytes written, EXCLUDING the null terminator. 766 | 767 | function stringToUTF8(str, outPtr, maxBytesToWrite) { 768 | return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); 769 | } 770 | 771 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. 772 | 773 | function lengthBytesUTF8(str) { 774 | var len = 0; 775 | for (var i = 0; i < str.length; ++i) { 776 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 777 | // See http://unicode.org/faq/utf_bom.html#utf16-3 778 | var u = str.charCodeAt(i); // possibly a lead surrogate 779 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 780 | if (u <= 0x7F) { 781 | ++len; 782 | } else if (u <= 0x7FF) { 783 | len += 2; 784 | } else if (u <= 0xFFFF) { 785 | len += 3; 786 | } else if (u <= 0x1FFFFF) { 787 | len += 4; 788 | } else if (u <= 0x3FFFFFF) { 789 | len += 5; 790 | } else { 791 | len += 6; 792 | } 793 | } 794 | return len; 795 | } 796 | 797 | // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns 798 | // a copy of that string as a Javascript String object. 799 | 800 | var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; 801 | function UTF16ToString(ptr) { 802 | var endPtr = ptr; 803 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 804 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 805 | var idx = endPtr >> 1; 806 | while (HEAP16[idx]) ++idx; 807 | endPtr = idx << 1; 808 | 809 | if (endPtr - ptr > 32 && UTF16Decoder) { 810 | return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); 811 | } else { 812 | var i = 0; 813 | 814 | var str = ''; 815 | while (1) { 816 | var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; 817 | if (codeUnit == 0) return str; 818 | ++i; 819 | // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. 820 | str += String.fromCharCode(codeUnit); 821 | } 822 | } 823 | } 824 | 825 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 826 | // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP. 827 | // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write. 828 | // Parameters: 829 | // str: the Javascript string to copy. 830 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 831 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 832 | // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else. 833 | // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator. 834 | // Returns the number of bytes written, EXCLUDING the null terminator. 835 | 836 | function stringToUTF16(str, outPtr, maxBytesToWrite) { 837 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 838 | if (maxBytesToWrite === undefined) { 839 | maxBytesToWrite = 0x7FFFFFFF; 840 | } 841 | if (maxBytesToWrite < 2) return 0; 842 | maxBytesToWrite -= 2; // Null terminator. 843 | var startPtr = outPtr; 844 | var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; 845 | for (var i = 0; i < numCharsToWrite; ++i) { 846 | // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. 847 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 848 | HEAP16[((outPtr)>>1)]=codeUnit; 849 | outPtr += 2; 850 | } 851 | // Null-terminate the pointer to the HEAP. 852 | HEAP16[((outPtr)>>1)]=0; 853 | return outPtr - startPtr; 854 | } 855 | 856 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 857 | 858 | function lengthBytesUTF16(str) { 859 | return str.length*2; 860 | } 861 | 862 | function UTF32ToString(ptr) { 863 | var i = 0; 864 | 865 | var str = ''; 866 | while (1) { 867 | var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; 868 | if (utf32 == 0) 869 | return str; 870 | ++i; 871 | // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. 872 | // See http://unicode.org/faq/utf_bom.html#utf16-3 873 | if (utf32 >= 0x10000) { 874 | var ch = utf32 - 0x10000; 875 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 876 | } else { 877 | str += String.fromCharCode(utf32); 878 | } 879 | } 880 | } 881 | 882 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 883 | // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP. 884 | // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write. 885 | // Parameters: 886 | // str: the Javascript string to copy. 887 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 888 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 889 | // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else. 890 | // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator. 891 | // Returns the number of bytes written, EXCLUDING the null terminator. 892 | 893 | function stringToUTF32(str, outPtr, maxBytesToWrite) { 894 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 895 | if (maxBytesToWrite === undefined) { 896 | maxBytesToWrite = 0x7FFFFFFF; 897 | } 898 | if (maxBytesToWrite < 4) return 0; 899 | var startPtr = outPtr; 900 | var endPtr = startPtr + maxBytesToWrite - 4; 901 | for (var i = 0; i < str.length; ++i) { 902 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. 903 | // See http://unicode.org/faq/utf_bom.html#utf16-3 904 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 905 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { 906 | var trailSurrogate = str.charCodeAt(++i); 907 | codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); 908 | } 909 | HEAP32[((outPtr)>>2)]=codeUnit; 910 | outPtr += 4; 911 | if (outPtr + 4 > endPtr) break; 912 | } 913 | // Null-terminate the pointer to the HEAP. 914 | HEAP32[((outPtr)>>2)]=0; 915 | return outPtr - startPtr; 916 | } 917 | 918 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 919 | 920 | function lengthBytesUTF32(str) { 921 | var len = 0; 922 | for (var i = 0; i < str.length; ++i) { 923 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. 924 | // See http://unicode.org/faq/utf_bom.html#utf16-3 925 | var codeUnit = str.charCodeAt(i); 926 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. 927 | len += 4; 928 | } 929 | 930 | return len; 931 | } 932 | 933 | // Allocate heap space for a JS string, and write it there. 934 | // It is the responsibility of the caller to free() that memory. 935 | function allocateUTF8(str) { 936 | var size = lengthBytesUTF8(str) + 1; 937 | var ret = _malloc(size); 938 | if (ret) stringToUTF8Array(str, HEAP8, ret, size); 939 | return ret; 940 | } 941 | 942 | // Allocate stack space for a JS string, and write it there. 943 | function allocateUTF8OnStack(str) { 944 | var size = lengthBytesUTF8(str) + 1; 945 | var ret = stackAlloc(size); 946 | stringToUTF8Array(str, HEAP8, ret, size); 947 | return ret; 948 | } 949 | 950 | function demangle(func) { 951 | return func; 952 | } 953 | 954 | function demangleAll(text) { 955 | var regex = 956 | /__Z[\w\d_]+/g; 957 | return text.replace(regex, 958 | function(x) { 959 | var y = demangle(x); 960 | return x === y ? x : (x + ' [' + y + ']'); 961 | }); 962 | } 963 | 964 | function jsStackTrace() { 965 | var err = new Error(); 966 | if (!err.stack) { 967 | // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown, 968 | // so try that as a special-case. 969 | try { 970 | throw new Error(0); 971 | } catch(e) { 972 | err = e; 973 | } 974 | if (!err.stack) { 975 | return '(no stack trace available)'; 976 | } 977 | } 978 | return err.stack.toString(); 979 | } 980 | 981 | function stackTrace() { 982 | var js = jsStackTrace(); 983 | if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); 984 | return demangleAll(js); 985 | } 986 | 987 | // Memory management 988 | 989 | var PAGE_SIZE = 16384; 990 | var WASM_PAGE_SIZE = 65536; 991 | var ASMJS_PAGE_SIZE = 16777216; 992 | var MIN_TOTAL_MEMORY = 16777216; 993 | 994 | function alignUp(x, multiple) { 995 | if (x % multiple > 0) { 996 | x += multiple - (x % multiple); 997 | } 998 | return x; 999 | } 1000 | 1001 | var HEAP, 1002 | /** @type {ArrayBuffer} */ 1003 | buffer, 1004 | /** @type {Int8Array} */ 1005 | HEAP8, 1006 | /** @type {Uint8Array} */ 1007 | HEAPU8, 1008 | /** @type {Int16Array} */ 1009 | HEAP16, 1010 | /** @type {Uint16Array} */ 1011 | HEAPU16, 1012 | /** @type {Int32Array} */ 1013 | HEAP32, 1014 | /** @type {Uint32Array} */ 1015 | HEAPU32, 1016 | /** @type {Float32Array} */ 1017 | HEAPF32, 1018 | /** @type {Float64Array} */ 1019 | HEAPF64; 1020 | 1021 | function updateGlobalBuffer(buf) { 1022 | Module['buffer'] = buffer = buf; 1023 | } 1024 | 1025 | function updateGlobalBufferViews() { 1026 | Module['HEAP8'] = HEAP8 = new Int8Array(buffer); 1027 | Module['HEAP16'] = HEAP16 = new Int16Array(buffer); 1028 | Module['HEAP32'] = HEAP32 = new Int32Array(buffer); 1029 | Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer); 1030 | Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer); 1031 | Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer); 1032 | Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer); 1033 | Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer); 1034 | } 1035 | 1036 | var STATIC_BASE, STATICTOP, staticSealed; // static area 1037 | var STACK_BASE, STACKTOP, STACK_MAX; // stack area 1038 | var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk 1039 | 1040 | STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0; 1041 | staticSealed = false; 1042 | 1043 | 1044 | 1045 | function abortOnCannotGrowMemory() { 1046 | abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); 1047 | } 1048 | 1049 | 1050 | function enlargeMemory() { 1051 | abortOnCannotGrowMemory(); 1052 | } 1053 | 1054 | 1055 | var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; 1056 | var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216; 1057 | if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); 1058 | 1059 | // Initialize the runtime's memory 1060 | 1061 | 1062 | 1063 | // Use a provided buffer, if there is one, or else allocate a new one 1064 | if (Module['buffer']) { 1065 | buffer = Module['buffer']; 1066 | } else { 1067 | // Use a WebAssembly memory where available 1068 | if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { 1069 | Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE }); 1070 | buffer = Module['wasmMemory'].buffer; 1071 | } else 1072 | { 1073 | buffer = new ArrayBuffer(TOTAL_MEMORY); 1074 | } 1075 | Module['buffer'] = buffer; 1076 | } 1077 | updateGlobalBufferViews(); 1078 | 1079 | 1080 | function getTotalMemory() { 1081 | return TOTAL_MEMORY; 1082 | } 1083 | 1084 | // Endianness check (note: assumes compiler arch was little-endian) 1085 | HEAP32[0] = 0x63736d65; /* 'emsc' */ 1086 | HEAP16[1] = 0x6373; 1087 | if (HEAPU8[2] !== 0x73 || HEAPU8[3] !== 0x63) throw 'Runtime error: expected the system to be little-endian!'; 1088 | 1089 | function callRuntimeCallbacks(callbacks) { 1090 | while(callbacks.length > 0) { 1091 | var callback = callbacks.shift(); 1092 | if (typeof callback == 'function') { 1093 | callback(); 1094 | continue; 1095 | } 1096 | var func = callback.func; 1097 | if (typeof func === 'number') { 1098 | if (callback.arg === undefined) { 1099 | Module['dynCall_v'](func); 1100 | } else { 1101 | Module['dynCall_vi'](func, callback.arg); 1102 | } 1103 | } else { 1104 | func(callback.arg === undefined ? null : callback.arg); 1105 | } 1106 | } 1107 | } 1108 | 1109 | var __ATPRERUN__ = []; // functions called before the runtime is initialized 1110 | var __ATINIT__ = []; // functions called during startup 1111 | var __ATMAIN__ = []; // functions called when main() is to be run 1112 | var __ATEXIT__ = []; // functions called during shutdown 1113 | var __ATPOSTRUN__ = []; // functions called after the runtime has exited 1114 | 1115 | var runtimeInitialized = false; 1116 | var runtimeExited = false; 1117 | 1118 | 1119 | function preRun() { 1120 | // compatibility - merge in anything from Module['preRun'] at this time 1121 | if (Module['preRun']) { 1122 | if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; 1123 | while (Module['preRun'].length) { 1124 | addOnPreRun(Module['preRun'].shift()); 1125 | } 1126 | } 1127 | callRuntimeCallbacks(__ATPRERUN__); 1128 | } 1129 | 1130 | function ensureInitRuntime() { 1131 | if (runtimeInitialized) return; 1132 | runtimeInitialized = true; 1133 | callRuntimeCallbacks(__ATINIT__); 1134 | } 1135 | 1136 | function preMain() { 1137 | callRuntimeCallbacks(__ATMAIN__); 1138 | } 1139 | 1140 | function exitRuntime() { 1141 | callRuntimeCallbacks(__ATEXIT__); 1142 | runtimeExited = true; 1143 | } 1144 | 1145 | function postRun() { 1146 | // compatibility - merge in anything from Module['postRun'] at this time 1147 | if (Module['postRun']) { 1148 | if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; 1149 | while (Module['postRun'].length) { 1150 | addOnPostRun(Module['postRun'].shift()); 1151 | } 1152 | } 1153 | callRuntimeCallbacks(__ATPOSTRUN__); 1154 | } 1155 | 1156 | function addOnPreRun(cb) { 1157 | __ATPRERUN__.unshift(cb); 1158 | } 1159 | 1160 | function addOnInit(cb) { 1161 | __ATINIT__.unshift(cb); 1162 | } 1163 | 1164 | function addOnPreMain(cb) { 1165 | __ATMAIN__.unshift(cb); 1166 | } 1167 | 1168 | function addOnExit(cb) { 1169 | __ATEXIT__.unshift(cb); 1170 | } 1171 | 1172 | function addOnPostRun(cb) { 1173 | __ATPOSTRUN__.unshift(cb); 1174 | } 1175 | 1176 | // Deprecated: This function should not be called because it is unsafe and does not provide 1177 | // a maximum length limit of how many bytes it is allowed to write. Prefer calling the 1178 | // function stringToUTF8Array() instead, which takes in a maximum length that can be used 1179 | // to be secure from out of bounds writes. 1180 | /** @deprecated */ 1181 | function writeStringToMemory(string, buffer, dontAddNull) { 1182 | warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); 1183 | 1184 | var /** @type {number} */ lastChar, /** @type {number} */ end; 1185 | if (dontAddNull) { 1186 | // stringToUTF8Array always appends null. If we don't want to do that, remember the 1187 | // character that existed at the location where the null will be placed, and restore 1188 | // that after the write (below). 1189 | end = buffer + lengthBytesUTF8(string); 1190 | lastChar = HEAP8[end]; 1191 | } 1192 | stringToUTF8(string, buffer, Infinity); 1193 | if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. 1194 | } 1195 | 1196 | function writeArrayToMemory(array, buffer) { 1197 | HEAP8.set(array, buffer); 1198 | } 1199 | 1200 | function writeAsciiToMemory(str, buffer, dontAddNull) { 1201 | for (var i = 0; i < str.length; ++i) { 1202 | HEAP8[((buffer++)>>0)]=str.charCodeAt(i); 1203 | } 1204 | // Null-terminate the pointer to the HEAP. 1205 | if (!dontAddNull) HEAP8[((buffer)>>0)]=0; 1206 | } 1207 | 1208 | function unSign(value, bits, ignore) { 1209 | if (value >= 0) { 1210 | return value; 1211 | } 1212 | return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts 1213 | : Math.pow(2, bits) + value; 1214 | } 1215 | function reSign(value, bits, ignore) { 1216 | if (value <= 0) { 1217 | return value; 1218 | } 1219 | var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 1220 | : Math.pow(2, bits-1); 1221 | if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that 1222 | // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors 1223 | // TODO: In i64 mode 1, resign the two parts separately and safely 1224 | value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts 1225 | } 1226 | return value; 1227 | } 1228 | 1229 | 1230 | var Math_abs = Math.abs; 1231 | var Math_cos = Math.cos; 1232 | var Math_sin = Math.sin; 1233 | var Math_tan = Math.tan; 1234 | var Math_acos = Math.acos; 1235 | var Math_asin = Math.asin; 1236 | var Math_atan = Math.atan; 1237 | var Math_atan2 = Math.atan2; 1238 | var Math_exp = Math.exp; 1239 | var Math_log = Math.log; 1240 | var Math_sqrt = Math.sqrt; 1241 | var Math_ceil = Math.ceil; 1242 | var Math_floor = Math.floor; 1243 | var Math_pow = Math.pow; 1244 | var Math_imul = Math.imul; 1245 | var Math_fround = Math.fround; 1246 | var Math_round = Math.round; 1247 | var Math_min = Math.min; 1248 | var Math_max = Math.max; 1249 | var Math_clz32 = Math.clz32; 1250 | var Math_trunc = Math.trunc; 1251 | 1252 | // A counter of dependencies for calling run(). If we need to 1253 | // do asynchronous work before running, increment this and 1254 | // decrement it. Incrementing must happen in a place like 1255 | // PRE_RUN_ADDITIONS (used by emcc to add file preloading). 1256 | // Note that you can add dependencies in preRun, even though 1257 | // it happens right before run - run will be postponed until 1258 | // the dependencies are met. 1259 | var runDependencies = 0; 1260 | var runDependencyWatcher = null; 1261 | var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled 1262 | 1263 | function getUniqueRunDependency(id) { 1264 | return id; 1265 | } 1266 | 1267 | function addRunDependency(id) { 1268 | runDependencies++; 1269 | if (Module['monitorRunDependencies']) { 1270 | Module['monitorRunDependencies'](runDependencies); 1271 | } 1272 | } 1273 | 1274 | function removeRunDependency(id) { 1275 | runDependencies--; 1276 | if (Module['monitorRunDependencies']) { 1277 | Module['monitorRunDependencies'](runDependencies); 1278 | } 1279 | if (runDependencies == 0) { 1280 | if (runDependencyWatcher !== null) { 1281 | clearInterval(runDependencyWatcher); 1282 | runDependencyWatcher = null; 1283 | } 1284 | if (dependenciesFulfilled) { 1285 | var callback = dependenciesFulfilled; 1286 | dependenciesFulfilled = null; 1287 | callback(); // can add another dependenciesFulfilled 1288 | } 1289 | } 1290 | } 1291 | 1292 | Module["preloadedImages"] = {}; // maps url to image data 1293 | Module["preloadedAudios"] = {}; // maps url to audio data 1294 | 1295 | 1296 | 1297 | var memoryInitializer = null; 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | // Prefix of data URIs emitted by SINGLE_FILE and related options. 1305 | var dataURIPrefix = 'data:application/octet-stream;base64,'; 1306 | 1307 | // Indicates whether filename is a base64 data URI. 1308 | function isDataURI(filename) { 1309 | return String.prototype.startsWith ? 1310 | filename.startsWith(dataURIPrefix) : 1311 | filename.indexOf(dataURIPrefix) === 0; 1312 | } 1313 | 1314 | 1315 | 1316 | 1317 | function integrateWasmJS() { 1318 | // wasm.js has several methods for creating the compiled code module here: 1319 | // * 'native-wasm' : use native WebAssembly support in the browser 1320 | // * 'interpret-s-expr': load s-expression code from a .wast and interpret 1321 | // * 'interpret-binary': load binary wasm and interpret 1322 | // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret 1323 | // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing) 1324 | // The method is set at compile time (BINARYEN_METHOD) 1325 | // The method can be a comma-separated list, in which case, we will try the 1326 | // options one by one. Some of them can fail gracefully, and then we can try 1327 | // the next. 1328 | 1329 | // inputs 1330 | 1331 | var method = 'native-wasm'; 1332 | 1333 | var wasmTextFile = 'helloworld-std.wast'; 1334 | var wasmBinaryFile = 'helloworld-std.wasm'; 1335 | var asmjsCodeFile = 'helloworld-std.temp.asm.js'; 1336 | 1337 | if (typeof Module['locateFile'] === 'function') { 1338 | if (!isDataURI(wasmTextFile)) { 1339 | wasmTextFile = Module['locateFile'](wasmTextFile); 1340 | } 1341 | if (!isDataURI(wasmBinaryFile)) { 1342 | wasmBinaryFile = Module['locateFile'](wasmBinaryFile); 1343 | } 1344 | if (!isDataURI(asmjsCodeFile)) { 1345 | asmjsCodeFile = Module['locateFile'](asmjsCodeFile); 1346 | } 1347 | } 1348 | 1349 | // utilities 1350 | 1351 | var wasmPageSize = 64*1024; 1352 | 1353 | var info = { 1354 | 'global': null, 1355 | 'env': null, 1356 | 'asm2wasm': { // special asm2wasm imports 1357 | "f64-rem": function(x, y) { 1358 | return x % y; 1359 | }, 1360 | "debugger": function() { 1361 | debugger; 1362 | } 1363 | }, 1364 | 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program. 1365 | }; 1366 | 1367 | var exports = null; 1368 | 1369 | 1370 | function mergeMemory(newBuffer) { 1371 | // The wasm instance creates its memory. But static init code might have written to 1372 | // buffer already, including the mem init file, and we must copy it over in a proper merge. 1373 | // TODO: avoid this copy, by avoiding such static init writes 1374 | // TODO: in shorter term, just copy up to the last static init write 1375 | var oldBuffer = Module['buffer']; 1376 | if (newBuffer.byteLength < oldBuffer.byteLength) { 1377 | Module['printErr']('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here'); 1378 | } 1379 | var oldView = new Int8Array(oldBuffer); 1380 | var newView = new Int8Array(newBuffer); 1381 | 1382 | 1383 | newView.set(oldView); 1384 | updateGlobalBuffer(newBuffer); 1385 | updateGlobalBufferViews(); 1386 | } 1387 | 1388 | function fixImports(imports) { 1389 | return imports; 1390 | } 1391 | 1392 | function getBinary() { 1393 | try { 1394 | if (Module['wasmBinary']) { 1395 | return new Uint8Array(Module['wasmBinary']); 1396 | } 1397 | if (Module['readBinary']) { 1398 | return Module['readBinary'](wasmBinaryFile); 1399 | } else { 1400 | throw "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)"; 1401 | } 1402 | } 1403 | catch (err) { 1404 | abort(err); 1405 | } 1406 | } 1407 | 1408 | function getBinaryPromise() { 1409 | // if we don't have the binary yet, and have the Fetch api, use that 1410 | // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web 1411 | if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { 1412 | return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { 1413 | if (!response['ok']) { 1414 | throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; 1415 | } 1416 | return response['arrayBuffer'](); 1417 | }).catch(function () { 1418 | return getBinary(); 1419 | }); 1420 | } 1421 | // Otherwise, getBinary should be able to get it synchronously 1422 | return new Promise(function(resolve, reject) { 1423 | resolve(getBinary()); 1424 | }); 1425 | } 1426 | 1427 | // do-method functions 1428 | 1429 | 1430 | function doNativeWasm(global, env, providedBuffer) { 1431 | if (typeof WebAssembly !== 'object') { 1432 | Module['printErr']('no native wasm support detected'); 1433 | return false; 1434 | } 1435 | // prepare memory import 1436 | if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) { 1437 | Module['printErr']('no native wasm Memory in use'); 1438 | return false; 1439 | } 1440 | env['memory'] = Module['wasmMemory']; 1441 | // Load the wasm module and create an instance of using native support in the JS engine. 1442 | info['global'] = { 1443 | 'NaN': NaN, 1444 | 'Infinity': Infinity 1445 | }; 1446 | info['global.Math'] = Math; 1447 | info['env'] = env; 1448 | // handle a generated wasm instance, receiving its exports and 1449 | // performing other necessary setup 1450 | function receiveInstance(instance, module) { 1451 | exports = instance.exports; 1452 | if (exports.memory) mergeMemory(exports.memory); 1453 | Module['asm'] = exports; 1454 | Module["usingWasm"] = true; 1455 | removeRunDependency('wasm-instantiate'); 1456 | } 1457 | addRunDependency('wasm-instantiate'); 1458 | 1459 | // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback 1460 | // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel 1461 | // to any other async startup actions they are performing. 1462 | if (Module['instantiateWasm']) { 1463 | try { 1464 | return Module['instantiateWasm'](info, receiveInstance); 1465 | } catch(e) { 1466 | Module['printErr']('Module.instantiateWasm callback failed with error: ' + e); 1467 | return false; 1468 | } 1469 | } 1470 | 1471 | function receiveInstantiatedSource(output) { 1472 | // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. 1473 | // receiveInstance() will swap in the exports (to Module.asm) so they can be called 1474 | receiveInstance(output['instance'], output['module']); 1475 | } 1476 | function instantiateArrayBuffer(receiver) { 1477 | getBinaryPromise().then(function(binary) { 1478 | return WebAssembly.instantiate(binary, info); 1479 | }).then(receiver).catch(function(reason) { 1480 | Module['printErr']('failed to asynchronously prepare wasm: ' + reason); 1481 | abort(reason); 1482 | }); 1483 | } 1484 | // Prefer streaming instantiation if available. 1485 | if (!Module['wasmBinary'] && 1486 | typeof WebAssembly.instantiateStreaming === 'function' && 1487 | !isDataURI(wasmBinaryFile) && 1488 | typeof fetch === 'function') { 1489 | WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info) 1490 | .then(receiveInstantiatedSource) 1491 | .catch(function(reason) { 1492 | // We expect the most common failure cause to be a bad MIME type for the binary, 1493 | // in which case falling back to ArrayBuffer instantiation should work. 1494 | Module['printErr']('wasm streaming compile failed: ' + reason); 1495 | Module['printErr']('falling back to ArrayBuffer instantiation'); 1496 | instantiateArrayBuffer(receiveInstantiatedSource); 1497 | }); 1498 | } else { 1499 | instantiateArrayBuffer(receiveInstantiatedSource); 1500 | } 1501 | return {}; // no exports yet; we'll fill them in later 1502 | } 1503 | 1504 | 1505 | // We may have a preloaded value in Module.asm, save it 1506 | Module['asmPreload'] = Module['asm']; 1507 | 1508 | // Memory growth integration code 1509 | 1510 | var asmjsReallocBuffer = Module['reallocBuffer']; 1511 | 1512 | var wasmReallocBuffer = function(size) { 1513 | var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. 1514 | size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size 1515 | var old = Module['buffer']; 1516 | var oldSize = old.byteLength; 1517 | if (Module["usingWasm"]) { 1518 | // native wasm support 1519 | try { 1520 | var result = Module['wasmMemory'].grow((size - oldSize) / wasmPageSize); // .grow() takes a delta compared to the previous size 1521 | if (result !== (-1 | 0)) { 1522 | // success in native wasm memory growth, get the buffer from the memory 1523 | return Module['buffer'] = Module['wasmMemory'].buffer; 1524 | } else { 1525 | return null; 1526 | } 1527 | } catch(e) { 1528 | return null; 1529 | } 1530 | } 1531 | }; 1532 | 1533 | Module['reallocBuffer'] = function(size) { 1534 | if (finalMethod === 'asmjs') { 1535 | return asmjsReallocBuffer(size); 1536 | } else { 1537 | return wasmReallocBuffer(size); 1538 | } 1539 | }; 1540 | 1541 | // we may try more than one; this is the final one, that worked and we are using 1542 | var finalMethod = ''; 1543 | 1544 | // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate 1545 | // the wasm module at that time, and it receives imports and provides exports and so forth, the app 1546 | // doesn't need to care that it is wasm or olyfilled wasm or asm.js. 1547 | 1548 | Module['asm'] = function(global, env, providedBuffer) { 1549 | env = fixImports(env); 1550 | 1551 | // import table 1552 | if (!env['table']) { 1553 | var TABLE_SIZE = Module['wasmTableSize']; 1554 | if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least 1555 | var MAX_TABLE_SIZE = Module['wasmMaxTableSize']; 1556 | if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') { 1557 | if (MAX_TABLE_SIZE !== undefined) { 1558 | env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, 'maximum': MAX_TABLE_SIZE, 'element': 'anyfunc' }); 1559 | } else { 1560 | env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, element: 'anyfunc' }); 1561 | } 1562 | } else { 1563 | env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least 1564 | } 1565 | Module['wasmTable'] = env['table']; 1566 | } 1567 | 1568 | if (!env['memoryBase']) { 1569 | env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves 1570 | } 1571 | if (!env['tableBase']) { 1572 | env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change 1573 | } 1574 | 1575 | // try the methods. each should return the exports if it succeeded 1576 | 1577 | var exports; 1578 | exports = doNativeWasm(global, env, providedBuffer); 1579 | 1580 | if (!exports) abort('no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods'); 1581 | 1582 | 1583 | return exports; 1584 | }; 1585 | 1586 | var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later 1587 | } 1588 | 1589 | integrateWasmJS(); 1590 | 1591 | // === Body === 1592 | 1593 | var ASM_CONSTS = []; 1594 | 1595 | 1596 | 1597 | 1598 | 1599 | STATIC_BASE = GLOBAL_BASE; 1600 | 1601 | STATICTOP = STATIC_BASE + 1056; 1602 | /* global initializers */ __ATINIT__.push(); 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | var STATIC_BUMP = 1056; 1611 | Module["STATIC_BASE"] = STATIC_BASE; 1612 | Module["STATIC_BUMP"] = STATIC_BUMP; 1613 | 1614 | /* no memory initializer */ 1615 | var tempDoublePtr = STATICTOP; STATICTOP += 16; 1616 | 1617 | function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much 1618 | 1619 | HEAP8[tempDoublePtr] = HEAP8[ptr]; 1620 | 1621 | HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; 1622 | 1623 | HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; 1624 | 1625 | HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; 1626 | 1627 | } 1628 | 1629 | function copyTempDouble(ptr) { 1630 | 1631 | HEAP8[tempDoublePtr] = HEAP8[ptr]; 1632 | 1633 | HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; 1634 | 1635 | HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; 1636 | 1637 | HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; 1638 | 1639 | HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; 1640 | 1641 | HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; 1642 | 1643 | HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; 1644 | 1645 | HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; 1646 | 1647 | } 1648 | 1649 | // {{PRE_LIBRARY}} 1650 | 1651 | DYNAMICTOP_PTR = staticAlloc(4); 1652 | 1653 | STACK_BASE = STACKTOP = alignMemory(STATICTOP); 1654 | 1655 | STACK_MAX = STACK_BASE + TOTAL_STACK; 1656 | 1657 | DYNAMIC_BASE = alignMemory(STACK_MAX); 1658 | 1659 | HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; 1660 | 1661 | staticSealed = true; // seal the static portion of memory 1662 | 1663 | var ASSERTIONS = false; 1664 | 1665 | /** @type {function(string, boolean=, number=)} */ 1666 | function intArrayFromString(stringy, dontAddNull, length) { 1667 | var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; 1668 | var u8array = new Array(len); 1669 | var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); 1670 | if (dontAddNull) u8array.length = numBytesWritten; 1671 | return u8array; 1672 | } 1673 | 1674 | function intArrayToString(array) { 1675 | var ret = []; 1676 | for (var i = 0; i < array.length; i++) { 1677 | var chr = array[i]; 1678 | if (chr > 0xFF) { 1679 | if (ASSERTIONS) { 1680 | assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.'); 1681 | } 1682 | chr &= 0xFF; 1683 | } 1684 | ret.push(String.fromCharCode(chr)); 1685 | } 1686 | return ret.join(''); 1687 | } 1688 | 1689 | 1690 | 1691 | Module['wasmTableSize'] = 0; 1692 | 1693 | Module['wasmMaxTableSize'] = 0; 1694 | 1695 | Module.asmGlobalArg = {}; 1696 | 1697 | Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX }; 1698 | // EMSCRIPTEN_START_ASM 1699 | var asm =Module["asm"]// EMSCRIPTEN_END_ASM 1700 | (Module.asmGlobalArg, Module.asmLibraryArg, buffer); 1701 | 1702 | Module["asm"] = asm; 1703 | var _len = Module["_len"] = function() { return Module["asm"]["_len"].apply(null, arguments) }; 1704 | var _str = Module["_str"] = function() { return Module["asm"]["_str"].apply(null, arguments) }; 1705 | ; 1706 | 1707 | 1708 | 1709 | // === Auto-generated postamble setup entry stuff === 1710 | 1711 | Module['asm'] = asm; 1712 | 1713 | 1714 | 1715 | 1716 | 1717 | 1718 | 1719 | 1720 | 1721 | 1722 | 1723 | 1724 | 1725 | 1726 | 1727 | 1728 | 1729 | 1730 | 1731 | 1732 | 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1743 | 1744 | 1745 | 1746 | 1747 | 1748 | 1749 | 1750 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 | 1757 | 1758 | 1759 | 1760 | 1761 | 1762 | 1763 | 1764 | 1765 | 1766 | 1767 | 1768 | 1769 | 1770 | 1771 | 1772 | 1773 | 1774 | 1775 | 1776 | 1777 | 1778 | 1779 | 1780 | 1781 | 1782 | 1783 | 1784 | /** 1785 | * @constructor 1786 | * @extends {Error} 1787 | * @this {ExitStatus} 1788 | */ 1789 | function ExitStatus(status) { 1790 | this.name = "ExitStatus"; 1791 | this.message = "Program terminated with exit(" + status + ")"; 1792 | this.status = status; 1793 | }; 1794 | ExitStatus.prototype = new Error(); 1795 | ExitStatus.prototype.constructor = ExitStatus; 1796 | 1797 | var initialStackTop; 1798 | var calledMain = false; 1799 | 1800 | dependenciesFulfilled = function runCaller() { 1801 | // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) 1802 | if (!Module['calledRun']) run(); 1803 | if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled 1804 | } 1805 | 1806 | 1807 | 1808 | 1809 | 1810 | /** @type {function(Array=)} */ 1811 | function run(args) { 1812 | args = args || Module['arguments']; 1813 | 1814 | if (runDependencies > 0) { 1815 | return; 1816 | } 1817 | 1818 | 1819 | preRun(); 1820 | 1821 | if (runDependencies > 0) return; // a preRun added a dependency, run will be called later 1822 | if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame 1823 | 1824 | function doRun() { 1825 | if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening 1826 | Module['calledRun'] = true; 1827 | 1828 | if (ABORT) return; 1829 | 1830 | ensureInitRuntime(); 1831 | 1832 | preMain(); 1833 | 1834 | if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); 1835 | 1836 | 1837 | postRun(); 1838 | } 1839 | 1840 | if (Module['setStatus']) { 1841 | Module['setStatus']('Running...'); 1842 | setTimeout(function() { 1843 | setTimeout(function() { 1844 | Module['setStatus'](''); 1845 | }, 1); 1846 | doRun(); 1847 | }, 1); 1848 | } else { 1849 | doRun(); 1850 | } 1851 | } 1852 | Module['run'] = run; 1853 | 1854 | 1855 | function exit(status, implicit) { 1856 | 1857 | // if this is just main exit-ing implicitly, and the status is 0, then we 1858 | // don't need to do anything here and can just leave. if the status is 1859 | // non-zero, though, then we need to report it. 1860 | // (we may have warned about this earlier, if a situation justifies doing so) 1861 | if (implicit && Module['noExitRuntime'] && status === 0) { 1862 | return; 1863 | } 1864 | 1865 | if (Module['noExitRuntime']) { 1866 | } else { 1867 | 1868 | ABORT = true; 1869 | EXITSTATUS = status; 1870 | STACKTOP = initialStackTop; 1871 | 1872 | exitRuntime(); 1873 | 1874 | if (Module['onExit']) Module['onExit'](status); 1875 | } 1876 | 1877 | if (ENVIRONMENT_IS_NODE) { 1878 | process['exit'](status); 1879 | } 1880 | Module['quit'](status, new ExitStatus(status)); 1881 | } 1882 | Module['exit'] = exit; 1883 | 1884 | var abortDecorators = []; 1885 | 1886 | function abort(what) { 1887 | if (Module['onAbort']) { 1888 | Module['onAbort'](what); 1889 | } 1890 | 1891 | if (what !== undefined) { 1892 | Module.print(what); 1893 | Module.printErr(what); 1894 | what = JSON.stringify(what) 1895 | } else { 1896 | what = ''; 1897 | } 1898 | 1899 | ABORT = true; 1900 | EXITSTATUS = 1; 1901 | 1902 | throw 'abort(' + what + '). Build with -s ASSERTIONS=1 for more info.'; 1903 | } 1904 | Module['abort'] = abort; 1905 | 1906 | // {{PRE_RUN_ADDITIONS}} 1907 | 1908 | if (Module['preInit']) { 1909 | if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; 1910 | while (Module['preInit'].length > 0) { 1911 | Module['preInit'].pop()(); 1912 | } 1913 | } 1914 | 1915 | 1916 | Module["noExitRuntime"] = true; 1917 | 1918 | run(); 1919 | 1920 | // {{POST_RUN_ADDITIONS}} 1921 | 1922 | 1923 | 1924 | 1925 | 1926 | // {{MODULE_ADDITIONS}} 1927 | 1928 | 1929 | 1930 | -------------------------------------------------------------------------------- /packages/clang/wasm/helloworld-std.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ragingwind/wasm-helloworld/3b49e9f944cfb94191dd6312517b96c444544080/packages/clang/wasm/helloworld-std.wasm -------------------------------------------------------------------------------- /packages/go/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | GOARCH=wasm GOOS=js ${GOROOT}/bin/go build -o ./wasm/main.wasm ./src/main.go 3 | 4 | build-server: 5 | go build -o ./server ./src/server.go 6 | 7 | run: 8 | ./server ${PORT} -------------------------------------------------------------------------------- /packages/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 |
13 | 14 | -------------------------------------------------------------------------------- /packages/go/readme.md: -------------------------------------------------------------------------------- 1 | # Install 2 | 3 | - Go lang with vesion [over 1.11](https://golang.org/dl/) 4 | 5 | # Usage 6 | 7 | ``` 8 | # build with your go bin, make sure that your go must support web assembly 9 | GOROOT=~/Go/release/go1.11beta1/ make build 10 | 11 | # run and visit https://localhost:8080 12 | make PORT=8080 run 13 | 14 | # build server as you want 15 | make build-server 16 | ``` -------------------------------------------------------------------------------- /packages/go/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ragingwind/wasm-helloworld/3b49e9f944cfb94191dd6312517b96c444544080/packages/go/server -------------------------------------------------------------------------------- /packages/go/src/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "syscall/js" 5 | ) 6 | 7 | func main() { 8 | output := js.Global().Get("document").Call("querySelector", "#output") 9 | output.Set("textContent", Add(10, 90)) 10 | } 11 | 12 | func Add(a, b int) int { 13 | return a + b 14 | } 15 | -------------------------------------------------------------------------------- /packages/go/src/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | func wasmHandler(w http.ResponseWriter, r *http.Request) { 11 | w.Header().Set("Content-Type", "application/wasm") 12 | http.ServeFile(w, r, "./wasm/main.wasm") 13 | } 14 | 15 | func main() { 16 | var port string 17 | if len(os.Args) > 1 { 18 | port = os.Args[1] 19 | } else { 20 | port = "8080" 21 | } 22 | 23 | mux := http.NewServeMux() 24 | mux.Handle("/", http.FileServer(http.Dir("."))) 25 | mux.HandleFunc("/main.wasm", wasmHandler) 26 | log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), mux)) 27 | } 28 | -------------------------------------------------------------------------------- /packages/go/wasm/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ragingwind/wasm-helloworld/3b49e9f944cfb94191dd6312517b96c444544080/packages/go/wasm/main.wasm -------------------------------------------------------------------------------- /packages/go/wasm_exec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // https://raw.githubusercontent.com/golang/go/master/misc/wasm/wasm_exec.js 5 | 6 | (() => { 7 | // Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API). 8 | const isNodeJS = typeof process !== "undefined"; 9 | if (isNodeJS) { 10 | global.require = require; 11 | global.fs = require("fs"); 12 | 13 | const nodeCrypto = require("crypto"); 14 | global.crypto = { 15 | getRandomValues(b) { 16 | nodeCrypto.randomFillSync(b); 17 | }, 18 | }; 19 | 20 | global.performance = { 21 | now() { 22 | const [sec, nsec] = process.hrtime(); 23 | return sec * 1000 + nsec / 1000000; 24 | }, 25 | }; 26 | 27 | const util = require("util"); 28 | global.TextEncoder = util.TextEncoder; 29 | global.TextDecoder = util.TextDecoder; 30 | } else { 31 | window.global = window; 32 | 33 | let outputBuf = ""; 34 | global.fs = { 35 | constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_NONBLOCK: -1, O_SYNC: -1 }, // unused 36 | writeSync(fd, buf) { 37 | outputBuf += decoder.decode(buf); 38 | const nl = outputBuf.lastIndexOf("\n"); 39 | if (nl != -1) { 40 | console.log(outputBuf.substr(0, nl)); 41 | outputBuf = outputBuf.substr(nl + 1); 42 | } 43 | return buf.length; 44 | }, 45 | openSync(path, flags, mode) { 46 | const err = new Error("not implemented"); 47 | err.code = "ENOSYS"; 48 | throw err; 49 | }, 50 | }; 51 | } 52 | 53 | const encoder = new TextEncoder("utf-8"); 54 | const decoder = new TextDecoder("utf-8"); 55 | 56 | global.Go = class { 57 | constructor() { 58 | this.argv = ["js"]; 59 | this.env = {}; 60 | this.exit = (code) => { 61 | if (code !== 0) { 62 | console.warn("exit code:", code); 63 | } 64 | }; 65 | this._callbackTimeouts = new Map(); 66 | this._nextCallbackTimeoutID = 1; 67 | 68 | const mem = () => { 69 | // The buffer may change when requesting more memory. 70 | return new DataView(this._inst.exports.mem.buffer); 71 | } 72 | 73 | const setInt64 = (addr, v) => { 74 | mem().setUint32(addr + 0, v, true); 75 | mem().setUint32(addr + 4, Math.floor(v / 4294967296), true); 76 | } 77 | 78 | const getInt64 = (addr) => { 79 | const low = mem().getUint32(addr + 0, true); 80 | const high = mem().getInt32(addr + 4, true); 81 | return low + high * 4294967296; 82 | } 83 | 84 | const loadValue = (addr) => { 85 | const f = mem().getFloat64(addr, true); 86 | if (!isNaN(f)) { 87 | return f; 88 | } 89 | 90 | const id = mem().getUint32(addr, true); 91 | return this._values[id]; 92 | } 93 | 94 | const storeValue = (addr, v) => { 95 | if (typeof v === "number") { 96 | if (isNaN(v)) { 97 | mem().setUint32(addr + 4, 0x7FF80000, true); // NaN 98 | mem().setUint32(addr, 0, true); 99 | return; 100 | } 101 | mem().setFloat64(addr, v, true); 102 | return; 103 | } 104 | 105 | mem().setUint32(addr + 4, 0x7FF80000, true); // NaN 106 | 107 | switch (v) { 108 | case undefined: 109 | mem().setUint32(addr, 1, true); 110 | return; 111 | case null: 112 | mem().setUint32(addr, 2, true); 113 | return; 114 | case true: 115 | mem().setUint32(addr, 3, true); 116 | return; 117 | case false: 118 | mem().setUint32(addr, 4, true); 119 | return; 120 | } 121 | 122 | if (typeof v === "string") { 123 | let ref = this._stringRefs.get(v); 124 | if (ref === undefined) { 125 | ref = this._values.length; 126 | this._values.push(v); 127 | this._stringRefs.set(v, ref); 128 | } 129 | mem().setUint32(addr, ref, true); 130 | return; 131 | } 132 | 133 | if (typeof v === "symbol") { 134 | let ref = this._symbolRefs.get(v); 135 | if (ref === undefined) { 136 | ref = this._values.length; 137 | this._values.push(v); 138 | this._symbolRefs.set(v, ref); 139 | } 140 | mem().setUint32(addr, ref, true); 141 | return; 142 | } 143 | 144 | let ref = v[this._refProp]; 145 | if (ref === undefined || this._values[ref] !== v) { 146 | ref = this._values.length; 147 | this._values.push(v); 148 | v[this._refProp] = ref; 149 | } 150 | mem().setUint32(addr, ref, true); 151 | } 152 | 153 | const loadSlice = (addr) => { 154 | const array = getInt64(addr + 0); 155 | const len = getInt64(addr + 8); 156 | return new Uint8Array(this._inst.exports.mem.buffer, array, len); 157 | } 158 | 159 | const loadSliceOfValues = (addr) => { 160 | const array = getInt64(addr + 0); 161 | const len = getInt64(addr + 8); 162 | const a = new Array(len); 163 | for (let i = 0; i < len; i++) { 164 | a[i] = loadValue(array + i * 8); 165 | } 166 | return a; 167 | } 168 | 169 | const loadString = (addr) => { 170 | const saddr = getInt64(addr + 0); 171 | const len = getInt64(addr + 8); 172 | return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); 173 | } 174 | 175 | const timeOrigin = Date.now() - performance.now(); 176 | this.importObject = { 177 | go: { 178 | // func wasmExit(code int32) 179 | "runtime.wasmExit": (sp) => { 180 | this.exited = true; 181 | this.exit(mem().getInt32(sp + 8, true)); 182 | }, 183 | 184 | // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) 185 | "runtime.wasmWrite": (sp) => { 186 | const fd = getInt64(sp + 8); 187 | const p = getInt64(sp + 16); 188 | const n = mem().getInt32(sp + 24, true); 189 | fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); 190 | }, 191 | 192 | // func nanotime() int64 193 | "runtime.nanotime": (sp) => { 194 | setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); 195 | }, 196 | 197 | // func walltime() (sec int64, nsec int32) 198 | "runtime.walltime": (sp) => { 199 | const msec = (new Date).getTime(); 200 | setInt64(sp + 8, msec / 1000); 201 | mem().setInt32(sp + 16, (msec % 1000) * 1000000, true); 202 | }, 203 | 204 | // func scheduleCallback(delay int64) int32 205 | "runtime.scheduleCallback": (sp) => { 206 | const id = this._nextCallbackTimeoutID; 207 | this._nextCallbackTimeoutID++; 208 | this._callbackTimeouts.set(id, setTimeout( 209 | () => { this._resolveCallbackPromise(); }, 210 | getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early 211 | )); 212 | mem().setInt32(sp + 16, id, true); 213 | }, 214 | 215 | // func clearScheduledCallback(id int32) 216 | "runtime.clearScheduledCallback": (sp) => { 217 | const id = mem().getInt32(sp + 8, true); 218 | clearTimeout(this._callbackTimeouts.get(id)); 219 | this._callbackTimeouts.delete(id); 220 | }, 221 | 222 | // func getRandomData(r []byte) 223 | "runtime.getRandomData": (sp) => { 224 | crypto.getRandomValues(loadSlice(sp + 8)); 225 | }, 226 | 227 | // func stringVal(value string) ref 228 | "syscall/js.stringVal": (sp) => { 229 | storeValue(sp + 24, loadString(sp + 8)); 230 | }, 231 | 232 | // func valueGet(v ref, p string) ref 233 | "syscall/js.valueGet": (sp) => { 234 | storeValue(sp + 32, Reflect.get(loadValue(sp + 8), loadString(sp + 16))); 235 | }, 236 | 237 | // func valueSet(v ref, p string, x ref) 238 | "syscall/js.valueSet": (sp) => { 239 | Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); 240 | }, 241 | 242 | // func valueIndex(v ref, i int) ref 243 | "syscall/js.valueIndex": (sp) => { 244 | storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); 245 | }, 246 | 247 | // valueSetIndex(v ref, i int, x ref) 248 | "syscall/js.valueSetIndex": (sp) => { 249 | Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); 250 | }, 251 | 252 | // func valueCall(v ref, m string, args []ref) (ref, bool) 253 | "syscall/js.valueCall": (sp) => { 254 | try { 255 | const v = loadValue(sp + 8); 256 | const m = Reflect.get(v, loadString(sp + 16)); 257 | const args = loadSliceOfValues(sp + 32); 258 | storeValue(sp + 56, Reflect.apply(m, v, args)); 259 | mem().setUint8(sp + 64, 1); 260 | } catch (err) { 261 | storeValue(sp + 56, err); 262 | mem().setUint8(sp + 64, 0); 263 | } 264 | }, 265 | 266 | // func valueInvoke(v ref, args []ref) (ref, bool) 267 | "syscall/js.valueInvoke": (sp) => { 268 | try { 269 | const v = loadValue(sp + 8); 270 | const args = loadSliceOfValues(sp + 16); 271 | storeValue(sp + 40, Reflect.apply(v, undefined, args)); 272 | mem().setUint8(sp + 48, 1); 273 | } catch (err) { 274 | storeValue(sp + 40, err); 275 | mem().setUint8(sp + 48, 0); 276 | } 277 | }, 278 | 279 | // func valueNew(v ref, args []ref) (ref, bool) 280 | "syscall/js.valueNew": (sp) => { 281 | try { 282 | const v = loadValue(sp + 8); 283 | const args = loadSliceOfValues(sp + 16); 284 | storeValue(sp + 40, Reflect.construct(v, args)); 285 | mem().setUint8(sp + 48, 1); 286 | } catch (err) { 287 | storeValue(sp + 40, err); 288 | mem().setUint8(sp + 48, 0); 289 | } 290 | }, 291 | 292 | // func valueLength(v ref) int 293 | "syscall/js.valueLength": (sp) => { 294 | setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); 295 | }, 296 | 297 | // valuePrepareString(v ref) (ref, int) 298 | "syscall/js.valuePrepareString": (sp) => { 299 | const str = encoder.encode(String(loadValue(sp + 8))); 300 | storeValue(sp + 16, str); 301 | setInt64(sp + 24, str.length); 302 | }, 303 | 304 | // valueLoadString(v ref, b []byte) 305 | "syscall/js.valueLoadString": (sp) => { 306 | const str = loadValue(sp + 8); 307 | loadSlice(sp + 16).set(str); 308 | }, 309 | 310 | // func valueInstanceOf(v ref, t ref) bool 311 | "syscall/js.valueInstanceOf": (sp) => { 312 | mem().setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16)); 313 | }, 314 | 315 | "debug": (value) => { 316 | console.log(value); 317 | }, 318 | } 319 | }; 320 | } 321 | 322 | async run(instance) { 323 | this._inst = instance; 324 | this._values = [ // TODO: garbage collection 325 | NaN, 326 | undefined, 327 | null, 328 | true, 329 | false, 330 | global, 331 | this._inst.exports.mem, 332 | () => { // resolveCallbackPromise 333 | if (this.exited) { 334 | throw new Error("bad callback: Go program has already exited"); 335 | } 336 | setTimeout(this._resolveCallbackPromise, 0); // make sure it is asynchronous 337 | }, 338 | ]; 339 | this._stringRefs = new Map(); 340 | this._symbolRefs = new Map(); 341 | this._refProp = Symbol(); 342 | this.exited = false; 343 | 344 | const mem = new DataView(this._inst.exports.mem.buffer) 345 | 346 | // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. 347 | let offset = 4096; 348 | 349 | const strPtr = (str) => { 350 | let ptr = offset; 351 | new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + "\0")); 352 | offset += str.length + (8 - (str.length % 8)); 353 | return ptr; 354 | }; 355 | 356 | const argc = this.argv.length; 357 | 358 | const argvPtrs = []; 359 | this.argv.forEach((arg) => { 360 | argvPtrs.push(strPtr(arg)); 361 | }); 362 | 363 | const keys = Object.keys(this.env).sort(); 364 | argvPtrs.push(keys.length); 365 | keys.forEach((key) => { 366 | argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); 367 | }); 368 | 369 | const argv = offset; 370 | argvPtrs.forEach((ptr) => { 371 | mem.setUint32(offset, ptr, true); 372 | mem.setUint32(offset + 4, 0, true); 373 | offset += 8; 374 | }); 375 | 376 | while (true) { 377 | const callbackPromise = new Promise((resolve) => { 378 | this._resolveCallbackPromise = resolve; 379 | }); 380 | this._inst.exports.run(argc, argv); 381 | if (this.exited) { 382 | break; 383 | } 384 | await callbackPromise; 385 | } 386 | } 387 | } 388 | 389 | if (isNodeJS) { 390 | if (process.argv.length < 3) { 391 | process.stderr.write("usage: go_js_wasm_exec [wasm binary] [arguments]\n"); 392 | process.exit(1); 393 | } 394 | 395 | const go = new Go(); 396 | go.argv = process.argv.slice(2); 397 | go.env = process.env; 398 | go.exit = process.exit; 399 | WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => { 400 | process.on("exit", () => { // Node.js exits if no callback is pending 401 | if (!go.exited) { 402 | console.error("error: all goroutines asleep and no JavaScript callback pending - deadlock!"); 403 | process.exit(1); 404 | } 405 | }); 406 | return go.run(result.instance); 407 | }).catch((err) => { 408 | console.error(err); 409 | go.exited = true; 410 | process.exit(1); 411 | }); 412 | } 413 | })(); -------------------------------------------------------------------------------- /packages/rust-parcel/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/rust-parcel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clang", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "start": "parcel index.html --open -p 8080", 6 | "build": "parcel build src/index.js --out-dir ./dist" 7 | }, 8 | "devDependencies": { 9 | "parcel-bundler": "^1.7.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/rust-parcel/readme.md: -------------------------------------------------------------------------------- 1 | # Rust with parcel packager 2 | 3 | > Parcel packager allows us to import rust source code directly in source files. 4 | 5 | ## Uses 6 | 7 | ```sh 8 | # Install deps 9 | yarn install 10 | 11 | # Build or 12 | yarn build 13 | 14 | # Start dev server 15 | yarn start 16 | ``` 17 | 18 | # License 19 | 20 | MIT @ CODEBUSKING -------------------------------------------------------------------------------- /packages/rust-parcel/src/index.js: -------------------------------------------------------------------------------- 1 | import('../wasm/add.rs').then(({add}) => { 2 | document.body.innerHTML += `add(2, 3) = ${add(2, 3)}
` 3 | }) 4 | 5 | import('../wasm/square.wasm').then(({square}) => { 6 | document.body.innerHTML += `square(10) = ${square(10)}
` 7 | }) -------------------------------------------------------------------------------- /packages/rust-parcel/wasm/add.rs: -------------------------------------------------------------------------------- 1 | pub fn main() {} 2 | 3 | #[no_mangle] 4 | pub extern fn add(a: i32, b: i32) -> i32 { 5 | return a + b 6 | } -------------------------------------------------------------------------------- /packages/rust-parcel/wasm/square.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ragingwind/wasm-helloworld/3b49e9f944cfb94191dd6312517b96c444544080/packages/rust-parcel/wasm/square.wasm -------------------------------------------------------------------------------- /packages/rust-thread/.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | target -------------------------------------------------------------------------------- /packages/rust-thread/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "anyhow" 5 | version = "1.0.22" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "bumpalo" 10 | version = "2.6.0" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [[package]] 14 | name = "cfg-if" 15 | version = "0.1.10" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | 18 | [[package]] 19 | name = "heck" 20 | version = "0.3.1" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | dependencies = [ 23 | "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 24 | ] 25 | 26 | [[package]] 27 | name = "itoa" 28 | version = "0.4.4" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "js-sys" 33 | version = "0.3.31" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | dependencies = [ 36 | "wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 37 | ] 38 | 39 | [[package]] 40 | name = "lazy_static" 41 | version = "1.4.0" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | 44 | [[package]] 45 | name = "log" 46 | version = "0.4.8" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | dependencies = [ 49 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 50 | ] 51 | 52 | [[package]] 53 | name = "memchr" 54 | version = "2.2.1" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | 57 | [[package]] 58 | name = "nom" 59 | version = "4.2.3" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | dependencies = [ 62 | "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 63 | "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 64 | ] 65 | 66 | [[package]] 67 | name = "proc-macro2" 68 | version = "1.0.6" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | dependencies = [ 71 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 72 | ] 73 | 74 | [[package]] 75 | name = "quote" 76 | version = "1.0.2" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | dependencies = [ 79 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 80 | ] 81 | 82 | [[package]] 83 | name = "rust-thread" 84 | version = "0.1.0" 85 | dependencies = [ 86 | "js-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", 87 | "wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 88 | "wasm-bindgen-futures 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "web-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", 90 | ] 91 | 92 | [[package]] 93 | name = "ryu" 94 | version = "1.0.2" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | 97 | [[package]] 98 | name = "serde" 99 | version = "1.0.102" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | 102 | [[package]] 103 | name = "serde_json" 104 | version = "1.0.41" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | dependencies = [ 107 | "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 108 | "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 109 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 110 | ] 111 | 112 | [[package]] 113 | name = "sourcefile" 114 | version = "0.1.4" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | 117 | [[package]] 118 | name = "syn" 119 | version = "1.0.8" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | dependencies = [ 122 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 123 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 124 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 125 | ] 126 | 127 | [[package]] 128 | name = "unicode-segmentation" 129 | version = "1.6.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | 132 | [[package]] 133 | name = "unicode-xid" 134 | version = "0.2.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | 137 | [[package]] 138 | name = "version_check" 139 | version = "0.1.5" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | 142 | [[package]] 143 | name = "wasm-bindgen" 144 | version = "0.2.54" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | dependencies = [ 147 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 148 | "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", 149 | "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 150 | "wasm-bindgen-macro 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 151 | ] 152 | 153 | [[package]] 154 | name = "wasm-bindgen-backend" 155 | version = "0.2.54" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | dependencies = [ 158 | "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 159 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 160 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 161 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 162 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 163 | "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 164 | "wasm-bindgen-shared 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 165 | ] 166 | 167 | [[package]] 168 | name = "wasm-bindgen-futures" 169 | version = "0.4.4" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | dependencies = [ 172 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 173 | "js-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", 174 | "wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 175 | "web-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", 176 | ] 177 | 178 | [[package]] 179 | name = "wasm-bindgen-macro" 180 | version = "0.2.54" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | dependencies = [ 183 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 184 | "wasm-bindgen-macro-support 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 185 | ] 186 | 187 | [[package]] 188 | name = "wasm-bindgen-macro-support" 189 | version = "0.2.54" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | dependencies = [ 192 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 193 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 194 | "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 195 | "wasm-bindgen-backend 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 196 | "wasm-bindgen-shared 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 197 | ] 198 | 199 | [[package]] 200 | name = "wasm-bindgen-shared" 201 | version = "0.2.54" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | 204 | [[package]] 205 | name = "wasm-bindgen-webidl" 206 | version = "0.2.54" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | dependencies = [ 209 | "anyhow 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", 210 | "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 211 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 212 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 213 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 214 | "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 215 | "wasm-bindgen-backend 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 216 | "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 217 | ] 218 | 219 | [[package]] 220 | name = "web-sys" 221 | version = "0.3.31" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | dependencies = [ 224 | "anyhow 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", 225 | "js-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)", 226 | "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 227 | "wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 228 | "wasm-bindgen-webidl 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 229 | ] 230 | 231 | [[package]] 232 | name = "weedle" 233 | version = "0.10.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | dependencies = [ 236 | "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 237 | ] 238 | 239 | [metadata] 240 | "checksum anyhow 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "e19f23ab207147bbdbcdfa7f7e4ca5e84963d79bae3937074682177ab9150968" 241 | "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" 242 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 243 | "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 244 | "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" 245 | "checksum js-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d8657b7ca06a6044ece477f6900bf7670f8b5fd0cce177a1d7094eef51e0adf4" 246 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 247 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 248 | "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 249 | "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" 250 | "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" 251 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 252 | "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" 253 | "checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0" 254 | "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" 255 | "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" 256 | "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" 257 | "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" 258 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 259 | "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 260 | "checksum wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c4568ae1b4e07ca907b1a4de41174eaa3e5be4066c024475586b7842725f69a9" 261 | "checksum wasm-bindgen-backend 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5a00cfdce37367770062065fd3abb9278cbae86a0d918cacd0978a7acd51b481" 262 | "checksum wasm-bindgen-futures 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07573324d8331357b833487c57f7b8d45924a69d5e2c44b4420558b310b86943" 263 | "checksum wasm-bindgen-macro 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7c568f4d3cf6d7c1d72b165daf778fb0d6e09a24f96ac14fc8c4f66a96e86b72" 264 | "checksum wasm-bindgen-macro-support 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "430d12539ae324d16097b399e9d07a6d5ce0173b2a61a2d02346ca7c198daffe" 265 | "checksum wasm-bindgen-shared 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "8ae7167f0bbffd7fac2b12da0fa1f834c1d84671a1ae3c93ac8bde2e97179c39" 266 | "checksum wasm-bindgen-webidl 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "3021567c515a746a64ad0b269d120d46e687c0c95702a4750623db935ae6b5e7" 267 | "checksum web-sys 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)" = "ce8e893e021539beb87de8f06e77bdb390a3ab0db4cfeb569c4e377b55ed20de" 268 | "checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" 269 | -------------------------------------------------------------------------------- /packages/rust-thread/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-thread" 3 | version = "0.1.0" 4 | authors = ["Jimmy Moon "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | crate-type = ["cdylib"] 11 | 12 | [dependencies] 13 | js-sys = "0.3.31" 14 | wasm-bindgen = { version = "0.2.54", features = ['serde-serialize'] } 15 | wasm-bindgen-futures = "0.4.4" 16 | 17 | [dependencies.web-sys] 18 | version = "0.3.23" 19 | features = [ 20 | 'CanvasRenderingContext2d', 21 | 'ErrorEvent', 22 | 'Event', 23 | 'ImageData', 24 | 'Navigator', 25 | 'Window', 26 | 'Worker', 27 | 'WorkerOptions', 28 | 'DedicatedWorkerGlobalScope', 29 | 'MessageEvent', 30 | ] -------------------------------------------------------------------------------- /packages/rust-thread/build.sh: -------------------------------------------------------------------------------- 1 | mkdir -p pkg 2 | PATH=$PATH:$(dirname $(find $(rustc --print sysroot) -name 'rust-lld')) \ 3 | RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' rustup run nightly wasm-pack build -t no-modules -- -Z build-std 4 | 5 | python3 -m http.server -------------------------------------------------------------------------------- /packages/rust-thread/index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/rust-thread/readme.md: -------------------------------------------------------------------------------- 1 | # rust-thread example 2 | 3 | > Build thread with Rust and wasm-bindgen, custom worker.js. It's kind of snippets from origin source, [raytrace-paraller](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/raytrace-parallel) to understand how thread works in Rust. It would be updated to more practical example. 4 | 5 | # How to run 6 | 7 | ```sh 8 | # build 9 | ./build.sh 10 | ``` 11 | 12 | # License 13 | 14 | MIT @ Jimmy Moon -------------------------------------------------------------------------------- /packages/rust-thread/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(target_arch = "wasm32"), allow(dead_code))] 2 | 3 | use wasm_bindgen::prelude::*; 4 | 5 | mod thread; 6 | 7 | macro_rules! console_log { 8 | ($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string())) 9 | } 10 | 11 | #[wasm_bindgen] 12 | extern "C" { 13 | #[wasm_bindgen(js_namespace = console)] 14 | fn log(s: &str); 15 | #[wasm_bindgen(js_namespace = console, js_name = log)] 16 | fn logv(x: &JsValue); 17 | } 18 | 19 | #[wasm_bindgen] 20 | pub fn start() -> Result<(), JsValue> { 21 | let thread = thread::WorkerThread::new("./worker.js", "worker1")?; 22 | thread.run(move || { 23 | console_log!("run in wasm"); 24 | })?; 25 | 26 | Ok(()) 27 | } -------------------------------------------------------------------------------- /packages/rust-thread/src/thread.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | use wasm_bindgen::prelude::*; 3 | use web_sys::{Worker, WorkerOptions}; 4 | 5 | pub struct WorkerThread { 6 | worker: Rc 7 | } 8 | 9 | pub struct Work { 10 | pub func: Box, 11 | } 12 | 13 | impl WorkerThread { 14 | pub fn new(script: &str, name: &str) -> Result { 15 | let mut options = WorkerOptions::new(); 16 | options.name(String::from(name).as_str()); 17 | 18 | let worker = Worker::new_with_options(script, &options)?; 19 | let thread = WorkerThread { 20 | worker: Rc::new(worker) 21 | }; 22 | 23 | let wasm = js_sys::Array::new(); 24 | wasm.push(&wasm_bindgen::module()); 25 | wasm.push(&wasm_bindgen::memory()); 26 | thread.post_message("init", &wasm)?; 27 | 28 | Ok(thread) 29 | } 30 | 31 | pub fn post_message(&self, command: &str, payload: &JsValue) -> Result<(), JsValue> { 32 | let commands = js_sys::Array::new(); 33 | commands.push(&JsValue::from_str(command)); 34 | commands.push(payload); 35 | self.worker.post_message(&commands)?; 36 | Ok(()) 37 | } 38 | 39 | pub fn run(&self, f: impl FnOnce() + Send + 'static) -> Result<(), JsValue> { 40 | let work = Box::new(Work { func: Box::new(f) }); 41 | let ptr = Box::into_raw(work); 42 | 43 | match self.post_message("work", &JsValue::from(ptr as u32)) { 44 | Ok(()) => Ok(()), 45 | Err(e) => { 46 | unsafe { 47 | drop(Box::from_raw(ptr)); 48 | } 49 | Err(e) 50 | } 51 | } 52 | } 53 | } 54 | 55 | #[wasm_bindgen] 56 | pub fn thread_execute(ptr: u32) -> Result<(), JsValue> { 57 | let ptr = unsafe { Box::from_raw(ptr as *mut Work) }; 58 | (ptr.func)(); 59 | Ok(()) 60 | } -------------------------------------------------------------------------------- /packages/rust-thread/worker.js: -------------------------------------------------------------------------------- 1 | importScripts("./pkg/rust_thread.js"); 2 | 3 | console.log('worker: worker started', self.name); 4 | 5 | self.onmessage = async ({data}) => { 6 | console.log('message from wasm', data); 7 | try { 8 | switch (data[0]) { 9 | case 'init': 10 | await wasm_bindgen(...data[1]); 11 | break; 12 | case 'work': 13 | wasm_bindgen.thread_execute(data[1]); 14 | break; 15 | } 16 | } catch (e) { 17 | console.error(e); 18 | } 19 | } -------------------------------------------------------------------------------- /packages/rust-wasi-node/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | target -------------------------------------------------------------------------------- /packages/rust-wasi-node/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "rust-wasi-node" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /packages/rust-wasi-node/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-wasi-node" 3 | version = "0.1.0" 4 | authors = ["Jimmy Moon "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | 11 | [lib] 12 | crate-type = ['cdylib'] -------------------------------------------------------------------------------- /packages/rust-wasi-node/readme.md: -------------------------------------------------------------------------------- 1 | # rust-wasi-node example 2 | 3 | > The demo shows how WASI work with Node.js 4 | 5 | # How to make 6 | 7 | ## Install cargo-wasi 8 | 9 | ``` 10 | cargo install cargo-wasi 11 | ``` 12 | 13 | ## Create a project as lib 14 | 15 | ``` 16 | cargo new rust-wasi-node --lib 17 | ``` 18 | 19 | ## Update Cargo.toml for lib project 20 | 21 | add `[lib]` section below 22 | 23 | ``` 24 | [lib] 25 | crate-type = ['cdylib'] 26 | ``` 27 | 28 | ## Implement `src/lib.rs` 29 | 30 | Write(Copy) code with below into `src/lib.rs` 31 | 32 | ``` 33 | use std::io::prelude::*; 34 | use std::fs; 35 | 36 | // export name with no mangling 37 | #[no_mangle] 38 | pub extern "C" fn print_hello() { 39 | // use system stdio 40 | println!("Hello, world!"); 41 | 42 | // use system file io 43 | let mut file = fs::File::create("/host/helloworld.txt").unwrap(); 44 | 45 | // write the text to the file we created 46 | write!(file, "Hello world!\n").unwrap(); 47 | } 48 | ``` 49 | 50 | ## Build 51 | 52 | Run commands below 53 | 54 | ``` 55 | rustup target add wasm32-wasi 56 | cargo build --target wasm32-wasi 57 | ``` 58 | 59 | ## Run with wasmtime 60 | 61 | Pass `/host` path to map host device location to virtual filesystem. To current directory(.) on the host filesystem will be mapped to `/host` virtual filesystem. For example: 62 | 63 | ``` 64 | --mapdir /host::. 65 | ``` 66 | 67 | Run wasmtime with using commadn below 68 | 69 | ``` 70 | wasmtime --mapdir /host::. --invoke print_hello target/wasm32-wasi/debug/rust_wasi_node.wasm 71 | cat ./helloworld.txt 72 | ``` 73 | 74 | ## Run on Node.js 75 | 76 | Create a file to `runtime/index.mjs` 77 | 78 | ``` 79 | mkdir -p runtime 80 | touch runtime/index.mjs 81 | ``` 82 | 83 | Write this code to `runtime/index.mjs`: 84 | 85 | ``` 86 | 'use strict'; 87 | 88 | import fs from 'fs'; 89 | import path from 'path'; 90 | import { fileURLToPath } from 'url'; 91 | import { WASI } from 'wasi'; 92 | 93 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 94 | 95 | const wasi = new WASI({ 96 | // Same as --mapdir of wasmtime, map virtual filesystem to host filesystem 97 | preopens: { 98 | '/host': process.cwd(), 99 | }, 100 | }); 101 | 102 | // pass import Object to WASM to use host APIs 103 | const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; 104 | 105 | // Load, and compile, and instantiate WASM 106 | const wasm = await WebAssembly.compile(fs.readFileSync(path.resolve(__dirname, '../target/wasm32-wasi/debug/rust_wasi_node.wasm'))); 107 | const instance = await WebAssembly.instantiate(wasm, importObject); 108 | 109 | // WASI try to initialize WASM instanced 110 | wasi.initialize(instance); 111 | 112 | // Run WASM function 113 | instance.exports.print_hello(); 114 | ``` 115 | 116 | Before running, please make sure that the version of Node.js. It have to be over 16 117 | 118 | ``` 119 | node -v 120 | ``` 121 | 122 | And then run with experimental flag 123 | 124 | ``` 125 | node --experimental-wasi-unstable-preview1 ./runtime/index.mjs 126 | cat ./helloworld.txt 127 | ``` 128 | 129 | # Reference 130 | 131 | - https://github.com/bytecodealliance/wasmtime/blob/main/docs/wasm-rust.md#writing-libraries 132 | - https://github.com/bytecodealliance/wasmtime/blob/main/docs/wasm-rust.md#webassembly-interface-types 133 | - https://wasmbyexample.dev/examples/wasi-hello-world/wasi-hello-world.rust.en-us.html 134 | - https://nodejs.org/api/wasi.html -------------------------------------------------------------------------------- /packages/rust-wasi-node/runtime/index.mjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import fs from 'fs'; 4 | import path from 'path'; 5 | import { fileURLToPath } from 'url'; 6 | import { WASI } from 'wasi'; 7 | 8 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 9 | 10 | const wasi = new WASI({ 11 | // Same as --mapdir of wasmtime, map virtual filesystem to host filesystem 12 | preopens: { 13 | '/host': process.cwd(), 14 | }, 15 | }); 16 | 17 | // pass import Object to WASM to use host APIs 18 | const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; 19 | 20 | // Load, and compile, and instantiate WASM 21 | const wasm = await WebAssembly.compile(fs.readFileSync(path.resolve(__dirname, '../target/wasm32-wasi/debug/rust_wasi_node.wasm'))); 22 | const instance = await WebAssembly.instantiate(wasm, importObject); 23 | 24 | // WASI try to initialize WASM instanced 25 | wasi.initialize(instance); 26 | 27 | // Run WASM function 28 | instance.exports.print_hello(); -------------------------------------------------------------------------------- /packages/rust-wasi-node/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | use std::fs; 3 | 4 | #[no_mangle] 5 | pub extern "C" fn print_hello() { 6 | println!("Hello, world!"); 7 | let mut file = fs::File::create("host/helloworld.txt").unwrap(); 8 | 9 | // Write the text to the file we created 10 | write!(file, "Hello world!\n").unwrap(); 11 | } 12 | -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .cache 4 | .vscode 5 | 6 | /src/alert*.* 7 | /target 8 | **/*.rs.bk 9 | -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "alert" 3 | version = "0.1.0" 4 | dependencies = [ 5 | "wasm-bindgen 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 6 | ] 7 | 8 | [[package]] 9 | name = "dtoa" 10 | version = "0.4.3" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [[package]] 14 | name = "itoa" 15 | version = "0.4.2" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | 18 | [[package]] 19 | name = "proc-macro2" 20 | version = "0.4.6" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | dependencies = [ 23 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 24 | ] 25 | 26 | [[package]] 27 | name = "quote" 28 | version = "0.6.3" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | dependencies = [ 31 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 32 | ] 33 | 34 | [[package]] 35 | name = "serde" 36 | version = "1.0.70" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | 39 | [[package]] 40 | name = "serde_derive" 41 | version = "1.0.70" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | dependencies = [ 44 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 45 | "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 46 | "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", 47 | ] 48 | 49 | [[package]] 50 | name = "serde_json" 51 | version = "1.0.22" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | dependencies = [ 54 | "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", 57 | ] 58 | 59 | [[package]] 60 | name = "syn" 61 | version = "0.14.4" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | dependencies = [ 64 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 65 | "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 67 | ] 68 | 69 | [[package]] 70 | name = "unicode-xid" 71 | version = "0.1.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | 74 | [[package]] 75 | name = "wasm-bindgen" 76 | version = "0.2.11" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | dependencies = [ 79 | "wasm-bindgen-macro 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 80 | ] 81 | 82 | [[package]] 83 | name = "wasm-bindgen-backend" 84 | version = "0.2.11" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | dependencies = [ 87 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 88 | "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", 90 | "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", 91 | "wasm-bindgen-shared 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 92 | ] 93 | 94 | [[package]] 95 | name = "wasm-bindgen-macro" 96 | version = "0.2.11" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | dependencies = [ 99 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 100 | "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 101 | "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "wasm-bindgen-backend 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 103 | ] 104 | 105 | [[package]] 106 | name = "wasm-bindgen-shared" 107 | version = "0.2.11" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | dependencies = [ 110 | "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", 112 | ] 113 | 114 | [metadata] 115 | "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" 116 | "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" 117 | "checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" 118 | "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" 119 | "checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920" 120 | "checksum serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3525a779832b08693031b8ecfb0de81cd71cfd3812088fafe9a7496789572124" 121 | "checksum serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "84b8035cabe9b35878adec8ac5fe03d5f6bc97ff6edd7ccb96b44c1276ba390e" 122 | "checksum syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea" 123 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 124 | "checksum wasm-bindgen 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e38789b21dd56c9b172efb263d635ba5203d4f6c65a7010a26fba1aaa8c55bda" 125 | "checksum wasm-bindgen-backend 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3360d814e6dfc2d1de99d20e224310cb2a640e5749133d7e7e6be2f8d401378a" 126 | "checksum wasm-bindgen-macro 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "00cae1d10619d295b817c40cb5bb2fa7969d5abf39c74ceac4dd7e8b285376f0" 127 | "checksum wasm-bindgen-shared 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "12fc3992a9356fb2eec8133e6336996cea864ebfe21660793ecd4a9d522b2985" 128 | -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "alert" 3 | version = "0.1.0" 4 | authors = ["Jimmy Moon "] 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | path="./wasm/alert.rs" 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2.11" 12 | -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rust-wasm-bindgen", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "cargo": "cargo +nightly build --target wasm32-unknown-unknown && wasm-bindgen target/wasm32-unknown-unknown/debug/alert.wasm --out-dir ./src", 6 | "clean": "rm -rf ./dist .cache ./target", 7 | "build": "webpack ./src/index.js -o dist/index.js", 8 | "start": "webpack-dev-server" 9 | }, 10 | "devDependencies": { 11 | "webpack": "^4.16.0", 12 | "webpack-cli": "^3.0.8", 13 | "webpack-dev-server": "^3.1.4" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/readme.md: -------------------------------------------------------------------------------- 1 | # Rust with wasm-bindgen 2 | 3 | > This sample has been wrote following by [Basic Usage](https://github.com/rustwasm/wasm-bindgen/blob/master/guide/src/basic-usage.md) with wasm-bindgen. Webpack will served files because of a [lack of features in parcel](https://github.com/rustwasm/wasm-bindgen/issues/182) 4 | 5 | ## Changes 6 | 7 | - Using `import()` for asynchrounos loading 8 | - Using npm script instead of `build.sh` 9 | - Custom path with Cargo 10 | 11 | ## Uses 12 | 13 | ```sh 14 | # Install deps 15 | yarn install 16 | 17 | # Build wasm source first. Generated files will be placed at 'src' 18 | yarn cargo 19 | 20 | # Start dev server of webpack than go to the local server 21 | yarn start 22 | ``` 23 | 24 | # License 25 | 26 | MIT @ CODEBUSKING -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/src/index.js: -------------------------------------------------------------------------------- 1 | import('./alert').then(m => { 2 | m.greet("World!"); 3 | }) -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/wasm/alert.rs: -------------------------------------------------------------------------------- 1 | #![feature(proc_macro, wasm_custom_section, wasm_import_module)] 2 | 3 | extern crate wasm_bindgen; 4 | use wasm_bindgen::prelude::*; 5 | 6 | #[wasm_bindgen] 7 | extern { 8 | fn alert(s: &str); 9 | } 10 | 11 | #[wasm_bindgen] 12 | pub fn greet(name: &str) { 13 | alert(&format!("Hello, {}!", name)); 14 | } -------------------------------------------------------------------------------- /packages/rust-wasm-bindgen/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.js', 5 | output: { 6 | path: path.resolve(__dirname, 'dist'), 7 | filename: 'index.js', 8 | publicPath: 'src' 9 | }, 10 | mode: 'development' 11 | }; -------------------------------------------------------------------------------- /packages/rust-wasm-pack/.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | target -------------------------------------------------------------------------------- /packages/rust-wasm-pack/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "bumpalo" 5 | version = "2.6.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "cfg-if" 10 | version = "0.1.10" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | 13 | [[package]] 14 | name = "lazy_static" 15 | version = "1.4.0" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | 18 | [[package]] 19 | name = "log" 20 | version = "0.4.8" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | dependencies = [ 23 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 24 | ] 25 | 26 | [[package]] 27 | name = "proc-macro2" 28 | version = "1.0.6" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | dependencies = [ 31 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 32 | ] 33 | 34 | [[package]] 35 | name = "quote" 36 | version = "1.0.2" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | dependencies = [ 39 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 40 | ] 41 | 42 | [[package]] 43 | name = "square" 44 | version = "0.1.0" 45 | dependencies = [ 46 | "wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 47 | ] 48 | 49 | [[package]] 50 | name = "syn" 51 | version = "1.0.8" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | dependencies = [ 54 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 57 | ] 58 | 59 | [[package]] 60 | name = "unicode-xid" 61 | version = "0.2.0" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | 64 | [[package]] 65 | name = "wasm-bindgen" 66 | version = "0.2.54" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | dependencies = [ 69 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 70 | "wasm-bindgen-macro 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 71 | ] 72 | 73 | [[package]] 74 | name = "wasm-bindgen-backend" 75 | version = "0.2.54" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | dependencies = [ 78 | "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 79 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 80 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 81 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 82 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 83 | "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 84 | "wasm-bindgen-shared 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 85 | ] 86 | 87 | [[package]] 88 | name = "wasm-bindgen-macro" 89 | version = "0.2.54" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | dependencies = [ 92 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "wasm-bindgen-macro-support 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 94 | ] 95 | 96 | [[package]] 97 | name = "wasm-bindgen-macro-support" 98 | version = "0.2.54" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | dependencies = [ 101 | "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "wasm-bindgen-backend 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "wasm-bindgen-shared 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", 106 | ] 107 | 108 | [[package]] 109 | name = "wasm-bindgen-shared" 110 | version = "0.2.54" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | 113 | [metadata] 114 | "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" 115 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 116 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 117 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 118 | "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" 119 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 120 | "checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" 121 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 122 | "checksum wasm-bindgen 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c4568ae1b4e07ca907b1a4de41174eaa3e5be4066c024475586b7842725f69a9" 123 | "checksum wasm-bindgen-backend 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5a00cfdce37367770062065fd3abb9278cbae86a0d918cacd0978a7acd51b481" 124 | "checksum wasm-bindgen-macro 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7c568f4d3cf6d7c1d72b165daf778fb0d6e09a24f96ac14fc8c4f66a96e86b72" 125 | "checksum wasm-bindgen-macro-support 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "430d12539ae324d16097b399e9d07a6d5ce0173b2a61a2d02346ca7c198daffe" 126 | "checksum wasm-bindgen-shared 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "8ae7167f0bbffd7fac2b12da0fa1f834c1d84671a1ae3c93ac8bde2e97179c39" 127 | -------------------------------------------------------------------------------- /packages/rust-wasm-pack/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "square" 3 | version = "0.1.0" 4 | authors = ["Jimmy Moon "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [lib] 10 | crate-type = ["cdylib"] 11 | 12 | [dependencies] 13 | wasm-bindgen = "0.2" 14 | -------------------------------------------------------------------------------- /packages/rust-wasm-pack/build.sh: -------------------------------------------------------------------------------- 1 | mkdir -p pkg 2 | rustc --target wasm32-unknown-unknown -O ./src/lib.rs -o ./pkg/square.wasm 3 | -------------------------------------------------------------------------------- /packages/rust-wasm-pack/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/rust-wasm-pack/readme.md: -------------------------------------------------------------------------------- 1 | # rust-wasm-pack example 2 | 3 | > Build wasm by [wasm-pack](https://github.com/rustwasm/wasm-pack) 4 | 5 | # How to run 6 | 7 | ```sh 8 | # build 9 | wasm-pack build 10 | 11 | # run webserver by command-based 12 | serve . 13 | ``` 14 | 15 | # License 16 | 17 | MIT @ Jimmy Moon -------------------------------------------------------------------------------- /packages/rust-wasm-pack/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub fn main() {} 2 | 3 | #[no_mangle] 4 | pub extern fn square (x: u32) -> u32 { 5 | x * x 6 | } -------------------------------------------------------------------------------- /packages/rust-webgl/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-object-rest-spread", 4 | ["transform-runtime", { 5 | "polyfill": false, 6 | "regenerator": true 7 | }] 8 | ] 9 | } -------------------------------------------------------------------------------- /packages/rust-webgl/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .cache 4 | .vscode 5 | 6 | /target 7 | **/*.rs.bk 8 | 9 | /target 10 | **/*.rs.bk 11 | 12 | /target 13 | **/*.rs.bk 14 | 15 | /target 16 | **/*.rs.bk 17 | 18 | /target 19 | **/*.rs.bk 20 | -------------------------------------------------------------------------------- /packages/rust-webgl/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "bitflags" 3 | version = "1.0.3" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | 6 | [[package]] 7 | name = "cfg-if" 8 | version = "0.1.4" 9 | source = "registry+https://github.com/rust-lang/crates.io-index" 10 | 11 | [[package]] 12 | name = "gl_generator" 13 | version = "0.9.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 19 | ] 20 | 21 | [[package]] 22 | name = "gleam" 23 | version = "0.5.1" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | dependencies = [ 26 | "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "khronos_api" 31 | version = "2.2.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "log" 36 | version = "0.4.3" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | dependencies = [ 39 | "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 40 | ] 41 | 42 | [[package]] 43 | name = "triangle" 44 | version = "0.1.0" 45 | dependencies = [ 46 | "gleam 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 47 | ] 48 | 49 | [[package]] 50 | name = "xml-rs" 51 | version = "0.7.0" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | dependencies = [ 54 | "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 55 | ] 56 | 57 | [metadata] 58 | "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" 59 | "checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e" 60 | "checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" 61 | "checksum gleam 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12b793fcf40a23dd372f184c228ab3eb96f88c50bb4fba8319c483aa025a4e45" 62 | "checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" 63 | "checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2" 64 | "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" 65 | -------------------------------------------------------------------------------- /packages/rust-webgl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "triangle" 3 | version = "0.1.0" 4 | authors = ["Jimmy Moon "] 5 | 6 | [dependencies] 7 | gleam = "0.5.1" -------------------------------------------------------------------------------- /packages/rust-webgl/README.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ```sh 4 | # install deps (rust/cargo must be installed before build) 5 | yarn install 6 | 7 | # build rs to wasm with rust 8 | yarn build 9 | 10 | # serve and go to the server, http://localhost:8080 11 | yarn start 12 | ``` 13 | 14 | # References 15 | 16 | - [WebGL context](https://goo.gl/NgRnm6) 17 | - [gleam - Rust](https://goo.gl/UXRADj) 18 | - [likr/rust-webgl2-example](https://goo.gl/YBj58c) 19 | -------------------------------------------------------------------------------- /packages/rust-webgl/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TRIAGNLES - WEBGL 7 | 8 | 9 | 10 | 11 | 20 | 21 | -------------------------------------------------------------------------------- /packages/rust-webgl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rust-webgl", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "author": "Jimmy Moon ", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "parcel index.html --open -p 8080", 9 | "build": "parcel build index.html --out-dir ./dist && npm run cargo", 10 | "cargo": "cargo build --release --target=wasm32-unknown-emscripten && cp target/wasm32-unknown-emscripten/release/*.js ./dist && cp target/wasm32-unknown-emscripten/release/*.wasm ./dist" 11 | }, 12 | "devDependencies": { 13 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 14 | "babel-plugin-transform-runtime": "^6.23.0", 15 | "parcel-bundler": "^1.9.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/rust-webgl/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::rc::Rc; 2 | 3 | extern crate gleam; 4 | use gleam::gl; 5 | use gleam::gl::{GLenum}; 6 | 7 | mod webgl; 8 | use webgl::{ 9 | emscripten_GetProcAddress, emscripten_get_element_css_size, 10 | emscripten_webgl_create_context, emscripten_webgl_init_context_attributes, 11 | emscripten_webgl_make_context_current, EmscriptenWebGLContextAttributes, 12 | }; 13 | 14 | const VERTICES: [f32; 6] = [ 15 | 0.0, 0.5, 16 | 0.5, -0.5, 17 | -0.5, -0.5, 18 | ]; 19 | 20 | const INDICES: [u16; 3] = [0, 1, 2]; 21 | 22 | const VERT_CODE: &[&[u8]] = &[b" 23 | attribute vec3 coordinates; 24 | void main(void) { 25 | gl_Position = vec4(coordinates, 1.0); 26 | }" 27 | ]; 28 | 29 | const FRAG_CODE: &[&[u8]] = &[b" 30 | void main(void) { 31 | gl_FragColor = vec4(1.0, 1.0, 1.0, 1); 32 | }" 33 | ]; 34 | 35 | fn get_canvas_size() -> (u32, u32) { 36 | unsafe { 37 | let mut width = std::mem::uninitialized(); 38 | let mut height = std::mem::uninitialized(); 39 | emscripten_get_element_css_size(std::ptr::null(), &mut width, &mut height); 40 | (width as u32, height as u32) 41 | } 42 | } 43 | 44 | fn init_webgl() -> Rc { 45 | unsafe { 46 | let mut attributes: EmscriptenWebGLContextAttributes = std::mem::uninitialized(); 47 | emscripten_webgl_init_context_attributes(&mut attributes); 48 | attributes.majorVersion = 2; 49 | 50 | let handle = emscripten_webgl_create_context(std::ptr::null(), &attributes); 51 | emscripten_webgl_make_context_current(handle); 52 | 53 | return gl::GlesFns::load_with(|addr| { 54 | let addr = std::ffi::CString::new(addr).unwrap(); 55 | emscripten_GetProcAddress(addr.into_raw() as *const _) as *const _ 56 | }); 57 | } 58 | } 59 | 60 | fn create_buffer(gl: &Rc, vertices: Vec, indices: Vec) { 61 | let buffers = gl.gen_buffers(2); 62 | let vertex_buffer = buffers[0]; 63 | 64 | gl.bind_buffer(gl::ARRAY_BUFFER, vertex_buffer); 65 | gl.buffer_data_untyped( 66 | gl::ARRAY_BUFFER, 67 | 4 * vertices.len() as isize, 68 | vertices.as_ptr() as *const _, 69 | gl::STATIC_DRAW, 70 | ); 71 | 72 | let element_buffer = buffers[1]; 73 | gl.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, element_buffer); 74 | gl.buffer_data_untyped( 75 | gl::ELEMENT_ARRAY_BUFFER, 76 | 2 * indices.len() as isize, 77 | indices.as_ptr() as *const _, 78 | gl::STATIC_DRAW, 79 | ); 80 | } 81 | 82 | fn create_shader(gl: &Rc, shader_type: GLenum, code: &[&[u8]]) -> u32 { 83 | let shader = gl.create_shader(shader_type); 84 | gl.shader_source(shader, code); 85 | gl.compile_shader(shader); 86 | 87 | let mut compiled = [0]; 88 | unsafe { 89 | gl.get_shader_iv(shader, gl::COMPILE_STATUS, &mut compiled); 90 | } 91 | 92 | if compiled[0] == 0 { 93 | gl.delete_shader(shader); 94 | } 95 | 96 | return shader; 97 | } 98 | 99 | fn create_shaders(gl: &Rc, vert_code: &[&[u8]], frag_code: &[&[u8]]) { 100 | let vert_shader = create_shader(gl, gl::VERTEX_SHADER, vert_code); 101 | let frag_shader = create_shader(gl, gl::FRAGMENT_SHADER, frag_code); 102 | let program = gl.create_program(); 103 | 104 | gl.attach_shader(program, vert_shader); 105 | gl.attach_shader(program, frag_shader); 106 | gl.link_program(program); 107 | gl.use_program(program); 108 | 109 | let coordinate_var = gl.get_attrib_location(program, "coordinates") as u32; 110 | gl.enable_vertex_attrib_array(coordinate_var); 111 | gl.vertex_attrib_pointer(coordinate_var, 2, gl::FLOAT, false, 0, 0); 112 | } 113 | 114 | fn draw(gl: &Rc) { 115 | let (width, height) = get_canvas_size(); 116 | gl.viewport(0, 0, width as i32, height as i32); 117 | gl.clear_color(0.0, 0.0, 0.0, 1.0); 118 | gl.clear(gl::COLOR_BUFFER_BIT); 119 | gl.draw_elements(gl::TRIANGLES, 3, gl::UNSIGNED_SHORT, 0); 120 | } 121 | 122 | pub fn main() { 123 | let gl = init_webgl(); 124 | create_buffer(&gl, VERTICES.to_vec(), INDICES.to_vec()); 125 | create_shaders(&gl, VERT_CODE, FRAG_CODE); 126 | draw(&gl); 127 | } 128 | -------------------------------------------------------------------------------- /packages/rust-webgl/src/webgl.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(non_snake_case)] 3 | 4 | pub type EMSCRIPTEN_WEBGL_CONTEXT_HANDLE = ::std::os::raw::c_int; 5 | 6 | #[repr(C)] 7 | #[derive(Debug, Copy)] 8 | pub struct EmscriptenWebGLContextAttributes { 9 | pub alpha: ::std::os::raw::c_int, 10 | pub depth: ::std::os::raw::c_int, 11 | pub stencil: ::std::os::raw::c_int, 12 | pub antialias: ::std::os::raw::c_int, 13 | pub premultipliedAlpha: ::std::os::raw::c_int, 14 | pub preserveDrawingBuffer: ::std::os::raw::c_int, 15 | pub preferLowPowerToHighPerformance: ::std::os::raw::c_int, 16 | pub failIfMajorPerformanceCaveat: ::std::os::raw::c_int, 17 | pub majorVersion: ::std::os::raw::c_int, 18 | pub minorVersion: ::std::os::raw::c_int, 19 | pub enableExtensionsByDefault: ::std::os::raw::c_int, 20 | pub explicitSwapControl: ::std::os::raw::c_int, 21 | } 22 | 23 | impl Clone for EmscriptenWebGLContextAttributes { 24 | fn clone(&self) -> Self { 25 | *self 26 | } 27 | } 28 | 29 | extern "C" { 30 | pub fn emscripten_GetProcAddress( 31 | name: *const ::std::os::raw::c_char, 32 | ) -> *const ::std::os::raw::c_void; 33 | 34 | pub fn emscripten_webgl_init_context_attributes( 35 | attributes: *mut EmscriptenWebGLContextAttributes, 36 | ); 37 | 38 | pub fn emscripten_webgl_create_context( 39 | target: *const ::std::os::raw::c_char, 40 | attributes: *const EmscriptenWebGLContextAttributes, 41 | ) -> EMSCRIPTEN_WEBGL_CONTEXT_HANDLE; 42 | 43 | pub fn emscripten_webgl_make_context_current( 44 | context: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE, 45 | ) -> ::std::os::raw::c_int; 46 | 47 | pub fn emscripten_get_element_css_size( 48 | target: *const ::std::os::raw::c_char, 49 | width: *mut f64, 50 | height: *mut f64, 51 | ) -> ::std::os::raw::c_int; 52 | } 53 | -------------------------------------------------------------------------------- /packages/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /packages/rust/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clang", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "start": "../node_modules/.bin/serve .", 6 | "build:wasm": "rustc --target wasm32-unknown-unknown -O ./wasm/math.rs -o ./wasm/math.wasm", 7 | "build": "npm run build:wasm" 8 | } 9 | } -------------------------------------------------------------------------------- /packages/rust/readme.md: -------------------------------------------------------------------------------- 1 | # add target 2 | 3 | ``` 4 | rustup update 5 | rustup target add wasm32-unknown-unknown 6 | ``` 7 | 8 | # License 9 | 10 | MIT @ CODEBUSKING -------------------------------------------------------------------------------- /packages/rust/wasm-loader.js: -------------------------------------------------------------------------------- 1 | function setEnvironment({env = {}}) { 2 | if (!env.memory) { 3 | env.memory = new WebAssembly.Memory({ 4 | initial: 256, 5 | maximum: 256 6 | }) 7 | } 8 | 9 | if (!env.table) { 10 | env.table = new WebAssembly.Table({ 11 | initial: 0, 12 | maximum: 0, 13 | element: 'anyfunc' 14 | }) 15 | } 16 | 17 | return { 18 | ...{ 19 | tableBase: 0, 20 | memoryBase: 0, 21 | STACKTOP: 0, 22 | STACK_MAX: env.memory.buffer.byteLength, 23 | abortStackOverflow() {}, 24 | abort() {} 25 | }, 26 | ...env 27 | } 28 | } 29 | 30 | async function wasmInstantiate(req, importObject = {}) { 31 | const bytes = await window.fetch(req).then(x => x.arrayBuffer()) 32 | 33 | importObject = { 34 | global: {}, 35 | ...importObject, 36 | env: setEnvironment(importObject) 37 | } 38 | 39 | return { 40 | ...await WebAssembly.instantiate(bytes, importObject), 41 | ...importObject 42 | } 43 | } -------------------------------------------------------------------------------- /packages/rust/wasm/math.rs: -------------------------------------------------------------------------------- 1 | pub fn main() {} 2 | 3 | #[no_mangle] 4 | pub extern fn square (x: u32) -> u32 { 5 | x * x 6 | } -------------------------------------------------------------------------------- /packages/rust/wasm/math.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ragingwind/wasm-helloworld/3b49e9f944cfb94191dd6312517b96c444544080/packages/rust/wasm/math.wasm -------------------------------------------------------------------------------- /packages/ts-assembly-script/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /packages/ts-assembly-script/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clang", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "start": "../node_modules/.bin/serve .", 6 | "build:wasm": " asc ./wasm/fibonacci.ts -o ./wasm/fibonacci.wasm --optimize --validate --sourceMap", 7 | "build": "npm run build:wasm" 8 | }, 9 | "devDependencies": { 10 | "assemblyscript": "AssemblyScript/assemblyscript" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/ts-assembly-script/readme.md: -------------------------------------------------------------------------------- 1 | # Hello World for WASM with AssemblyScript 2 | 3 | - [More types](https://github.com/AssemblyScript/assemblyscript/wiki/Types) -------------------------------------------------------------------------------- /packages/ts-assembly-script/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../node_modules/assemblyscript/std/assembly.json", 3 | "include": [ 4 | "./**/*.ts" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/ts-assembly-script/wasm-loader.js: -------------------------------------------------------------------------------- 1 | function setEnvironment({env = {}}) { 2 | if (!env.memory) { 3 | env.memory = new WebAssembly.Memory({ 4 | initial: 256, 5 | maximum: 256 6 | }) 7 | } 8 | 9 | if (!env.table) { 10 | env.table = new WebAssembly.Table({ 11 | initial: 0, 12 | maximum: 0, 13 | element: 'anyfunc' 14 | }) 15 | } 16 | 17 | return { 18 | ...{ 19 | tableBase: 0, 20 | memoryBase: 0, 21 | STACKTOP: 0, 22 | STACK_MAX: env.memory.buffer.byteLength, 23 | abortStackOverflow() {}, 24 | abort() {} 25 | }, 26 | ...env 27 | } 28 | } 29 | 30 | async function wasmInstantiate(req, importObject = {}) { 31 | const bytes = await window.fetch(req).then(x => x.arrayBuffer()) 32 | 33 | importObject = { 34 | global: {}, 35 | ...importObject, 36 | env: setEnvironment(importObject) 37 | } 38 | 39 | return { 40 | ...await WebAssembly.instantiate(bytes, importObject), 41 | ...importObject 42 | } 43 | } -------------------------------------------------------------------------------- /packages/ts-assembly-script/wasm/fibonacci.ts: -------------------------------------------------------------------------------- 1 | export function fibonacci (n: i32): i32 { 2 | n = n | 0; 3 | if (n < 2) { 4 | return 1 5 | } 6 | return (fibonacci(n - 2) | 0) + (fibonacci(n - 1) | 0) | 0 7 | } -------------------------------------------------------------------------------- /packages/ts-assembly-script/wasm/fibonacci.wasm: -------------------------------------------------------------------------------- 1 | asm` fibonaccimemory 2 |  AH@A Ak Akj "namewasm/fibonacci/fibonacci$sourceMappingURLfibonacci.wasm.map -------------------------------------------------------------------------------- /packages/ts-assembly-script/wasm/fibonacci.wasm.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["wasm/fibonacci.ts"],"names":[],"mappings":"8DAEE,AAAI,AADA,EACI,SAGD,AAAC,AAAU,EAAI,KAAW,AAAU,EAAI","sourceRoot":"assemblyscript:///","sourceContents":["export function fibonacci (n: i32): i32 {\n n = n | 0;\n if (n < 2) {\n return 1\n }\n return (fibonacci(n - 2) | 0) + (fibonacci(n - 1) | 0) | 0\n}"]} -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Hello World for WebAssembly 2 | 3 | > The first step for beginners about WASM, WebAssembly 4 | 5 | # Prerequisites 6 | 7 | WebAssembly is required bunch of preperations for compiling native soruce codes. While you use emscripten directly install on your system, Surmma at Google Chrome Team suggests [the alternative way](https://developers.google.com/web/updates/2018/03/emscripting-a-c-library) with docker. 8 | 9 | ## Build Environment with Docker 10 | 11 | ## Build Environment with Emscripten Toolchain 12 | 13 | - Setup git, CMake, gcc and python on your system 14 | - Install [Emscripten toolchain](http://webassembly.org/getting-started/developers-guide/) and [The WebAssembly Binary Toolkit](https://github.com/WebAssembly/wabt) 15 | - Install compilers for Go, Rust and C/C++ 16 | 17 | # Installation Dependencies 18 | 19 | Each demo has own npm dependencies or own environment to build and start application. In case of Node.js environment, for getting convenience of installation, you should install dependencies with `yarn install --modules-folder=../node_modules` 20 | 21 | # Demos 22 | 23 | ## C/C++ Languages 24 | - clang: Emscripten and WASM APIs, Basic sample, show two of types compiling, static and dynamic 25 | - clang-thread: Show how to use c with thread. Implementation of official sample from Google\ 26 | - clang-array: Show how to manage numberic array 27 | - clang-simd: Show how WASM is working with SIMD 28 | 29 | ## Rust Languages 30 | - rust: Rust Language with Emscripten and WASM APIs 31 | - rust-parcel: Rust Language with parcel bundler 32 | - rust-thread 33 | - rust-wasm-bindgen: Rust Language with wasm-bindgen 34 | - rust-wasm-pack 35 | - rust-webgl 36 | - rust-wasi-node: WASI demo with Rust and Node.js 37 | 38 | ## Typescript 39 | - ts-assembly-script: Typescript(AssemblyScript) with WASM APIs 40 | 41 | ## Golang 42 | - go: Go with WASM 43 | 44 | ## asm.js 45 | - asm-webpack: asm.js with WABT and webpack 4 46 | 47 | # License 48 | 49 | MIT @ Jimmy Moon 50 | --------------------------------------------------------------------------------