├── .gitignore ├── .travis.yml ├── AUDIENCE.md ├── README.md ├── assets ├── Web_Assembly_Logo.svg ├── favicon.ico ├── icon-apple.png ├── icon.png └── readmeBanner.png ├── build-system ├── build.js └── homepage.js ├── demo-util ├── domConsole.js └── instantiateWasm.js ├── devops └── build.sh ├── examples ├── classes │ ├── classes.assemblyscript.en-us.md │ └── demo │ │ └── assemblyscript │ │ ├── ASBindTest.ts │ │ ├── ASBindTest.wasm │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json ├── exports │ ├── demo │ │ ├── assemblyscript │ │ │ ├── README.md │ │ │ ├── exports.js │ │ │ ├── exports.ts │ │ │ ├── exports.wasm │ │ │ ├── exports.wat │ │ │ └── index.html │ │ ├── go │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── main.go │ │ │ ├── main.wasm │ │ │ └── wasm_exec.js │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── exports.d.ts │ │ │ ├── exports.js │ │ │ ├── exports_bg.d.ts │ │ │ ├── exports_bg.wasm │ │ │ └── package.json │ │ │ └── src │ │ │ └── lib.rs │ ├── exports.assemblyscript.en-us.md │ ├── exports.go.en-us.md │ ├── exports.rust.en-us.md │ └── exports.rust.pt-br.md ├── hello-world │ ├── demo │ │ ├── assemblyscript │ │ │ ├── README.md │ │ │ ├── hello-world.js │ │ │ ├── hello-world.ts │ │ │ ├── hello-world.wasm │ │ │ ├── hello-world.wat │ │ │ └── index.html │ │ ├── go │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── main.go │ │ │ ├── main.wasm │ │ │ └── wasm_exec.js │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── hello_world.d.ts │ │ │ ├── hello_world.js │ │ │ ├── hello_world_bg.d.ts │ │ │ ├── hello_world_bg.wasm │ │ │ └── package.json │ │ │ └── src │ │ │ └── lib.rs │ ├── hello-world.assemblyscript.en-us.md │ ├── hello-world.c.en-us.md │ ├── hello-world.go.en-us.md │ ├── hello-world.rust.en-us.md │ └── hello-world.rust.pt-br.md ├── importing-javascript-functions-into-webassembly │ ├── demo │ │ ├── assemblyscript │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── index.ts │ │ │ ├── index.wasm │ │ │ └── index.wat │ │ ├── go │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── main.go │ │ │ ├── main.wasm │ │ │ └── wasm_exec.js │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── importing_javascript_functions_into_webassembly.d.ts │ │ │ ├── importing_javascript_functions_into_webassembly.js │ │ │ ├── importing_javascript_functions_into_webassembly_bg.d.ts │ │ │ ├── importing_javascript_functions_into_webassembly_bg.wasm │ │ │ └── package.json │ │ │ └── src │ │ │ └── lib.rs │ ├── importing-javascript-functions-into-webassembly.assemblyscript.en-us.md │ ├── importing-javascript-functions-into-webassembly.go.en-us.md │ ├── importing-javascript-functions-into-webassembly.rust.en-us.md │ └── importing-javascript-functions-into-webassembly.rust.pt-br.md ├── introduction │ ├── introduction.all.en-us.md │ └── introduction.all.pt-br.md ├── passing-high-level-data-types-with-as-bind │ ├── demo │ │ └── assemblyscript │ │ │ ├── addWasmByExample.wasm │ │ │ ├── assembly │ │ │ ├── index.ts │ │ │ └── tsconfig.json │ │ │ ├── build │ │ │ └── .gitignore │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── package-lock.json │ │ │ ├── package.json │ │ │ └── tests │ │ │ └── index.js │ └── passing-high-level-data-types-with-as-bind.assemblyscript.en-us.md ├── passing-high-level-data-types-with-wasm-bindgen │ ├── demo │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── strings.d.ts │ │ │ ├── strings.js │ │ │ ├── strings_bg.d.ts │ │ │ └── strings_bg.wasm │ │ │ └── src │ │ │ └── lib.rs │ ├── passing-high-level-data-types-with-wasm-bindgen.rust.en-us.md │ └── passing-high-level-data-types-with-wasm-bindgen.rust.pt-br.md ├── reading-and-writing-audio │ ├── demo │ │ ├── assemblyscript │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── index.ts │ │ │ ├── index.wasm │ │ │ └── index.wat │ │ ├── go │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── main.go │ │ │ ├── main.wasm │ │ │ └── wasm_exec.js │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── audio.d.ts │ │ │ ├── audio.js │ │ │ ├── audio_bg.d.ts │ │ │ ├── audio_bg.wasm │ │ │ ├── graphics.d.ts │ │ │ ├── graphics.js │ │ │ ├── graphics_bg.d.ts │ │ │ ├── graphics_bg.wasm │ │ │ └── package.json │ │ │ └── src │ │ │ └── lib.rs │ ├── reading-and-writing-audio.assemblyscript.en-us.md │ ├── reading-and-writing-audio.go.en-us.md │ ├── reading-and-writing-audio.rust.en-us.md │ └── reading-and-writing-audio.rust.pt-br.md ├── reading-and-writing-graphics │ ├── demo │ │ ├── assemblyscript │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── index.ts │ │ │ ├── index.wasm │ │ │ └── index.wat │ │ ├── go │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── main.go │ │ │ ├── main.wasm │ │ │ └── wasm_exec.js │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── index.js │ │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── graphics.d.ts │ │ │ ├── graphics.js │ │ │ ├── graphics_bg.d.ts │ │ │ ├── graphics_bg.wasm │ │ │ └── package.json │ │ │ └── src │ │ │ └── lib.rs │ ├── reading-and-writing-graphics.assemblyscript.en-us.md │ ├── reading-and-writing-graphics.go.en-us.md │ ├── reading-and-writing-graphics.rust.en-us.md │ └── reading-and-writing-graphics.rust.pt-br.md ├── strings │ ├── demo │ │ └── c │ │ │ ├── caesar.cpp │ │ │ ├── caesar.wasm │ │ │ └── index.html │ └── strings.c.en-us.md ├── wasi-hello-world │ ├── demo │ │ ├── assemblyscript │ │ │ ├── assembly │ │ │ │ └── index.ts │ │ │ ├── build │ │ │ │ ├── index.wasm │ │ │ │ └── index.wat │ │ │ ├── helloworld.txt │ │ │ ├── package-lock.json │ │ │ └── package.json │ │ ├── go │ │ │ ├── helloworld.txt │ │ │ ├── main.go │ │ │ ├── main.wasm │ │ │ └── run.sh │ │ └── rust │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── helloworld.txt │ │ │ └── src │ │ │ └── main.rs │ ├── wasi-hello-world.assemblyscript.en-us.md │ ├── wasi-hello-world.go.en-us.md │ ├── wasi-hello-world.rust.en-us.md │ └── wasi-hello-world.rust.pt-br.md ├── wasi-introduction │ ├── wasi-introduction.all.en-us.md │ └── wasi-introduction.all.pt-br.md └── webassembly-linear-memory │ ├── demo │ ├── assemblyscript │ │ ├── README.md │ │ ├── index.html │ │ ├── index.js │ │ ├── index.ts │ │ ├── index.wasm │ │ └── index.wat │ ├── go │ │ ├── README.md │ │ ├── index.html │ │ ├── index.js │ │ ├── main.go │ │ ├── main.wasm │ │ └── wasm_exec.js │ └── rust │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── index.html │ │ ├── index.js │ │ ├── pkg │ │ ├── README.md │ │ ├── package.json │ │ ├── webassembly_linear_memory.d.ts │ │ ├── webassembly_linear_memory.js │ │ ├── webassembly_linear_memory_bg.d.ts │ │ └── webassembly_linear_memory_bg.wasm │ │ └── src │ │ └── lib.rs │ ├── webassembly-linear-memory.assemblyscript.en-us.md │ ├── webassembly-linear-memory.go.en-us.md │ ├── webassembly-linear-memory.rust.en-us.md │ └── webassembly-linear-memory.rust.pt-br.md ├── package-lock.json ├── package.json └── shell ├── about.html ├── additional-resources.html ├── all-examples-list.html ├── demo-redirect.html ├── example-redirect.html ├── example.html ├── home.html ├── index.html ├── js ├── demoRedirect.js ├── examplesList.js ├── examplesRedirect.js ├── index.js ├── indexRedirect.js └── sourceRedirect.js ├── manifest.json ├── partials ├── announcements.html ├── footer.html ├── head.html └── header.html ├── source-redirect.html └── styles ├── examples-list.css └── index.css /.gitignore: -------------------------------------------------------------------------------- 1 | # Build output 2 | dist/ 3 | 4 | # Rust 5 | **/rust/target/**/* 6 | **/rust/pkg/.gitignore 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # TypeScript v1 declaration files 47 | typings/ 48 | 49 | # Optional npm cache directory 50 | .npm 51 | 52 | # Optional eslint cache 53 | .eslintcache 54 | 55 | # Optional REPL history 56 | .node_repl_history 57 | 58 | # Output of 'npm pack' 59 | *.tgz 60 | 61 | # Yarn Integrity file 62 | .yarn-integrity 63 | 64 | # dotenv environment variables file 65 | .env 66 | 67 | # next.js build output 68 | .next 69 | 70 | # macOS cruft 71 | .DS_Store 72 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | email: false 3 | language: node_js 4 | sudo: false 5 | node_js: 6 | - "node" 7 | install: 8 | - npm install 9 | script: 10 | - npm run lint:ci 11 | - npm run build 12 | -------------------------------------------------------------------------------- /assets/Web_Assembly_Logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/assets/favicon.ico -------------------------------------------------------------------------------- /assets/icon-apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/assets/icon-apple.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/assets/icon.png -------------------------------------------------------------------------------- /assets/readmeBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/assets/readmeBanner.png -------------------------------------------------------------------------------- /build-system/homepage.js: -------------------------------------------------------------------------------- 1 | // Supported homepage reading languages 2 | const readingLanguages = ["en-us", "pt-br"]; 3 | 4 | // Our introduction text 5 | const introductionHtml = { 6 | "en-us": ` 7 |

8 | WebAssembly (Wasm) is an universal low level bytecode that runs on the 9 | web. It is a compilation target for languages like 10 | Rust, AssemblyScript (Typescript-like), Emscripten (C/C++), and much 12 | more! 14 | Wasm offer a compact binary format with predictable performance, and 15 | portability to run alongside Javascript and other host languages. Wasm is 16 | currently shipped in all major browsers, and has runtimes meant for 17 | running on servers or interfacing with systems using WASI. 18 |

19 | 20 |
21 |

What is Wasm By Example?

22 |

23 | Wasm By Example is a concise, hands-on introduction to WebAssembly using 24 | code snippets and annotated WebAssembly example programs. Learn more 25 | about Wasm at the 26 | WebAssembly Introduction 30 | 31 | or browse the list of examples below. 32 |

33 |
34 | ` 35 | }; 36 | 37 | const examplesTitle = { 38 | "en-us": "Examples" 39 | }; 40 | 41 | // Our overall example order 42 | const exampleOrder = [ 43 | "introduction", 44 | "hello-world", 45 | "exports", 46 | "webassembly-linear-memory", 47 | "importing-javascript-functions-into-webassembly", 48 | "reading-and-writing-graphics", 49 | "reading-and-writing-audio", 50 | "passing-high-level-data-types-with-wasm-bindgen", 51 | "passing-high-level-data-types-with-as-bind", 52 | "strings", 53 | "classes", 54 | "wasi-introduction", 55 | "wasi-hello-world" 56 | ]; 57 | 58 | // Catgeories 59 | const concepts = { 60 | title: { 61 | "en-us": "Concepts" 62 | }, 63 | description: { 64 | "en-us": 65 | "Examples that express some of the major underlying concepts in WebAssembly. Some of these examples are not the most convenient or productive way for building projects with WebAssembly. However, these minimal examples are great for learning, or developing straightforward / lower-level parts of an application." 66 | }, 67 | examples: [ 68 | "introduction", 69 | "hello-world", 70 | "exports", 71 | "webassembly-linear-memory", 72 | "importing-javascript-functions-into-webassembly" 73 | ] 74 | }; 75 | 76 | const applyingTheConcepts = { 77 | title: { 78 | "en-us": "Applying the Concepts" 79 | }, 80 | description: { 81 | "en-us": 82 | "Examples that expand on the conceptual examples to show how these minimal examples could be used to build common features in larger applications." 83 | }, 84 | examples: ["reading-and-writing-graphics", "reading-and-writing-audio"] 85 | }; 86 | 87 | const ecosystemAndLanguage = { 88 | title: { 89 | "en-us": "Ecosystem tools and Language features" 90 | }, 91 | description: { 92 | "en-us": 93 | "Examples that highlight tools, libraries, and features of your selected programming language. These ecosystem components can drastically help in building powerful applications. For example, tools can be used to help pass data between your host runtime and WebAssembly module, and/or languages features can abstract away some of the lower-level parts of WebAssembly such as memory management." 94 | }, 95 | examples: [ 96 | "passing-high-level-data-types-with-wasm-bindgen", 97 | "passing-high-level-data-types-with-as-bind", 98 | "strings", 99 | "classes" 100 | ] 101 | }; 102 | 103 | const webassemblyOutsideTheBrowser = { 104 | title: { 105 | "en-us": "WebAssembly Outside of the Browser" 106 | }, 107 | description: { 108 | "en-us": 109 | "Examples that highlight the WebAssembly System Interface (WASI), standalone WebAssembly runtimes, tools for applications that use WASI, and use cases for tasks like cloud computing and internet-of-things devices. WebAssembly has a lot of key features that make it great for the browser web, and these same features make it a popular choice for uses outside of the browser as well." 110 | }, 111 | examples: ["wasi-introduction", "wasi-hello-world"] 112 | }; 113 | 114 | module.exports = { 115 | readingLanguages, 116 | introductionHtml, 117 | examplesTitle, 118 | exampleOrder, 119 | categories: [ 120 | concepts, 121 | applyingTheConcepts, 122 | ecosystemAndLanguage, 123 | webassemblyOutsideTheBrowser 124 | ] 125 | }; 126 | -------------------------------------------------------------------------------- /demo-util/domConsole.js: -------------------------------------------------------------------------------- 1 | // Set up a console element in the dom 2 | const consoleElement = document.createElement("pre"); 3 | consoleElement.style = `border: 1px solid black`; 4 | consoleElement.textContent = ` 5 | DOM Console: 6 | `; 7 | document.body.appendChild(consoleElement); 8 | 9 | export function domConsoleLog(string) { 10 | console.log(string); 11 | 12 | if (string === undefined) { 13 | string = "undefined"; 14 | } 15 | 16 | consoleElement.textContent = `${consoleElement.textContent} 17 | ${string} 18 | `; 19 | } 20 | -------------------------------------------------------------------------------- /demo-util/instantiateWasm.js: -------------------------------------------------------------------------------- 1 | export const wasmBrowserInstantiate = async (wasmModuleUrl, importObject) => { 2 | let response = undefined; 3 | 4 | if (!importObject) { 5 | importObject = { 6 | env: { 7 | abort: () => console.log("Abort!") 8 | } 9 | }; 10 | } 11 | 12 | if (WebAssembly.instantiateStreaming) { 13 | response = await WebAssembly.instantiateStreaming( 14 | fetch(wasmModuleUrl), 15 | importObject 16 | ); 17 | } else { 18 | const fetchAndInstantiateTask = async () => { 19 | const wasmArrayBuffer = await fetch(wasmModuleUrl).then(response => 20 | response.arrayBuffer() 21 | ); 22 | return WebAssembly.instantiate(wasmArrayBuffer, importObject); 23 | }; 24 | response = await fetchAndInstantiateTask(); 25 | } 26 | 27 | return response; 28 | }; 29 | -------------------------------------------------------------------------------- /devops/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script to do frontend staging deployments 4 | 5 | # redirect stdout/stderr to a file 6 | exec &> wasm-by-example-build.log 7 | 8 | cd ../ 9 | 10 | git stash 11 | 12 | git checkout master 13 | 14 | git pull origin master 15 | 16 | rm package-lock.json 17 | 18 | npm install 19 | 20 | npm run build 21 | 22 | # Copy the build output to public/ if successful build 23 | if [ $? -eq 0 ]; then 24 | rm -rf public 25 | mkdir -p public 26 | cp -r dist/* public/ 27 | else 28 | echo "Failed Building wasm-by-example" 29 | fi 30 | 31 | echo "Done!" 32 | -------------------------------------------------------------------------------- /examples/classes/demo/assemblyscript/ASBindTest.ts: -------------------------------------------------------------------------------- 1 | // Vector2D is a mathematical vector in 2D space. 2 | // It has an x and y directional component and a magnitude 3 | export class Vector2D { 4 | // x and y directional component of the vector 5 | x: i32; 6 | y: i32; 7 | // constructor for initializing the x and y components 8 | constructor(x: i32, y: i32) { 9 | this.x = x; 10 | this.y = y; 11 | } 12 | 13 | // the squared magnitude of the vector 14 | MagSQ(): i32 { 15 | return this.x * this.x + this.y * this.y; 16 | } 17 | 18 | // getting the magnitude of the vector 19 | Magnitude(): f32 { 20 | return f32.sqrt(this.MagSQ()); 21 | } 22 | } 23 | 24 | export class Vector3D extends Vector2D { 25 | // This adds a z attribute to the x and y attributes inherited from Vector2D 26 | z: i32; 27 | 28 | // I know It’s not technically a 3D vector if it has a w component :-p 29 | // I have this w component as a private attribute to demonstrate that 30 | // it will not be exported 31 | private w: i32; 32 | constructor(x: i32, y: i32, z: i32) { 33 | super(x, y); // calls the original constructor 34 | this.z = z; 35 | this.w = 0; 36 | } 37 | // This calls the Vector2D MagSQ function and adds the z component 38 | MagSQ(): i32 { 39 | return super.MagSQ() + this.z * this.z; 40 | } 41 | // Adding the Magnitude method to Vector3D would be unnecessary in TypeScript 42 | // AssemblyScript has no virtual function lookups, so Magnitude must be 43 | // overridden with the exact same code. Otherwise MagSQ would be called 44 | // on the Vector2D class instead of the Vector3D class. 45 | Magnitude(): f32 { 46 | return f32.sqrt(this.MagSQ()); 47 | } 48 | } 49 | // I’m creating this Vector3D object to show that private variables in 50 | // AssemblyScript are not so private. AssemblyScript does not yet enforce 51 | // access level modifiers like public, private and protected. 52 | let v = new Vector3D(3, 4, 5); 53 | 54 | // even though w is private, AssemblyScript does not prevent you from updating 55 | v.w = 1; 56 | -------------------------------------------------------------------------------- /examples/classes/demo/assemblyscript/ASBindTest.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/classes/demo/assemblyscript/ASBindTest.wasm -------------------------------------------------------------------------------- /examples/classes/demo/assemblyscript/index.js: -------------------------------------------------------------------------------- 1 | // I'm using node for this example 2 | const AsBind = require("as-bind/dist/as-bind.cjs.js"); 3 | const fs = require("fs"); 4 | const wasm = fs.readFileSync("./ASBindTest.wasm"); 5 | // asynchronous IIFE for async/await 6 | (async () => { 7 | // use as-bind to instantiate WebAssembly 8 | const asBindInstance = await AsBind.instantiate(wasm); 9 | // destructure the classes created in ASBindTest.ts 10 | ({ Vector2D, Vector3D } = asBindInstance.exports); 11 | let vec2 = new Vector2D(3, 4); // create new Vector2D object 12 | let vec3 = new Vector3D(3, 4, 5); // create new Vector3D objecst 13 | 14 | console.log(` 15 | ----- 2D VECTOR ----- 16 | x: ${vec2.x} 17 | y: ${vec2.y} 18 | Magnitude: ${vec2.Magnitude()} 19 | Magnitude Squared: ${vec2.MagSQ()} 20 | ----- 3D VECTOR ----- 21 | x: ${vec3.x} 22 | y: ${vec3.y} 23 | z: ${vec3.z} 24 | w: ${vec3.w} 25 | Magnitude: ${vec3.Magnitude()} 26 | Magnitude Squared: ${vec3.MagSQ()} 27 | `); 28 | })(); 29 | -------------------------------------------------------------------------------- /examples/classes/demo/assemblyscript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "npm run build && node index.js", 4 | "build": "asc ASBindTest.ts -o ASBindTest.wasm --exportRuntime --transform as-bind" 5 | }, 6 | "devDependencies": { 7 | "assemblyscript": "^0.19.9" 8 | }, 9 | "dependencies": { 10 | "as-bind": "^0.8.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/exports/demo/assemblyscript/README.md: -------------------------------------------------------------------------------- 1 | # Exports (Assemblyscript) 2 | 3 | Compile with `asc exports.ts -b exports.wasm -t exports.wat` 4 | -------------------------------------------------------------------------------- /examples/exports/demo/assemblyscript/exports.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 4 | import { domConsoleLog } from "/demo-util/domConsole.js"; 5 | 6 | const runWasmAdd = async () => { 7 | // Instantiate our wasm module 8 | const wasmModule = await wasmBrowserInstantiate("./exports.wasm"); 9 | 10 | // Get our exports object, with all of our exported Wasm Properties 11 | const exports = wasmModule.instance.exports; 12 | 13 | domConsoleLog(exports.callMeFromJavascript(24, 24)); // Logs 48 14 | 15 | // Since our constant is a global we use `.valueOf()`. 16 | // Though, in some cases this could simply be: exports.GET_THIS_CONSTANT_FROM_JAVASCRIPT 17 | domConsoleLog(exports.GET_THIS_CONSTANT_FROM_JAVASCRIPT.valueOf()); // Logs 2424 18 | 19 | // Trying to access a property we did NOT export 20 | domConsoleLog(exports.addIntegerWithConstant); // Logs undefined 21 | }; 22 | runWasmAdd(); 23 | -------------------------------------------------------------------------------- /examples/exports/demo/assemblyscript/exports.ts: -------------------------------------------------------------------------------- 1 | // This exports an add function. 2 | // It takes in two 32-bit integer values 3 | // And returns a 32-bit integer value. 4 | export function callMeFromJavascript(a: i32, b: i32): i32 { 5 | return addIntegerWithConstant(a, b); 6 | } 7 | 8 | // This exports a 32-bit integer constant 9 | export const GET_THIS_CONSTANT_FROM_JAVASCRIPT: i32 = 2424; 10 | 11 | // A NOT exported function 12 | // It takes in two 32-bit integer values 13 | // And returns a 32-bit integer value. 14 | function addIntegerWithConstant(a: i32, b: i32): i32 { 15 | return a + b + ADD_CONSTANT; 16 | } 17 | 18 | // A NOT export constant 19 | // a 32-bit integer constants 20 | const ADD_CONSTANT: i32 = 1; 21 | -------------------------------------------------------------------------------- /examples/exports/demo/assemblyscript/exports.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/exports/demo/assemblyscript/exports.wasm -------------------------------------------------------------------------------- /examples/exports/demo/assemblyscript/exports.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $FUNCSIG$iii (func (param i32 i32) (result i32))) 3 | (type $FUNCSIG$v (func)) 4 | (memory $0 0) 5 | (table $0 1 funcref) 6 | (elem (i32.const 0) $null) 7 | (global $exports/GET_THIS_CONSTANT_FROM_JAVASCRIPT i32 (i32.const 2424)) 8 | (global $exports/ADD_CONSTANT i32 (i32.const 1)) 9 | (global $~lib/memory/HEAP_BASE i32 (i32.const 8)) 10 | (export "memory" (memory $0)) 11 | (export "table" (table $0)) 12 | (export "callMeFromJavascript" (func $exports/callMeFromJavascript)) 13 | (export "GET_THIS_CONSTANT_FROM_JAVASCRIPT" (global $exports/GET_THIS_CONSTANT_FROM_JAVASCRIPT)) 14 | (func $exports/addIntegerWithConstant (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) 15 | local.get $0 16 | local.get $1 17 | i32.add 18 | global.get $exports/ADD_CONSTANT 19 | i32.add 20 | ) 21 | (func $exports/callMeFromJavascript (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) 22 | local.get $0 23 | local.get $1 24 | call $exports/addIntegerWithConstant 25 | ) 26 | (func $null (; 2 ;) (type $FUNCSIG$v) 27 | ) 28 | ) 29 | -------------------------------------------------------------------------------- /examples/exports/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exports - AssemblyScript 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/exports/demo/go/README.md: -------------------------------------------------------------------------------- 1 | Compile with TinyGo, by running: `tinygo build -o main.wasm -target wasm ./main.go` 2 | 3 | `wasm_exec.js` can be [copied from your TinyGo root](https://github.com/tinygo-org/tinygo/issues/1070). Which is [explained in the TinyGo Wasm Docs](https://tinygo.org/webassembly/webassembly/#how-it-works). 4 | -------------------------------------------------------------------------------- /examples/exports/demo/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exports - Go 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/exports/demo/go/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 4 | import { domConsoleLog } from "/demo-util/domConsole.js"; 5 | 6 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 7 | 8 | const runWasm = async () => { 9 | // Get the importObject from the go instance. 10 | const importObject = go.importObject; 11 | 12 | // Instantiate our wasm module 13 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 14 | 15 | // Allow the wasm_exec go instance, bootstrap and execute our wasm module 16 | go.run(wasmModule.instance); 17 | 18 | // Call the Add function export from wasm, save the result 19 | const result = wasmModule.instance.exports.callMeFromJavascript(24, 24); 20 | 21 | domConsoleLog(result); 22 | domConsoleLog(wasmModule.instance.exports.ADD_CONSTANT); // Should return undefined 23 | domConsoleLog(wasmModule.instance.exports.addIntegerWithConstant); // Should return undefined 24 | }; 25 | runWasm(); 26 | -------------------------------------------------------------------------------- /examples/exports/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Declare a main function, this is the entrypoint into our go module 4 | // That will be run. In our example, we won't need this 5 | func main() {} 6 | 7 | // This exports an add function. 8 | // It takes in two 32-bit integer values 9 | // And returns a 32-bit integer value. 10 | // To make this function callable from JavaScript, 11 | // we need to add the: "export myFunctionName" comment above the function 12 | //export callMeFromJavascript 13 | func callMeFromJavascript(x int, y int) int { 14 | return addIntegerWithConstant(x, y); 15 | } 16 | 17 | // A NOT exported constant 18 | // Go does not support exporting constants 19 | // for Wasm (that I know of). 20 | var ADD_CONSTANT int = 24; 21 | 22 | // A NOT exported function 23 | // It takes in two 32-bit integer values 24 | // And returns a 32-bit integer value. 25 | func addIntegerWithConstant(x int, y int) int { 26 | return x + y + ADD_CONSTANT; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /examples/exports/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/exports/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/exports/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "exports" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # Exports (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - Rust 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/index.js: -------------------------------------------------------------------------------- 1 | import wasmInit from "./pkg/exports.js"; 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { domConsoleLog } from "/demo-util/domConsole.js"; 4 | 5 | const runWasm = async () => { 6 | // Instantiate our wasm module 7 | const rustWasm = await wasmInit("./pkg/exports_bg.wasm"); 8 | 9 | // Call the Add function export from wasm, save the result 10 | const result = rustWasm.call_me_from_javascript(24, 24); 11 | 12 | domConsoleLog(result); 13 | domConsoleLog(rustWasm.ADD_CONSTANT); // Should return undefined 14 | domConsoleLog(rustWasm.add_integer_with_constant); // Should return undefined 15 | }; 16 | runWasm(); 17 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Assemblyscript) 2 | 3 | Compile with `asc hello-world.ts -b hello-world.wasm -t hello-world.wat` 4 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/pkg/exports.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @param {number} a 4 | * @param {number} b 5 | * @returns {number} 6 | */ 7 | export function call_me_from_javascript(a: number, b: number): number; 8 | 9 | /** 10 | * If `module_or_path` is {RequestInfo}, makes a request and 11 | * for everything else, calls `WebAssembly.instantiate` directly. 12 | * 13 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 14 | * 15 | * @returns {Promise} 16 | */ 17 | export default function init( 18 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 19 | ): Promise; 20 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/pkg/exports.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | /** 5 | * @param {number} a 6 | * @param {number} b 7 | * @returns {number} 8 | */ 9 | export function call_me_from_javascript(a, b) { 10 | return wasm.call_me_from_javascript(a, b); 11 | } 12 | __exports.call_me_from_javascript = call_me_from_javascript; 13 | 14 | function init(module) { 15 | let result; 16 | const imports = { "./exports": __exports }; 17 | 18 | if ( 19 | module instanceof URL || 20 | typeof module === "string" || 21 | module instanceof Request 22 | ) { 23 | const response = fetch(module); 24 | if (typeof WebAssembly.instantiateStreaming === "function") { 25 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 26 | console.warn( 27 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 28 | e 29 | ); 30 | return response 31 | .then(r => r.arrayBuffer()) 32 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 33 | }); 34 | } else { 35 | result = response 36 | .then(r => r.arrayBuffer()) 37 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 38 | } 39 | } else { 40 | result = WebAssembly.instantiate(module, imports).then(result => { 41 | if (result instanceof WebAssembly.Instance) { 42 | return { instance: result, module }; 43 | } else { 44 | return result; 45 | } 46 | }); 47 | } 48 | return result.then(({ instance, module }) => { 49 | wasm = instance.exports; 50 | init.__wbindgen_wasm_module = module; 51 | 52 | return wasm; 53 | }); 54 | } 55 | 56 | export default init; 57 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/pkg/exports_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function call_me_from_javascript(a: number, b: number): number; 4 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/pkg/exports_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/exports/demo/rust/pkg/exports_bg.wasm -------------------------------------------------------------------------------- /examples/exports/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exports", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "exports_bg.wasm", 9 | "exports.js", 10 | "exports.d.ts" 11 | ], 12 | "module": "exports.js", 13 | "types": "exports.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/exports/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 2 | // Import the wasm-bindgen crate. 3 | use wasm_bindgen::prelude::*; 4 | 5 | // This exports an add function. 6 | // It takes in two 32-bit integer values 7 | // And returns a 32-bit integer value. 8 | #[wasm_bindgen] 9 | pub fn call_me_from_javascript(a: i32, b: i32) -> i32 { 10 | return add_integer_with_constant(a, b); 11 | } 12 | 13 | // A NOT exported constant 14 | // Rust does not support exporting constants 15 | // for Wasm (that I know of). 16 | const ADD_CONSTANT: i32 = 24; 17 | 18 | // A NOT exported function 19 | // It takes in two 32-bit integer values 20 | // And returns a 32-bit integer value. 21 | fn add_integer_with_constant(a: i32, b: i32) -> i32 { 22 | return a + b + ADD_CONSTANT; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/exports/exports.assemblyscript.en-us.md: -------------------------------------------------------------------------------- 1 | # Exports 2 | 3 | ## Overview 4 | 5 | In our [Hello World Example](/example-redirect?exampleName=hello-world), we called a function exported from WebAssembly, in our Javascript. **However, you can export both functions and constants to Javascript**. Let's dive a little deeper into exports and how they are used. 6 | 7 | --- 8 | 9 | ## Implementation 10 | 11 | So first, let's create our `exports.ts` AssemblyScript file: 12 | 13 | ```typescript 14 | // This exports an add function. 15 | // It takes in two 32-bit integer values 16 | // And returns a 32-bit integer value. 17 | export function callMeFromJavascript(a: i32, b: i32): i32 { 18 | return addIntegerWithConstant(a, b); 19 | } 20 | 21 | // This exports a 32-bit integer constant 22 | export const GET_THIS_CONSTANT_FROM_JAVASCRIPT: i32 = 2424; 23 | 24 | // A NOT exported function 25 | // It takes in two 32-bit integer values 26 | // And returns a 32-bit integer value. 27 | function addIntegerWithConstant(a: i32, b: i32): i32 { 28 | return a + b + ADD_CONSTANT; 29 | } 30 | 31 | // A NOT export constant 32 | // a 32-bit integer constants 33 | const ADD_CONSTANT: i32 = 1; 34 | ``` 35 | 36 | Then, let's compile that into a wasm module, using the [AssemblyScript Compiler](https://docs.assemblyscript.org/details/compiler), which will output a `export-function.wasm`: 37 | 38 | ```bash 39 | asc exports.ts -b exports.wasm 40 | ``` 41 | 42 | Next, Let's load / instantiate the wasm module, `export-function.wasm` in a new `export-function.js` file. Looking at the [WebAssembly Module Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/WebAssembly/Module), We see that after instantiation of our module, our Module has a `.instance` property, which is a [WebAssembly Module Instance](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/WebAssembly/Instance). An example of instantiating a module can be found in the [Hello World Example](/example-redirect?exampleName=hello-world). Lastly, we see that our instance has an `.exports` property. The `.exports` property is an object that contains all of the exported functions / constants, that be called / accessed synchronously from Javascript. Functions can be called with normal function syntax, whereas constants require accessing them with `.valueOf()` depending on if they are exports as [WebAssembly Globals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Global). See the snippet below: 43 | 44 | ```javascript 45 | const runWasm = async () => { 46 | // Instantiate our wasm module 47 | const wasmModule = await wasmBrowserInstantiate("./exports.wasm"); 48 | 49 | // Get our exports object, with all of our exported Wasm Properties 50 | const exports = wasmModule.instance.exports; 51 | 52 | console.log(exports.callMeFromJavascript(24, 24)); // Logs 49 53 | 54 | // Since our constant is a global we use `.valueOf()`. 55 | // Though, in some cases this could simply be: exports.GET_THIS_CONSTANT_FROM_JAVASCRIPT 56 | console.log(exports.GET_THIS_CONSTANT_FROM_JAVASCRIPT.valueOf()); // Logs 2424 57 | 58 | // Trying to access a property we did NOT export 59 | console.log(exports.addIntegerWithConstant); // Logs undefined 60 | }; 61 | runWasm(); 62 | ``` 63 | 64 | Lastly, lets load our ES6 Module, `exports.js` Javascript file in our `index.html`. And you should get something similar to the demo ([Source Code](/source-redirect?path=examples/exports/demo/assemblyscript)) below! 65 | 66 | --- 67 | 68 | ## Demo 69 | 70 | 71 | 72 | Next let's take a look at [WebAssembly Linear Memory](/example-redirect?exampleName=webassembly-linear-memory). 73 | -------------------------------------------------------------------------------- /examples/exports/exports.go.en-us.md: -------------------------------------------------------------------------------- 1 | # Exports 2 | 3 | ## Overview 4 | 5 | In our [Hello World Example](/example-redirect?exampleName=hello-world), we called a function exported from WebAssembly, in our Javascript. Let's dive a little deeper into exports and how they are used. 6 | 7 | --- 8 | 9 | ## Implementation 10 | 11 | If you haven't done so already, you should set up your project following the steps laid out in the [Hello World Example](/example-redirect?exampleName=hello-world) example. 12 | 13 | First, let's add the following to our `main.go` file: 14 | 15 | ```go 16 | package main 17 | 18 | // Declare a main function, this is the entrypoint into our go module 19 | // That will be run. In our example, we won't need this 20 | func main() {} 21 | 22 | // This exports an add function. 23 | // It takes in two 32-bit integer values 24 | // And returns a 32-bit integer value. 25 | // To make this function callable from JavaScript, 26 | // we need to add the: "export myFunctionName" comment above the function 27 | //export callMeFromJavascript 28 | func callMeFromJavascript(x int, y int) int { 29 | return addIntegerWithConstant(x, y); 30 | } 31 | 32 | // A NOT exported constant 33 | // Go does not support exporting constants 34 | // for Wasm (that I know of). 35 | var ADD_CONSTANT int = 24; 36 | 37 | // A NOT exported function 38 | // It takes in two 32-bit integer values 39 | // And returns a 32-bit integer value. 40 | func addIntegerWithConstant(x int, y int) int { 41 | return x + y + ADD_CONSTANT; 42 | } 43 | ``` 44 | 45 | Then, let's compile `main.go` into a wasm module, using the TinyGo compiler. This will output a `main.wasm`: 46 | 47 | ```bash 48 | tinygo build -o main.wasm -target wasm ./main.go 49 | ``` 50 | 51 | --- 52 | 53 | Then, let's create an `index.html`, and get our appropriate `wasm_exec.js` following the steps laid out in the [Hello World Example](/example-redirect?exampleName=hello-world) example. 54 | 55 | --- 56 | 57 | Lastly, lets create our `index.js` JavaScript file. We will be using the same `wasmBrowserInstantiate` as mentioned in the [Hello World Example](/example-redirect?exampleName=hello-world) example: 58 | 59 | ```javascript 60 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 61 | 62 | const runWasm = async () => { 63 | // Get the importObject from the go instance. 64 | const importObject = go.importObject; 65 | 66 | // Instantiate our wasm module 67 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 68 | 69 | // Allow the wasm_exec go instance, bootstrap and execute our wasm module 70 | go.run(wasmModule.instance); 71 | 72 | // Call the Add function export from wasm, save the result 73 | const result = wasmModule.instance.exports.callMeFromJavascript(24, 24); 74 | 75 | console.log(result); 76 | console.log(wasmModule.instance.exports.ADD_CONSTANT); // Should return undefined 77 | console.log(wasmModule.instance.exports.addIntegerWithConstant); // Should return undefined 78 | }; 79 | runWasm(); 80 | ``` 81 | 82 | And that should be it! You should have something similar to the demo ([Source Code](/source-redirect?path=examples/exports/demo/go)) below: 83 | 84 | --- 85 | 86 | ## Demo 87 | 88 | 89 | 90 | Next let's take a look at [WebAssembly Linear Memory](/example-redirect?exampleName=webassembly-linear-memory). 91 | -------------------------------------------------------------------------------- /examples/exports/exports.rust.en-us.md: -------------------------------------------------------------------------------- 1 | # Exports 2 | 3 | ## Overview 4 | 5 | In our [Hello World Example](/example-redirect?exampleName=hello-world), we called a function exported from WebAssembly, in our Javascript. Let's dive a little deeper into exports and how they are used. 6 | 7 | --- 8 | 9 | ## Implementation 10 | 11 | If you haven't done so already, you should set up your project following the steps laid out in the [Hello World Example](/example-redirect?exampleName=hello-world) example. 12 | 13 | First, let's add the following to our `src/lib.rs` file: 14 | 15 | ```rust 16 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 17 | // Import the wasm-bindgen crate. 18 | use wasm_bindgen::prelude::*; 19 | 20 | // This exports an add function. 21 | // It takes in two 32-bit integer values 22 | // And returns a 32-bit integer value. 23 | #[wasm_bindgen] 24 | pub fn call_me_from_javascript(a: i32, b: i32) -> i32 { 25 | return add_integer_with_constant(a, b); 26 | } 27 | 28 | // A NOT exported constant 29 | // Rust does not support exporting constants 30 | // for Wasm (that I know of). 31 | const ADD_CONSTANT: i32 = 24; 32 | 33 | // A NOT exported function 34 | // It takes in two 32-bit integer values 35 | // And returns a 32-bit integer value. 36 | fn add_integer_with_constant(a: i32, b: i32) -> i32 { 37 | return a + b + ADD_CONSTANT; 38 | } 39 | ``` 40 | 41 | Then, let's compile that using [wasm-pack](https://github.com/rustwasm/wasm-pack), which will create a `pkg/` directory: 42 | 43 | ```bash 44 | wasm-pack build --target web 45 | ``` 46 | 47 | Next, lets create an `index.js` file to load and run our wasm output. Let's import the wasm initialization module from `pkg/exports.js` that was generated by wasm-pack. Then, let's call the module passing in the path to our wasm file at `pkg/exports_bg.wasm` that was generated by wasm-pack. Then, let's go ahead and call out exported functions, and explore what functions were NOT exported: 48 | 49 | > **NOTE:** In this example, we are using the exported function from the wasm module directly to help highlight the WebAssembly API. `wasm-bindgen` generates JavaScript bindings code that can be imported as an ES6 import, and is the reccomended way to work with your Rust Wasm modules. These JavaScript bindings are shown in the "Passing High Level Data Types with `wasm-bindgen`" example. 50 | 51 | ```javascript 52 | import wasmInit from "./pkg/exports.js"; 53 | 54 | const runWasm = async () => { 55 | // Instantiate our wasm module 56 | const rustWasm = await wasmInit("./pkg/exports_bg.wasm"); 57 | 58 | // Call the Add function export from wasm, save the result 59 | const result = rustWasm.call_me_from_javascript(24, 24); 60 | 61 | console.log(result); // Should output '72' 62 | console.log(rustWasm.ADD_CONSTANT); // Should output 'undefined' 63 | console.log(rustWasm.add_integer_with_constant); // Should output 'undefined' 64 | }; 65 | runWasm(); 66 | ``` 67 | 68 | Lastly, lets load our ES6 Module, `index.js` Javascript file in our `index.html`. And you should get something similar to the demo ([Source Code](/source-redirect?path=examples/exports/demo/rust)) below! 69 | 70 | --- 71 | 72 | ## Demo 73 | 74 | 75 | 76 | Next let's take a look at [WebAssembly Linear Memory](/example-redirect?exampleName=webassembly-linear-memory). 77 | -------------------------------------------------------------------------------- /examples/exports/exports.rust.pt-br.md: -------------------------------------------------------------------------------- 1 | # Exports 2 | 3 | ## Visão Geral 4 | 5 | No nosso [Exemplo de "Olá, Mundo"](/example-redirect?exampleName=hello-world), invocamos uma função exportada pelo WebAssembly, no nosso Javascript. Vamos nos aprofundar nos exports e em como usá-los. 6 | 7 | --- 8 | 9 | ## Implementação 10 | 11 | Se você ainda não fez isso, você deveria configurar o seu projeto seguindo os passos definidos no exemplo [Olá Mundo](/example-redirect?exampleName=hello-world). 12 | 13 | Primeiro, vamos adicionar o seguinte ao nosso archivo `src/lib.rs`: 14 | 15 | ```rust 16 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 17 | // Import the wasm-bindgen crate. 18 | use wasm_bindgen::prelude::*; 19 | 20 | // This exports an add function. 21 | // It takes in two 32-bit integer values 22 | // And returns a 32-bit integer value. 23 | #[wasm_bindgen] 24 | pub fn call_me_from_javascript(a: i32, b: i32) -> i32 { 25 | return add_integer_with_constant(a, b); 26 | } 27 | 28 | // A NOT exported constant 29 | // Rust does not support exporting constants 30 | // for Wasm (that I know of). 31 | const ADD_CONSTANT: i32 = 24; 32 | 33 | // A NOT exported function 34 | // It takes in two 32-bit integer values 35 | // And returns a 32-bit integer value. 36 | fn add_integer_with_constant(a: i32, b: i32) -> i32 { 37 | return a + b + ADD_CONSTANT; 38 | } 39 | ``` 40 | 41 | A seguir, vamos compilá-lo usando [wasm-pack](https://github.com/rustwasm/wasm-pack), que vai criar um diretório `pkg/`: 42 | 43 | ```bash 44 | wasm-pack build --target web 45 | ``` 46 | 47 | Depois, vamos criar um arquivo `index.js` para carregar e executar o resultado em wasm. Vamos importar o módulo de inicialização do arquivo `pkg/exports.js`, que foi criado pelo wasm-pack. Então, vamos invocar o módulo passando a localização de nosso arquivo wasm `pkg/exports_bg.wasm`, também gerado pelo wasm-pack. Agora, vamos em frente e invocamos as funções exportadas, e exploramos quais funções NÃO foram exportadas: 48 | 49 | ```javascript 50 | import wasmInit from "./pkg/exports.js"; 51 | 52 | const runWasm = async () => { 53 | // Instantiate our wasm module 54 | const rustWasm = await wasmInit("./pkg/exports_bg.wasm"); 55 | 56 | // Call the Add function export from wasm, save the result 57 | const result = rustWasm.call_me_from_javascript(24, 24); 58 | 59 | console.log(result); // Should output '72' 60 | console.log(rustWasm.ADD_CONSTANT); // Should output 'undefined' 61 | console.log(rustWasm.add_integer_with_constant); // Should output 'undefined' 62 | }; 63 | runWasm(); 64 | ``` 65 | 66 | Por último, vamos carregar o nosso módulo ES6, o arquivo Javascript `index.js`, no nosso `index.html`. E você deveria ver algo similar à demo ([Código Fonte](/source-redirect?path=examples/exports/demo/rust)) abaixo! 67 | 68 | --- 69 | 70 | ## Demo 71 | 72 | 73 | 74 | A seguir daremos uma olhada na [Memória Linear do WebAssembly](/example-redirect?exampleName=webassembly-linear-memory). 75 | -------------------------------------------------------------------------------- /examples/hello-world/demo/assemblyscript/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Assemblyscript) 2 | 3 | Compile with `asc hello-world.ts -b hello-world.wasm -t hello-world.wat` 4 | -------------------------------------------------------------------------------- /examples/hello-world/demo/assemblyscript/hello-world.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | 4 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 5 | 6 | const runWasmAdd = async () => { 7 | // Instantiate our wasm module 8 | const wasmModule = await wasmBrowserInstantiate("./hello-world.wasm"); 9 | 10 | // Call the Add function export from wasm, save the result 11 | const addResult = wasmModule.instance.exports.add(24, 24); 12 | 13 | // Set the result onto the body 14 | document.body.textContent = `Hello World! addResult: ${addResult}`; 15 | }; 16 | runWasmAdd(); 17 | -------------------------------------------------------------------------------- /examples/hello-world/demo/assemblyscript/hello-world.ts: -------------------------------------------------------------------------------- 1 | // This exports an add function. 2 | // It takes in two 32-bit integer values 3 | // And returns a 32-bit integer value. 4 | export function add(a: i32, b: i32): i32 { 5 | return a + b; 6 | } 7 | -------------------------------------------------------------------------------- /examples/hello-world/demo/assemblyscript/hello-world.wasm: -------------------------------------------------------------------------------- 1 | asm 2 | ``pA memorytableadd A  3 |  j  -------------------------------------------------------------------------------- /examples/hello-world/demo/assemblyscript/hello-world.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $FUNCSIG$iii (func (param i32 i32) (result i32))) 3 | (type $FUNCSIG$v (func)) 4 | (memory $0 0) 5 | (table $0 1 funcref) 6 | (elem (i32.const 0) $null) 7 | (global $~lib/memory/HEAP_BASE i32 (i32.const 8)) 8 | (export "memory" (memory $0)) 9 | (export "table" (table $0)) 10 | (export "add" (func $hello-world/add)) 11 | (func $hello-world/add (; 0 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) 12 | local.get $0 13 | local.get $1 14 | i32.add 15 | ) 16 | (func $null (; 1 ;) (type $FUNCSIG$v) 17 | ) 18 | ) 19 | -------------------------------------------------------------------------------- /examples/hello-world/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - AssemblyScript 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/hello-world/demo/go/README.md: -------------------------------------------------------------------------------- 1 | Compile with TinyGo, by running: `tinygo build -o main.wasm -target wasm ./main.go` 2 | 3 | `wasm_exec.js` can be [copied from your TinyGo root](https://github.com/tinygo-org/tinygo/issues/1070). Which is [explained in the TinyGo Wasm Docs](https://tinygo.org/webassembly/webassembly/#how-it-works). 4 | -------------------------------------------------------------------------------- /examples/hello-world/demo/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - Go 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/hello-world/demo/go/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 4 | 5 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 6 | 7 | const runWasmAdd = async () => { 8 | // Get the importObject from the go instance. 9 | const importObject = go.importObject; 10 | 11 | // Instantiate our wasm module 12 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 13 | 14 | // Allow the wasm_exec go instance, bootstrap and execute our wasm module 15 | go.run(wasmModule.instance); 16 | 17 | // Call the Add function export from wasm, save the result 18 | const addResult = wasmModule.instance.exports.add(24, 24); 19 | 20 | // Set the result onto the body 21 | document.body.textContent = `Hello World! addResult: ${addResult}`; 22 | }; 23 | runWasmAdd(); 24 | -------------------------------------------------------------------------------- /examples/hello-world/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Declare a main function, this is the entrypoint into our go module 4 | // That will be run. In our example, we won't need this 5 | func main() {} 6 | 7 | 8 | // This exports an add function. 9 | // It takes in two 32-bit integer values 10 | // And returns a 32-bit integer value. 11 | // To make this function callable from JavaScript, 12 | // we need to add the: "export add" comment above the function 13 | //export add 14 | func add(x int, y int) int { 15 | return x + y; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/hello-world/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/hello-world/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello-world" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - Rust 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/index.js: -------------------------------------------------------------------------------- 1 | // Import our outputted wasm ES6 module 2 | // Which, export default's, an initialization function 3 | import wasmInit from "./pkg/hello_world.js"; 4 | 5 | const runWasm = async () => { 6 | // Instantiate our wasm module 7 | const helloWorld = await wasmInit("./pkg/hello_world_bg.wasm"); 8 | 9 | // Call the Add function export from wasm, save the result 10 | const addResult = helloWorld.add(24, 24); 11 | 12 | // Set the result onto the body 13 | document.body.textContent = `Hello World! addResult: ${addResult}`; 14 | }; 15 | runWasm(); 16 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Assemblyscript) 2 | 3 | Compile with `asc hello-world.ts -b hello-world.wasm -t hello-world.wat` 4 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/pkg/hello_world.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @param {number} a 4 | * @param {number} b 5 | * @returns {number} 6 | */ 7 | export function add(a: number, b: number): number; 8 | 9 | /** 10 | * If `module_or_path` is {RequestInfo}, makes a request and 11 | * for everything else, calls `WebAssembly.instantiate` directly. 12 | * 13 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 14 | * 15 | * @returns {Promise} 16 | */ 17 | export default function init( 18 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 19 | ): Promise; 20 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/pkg/hello_world.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | /** 5 | * @param {number} a 6 | * @param {number} b 7 | * @returns {number} 8 | */ 9 | export function add(a, b) { 10 | return wasm.add(a, b); 11 | } 12 | __exports.add = add; 13 | 14 | function init(module) { 15 | let result; 16 | const imports = { "./hello_world": __exports }; 17 | 18 | if ( 19 | module instanceof URL || 20 | typeof module === "string" || 21 | module instanceof Request 22 | ) { 23 | const response = fetch(module); 24 | if (typeof WebAssembly.instantiateStreaming === "function") { 25 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 26 | console.warn( 27 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 28 | e 29 | ); 30 | return response 31 | .then(r => r.arrayBuffer()) 32 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 33 | }); 34 | } else { 35 | result = response 36 | .then(r => r.arrayBuffer()) 37 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 38 | } 39 | } else { 40 | result = WebAssembly.instantiate(module, imports).then(result => { 41 | if (result instanceof WebAssembly.Instance) { 42 | return { instance: result, module }; 43 | } else { 44 | return result; 45 | } 46 | }); 47 | } 48 | return result.then(({ instance, module }) => { 49 | wasm = instance.exports; 50 | init.__wbindgen_wasm_module = module; 51 | 52 | return wasm; 53 | }); 54 | } 55 | 56 | export default init; 57 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/pkg/hello_world_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function add(a: number, b: number): number; 4 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/pkg/hello_world_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/hello-world/demo/rust/pkg/hello_world_bg.wasm -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello-world", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "hello_world_bg.wasm", 9 | "hello_world.js", 10 | "hello_world.d.ts" 11 | ], 12 | "module": "hello_world.js", 13 | "types": "hello_world.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/hello-world/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 2 | // Import the wasm-bindgen crate. 3 | use wasm_bindgen::prelude::*; 4 | 5 | // Our Add function 6 | // wasm-pack requires "exported" functions 7 | // to include #[wasm_bindgen] 8 | #[wasm_bindgen] 9 | pub fn add(a: i32, b: i32) -> i32 { 10 | return a + b; 11 | } 12 | -------------------------------------------------------------------------------- /examples/hello-world/hello-world.c.en-us.md: -------------------------------------------------------------------------------- 1 | # Hello World! 2 | 3 | ## Overview 4 | 5 | Let's do a "Hello world" type of program in [C]() using [Emscripten](https://emscripten.org)! 6 | 7 | --- 8 | 9 | ## Tool Setup 10 | 11 | First, let's [get the emsdk](https://emscripten.org/docs/getting_started/downloads.html) which is Emscripten's tool to get the compiler and all the tools and things you need. To do that, it's easy to get it from github using git: 12 | 13 | ```bash 14 | git clone https://github.com/emscripten-core/emsdk.git 15 | cd emsdk 16 | ``` 17 | 18 | Next, we can use the emsdk to get the very latest stable build of Emscripten, and to activate it so it's ready to use: 19 | 20 | ```bash 21 | ./emsdk install latest 22 | ./emsdk activate latest 23 | source ./emsdk_env.sh 24 | ``` 25 | 26 | The last command sets up the path so it can find `emcc`, the Emscripten compiler tool, and everything else we need. 27 | 28 | ## Compiling the Code 29 | 30 | Open your favorite text editor and save this little hello world program as `hello.c`: 31 | 32 | ```c 33 | // hello.c 34 | #include 35 | 36 | int main() { 37 | printf("hello, world!\n"); 38 | return 0; 39 | } 40 | ``` 41 | 42 | We can compile that with 43 | 44 | ```bash 45 | emcc hello.c -o hello.js 46 | ``` 47 | 48 | That emits `hello.js` and `hello.wasm`. The wasm file contains the compiled code, while the JS has all the code to load and run it. By default Emscripten output supports running both on the Web and in Node.js, so let's do that: 49 | 50 | ```bash 51 | node hello.js 52 | ``` 53 | 54 | That will print `hello, world!` as expected. 55 | 56 | You can also tell `emcc` to optimize the code - very important for code size - and also to emit HTML for you, for example like this: 57 | 58 | ```bash 59 | emcc hello.c -O3 -o hello.html 60 | ``` 61 | 62 | You can then run a local webserver (like `python -m SimpleHTTPServer 8000`) and browse to `localhost:8000/hello.html`, where you'll see the expected output. 63 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/assemblyscript/README.md: -------------------------------------------------------------------------------- 1 | # Importing JavaScript Functions into Wasm (Assemblyscript) 2 | 3 | Compile with `asc index.ts -b index.wasm -t index.wat` 4 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Importing Javascript Functions into Wasm - AssemblyScript 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/assemblyscript/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | 4 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 5 | import { domConsoleLog } from "/demo-util/domConsole.js"; 6 | 7 | const runWasmAdd = async () => { 8 | // Instantiate our wasm module 9 | const wasmModule = await wasmBrowserInstantiate("./index.wasm", { 10 | index: { 11 | consoleLog: value => domConsoleLog("Called from Wasm: " + value) 12 | } 13 | }); 14 | }; 15 | runWasmAdd(); 16 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/assemblyscript/index.ts: -------------------------------------------------------------------------------- 1 | // Declared `importObject` function 2 | declare function consoleLog(arg0: i32): void; 3 | 4 | // Log out the number 24 5 | consoleLog(24); 6 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/assemblyscript/index.wasm: -------------------------------------------------------------------------------- 1 | asm``index 2 | consoleLogpA memorytable A  3 | A   -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/assemblyscript/index.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $FUNCSIG$vi (func (param i32))) 3 | (type $FUNCSIG$v (func)) 4 | (import "index" "consoleLog" (func $index/consoleLog (param i32))) 5 | (memory $0 0) 6 | (table $0 1 funcref) 7 | (elem (i32.const 0) $null) 8 | (global $~lib/memory/HEAP_BASE i32 (i32.const 8)) 9 | (export "memory" (memory $0)) 10 | (export "table" (table $0)) 11 | (start $start) 12 | (func $start:index (; 1 ;) (type $FUNCSIG$v) 13 | i32.const 24 14 | call $index/consoleLog 15 | ) 16 | (func $start (; 2 ;) (type $FUNCSIG$v) 17 | call $start:index 18 | ) 19 | (func $null (; 3 ;) (type $FUNCSIG$v) 20 | ) 21 | ) 22 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/go/README.md: -------------------------------------------------------------------------------- 1 | Compile with TinyGo, by running: `tinygo build -o main.wasm -target wasm ./main.go` 2 | 3 | `wasm_exec.js` can be [copied from your TinyGo root](https://github.com/tinygo-org/tinygo/issues/1070). Which is [explained in the TinyGo Wasm Docs](https://tinygo.org/webassembly/webassembly/#how-it-works). 4 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Importing JavaScript Functions Into WebAssembly - Go 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/go/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 4 | import { domConsoleLog } from "/demo-util/domConsole.js"; 5 | 6 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 7 | 8 | const runWasm = async () => { 9 | // Get the importObject from the go instance. 10 | const importObject = go.importObject; 11 | // Set our function we want to use from WebAssembly, on our importObject 12 | // This should be set on the env key, of the import object. 13 | // The function itself should be set on the env object, where the key is 14 | // depending on the compiler, usually in the format similar to below, 15 | // but you can check for the "LinkError: WebAssembly.instantiate()", 16 | // which would show the name required. 17 | importObject.env["./main.go.jsPrintInt"] = value => domConsoleLog(value); 18 | 19 | // Instantiate our wasm module 20 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 21 | 22 | // Allow the wasm_exec go instance, bootstrap and execute our wasm module 23 | go.run(wasmModule.instance); 24 | 25 | // Call the export from wasm 26 | wasmModule.instance.exports.printIntFromWasm(24); 27 | }; 28 | runWasm(); 29 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Declare a function however do no give it a block of functionality. 4 | // We will be overriding this function in our javascript later so that 5 | // it calls our imported function 6 | func jsPrintInt(x int) 7 | 8 | // Declare a main function, this is the entrypoint into our go module 9 | // That will be run. We could just call out log function from here, but 10 | // going to export a function :) 11 | func main() {} 12 | 13 | // Export a function that takes in an integer 14 | // and calls an imported function from the importObject 15 | // to log out that integer, back inside of JavaScript 16 | //export printIntFromWasm 17 | func printIntFromWasm(x int) { 18 | jsPrintInt(x) 19 | } 20 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/importing-javascript-functions-into-webassembly/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "importing-javascript-functions-into-webassembly" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # Importing JavaScript Functions into Wasm (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - Rust 6 | 7 | 8 | 9 | 10 |

Please check your JavaScript console for the results.

11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/index.js: -------------------------------------------------------------------------------- 1 | import wasmInit from "./pkg/importing_javascript_functions_into_webassembly.js"; 2 | 3 | const runWasm = async () => { 4 | // Instantiate our wasm module 5 | const rustWasm = await wasmInit( 6 | "./pkg/importing_javascript_functions_into_webassembly_bg.wasm" 7 | ); 8 | 9 | // Run the exported function 10 | rustWasm.console_log_from_wasm(); // Should log "This console.log is from wasm!" 11 | }; 12 | runWasm(); 13 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Assemblyscript) 2 | 3 | Compile with `asc hello-world.ts -b hello-world.wasm -t hello-world.wat` 4 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/importing_javascript_functions_into_webassembly.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @returns {void} 4 | */ 5 | export function console_log_from_wasm(): void; 6 | 7 | /** 8 | * If `module_or_path` is {RequestInfo}, makes a request and 9 | * for everything else, calls `WebAssembly.instantiate` directly. 10 | * 11 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 12 | * 13 | * @returns {Promise} 14 | */ 15 | export default function init( 16 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 17 | ): Promise; 18 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/importing_javascript_functions_into_webassembly.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | let cachedTextDecoder = new TextDecoder("utf-8"); 5 | 6 | let cachegetUint8Memory = null; 7 | function getUint8Memory() { 8 | if ( 9 | cachegetUint8Memory === null || 10 | cachegetUint8Memory.buffer !== wasm.memory.buffer 11 | ) { 12 | cachegetUint8Memory = new Uint8Array(wasm.memory.buffer); 13 | } 14 | return cachegetUint8Memory; 15 | } 16 | 17 | function getStringFromWasm(ptr, len) { 18 | return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len)); 19 | } 20 | 21 | function __wbg_log_f48fd9f1562bf74d(arg0, arg1) { 22 | let varg0 = getStringFromWasm(arg0, arg1); 23 | console.log(varg0); 24 | } 25 | __exports.__wbg_log_f48fd9f1562bf74d = __wbg_log_f48fd9f1562bf74d; 26 | /** 27 | * @returns {void} 28 | */ 29 | export function console_log_from_wasm() { 30 | return wasm.console_log_from_wasm(); 31 | } 32 | __exports.console_log_from_wasm = console_log_from_wasm; 33 | 34 | function init(module) { 35 | let result; 36 | const imports = { 37 | "./importing_javascript_functions_into_webassembly": __exports 38 | }; 39 | 40 | if ( 41 | module instanceof URL || 42 | typeof module === "string" || 43 | module instanceof Request 44 | ) { 45 | const response = fetch(module); 46 | if (typeof WebAssembly.instantiateStreaming === "function") { 47 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 48 | console.warn( 49 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 50 | e 51 | ); 52 | return response 53 | .then(r => r.arrayBuffer()) 54 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 55 | }); 56 | } else { 57 | result = response 58 | .then(r => r.arrayBuffer()) 59 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 60 | } 61 | } else { 62 | result = WebAssembly.instantiate(module, imports).then(result => { 63 | if (result instanceof WebAssembly.Instance) { 64 | return { instance: result, module }; 65 | } else { 66 | return result; 67 | } 68 | }); 69 | } 70 | return result.then(({ instance, module }) => { 71 | wasm = instance.exports; 72 | init.__wbindgen_wasm_module = module; 73 | 74 | return wasm; 75 | }); 76 | } 77 | 78 | export default init; 79 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/importing_javascript_functions_into_webassembly_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function console_log_from_wasm(): void; 4 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/importing_javascript_functions_into_webassembly_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/importing_javascript_functions_into_webassembly_bg.wasm -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "importing-javascript-functions-into-webassembly", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "importing_javascript_functions_into_webassembly_bg.wasm", 9 | "importing_javascript_functions_into_webassembly.js", 10 | "importing_javascript_functions_into_webassembly.d.ts" 11 | ], 12 | "module": "importing_javascript_functions_into_webassembly.js", 13 | "types": "importing_javascript_functions_into_webassembly.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // This example is a simplified version of: 2 | // https://github.com/rustwasm/wasm-bindgen/blob/master/examples/console_log/src/lib.rs 3 | 4 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 5 | // Import the wasm-bindgen crate. 6 | use wasm_bindgen::prelude::*; 7 | 8 | // Let's define our external function (imported from JS) 9 | // Here, we will define our external `console.log` 10 | #[wasm_bindgen] 11 | extern "C" { 12 | // Use `js_namespace` here to bind `console.log(..)` instead of just 13 | // `log(..)` 14 | #[wasm_bindgen(js_namespace = console)] 15 | fn log(s: &str); 16 | } 17 | 18 | // Export a function that will be called in JavaScript 19 | // but call the "imported" console.log. 20 | #[wasm_bindgen] 21 | pub fn console_log_from_wasm() { 22 | log("This console.log is from wasm!"); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/importing-javascript-functions-into-webassembly.assemblyscript.en-us.md: -------------------------------------------------------------------------------- 1 | # Importing Javascript Functions Into WebAssembly 2 | 3 | ## Overview 4 | 5 | When you are instantiating Wasm modules, you are able to pass in an [`importObject`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming). This `importObject` can be used to call host (Javascript) functions within Wasm! In this example, we will import and implement a simple console.log, which is called within Wasm: 6 | 7 | --- 8 | 9 | ## Implementation 10 | 11 | First, let's start with our `index.ts`: 12 | 13 | ```typescript 14 | // Declared `importObject` function 15 | declare function consoleLog(arg0: i32): void; 16 | 17 | // Log out the number 24 18 | consoleLog(24); 19 | ``` 20 | 21 | Then, let's compile that into a wasm module, using the [AssemblyScript Compiler](https://docs.assemblyscript.org/details/compiler), which will output a `index.wasm`: 22 | 23 | ```bash 24 | asc index.ts -b index.wasm 25 | ``` 26 | 27 | Next, Let's load / instantiate the was module, `index.wasm` in a new `index.js` file. The only difference here, compared to earlier examples, is that this time we will be passing in our `importObject` into our `wasmBrowserInstantiate`. This import object will have a property, `consoleLog`, which matches the declared function `consoleLog` in our `index.ts`. **Note:** for Assemblyscript version `0.7.0`, declared imports need to be wrapped in the `index` property of the `importObject`. In later versions of AssemblyScript this may change. But let's see the example below: 28 | 29 | ```javascript 30 | const runWasm = async () => { 31 | // Instantiate our wasm module 32 | // And pass in a wasm module 33 | const wasmModule = await wasmBrowserInstantiate("./index.wasm", { 34 | index: { 35 | consoleLog: value => console.log(value) 36 | } 37 | }); 38 | }; 39 | runWasm(); 40 | ``` 41 | 42 | Lastly, lets load our ES6 Module, `index.js` Javascript file in our `index.html`. And you should get something similar to the demo ([Source Code](/source-redirect?path=examples/importing-javascript-functions-into-webassembly/demo/assemblyscript)) below! 43 | 44 | --- 45 | 46 | ## Demo 47 | 48 | 49 | 50 | And that's it for the basics! Next, lets took a look at some "Advanced Web Demos", with an example of [Reading and Writing Graphics with WebAssembly](/example-redirect?exampleName=reading-and-writing-graphics). 51 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/importing-javascript-functions-into-webassembly.go.en-us.md: -------------------------------------------------------------------------------- 1 | # Importing Javascript Functions Into WebAssembly 2 | 3 | ## Overview 4 | 5 | When you are instantiating Wasm modules, you are able to pass in an [`importObject`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming). This `importObject` can be used to call host (Javascript) functions within Wasm! In this example, we will import and implement a simple console.log, which is called within Wasm: 6 | 7 | --- 8 | 9 | ## Implementation 10 | 11 | If you haven't done so already, you should set up your project following the steps laid out in the [Hello World Example](/example-redirect?exampleName=hello-world) example. 12 | 13 | First, let's add the following to our `main.go` file: 14 | 15 | ```go 16 | package main 17 | 18 | // Declare a function however do no give it a block of functionality. 19 | // We will be overriding this function in our javascript later so that 20 | // it calls our imported function 21 | func jsPrintInt(x int) 22 | 23 | // Declare a main function, this is the entrypoint into our go module 24 | // That will be run. We could just call out log function from here, but 25 | // going to export a function :) 26 | func main() {} 27 | 28 | // Export a function that takes in an integer 29 | // and calls an imported function from the importObject 30 | // to log out that integer, back inside of JavaScript 31 | //export printIntFromWasm 32 | func printIntFromWasm(x int) { 33 | jsPrintInt(x) 34 | } 35 | ``` 36 | 37 | Then, let's compile `main.go` into a wasm module, using the TinyGo compiler. This will output a `main.wasm`: 38 | 39 | ```bash 40 | tinygo build -o main.wasm -target wasm ./main.go 41 | ``` 42 | 43 | --- 44 | 45 | Then, let's create an `index.html`, and get our appropriate `wasm_exec.js` following the steps laid out in the [Hello World Example](/example-redirect?exampleName=hello-world) example. 46 | 47 | --- 48 | 49 | Lastly, lets create our `index.js` JavaScript file. We will be using the same `wasmBrowserInstantiate` as mentioned in the [Hello World Example](/example-redirect?exampleName=hello-world) example: 50 | 51 | ```javascript 52 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 53 | 54 | const runWasm = async () => { 55 | // Get the importObject from the go instance. 56 | const importObject = go.importObject; 57 | 58 | // Set our function we want to use from WebAssembly, on our importObject 59 | // This should be set on the env key, of the import object. 60 | // The function itself should be set on the env object, where the key is 61 | // depending on the compiler, usually in the format similar to below, 62 | // but you can check for the "LinkError: WebAssembly.instantiate()", 63 | // which would show the name required. 64 | importObject.env["./main.go.jsPrintInt"] = value => console.log(value); 65 | 66 | // Instantiate our wasm module 67 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 68 | 69 | // Allow the wasm_exec go instance, bootstrap and execute our wasm module 70 | go.run(wasmModule.instance); 71 | 72 | // Call the export from wasm 73 | wasmModule.instance.exports.printIntFromWasm(24); 74 | }; 75 | runWasm(); 76 | ``` 77 | 78 | --- 79 | 80 | ## Demo 81 | 82 | 83 | 84 | And that's it for the basics! Next, lets took a look at some "Advanced Web Demos", with an example of [Reading and Writing Graphics with WebAssembly](/example-redirect?exampleName=reading-and-writing-graphics). 85 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/importing-javascript-functions-into-webassembly.rust.en-us.md: -------------------------------------------------------------------------------- 1 | # Importing Javascript Functions Into WebAssembly 2 | 3 | ## Overview 4 | 5 | When you are instantiating Wasm modules, you are able to pass in an [`importObject`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming). This `importObject` can be used to call host (Javascript) functions within Wasm! 6 | 7 | In rust, tools like [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen), which is part of wasm-pack workflow, abstracts away the `importObject`. 8 | 9 | In this example, we will import and implement a simple `console.log` which is called within Wasm. This example is inspired by the [console_log example ](https://github.com/rustwasm/wasm-bindgen/blob/master/examples/console_log/src/lib.rs), but simplified. So let's jump into the example: 10 | 11 | --- 12 | 13 | ## Implementation 14 | 15 | First, let's add the following to our `src/lib.rs` file: 16 | 17 | ```rust 18 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 19 | // Import the wasm-bindgen crate. 20 | use wasm_bindgen::prelude::*; 21 | 22 | // Let's define our external function (imported from JS) 23 | // Here, we will define our external `console.log` 24 | #[wasm_bindgen] 25 | extern "C" { 26 | // Use `js_namespace` here to bind `console.log(..)` instead of just 27 | // `log(..)` 28 | #[wasm_bindgen(js_namespace = console)] 29 | fn log(s: &str); 30 | } 31 | 32 | // Export a function that will be called in JavaScript 33 | // but call the "imported" console.log. 34 | #[wasm_bindgen] 35 | pub fn console_log_from_wasm() { 36 | log("This console.log is from wasm!"); 37 | } 38 | ``` 39 | 40 | Then, let's compile that using [wasm-pack](https://github.com/rustwasm/wasm-pack), which will create a `pkg/` directory: 41 | 42 | ```bash 43 | wasm-pack build --target web 44 | ``` 45 | 46 | Next, lets create an `index.js` file to load and run our wasm output. Let's import the wasm initialization module from `pkg/importing_javascript_functions_into_webassembly.js` that was generated by wasm-pack. Then, let's call the module passing in the path to our wasm file at `pkg/importing_javascript_functions_into_webassembly_bg.wasm` that was generated by wasm-pack. Then, we will go ahead and call our exported wasm function, that will call the "imported" `console.log` JavaScript function: 47 | 48 | > **NOTE:** In this example, we are using the exported function from the wasm module directly to help highlight the WebAssembly API. `wasm-bindgen` generates JavaScript bindings code that can be imported as an ES6 import, and is the reccomended way to work with your Rust Wasm modules. These JavaScript bindings are shown in the "Passing High Level Data Types with `wasm-bindgen`" example. 49 | 50 | ```javascript 51 | const runWasm = async () => { 52 | // Instantiate our wasm module 53 | const rustWasm = await wasmInit( 54 | "./pkg/importing_javascript_functions_into_webassembly_bg.wasm" 55 | ); 56 | 57 | // Run the exported function 58 | rustWasm.console_log_from_wasm(); // Should log "This console.log is from wasm!" 59 | }; 60 | runWasm(); 61 | ``` 62 | 63 | Lastly, lets load our ES6 Module, `index.js` Javascript file in our `index.html`. And you should get something similar to the demo ([Source Code](/source-redirect?path=examples/importing-javascript-functions-into-webassembly/demo/rust)) below! 64 | 65 | --- 66 | 67 | ## Demo 68 | 69 | 70 | 71 | And that's it for the basics! Next, lets took a look at some "Advanced Web Demos", with an example of [Reading and Writing Graphics with WebAssembly](/example-redirect?exampleName=reading-and-writing-graphics). 72 | -------------------------------------------------------------------------------- /examples/importing-javascript-functions-into-webassembly/importing-javascript-functions-into-webassembly.rust.pt-br.md: -------------------------------------------------------------------------------- 1 | # Como Importar Funções do Javascript Em WebAssembly 2 | 3 | ## Visão Geral 4 | 5 | Quando você está instanciando módulos do Wasm, você é capaz de lhes passar um [`importObject`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiateStreaming). Este `importObject` pode ser usado para invocar funções do host (Javascript) dentro do Wasm! 6 | 7 | Em rust, as ferramentas tipo o [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen), que é parte do fluxo de trabalho do wasm-pack, abstraem o `importObject`. 8 | 9 | Neste exemplo, iremos importar e implementar um simples `console.log` que será invocado dentro do Wasm. Este exemplo foi inspirado pelo [exemplo de console_log](https://github.com/rustwasm/wasm-bindgen/blob/master/examples/console_log/src/lib.rs), mas simplificado. Assim que vamos direto ao exemplo: 10 | 11 | --- 12 | 13 | ## Implementação 14 | 15 | Primeiro, vamos adicionar o seguinte ao nosso arquivo `src/lib.rs`: 16 | 17 | ```rust 18 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 19 | // Import the wasm-bindgen crate. 20 | use wasm_bindgen::prelude::*; 21 | 22 | // Let's define our external function (imported from JS) 23 | // Here, we will define our external `console.log` 24 | #[wasm_bindgen] 25 | extern "C" { 26 | // Use `js_namespace` here to bind `console.log(..)` instead of just 27 | // `log(..)` 28 | #[wasm_bindgen(js_namespace = console)] 29 | fn log(s: &str); 30 | } 31 | 32 | // Export a function that will be called in JavaScript 33 | // but call the "imported" console.log. 34 | #[wasm_bindgen] 35 | pub fn console_log_from_wasm() { 36 | log("This console.log is from wasm!"); 37 | } 38 | ``` 39 | 40 | Então, vamos compilá-lo usando o [wasm-pack](https://github.com/rustwasm/wasm-pack), que vai criar um diretório `pkg/`: 41 | 42 | ```bash 43 | wasm-pack build --target web 44 | ``` 45 | 46 | A seguir, criamos um arquivo `index.js` que carrega e roda o nosso wasm gerado. Importamos o módulo de inicialização do wasm `pkg/importing_javascript_functions_into_webassembly.js` que também foi gerado pelo wasm-pack. Então, invocamos o módulo passando a localização do nosso arquivo wasm `pkg/importing_javascript_functions_into_webassembly_bg.wasm`, mais uma vez gerado pelo wasm-pack. Então, vamos em frente e invocamos a nossa função exportada pelo wasm, que por sua vez invoca a função Javascript `console.log` que foi "importada": 47 | 48 | ```javascript 49 | const runWasm = async () => { 50 | // Instantiate our wasm module 51 | const rustWasm = await wasmInit( 52 | "./pkg/importing_javascript_functions_into_webassembly_bg.wasm" 53 | ); 54 | 55 | // Run the exported function 56 | rustWasm.console_log_from_wasm(); // Should log "This console.log is from wasm!" 57 | }; 58 | runWasm(); 59 | ``` 60 | 61 | Por último, carregamos o nosso Módulo ES6, o arquivo Javascript `index.js` no nosso `index.html`. E você deveria obter um resultado similar à demo ([Código Fonte](/source-redirect?path=examples/importing-javascript-functions-into-webassembly/demo/rust)) abaixo! 62 | 63 | --- 64 | 65 | ## Demo 66 | 67 | 68 | 69 | E pronto, isso é tudo para cobrir o básico! A seguir, vamos dar uma olhada em algumas "Demos Web Avançadas", com um exemplo de [Como Ler e Escrever Gráficos com o WebAssembly](/example-redirect?exampleName=reading-and-writing-graphics). 70 | -------------------------------------------------------------------------------- /examples/introduction/introduction.all.en-us.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Let's do a brief introduction into major concepts of WebAssembly: 4 | 5 | - WebAssembly is a compile-targeted language for running bytecode on the web. 6 | - Relative to Javascript, WebAssembly offers predictable performance. It is not inherently **faster** than Javascript, but it **can be faster than JavaScript** in the correct use case. Such as **computationally intensive tasks**, like nested loops or handling large amounts of data. Therefore, **WebAssembly is a complement to JavaScript, and not a replacement**. 7 | - WebAssembly is extremely portable. WebAssembly runs on: all major web browsers, V8 runtimes like [Node.js](https://nodejs.org/en/), and independent Wasm runtimes like [Wasmtime](https://wasmtime.dev/), [Lucet](https://github.com/bytecodealliance/lucet), and [Wasmer](https://github.com/wasmerio/wasmer). 8 | - WebAssembly has Linear Memory, in other words, one big expandable array. And in the context of Javascript, synchronously accessible by Javascript and Wasm. 9 | - WebAssembly can export functions and constants, And in the context of Javascript, synchronously accessible by Javascript and Wasm. 10 | - WebAssembly, in its current MVP, only handles integers and floats. However, tools and libraries exist to make passing high-level data types convenient. 11 | 12 | With that, let's take a look at our [Hello World](/example-redirect?exampleName=hello-world) to see some of the concepts in action. 13 | -------------------------------------------------------------------------------- /examples/introduction/introduction.all.pt-br.md: -------------------------------------------------------------------------------- 1 | # Introdução 2 | 3 | Vamos fazer uma breve introdução aos principais conceitos do WebAssembly: 4 | 5 | - o WebAssembly é uma linguagem para rodar "bytecode" na web, e que também serve de alvo para compiladores. 6 | - Em comparação com o Javascript, o WebAssembly oferece uma performance previsível. Não é inerentemente **mais rápido** que o Javascript, mas **pode ser mais rápido que o Javascript** se usado corretamente. Por ejemplo, em **tarefas de computação intensiva**, como loops dentro de outros loops ou o processamento de grandes quantidades de dados. Portanto, **o WebAssembly é um complemento ao JavaScript, e não um substituto**. 7 | - o WebAssembly é extremamente portável. O WebAssembly roda em: todos os principais browsers web, os runtimes V8 como [Node.js](https://nodejs.org/en/), e runtimes independentes de Wasm como [Wasmtime](https://wasmtime.dev/), [Lucet](https://github.com/bytecodealliance/lucet), e [Wasmer](https://github.com/wasmerio/wasmer). 8 | - o WebAssembly usa Memória Linear, ou seja, uma array grande e expansível. E, no contexto do Javascript, acessível em modo síncrono tanto pelo Javascript como por Wasm. 9 | - o WebAssembly pode exportar funções e constantes, que, no contexto do Javascript, também são acessíveis em modo síncrono tanto pelo Javascript como por Wasm. 10 | - o WebAssembly, na atual versão que é parte de um MVP (produto mínimo viável), processa somente inteiros e pontos flutuantes. No entanto, há ferramentas e bibliotecas que permitem, de forma conveniente, o fluxo de dados de mais alto nível. 11 | 12 | Com isso em mente, vamos dar uma olhada no nosso [Olá, Mundo](/example-redirect?exampleName=hello-world) para observar alguns destes conceitos em ação. 13 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/addWasmByExample.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/addWasmByExample.wasm -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/assembly/index.ts: -------------------------------------------------------------------------------- 1 | export function addWasmByExample(inputString: string): string { 2 | return inputString + "Wasm By Example"; 3 | } 4 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/assembly/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../../../../.nvm/versions/node/v13.9.0/lib/node_modules/assemblyscript/std/assembly.json", 3 | "include": ["./**/*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/build/.gitignore: -------------------------------------------------------------------------------- 1 | *.wasm 2 | *.wasm.map 3 | *.asm.js 4 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | As-bind - AssemblyScript 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/index.js: -------------------------------------------------------------------------------- 1 | // We are including as-bind from the npm CDN unpkg. If you use a JavaScript bundler, you could use "as-bind". 2 | import * as AsBind from "https://unpkg.com/as-bind@0.8.0/dist/as-bind.esm.js"; 3 | import { domConsoleLog } from "/demo-util/domConsole.js"; 4 | 5 | const wasm = fetch("./addWasmByExample.wasm"); 6 | 7 | const asyncTask = async () => { 8 | const asBindInstance = await AsBind.instantiate(wasm); 9 | 10 | // You can now use your wasm / as-bind instance! 11 | const response = asBindInstance.exports.addWasmByExample("Hello from "); 12 | domConsoleLog(response); // Hello from Wasm By Example 13 | }; 14 | asyncTask(); 15 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "asc assembly/index.ts -b addWasmByExample.wasm --exportRuntime --transform as-bind" 4 | }, 5 | "devDependencies": { 6 | "assemblyscript": "^0.19.9" 7 | }, 8 | "dependencies": { 9 | "as-bind": "^0.8.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript/tests/index.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | const myModule = require(".."); 3 | assert.equal(myModule.add(1, 2), 3); 4 | console.log("ok"); 5 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-as-bind/passing-high-level-data-types-with-as-bind.assemblyscript.en-us.md: -------------------------------------------------------------------------------- 1 | # Passing High Level Data Types with `as-bind` 2 | 3 | ## Overview 4 | 5 | Using buffers and pointers, is a great way to get started with WebAssembly, and drill in its concepts while being productive. But once we start wanting to use higher level data structures efficiently and easily, is where things will get a little more complicated. Thankfully, the AssemblyScript community built [as-bind](https://github.com/torch2424/as-bind), which is a convenient abstraction over [AssemblyScript's loader](https://github.com/AssemblyScript/assemblyscript/tree/master/lib/loader). As mentioned before, `as-bind` abstracts away linear memory, and allows using higher-level data structures between AssemblyScript and JavaScript. 6 | 7 | Let's kick things off! To show off how we can use `as-bind`, let's see how we can use strings in WebAssembly and share them with JavaScript: 8 | 9 | --- 10 | 11 | ## Implementation 12 | 13 | First, we will need to install as-bind into our JavaScript project. If you do not currently have a modern JavaScript project, you can use [`asinit` to generate an AssemblyScript/Javascript project](https://docs.assemblyscript.org/quick-start). After you have generated your project, you can install as-bind by running: 14 | 15 | ```bash 16 | npm install --save as-bind 17 | ``` 18 | 19 | First, let's add the following to our `assembly/index.ts` file: 20 | 21 | ```typescript 22 | export function addWasmByExample(inputString: string): string { 23 | return inputString + "Wasm By Example"; 24 | } 25 | ``` 26 | 27 | What you will notice that is interesting, in other examples we've had to ensure all of our exported functions returned a supported WebAssembly number type. Now that we will be using as-bind, we can export a function that returns a string! 28 | 29 | Now, let's compile our assemblyscript. [as-bind has a compiler transform flag](https://github.com/torch2424/as-bind#quick-start) that must be included when compiling your AssemblyScript. Therefore, we would run: 30 | 31 | ```bash 32 | asc assembly/index.ts -b addWasmByExample.wasm --exportRuntime --transform as-bind 33 | ``` 34 | 35 | Next, lets modify our `index.js` file to load and run our wasm output. We will be utilizing as-bind in our JavaScript as described in the [as-bind quick-start](https://github.com/torch2424/as-bind#quick-start). Let's dive into our resulting `index.js`: 36 | 37 | ```javascript 38 | // We are including as-bind from the npm CDN unpkg. If you use a JavaScript bundler, you could use "as-bind". 39 | import * as AsBind from "https://unpkg.com/as-bind@0.8.0/dist/as-bind.esm.js"; 40 | 41 | const wasm = fetch("./addWasmByExample.wasm"); 42 | 43 | const asyncTask = async () => { 44 | const asBindInstance = await AsBind.instantiate(wasm); 45 | 46 | // You can now use your wasm / as-bind instance! 47 | const response = asBindInstance.exports.addWasmByExample("Hello from "); 48 | console.log(response); // Hello from Wasm By Example 49 | }; 50 | asyncTask(); 51 | ``` 52 | 53 | Another nice thing to notice, as-bind will handle our WebAssembly instantion for us! This is because during as-bind's instantiation step, it is wrapping our export function calls with their own as-bind function calls. The original exports can still be accessed at: `asBindInstance.unboundExports`. 54 | 55 | Lastly, lets create an `index.html` similar to one described in the [hello-world](/example-redirect?exampleName=hello-world), and load our `index.js` Javascript file in our `index.html`. Then, you should get something similar to the demo ([Source Code](/source-redirect?path=examples/passing-high-level-data-types-with-as-bind/demo/assemblyscript)) below! 56 | 57 | --- 58 | 59 | ## Demo 60 | 61 | 62 | 63 | --- 64 | 65 | **[as-bind](https://github.com/torch2424/as-bind) supports more than just strings, and has support for many different types!** I'd highly reccomend reading the [as-bind README](https://github.com/torch2424/as-bind). 66 | 67 | Feel free to [fix, suggest, or contribute more examples for language features or communitty tools](https://github.com/torch2424/wasm-by-example)! 68 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "strings" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # Strings (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Strings - Rust 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/index.js: -------------------------------------------------------------------------------- 1 | // Here we are importing the default export from our 2 | // Outputted wasm-bindgen ES Module. As well as importing 3 | // the named exports that are individual wrapper functions 4 | // to facilitate handle data passing between JS and Wasm. 5 | import wasmInit, { 6 | add_wasm_by_example_to_string, 7 | test 8 | } from "./pkg/strings.js"; 9 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 10 | import { domConsoleLog } from "/demo-util/domConsole.js"; 11 | 12 | const runWasm = async () => { 13 | // Instantiate our wasm module 14 | const rustWasm = await wasmInit("./pkg/strings_bg.wasm"); 15 | 16 | // Call our exported function 17 | const helloString = add_wasm_by_example_to_string("Hello from "); 18 | 19 | // Log the result to the console 20 | domConsoleLog(helloString); 21 | }; 22 | runWasm(); 23 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Linear Memory (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "strings", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "strings_bg.wasm", 9 | "strings.js", 10 | "strings.d.ts" 11 | ], 12 | "module": "strings.js", 13 | "types": "strings.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/pkg/strings.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @param {string} input_string 4 | * @returns {string} 5 | */ 6 | export function add_wasm_by_example_to_string(input_string: string): string; 7 | /** 8 | * @returns {string} 9 | */ 10 | export function test(): string; 11 | 12 | /** 13 | * If `module_or_path` is {RequestInfo}, makes a request and 14 | * for everything else, calls `WebAssembly.instantiate` directly. 15 | * 16 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 17 | * 18 | * @returns {Promise} 19 | */ 20 | export default function init( 21 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 22 | ): Promise; 23 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/pkg/strings_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function add_wasm_by_example_to_string( 4 | a: number, 5 | b: number, 6 | c: number 7 | ): void; 8 | export function test(a: number): void; 9 | export function __wbindgen_global_argument_ptr(): number; 10 | export function __wbindgen_malloc(a: number): number; 11 | export function __wbindgen_realloc(a: number, b: number, c: number): number; 12 | export function __wbindgen_free(a: number, b: number): void; 13 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/pkg/strings_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/pkg/strings_bg.wasm -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 2 | // Import the wasm-bindgen crate. 3 | use wasm_bindgen::prelude::*; 4 | 5 | // Our function to concatenate the string "Wasm by Example" 6 | // to the input string. We are using .into(), to convert 7 | // the rust types of str to a String. 8 | #[wasm_bindgen] 9 | pub fn add_wasm_by_example_to_string(input_string: String) -> String { 10 | let result = format!("{} {}", input_string, "Wasm by Example"); 11 | return result.into(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/passing-high-level-data-types-with-wasm-bindgen.rust.en-us.md: -------------------------------------------------------------------------------- 1 | # Passing High Level Data Types with `wasm-bindgen` 2 | 3 | ## Overview 4 | 5 | Using buffers and pointers, is a great way to get started with WebAssembly, and drill in its concepts while being productive. But once we start wanting to use higher level data structures efficiently and easily, is where things will get a little more complicated. Thankfully, the rust/wasm community built [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen), which is part of the wasm-pack workflow we have been using throughout the examples. As mentioned before, wasm-bindgen abstracts away linear memory, and allows using higher-level data structures between Rust and JavaScript. 6 | 7 | Let's kick things off! To show off how we can use `wasm-bindgen`, let's see how we can use strings in WebAssembly and share them with JavaScript: 8 | 9 | --- 10 | 11 | ## Implementation 12 | 13 | First, let's add the following to our `src/lib.rs` file: 14 | 15 | ```rust 16 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 17 | // Import the wasm-bindgen crate. 18 | use wasm_bindgen::prelude::*; 19 | 20 | // Our function to concatenate the string "Wasm by Example" 21 | // to the input string. We are using .into(), to convert 22 | // the rust types of str to a String. 23 | #[wasm_bindgen] 24 | pub fn add_wasm_by_example_to_string(input_string: String) -> String { 25 | let result = format!("{} {}", input_string, "Wasm by Example"); 26 | return result.into(); 27 | } 28 | ``` 29 | 30 | Next, we can compile the module following the [Hello World](/example-redirect?exampleName=hello-world) examples compilation process, replacing the appropriate file names. 31 | 32 | Next, lets create an `index.js` file to load and run our wasm output. Now that we are using higher-level stata structures, we will have to leverage the named exports in our `./pkg/strings.js`. **The named exports generated by wasm-pack in our `./pkg/strings.js`, are functions that wrap around our exported wasm functions to handle the data passing to facilitate passing high level data structures between WebAssembly and JavaScript**. In our case, we can take a look at the supported [wasm-bindgen String](https://rustwasm.github.io/docs/wasm-bindgen/reference/types/string.html) type. In the future, you can use this resource to see other supported types and usage as well. Let's dive into our resulting `index.js`: 33 | 34 | ```javascript 35 | // Here we are importing the default export from our 36 | // Outputted wasm-bindgen ES Module. As well as importing 37 | // the named exports that are individual wrapper functions 38 | // to facilitate handle data passing between JS and Wasm. 39 | import wasmInit, { 40 | add_wasm_by_example_to_string, 41 | test 42 | } from "./pkg/strings.js"; 43 | 44 | const runWasm = async () => { 45 | // Instantiate our wasm module 46 | const rustWasm = await wasmInit("./pkg/strings_bg.wasm"); 47 | 48 | // Call our exported function 49 | const helloString = add_wasm_by_example_to_string("Hello from "); 50 | 51 | // Log the result to the console 52 | console.log(helloString); 53 | }; 54 | runWasm(); 55 | ``` 56 | 57 | Lastly, lets load our ES6 Module, `index.js` Javascript file in our `index.html`. And you should get something similar to the demo ([Source Code](/source-redirect?path=examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust)) below! 58 | 59 | --- 60 | 61 | ## Demo 62 | 63 | 64 | 65 | --- 66 | 67 | **[wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) supports more than just strings, and has support for many different types!** I'd highly reccomend taking a look at the [wasm-bindgen book](https://rustwasm.github.io/docs/wasm-bindgen/), and in particular, the section of the [supported types by wasm-bindgen](https://rustwasm.github.io/docs/wasm-bindgen/reference/types.html). 68 | 69 | Feel free to [fix, suggest, or contribute more examples for language features or communitty tools](https://github.com/torch2424/wasm-by-example)! 70 | -------------------------------------------------------------------------------- /examples/passing-high-level-data-types-with-wasm-bindgen/passing-high-level-data-types-with-wasm-bindgen.rust.pt-br.md: -------------------------------------------------------------------------------- 1 | # Passando Tipos de Dados de Alto Nível com o `wasm-bindgen` 2 | 3 | ## Visão Geral 4 | 5 | Usando buffers e ponteiros é um ótimo jeito de começar a testar o WebAssembly, se aprofundar nos conceitos e, ao mesmo tempo, ser produtivo. Mas a partir do momento em que quisermos usar estruturas de nível mais alto com eficiência e facilidade as coisas podem se complicar um pouco. Felizmente, a comunidade do rust/wasm criou o [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen), que é uma parte do fluxo de trabalho do wasm-pack, que estivemos usando en nossos exemplos. Como mencionado anteriormente, o wasm-bindgen abstrai a partir da memória linear e nos permite usar estruturas de nível mais alto entre o Rust e o JavaScript. 6 | 7 | Vamos iniciar as coisas! Para exibir como podemos usar o `wasm-bindgen`, vejamos como podemos usar as strings em WebAssembly e compartilhá-las com o Javascript: 8 | 9 | --- 10 | 11 | ## Implementação 12 | 13 | Primeiro, vamos adicionar o seguinte conteúdo no nosso arquivo `src/lib.rs`: 14 | 15 | ```rust 16 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 17 | // Import the wasm-bindgen crate. 18 | use wasm_bindgen::prelude::*; 19 | 20 | // Our function to concatenate the string "Wasm by Example" 21 | // to the input string. We are using .into(), to convert 22 | // the rust types of str to a String. 23 | #[wasm_bindgen] 24 | pub fn add_wasm_by_example_to_string(input_string: String) -> String { 25 | let result = format!("{} {}", input_string, "Wasm by Example"); 26 | return result.into(); 27 | } 28 | ``` 29 | 30 | Depois, podemos compilar o módulo seguindo os mesmos passos de compilação do exemplo de [Olá, Mundo](/example-redirect?exampleName=hello-world), substituindo os nomes de arquivos quando apropriado. 31 | 32 | A seguir, criamos um arquivo `index.js` para carregar e rodar o nosso módulo wasm. Agora que estamos usando as estruturas de dados de mais alto nível, iremos aproveitar os exports com nome no nosso `./pkg/strings.js`. **Os exports com nome gerados pelo wasm-pack no nosso `./pkg/strings.js` são funções que envolvem as nossas funções wasm exportadas e assim lidar com a passagem de dados, facilitando a passagem das estruturas de mais alto nível entre o WebAssembly e o JavaScript**. No nosso caso, podemos dar uma olhada no tipo suportado [String wasm-bindgen](https://rustwasm.github.io/docs/wasm-bindgen/reference/types/string.html). No futuro, você pode usar este recurso para ver outros tipos suportados bem como o usá-los. Vamos ver os detalhes do nosso `index.js` resultante: 33 | 34 | ```javascript 35 | // Here we are importing the default export from our 36 | // Outputted wasm-bindgen ES Module. As well as importing 37 | // the named exports that are individual wrapper functions 38 | // to facilitate handle data passing between JS and Wasm. 39 | import wasmInit, { 40 | add_wasm_by_example_to_string, 41 | test 42 | } from "./pkg/strings.js"; 43 | 44 | const runWasm = async () => { 45 | // Instantiate our wasm module 46 | const rustWasm = await wasmInit("./pkg/strings_bg.wasm"); 47 | 48 | // Call our exported function 49 | const helloString = add_wasm_by_example_to_string("Hello from "); 50 | 51 | // Log the result to the console 52 | console.log(helloString); 53 | }; 54 | runWasm(); 55 | ``` 56 | 57 | Por último, vamos carregar o nosso Módulo ES6, o arquivo Javascript `index.js` no nosso `index.html`. E você deveria obter um resultado parecido à demo ([Código Fonte](/source-redirect?path=examples/passing-high-level-data-types-with-wasm-bindgen/demo/rust)) abaixo! 58 | 59 | --- 60 | 61 | ## Demo 62 | 63 | 64 | 65 | --- 66 | 67 | **O [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) suporta mais apenas strings, e tem suporte para muito tipos diferentes!** É altamente recomendável dar uma olhada no [livro wasm-bindgen](https://rustwasm.github.io/docs/wasm-bindgen/), em particular a seção dos [tipos suportados pelo wasm-bindgen](https://rustwasm.github.io/docs/wasm-bindgen/reference/types.html). 68 | 69 | Sinta-se à vontade para [corrigir, sugerir, ou contribuir com mais exemplos de funcionalidades ou ferramentas da comunidade](https://github.com/torch2424/wasm-by-example)! 70 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/assemblyscript/README.md: -------------------------------------------------------------------------------- 1 | # Reading And Writing Audio (Assemblyscript) 2 | 3 | Compile with `asc index.ts -b index.wasm -t index.wat` 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Audio - AssemblyScript 6 | 7 | 8 | 9 | 10 |

NOTE: Be careful if using headphones

11 |

Original Sine Wave

12 |
13 |
14 |

Amplified Sine Wave

15 |
16 |
17 |

Pause

18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/assemblyscript/index.ts: -------------------------------------------------------------------------------- 1 | // Set up our memory 2 | // By growing our Wasm Memory by 1 page (64KB) 3 | memory.grow(1); 4 | 5 | // Create some buffer/pointers (array index and size) to where 6 | // in memory we are storing the pixels. 7 | // NOTE: Be sure to set a correct --memoryBase when 8 | // when writing to memory directly like we are here. 9 | // https://docs.assemblyscript.org/details/compiler 10 | // Javascript writes to the INPUT_BUFFER, 11 | // and Wasm will write the result in the OUTPUT_BUFFER 12 | export const INPUT_BUFFER_POINTER: i32 = 0; 13 | export const INPUT_BUFFER_SIZE: i32 = 1024; 14 | export const OUTPUT_BUFFER_POINTER: i32 = 15 | INPUT_BUFFER_POINTER + INPUT_BUFFER_SIZE; 16 | export const OUTPUT_BUFFER_SIZE: i32 = INPUT_BUFFER_SIZE; 17 | 18 | // Function to do the amplification 19 | export function amplifyAudioInBuffer(): void { 20 | // Loop over the samples 21 | for (let i = 0; i < INPUT_BUFFER_SIZE; i++) { 22 | // Load the sample at the index 23 | let audioSample: u8 = load(INPUT_BUFFER_POINTER + i); 24 | 25 | // Amplify the sample. All samples 26 | // Should be implemented as bytes. 27 | // Byte samples are represented as follows: 28 | // 127 is silence, 0 is negative max, 256 is positive max 29 | if (audioSample > 127) { 30 | let audioSampleDiff = audioSample - 127; 31 | audioSample = audioSample + audioSampleDiff; 32 | } else if (audioSample < 127) { 33 | audioSample = audioSample / 2; 34 | } 35 | 36 | // Store the audio sample into our output buffer 37 | store(OUTPUT_BUFFER_POINTER + i, audioSample); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/assemblyscript/index.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-audio/demo/assemblyscript/index.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/go/README.md: -------------------------------------------------------------------------------- 1 | Compile with TinyGo, by running: `tinygo build -o main.wasm -target wasm ./main.go` 2 | 3 | `wasm_exec.js` can be [copied from your TinyGo root](https://github.com/tinygo-org/tinygo/issues/1070). Which is [explained in the TinyGo Wasm Docs](https://tinygo.org/webassembly/webassembly/#how-it-works). 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reading and Writing Graphics - Go 6 | 7 | 8 |

NOTE: Be careful if using headphones

9 |

Original Sine Wave

10 |
11 |
12 |

Amplified Sine Wave

13 |
14 |
15 |

Pause

16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Create some buffer/pointers (array index and size) to where 4 | // in memory we are storing the pixels. 5 | // Javascript writes to the INPUT_BUFFER, 6 | // and Wasm will write the result in the OUTPUT_BUFFER 7 | const INPUT_BUFFER_SIZE int = 1024; 8 | var inputBuffer [INPUT_BUFFER_SIZE]uint8; 9 | const OUTPUT_BUFFER_SIZE int = INPUT_BUFFER_SIZE; 10 | var outputBuffer [OUTPUT_BUFFER_SIZE]uint8; 11 | 12 | // Declare a main function, this is the entrypoint into our go module 13 | // That will be run. In our example, we won't need this 14 | func main() {} 15 | 16 | // Functions to return a pointer (Index) to our buffer in wasm memory 17 | 18 | //export getInputBufferPointer 19 | func getInputBufferPointer() *[INPUT_BUFFER_SIZE]uint8 { 20 | return &inputBuffer 21 | } 22 | 23 | //export getOutputBufferPointer 24 | func getOutputBufferPointer() *[OUTPUT_BUFFER_SIZE]uint8 { 25 | return &outputBuffer 26 | } 27 | 28 | 29 | // Function to return the size of our buffer in wasm memory 30 | 31 | //export getInputBufferSize 32 | func getInputBufferSize() int { 33 | return INPUT_BUFFER_SIZE; 34 | } 35 | 36 | //export getOutputBufferSize 37 | func getOutputBufferSize() int { 38 | return OUTPUT_BUFFER_SIZE; 39 | } 40 | 41 | // Function to do the amplification 42 | //export amplifyAudioInBuffer 43 | func amplifyAudioInBuffer() { 44 | // Loop over the samples 45 | for i := 0; i < INPUT_BUFFER_SIZE; i++ { 46 | // Load the sample at the index 47 | audioSample := inputBuffer[i]; 48 | 49 | // Amplify the sample. All samples 50 | // Should be implemented as bytes. 51 | // Byte samples are represented as follows: 52 | // 127 is silence, 0 is negative max, 256 is positive max 53 | if audioSample > 127 { 54 | audioSampleDiff := audioSample - 127; 55 | audioSample = audioSample + audioSampleDiff; 56 | } else if audioSample < 127 { 57 | audioSample = audioSample / 2; 58 | } 59 | 60 | // Store the audio sample into our output buffer 61 | outputBuffer[i] = audioSample; 62 | } 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-audio/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "audio" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # Reading And Writing Audio (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reading and Writing Audio - Rust 6 | 7 | 8 | 9 | 10 |

NOTE: Be careful if using headphones

11 |

Original Sine Wave

12 |
13 |
14 |

Amplified Sine Wave

15 |
16 |
17 |

Pause

18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Reading And Writing Audio (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/audio.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @returns {number} 4 | */ 5 | export function get_input_buffer_pointer(): number; 6 | /** 7 | * @returns {number} 8 | */ 9 | export function get_output_buffer_pointer(): number; 10 | /** 11 | * @returns {void} 12 | */ 13 | export function amplify_audio(): void; 14 | 15 | /** 16 | * If `module_or_path` is {RequestInfo}, makes a request and 17 | * for everything else, calls `WebAssembly.instantiate` directly. 18 | * 19 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 20 | * 21 | * @returns {Promise} 22 | */ 23 | export default function init( 24 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 25 | ): Promise; 26 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/audio.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | /** 5 | * @returns {number} 6 | */ 7 | export function get_input_buffer_pointer() { 8 | return wasm.get_input_buffer_pointer(); 9 | } 10 | __exports.get_input_buffer_pointer = get_input_buffer_pointer; 11 | 12 | /** 13 | * @returns {number} 14 | */ 15 | export function get_output_buffer_pointer() { 16 | return wasm.get_output_buffer_pointer(); 17 | } 18 | __exports.get_output_buffer_pointer = get_output_buffer_pointer; 19 | 20 | /** 21 | * @returns {void} 22 | */ 23 | export function amplify_audio() { 24 | return wasm.amplify_audio(); 25 | } 26 | __exports.amplify_audio = amplify_audio; 27 | 28 | function init(module) { 29 | let result; 30 | const imports = { "./audio": __exports }; 31 | 32 | if ( 33 | module instanceof URL || 34 | typeof module === "string" || 35 | module instanceof Request 36 | ) { 37 | const response = fetch(module); 38 | if (typeof WebAssembly.instantiateStreaming === "function") { 39 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 40 | console.warn( 41 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 42 | e 43 | ); 44 | return response 45 | .then(r => r.arrayBuffer()) 46 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 47 | }); 48 | } else { 49 | result = response 50 | .then(r => r.arrayBuffer()) 51 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 52 | } 53 | } else { 54 | result = WebAssembly.instantiate(module, imports).then(result => { 55 | if (result instanceof WebAssembly.Instance) { 56 | return { instance: result, module }; 57 | } else { 58 | return result; 59 | } 60 | }); 61 | } 62 | return result.then(({ instance, module }) => { 63 | wasm = instance.exports; 64 | init.__wbindgen_wasm_module = module; 65 | 66 | return wasm; 67 | }); 68 | } 69 | 70 | export default init; 71 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/audio_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function get_input_buffer_pointer(): number; 4 | export function get_output_buffer_pointer(): number; 5 | export function amplify_audio(): void; 6 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/audio_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-audio/demo/rust/pkg/audio_bg.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/graphics.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @returns {number} 4 | */ 5 | export function get_input_buffer_pointer(): number; 6 | /** 7 | * @returns {number} 8 | */ 9 | export function get_output_buffer_pointer(): number; 10 | /** 11 | * @returns {void} 12 | */ 13 | export function amplify_audio(): void; 14 | 15 | /** 16 | * If `module_or_path` is {RequestInfo}, makes a request and 17 | * for everything else, calls `WebAssembly.instantiate` directly. 18 | * 19 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 20 | * 21 | * @returns {Promise} 22 | */ 23 | export default function init( 24 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 25 | ): Promise; 26 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/graphics.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | /** 5 | * @returns {number} 6 | */ 7 | export function get_input_buffer_pointer() { 8 | return wasm.get_input_buffer_pointer(); 9 | } 10 | __exports.get_input_buffer_pointer = get_input_buffer_pointer; 11 | 12 | /** 13 | * @returns {number} 14 | */ 15 | export function get_output_buffer_pointer() { 16 | return wasm.get_output_buffer_pointer(); 17 | } 18 | __exports.get_output_buffer_pointer = get_output_buffer_pointer; 19 | 20 | /** 21 | * @returns {void} 22 | */ 23 | export function amplify_audio() { 24 | return wasm.amplify_audio(); 25 | } 26 | __exports.amplify_audio = amplify_audio; 27 | 28 | function init(module) { 29 | let result; 30 | const imports = { "./graphics": __exports }; 31 | 32 | if ( 33 | module instanceof URL || 34 | typeof module === "string" || 35 | module instanceof Request 36 | ) { 37 | const response = fetch(module); 38 | if (typeof WebAssembly.instantiateStreaming === "function") { 39 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 40 | console.warn( 41 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 42 | e 43 | ); 44 | return response 45 | .then(r => r.arrayBuffer()) 46 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 47 | }); 48 | } else { 49 | result = response 50 | .then(r => r.arrayBuffer()) 51 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 52 | } 53 | } else { 54 | result = WebAssembly.instantiate(module, imports).then(result => { 55 | if (result instanceof WebAssembly.Instance) { 56 | return { instance: result, module }; 57 | } else { 58 | return result; 59 | } 60 | }); 61 | } 62 | return result.then(({ instance, module }) => { 63 | wasm = instance.exports; 64 | init.__wbindgen_wasm_module = module; 65 | 66 | return wasm; 67 | }); 68 | } 69 | 70 | export default init; 71 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/graphics_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function get_input_buffer_pointer(): number; 4 | export function get_output_buffer_pointer(): number; 5 | export function amplify_audio(): void; 6 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/graphics_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-audio/demo/rust/pkg/graphics_bg.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audio", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "audio_bg.wasm", 9 | "audio.js", 10 | "audio.d.ts" 11 | ], 12 | "module": "audio.js", 13 | "types": "audio.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/reading-and-writing-audio/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 2 | // Import the wasm-bindgen crate. 3 | use wasm_bindgen::prelude::*; 4 | 5 | // Define our number of samples we handle at once 6 | const NUMBER_OF_SAMPLES: usize = 1024; 7 | 8 | // Create a static mutable byte buffers. 9 | // We will use these for passing audio samples from 10 | // javascript to wasm, and from wasm to javascript 11 | // NOTE: global `static mut` means we will have "unsafe" code 12 | // but for passing memory between js and wasm should be fine. 13 | static mut INPUT_BUFFER: [u8; NUMBER_OF_SAMPLES] = [0; NUMBER_OF_SAMPLES]; 14 | static mut OUTPUT_BUFFER: [u8; NUMBER_OF_SAMPLES] = [0; NUMBER_OF_SAMPLES]; 15 | 16 | // Function to return a pointer to our 17 | // output buffer in wasm memory 18 | #[wasm_bindgen] 19 | pub fn get_input_buffer_pointer() -> *const u8 { 20 | let pointer: *const u8; 21 | unsafe { 22 | pointer = INPUT_BUFFER.as_ptr(); 23 | } 24 | 25 | return pointer; 26 | } 27 | 28 | // Function to return a pointer to our 29 | // output buffer in wasm memory 30 | #[wasm_bindgen] 31 | pub fn get_output_buffer_pointer() -> *const u8 { 32 | let pointer: *const u8; 33 | unsafe { 34 | pointer = OUTPUT_BUFFER.as_ptr(); 35 | } 36 | 37 | return pointer; 38 | } 39 | 40 | // Function to do the amplification. 41 | // By taking the samples currently in the input buffer 42 | // amplifying them, and placing the result in the output buffer 43 | #[wasm_bindgen] 44 | pub fn amplify_audio() { 45 | 46 | // Loop over the samples 47 | for i in 0..NUMBER_OF_SAMPLES { 48 | // Load the sample at the index 49 | let mut audio_sample: u8; 50 | unsafe { 51 | audio_sample = INPUT_BUFFER[i]; 52 | } 53 | 54 | // Amplify the sample. All samples 55 | // Should be implemented as bytes. 56 | // Byte samples are represented as follows: 57 | // 127 is silence, 0 is negative max, 256 is positive max 58 | if audio_sample > 127 { 59 | let audio_sample_diff = audio_sample - 127; 60 | audio_sample = audio_sample + audio_sample_diff; 61 | } else if audio_sample < 127 { 62 | audio_sample = audio_sample / 2; 63 | } 64 | 65 | // Store the audio sample into our output buffer 66 | unsafe { 67 | OUTPUT_BUFFER[i] = audio_sample; 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/assemblyscript/README.md: -------------------------------------------------------------------------------- 1 | # Reading And Writing Graphics (Assemblyscript) 2 | 3 | Compile with `asc index.ts -b index.wasm -t index.wat` 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reading and Writing Graphics - AssemblyScript 6 | 7 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/assemblyscript/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | 4 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 5 | 6 | const runWasm = async () => { 7 | // Instantiate our wasm module 8 | const wasmModule = await wasmBrowserInstantiate("./index.wasm"); 9 | 10 | // Get our exports object, with all of our exported Wasm Properties 11 | const exports = wasmModule.instance.exports; 12 | 13 | // Get our memory object from the exports 14 | const memory = exports.memory; 15 | 16 | // Create a Uint8Array to give us access to Wasm Memory 17 | const wasmByteMemoryArray = new Uint8Array(memory.buffer); 18 | 19 | // Get our canvas element from our index.html 20 | const canvasElement = document.querySelector("canvas"); 21 | 22 | // Set up Context and ImageData on the canvas 23 | const canvasContext = canvasElement.getContext("2d"); 24 | const canvasImageData = canvasContext.createImageData( 25 | canvasElement.width, 26 | canvasElement.height 27 | ); 28 | 29 | // Clear the canvas 30 | canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); 31 | 32 | const getDarkValue = () => { 33 | return Math.floor(Math.random() * 100); 34 | }; 35 | 36 | const getLightValue = () => { 37 | return Math.floor(Math.random() * 127) + 127; 38 | }; 39 | 40 | const drawCheckerBoard = () => { 41 | const checkerBoardSize = 20; 42 | 43 | // Generate a new checkboard in wasm 44 | exports.generateCheckerBoard( 45 | getDarkValue(), 46 | getDarkValue(), 47 | getDarkValue(), 48 | getLightValue(), 49 | getLightValue(), 50 | getLightValue() 51 | ); 52 | 53 | // Pull out the RGBA values from Wasm memory, the we wrote to in wasm, 54 | // starting at the checkerboard pointer (memory array index) 55 | const imageDataArray = wasmByteMemoryArray.slice( 56 | exports.CHECKERBOARD_BUFFER_POINTER.valueOf(), 57 | exports.CHECKERBOARD_BUFFER_SIZE.valueOf() 58 | ); 59 | 60 | // Set the values to the canvas image data 61 | canvasImageData.data.set(imageDataArray); 62 | 63 | // Clear the canvas 64 | canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); 65 | 66 | // Place the new generated checkerboard onto the canvas 67 | canvasContext.putImageData(canvasImageData, 0, 0); 68 | }; 69 | 70 | drawCheckerBoard(); 71 | setInterval(() => { 72 | drawCheckerBoard(); 73 | }, 1000); 74 | }; 75 | runWasm(); 76 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/assemblyscript/index.ts: -------------------------------------------------------------------------------- 1 | // Set up our memory 2 | // By growing our Wasm Memory by 1 page (64KB) 3 | memory.grow(1); 4 | 5 | // Define the size of our checkerboard 6 | const CHECKERBOARD_SIZE: i32 = 20; 7 | 8 | // Create a buffer/pointer (array index and size) to where 9 | // in memory we are storing the pixels. 10 | // NOTE: Be sure to set a correct --memoryBase when 11 | // when writing to memory directly like we are here. 12 | // https://docs.assemblyscript.org/details/compiler 13 | export const CHECKERBOARD_BUFFER_POINTER: i32 = 0; 14 | export const CHECKERBOARD_BUFFER_SIZE: i32 = 15 | CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4; 16 | 17 | // Function to generate our checkerboard, pixel by pixel 18 | export function generateCheckerBoard( 19 | darkValueRed: i32, 20 | darkValueGreen: i32, 21 | darkValueBlue: i32, 22 | lightValueRed: i32, 23 | lightValueGreen: i32, 24 | lightValueBlue: i32 25 | ): void { 26 | // Since Linear memory is a 1 dimensional array, but we want a grid 27 | // we will be doing 2d to 1d mapping 28 | // https://softwareengineering.stackexchange.com/questions/212808/treating-a-1d-data-structure-as-2d-grid 29 | for (let x: i32 = 0; x < CHECKERBOARD_SIZE; x++) { 30 | for (let y: i32 = 0; y < CHECKERBOARD_SIZE; y++) { 31 | // Set our default case to be dark squares 32 | let isDarkSquare: boolean = true; 33 | 34 | // We should change our default case if 35 | // We are on an odd y 36 | if (y % 2 === 0) { 37 | isDarkSquare = false; 38 | } 39 | 40 | // Lastly, alternate on our x value 41 | if (x % 2 === 0) { 42 | isDarkSquare = !isDarkSquare; 43 | } 44 | 45 | // Now that we determined if we are dark or light, 46 | // Let's set our square value 47 | let squareValueRed = darkValueRed; 48 | let squareValueGreen = darkValueGreen; 49 | let squareValueBlue = darkValueBlue; 50 | if (!isDarkSquare) { 51 | squareValueRed = lightValueRed; 52 | squareValueGreen = lightValueGreen; 53 | squareValueBlue = lightValueBlue; 54 | } 55 | 56 | // Let's calculate our index, using our 2d -> 1d mapping. 57 | // And then multiple by 4, for each pixel property (r,g,b,a). 58 | let squareNumber = y * CHECKERBOARD_SIZE + x; 59 | let squareRgbaIndex = squareNumber * 4; 60 | 61 | // Finally store the values. 62 | store( 63 | CHECKERBOARD_BUFFER_POINTER + squareRgbaIndex + 0, 64 | squareValueRed 65 | ); // Red 66 | store( 67 | CHECKERBOARD_BUFFER_POINTER + squareRgbaIndex + 1, 68 | squareValueGreen 69 | ); // Green 70 | store( 71 | CHECKERBOARD_BUFFER_POINTER + squareRgbaIndex + 2, 72 | squareValueBlue 73 | ); // Blue 74 | store(CHECKERBOARD_BUFFER_POINTER + squareRgbaIndex + 3, 255); // Alpha (Always opaque) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/assemblyscript/index.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-graphics/demo/assemblyscript/index.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/go/README.md: -------------------------------------------------------------------------------- 1 | Compile with TinyGo, by running: `tinygo build -o main.wasm -target wasm ./main.go` 2 | 3 | `wasm_exec.js` can be [copied from your TinyGo root](https://github.com/tinygo-org/tinygo/issues/1070). Which is [explained in the TinyGo Wasm Docs](https://tinygo.org/webassembly/webassembly/#how-it-works). 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reading and Writing Graphics - Go 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/go/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 4 | 5 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 6 | 7 | const runWasm = async () => { 8 | // Get the importObject from the go instance. 9 | const importObject = go.importObject; 10 | 11 | // Instantiate our wasm module 12 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 13 | 14 | // Allow the wasm_exec go instance, bootstrap and execute our wasm module 15 | go.run(wasmModule.instance); 16 | 17 | // Get our exports object, with all of our exported Wasm Properties 18 | const exports = wasmModule.instance.exports; 19 | 20 | // Get our memory object from the exports 21 | const memory = exports.memory; 22 | 23 | // Create a Uint8Array to give us access to Wasm Memory 24 | const wasmByteMemoryArray = new Uint8Array(memory.buffer); 25 | 26 | // Get the pointer (index) to where our graphics buffer is located in wasm linear memory 27 | const graphicsBufferPointer = exports.getGraphicsBufferPointer(); 28 | 29 | // Get the size of our graphics buffer that is located in wasm linear memory 30 | const graphicsBufferSize = exports.getGraphicsBufferSize(); 31 | 32 | // Get our canvas element from our index.html 33 | const canvasElement = document.querySelector("canvas"); 34 | 35 | // Set up Context and ImageData on the canvas 36 | const canvasContext = canvasElement.getContext("2d"); 37 | const canvasImageData = canvasContext.createImageData( 38 | canvasElement.width, 39 | canvasElement.height 40 | ); 41 | 42 | // Clear the canvas 43 | canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); 44 | 45 | const getDarkValue = () => { 46 | return Math.floor(Math.random() * 100); 47 | }; 48 | 49 | const getLightValue = () => { 50 | return Math.floor(Math.random() * 127) + 127; 51 | }; 52 | 53 | const drawCheckerBoard = () => { 54 | const checkerBoardSize = 20; 55 | 56 | // Generate a new checkboard in wasm 57 | exports.generateCheckerBoard( 58 | getDarkValue(), 59 | getDarkValue(), 60 | getDarkValue(), 61 | getLightValue(), 62 | getLightValue(), 63 | getLightValue() 64 | ); 65 | 66 | // Pull out the RGBA values from Wasm memory, the we wrote to in wasm, 67 | // starting at the checkerboard pointer (memory array index) 68 | const imageDataArray = wasmByteMemoryArray.slice( 69 | graphicsBufferPointer, 70 | graphicsBufferPointer + graphicsBufferSize 71 | ); 72 | 73 | // Set the values to the canvas image data 74 | canvasImageData.data.set(imageDataArray); 75 | 76 | // Clear the canvas 77 | canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); 78 | 79 | // Place the new generated checkerboard onto the canvas 80 | canvasContext.putImageData(canvasImageData, 0, 0); 81 | }; 82 | 83 | drawCheckerBoard(); 84 | setInterval(() => { 85 | drawCheckerBoard(); 86 | }, 1000); 87 | }; 88 | runWasm(); 89 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Define the size of our "checkerboard" 4 | const CHECKERBOARD_SIZE int = 20; 5 | 6 | /* 7 | * 1. What is going on here? 8 | * Create a byte buffer. 9 | * We will use for putting the output of our graphics, 10 | * to pass the output to js. 11 | * 12 | * 2. Why is the size CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4? 13 | * We want to have 20 pixels by 20 pixels. And 4 colors per pixel (r,g,b,a) 14 | * Which, the Canvas API Supports. 15 | */ 16 | const BUFFER_SIZE int = CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4; 17 | var graphicsBuffer [BUFFER_SIZE]uint8; 18 | 19 | 20 | // Declare a main function, this is the entrypoint into our go module 21 | // That will be run. In our example, we won't need this 22 | func main() {} 23 | 24 | // Function to return a pointer (Index) to our buffer in wasm memory 25 | //export getGraphicsBufferPointer 26 | func getGraphicsBufferPointer() *[BUFFER_SIZE]uint8 { 27 | return &graphicsBuffer 28 | } 29 | 30 | // Function to return the size of our buffer in wasm memory 31 | //export getGraphicsBufferSize 32 | func getGraphicsBufferSize() int { 33 | return BUFFER_SIZE; 34 | } 35 | 36 | // Function to generate our checkerboard, pixel by pixel 37 | //export generateCheckerBoard 38 | func generateCheckerBoard( 39 | darkValueRed uint8, 40 | darkValueGreen uint8, 41 | darkValueBlue uint8, 42 | lightValueRed uint8, 43 | lightValueGreen uint8, 44 | lightValueBlue uint8, 45 | ) { 46 | // Since Linear memory is a 1 dimensional array, but we want a grid 47 | // we will be doing 2d to 1d mapping 48 | // https://softwareengineering.stackexchange.com/questions/212808/treating-a-1d-data-structure-as-2d-grid 49 | for y := 0; y < CHECKERBOARD_SIZE; y++ { 50 | for x := 0; x < CHECKERBOARD_SIZE; x++ { 51 | // Set our default case to be dark squares 52 | isDarkSquare := true; 53 | 54 | // We should change our default case if 55 | // We are on an odd y 56 | if y % 2 == 0 { 57 | isDarkSquare = false; 58 | } 59 | 60 | // Lastly, alternate on our x value 61 | if x % 2 == 0 { 62 | isDarkSquare = !isDarkSquare; 63 | } 64 | 65 | // Now that we determined if we are dark or light, 66 | // Let's set our square value 67 | squareValueRed := darkValueRed; 68 | squareValueGreen := darkValueGreen; 69 | squareValueBlue := darkValueBlue; 70 | if !isDarkSquare { 71 | squareValueRed = lightValueRed; 72 | squareValueGreen = lightValueGreen; 73 | squareValueBlue = lightValueBlue; 74 | } 75 | 76 | // Let's calculate our index, using our 2d -> 1d mapping. 77 | // And then multiple by 4, for each pixel property (r,g,b,a). 78 | squareNumber := (y * CHECKERBOARD_SIZE) + x; 79 | squareRgbaIndex := squareNumber * 4; 80 | 81 | graphicsBuffer[squareRgbaIndex + 0] = squareValueRed; // Red 82 | graphicsBuffer[squareRgbaIndex + 1] = squareValueGreen; // Green 83 | graphicsBuffer[squareRgbaIndex + 2] = squareValueBlue; // Blue 84 | graphicsBuffer[squareRgbaIndex + 3] = 255; // Alpha (Always Opaque) 85 | } 86 | } 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-graphics/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "graphics" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # Reading And Writing Graphics (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Graphics - Rust 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/index.js: -------------------------------------------------------------------------------- 1 | import wasmInit from "./pkg/graphics.js"; 2 | 3 | const runWasm = async () => { 4 | // Instantiate our wasm module 5 | const rustWasm = await wasmInit("./pkg/graphics_bg.wasm"); 6 | 7 | // Create a Uint8Array to give us access to Wasm Memory 8 | const wasmByteMemoryArray = new Uint8Array(rustWasm.memory.buffer); 9 | 10 | // Get our canvas element from our index.html 11 | const canvasElement = document.querySelector("canvas"); 12 | 13 | // Set up Context and ImageData on the canvas 14 | const canvasContext = canvasElement.getContext("2d"); 15 | const canvasImageData = canvasContext.createImageData( 16 | canvasElement.width, 17 | canvasElement.height 18 | ); 19 | 20 | // Clear the canvas 21 | canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); 22 | 23 | // Write some functions to get a color value 24 | // for either the darker squares and lighter squares 25 | const getDarkValue = () => { 26 | return Math.floor(Math.random() * 100); 27 | }; 28 | const getLightValue = () => { 29 | return Math.floor(Math.random() * 127) + 127; 30 | }; 31 | 32 | const drawCheckerBoard = () => { 33 | const checkerBoardSize = 20; 34 | 35 | // Generate a new checkboard in wasm 36 | rustWasm.generate_checker_board( 37 | getDarkValue(), 38 | getDarkValue(), 39 | getDarkValue(), 40 | getLightValue(), 41 | getLightValue(), 42 | getLightValue() 43 | ); 44 | 45 | // Create a Uint8Array to give us access to Wasm Memory 46 | const wasmByteMemoryArray = new Uint8Array(rustWasm.memory.buffer); 47 | 48 | // Pull out the RGBA values from Wasm memory 49 | // Starting at the memory index of out output buffer (given by our pointer) 50 | // 20 * 20 * 4 = checkboard max X * checkerboard max Y * number of pixel properties (R,G.B,A) 51 | const outputPointer = rustWasm.get_output_buffer_pointer(); 52 | const imageDataArray = wasmByteMemoryArray.slice( 53 | outputPointer, 54 | outputPointer + checkerBoardSize * checkerBoardSize * 4 55 | ); 56 | 57 | // Set the values to the canvas image data 58 | canvasImageData.data.set(imageDataArray); 59 | 60 | // Clear the canvas 61 | canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); 62 | 63 | // Place the new generated checkerboard onto the canvas 64 | canvasContext.putImageData(canvasImageData, 0, 0); 65 | }; 66 | 67 | // Lastly, call our function to draw a checkerboard 68 | // And run this once every second 69 | drawCheckerBoard(); 70 | setInterval(() => { 71 | drawCheckerBoard(); 72 | }, 1000); 73 | }; 74 | runWasm(); 75 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Assemblyscript) 2 | 3 | Compile with `asc hello-world.ts -b hello-world.wasm -t hello-world.wat` 4 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/pkg/graphics.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @returns {number} 4 | */ 5 | export function get_output_buffer_pointer(): number; 6 | /** 7 | * @param {number} dark_value_red 8 | * @param {number} dark_value_green 9 | * @param {number} dark_value_blue 10 | * @param {number} light_value_red 11 | * @param {number} light_value_green 12 | * @param {number} light_value_blue 13 | * @returns {void} 14 | */ 15 | export function generate_checker_board( 16 | dark_value_red: number, 17 | dark_value_green: number, 18 | dark_value_blue: number, 19 | light_value_red: number, 20 | light_value_green: number, 21 | light_value_blue: number 22 | ): void; 23 | 24 | /** 25 | * If `module_or_path` is {RequestInfo}, makes a request and 26 | * for everything else, calls `WebAssembly.instantiate` directly. 27 | * 28 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 29 | * 30 | * @returns {Promise} 31 | */ 32 | export default function init( 33 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 34 | ): Promise; 35 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/pkg/graphics.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | /** 5 | * @returns {number} 6 | */ 7 | export function get_output_buffer_pointer() { 8 | return wasm.get_output_buffer_pointer(); 9 | } 10 | __exports.get_output_buffer_pointer = get_output_buffer_pointer; 11 | 12 | /** 13 | * @param {number} dark_value_red 14 | * @param {number} dark_value_green 15 | * @param {number} dark_value_blue 16 | * @param {number} light_value_red 17 | * @param {number} light_value_green 18 | * @param {number} light_value_blue 19 | * @returns {void} 20 | */ 21 | export function generate_checker_board( 22 | dark_value_red, 23 | dark_value_green, 24 | dark_value_blue, 25 | light_value_red, 26 | light_value_green, 27 | light_value_blue 28 | ) { 29 | return wasm.generate_checker_board( 30 | dark_value_red, 31 | dark_value_green, 32 | dark_value_blue, 33 | light_value_red, 34 | light_value_green, 35 | light_value_blue 36 | ); 37 | } 38 | __exports.generate_checker_board = generate_checker_board; 39 | 40 | function init(module) { 41 | let result; 42 | const imports = { "./graphics": __exports }; 43 | 44 | if ( 45 | module instanceof URL || 46 | typeof module === "string" || 47 | module instanceof Request 48 | ) { 49 | const response = fetch(module); 50 | if (typeof WebAssembly.instantiateStreaming === "function") { 51 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 52 | console.warn( 53 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 54 | e 55 | ); 56 | return response 57 | .then(r => r.arrayBuffer()) 58 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 59 | }); 60 | } else { 61 | result = response 62 | .then(r => r.arrayBuffer()) 63 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 64 | } 65 | } else { 66 | result = WebAssembly.instantiate(module, imports).then(result => { 67 | if (result instanceof WebAssembly.Instance) { 68 | return { instance: result, module }; 69 | } else { 70 | return result; 71 | } 72 | }); 73 | } 74 | return result.then(({ instance, module }) => { 75 | wasm = instance.exports; 76 | init.__wbindgen_wasm_module = module; 77 | 78 | return wasm; 79 | }); 80 | } 81 | 82 | export default init; 83 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/pkg/graphics_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function get_output_buffer_pointer(): number; 4 | export function generate_checker_board( 5 | a: number, 6 | b: number, 7 | c: number, 8 | d: number, 9 | e: number, 10 | f: number 11 | ): void; 12 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/pkg/graphics_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/reading-and-writing-graphics/demo/rust/pkg/graphics_bg.wasm -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphics", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "graphics_bg.wasm", 9 | "graphics.js", 10 | "graphics.d.ts" 11 | ], 12 | "module": "graphics.js", 13 | "types": "graphics.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/reading-and-writing-graphics/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 2 | // Import the wasm-bindgen crate. 3 | use wasm_bindgen::prelude::*; 4 | 5 | // Define the size of our "checkerboard" 6 | const CHECKERBOARD_SIZE: usize = 20; 7 | 8 | /* 9 | * 1. What is going on here? 10 | * Create a static mutable byte buffer. 11 | * We will use for putting the output of our graphics, 12 | * to pass the output to js. 13 | * NOTE: global `static mut` means we will have "unsafe" code 14 | * but for passing memory between js and wasm should be fine. 15 | * 16 | * 2. Why is the size CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4? 17 | * We want to have 20 pixels by 20 pixels. And 4 colors per pixel (r,g,b,a) 18 | * Which, the Canvas API Supports. 19 | */ 20 | const OUTPUT_BUFFER_SIZE: usize = CHECKERBOARD_SIZE * CHECKERBOARD_SIZE * 4; 21 | static mut OUTPUT_BUFFER: [u8; OUTPUT_BUFFER_SIZE] = [0; OUTPUT_BUFFER_SIZE]; 22 | 23 | // Function to return a pointer to our buffer 24 | // in wasm memory 25 | #[wasm_bindgen] 26 | pub fn get_output_buffer_pointer() -> *const u8 { 27 | let pointer: *const u8; 28 | unsafe { 29 | pointer = OUTPUT_BUFFER.as_ptr(); 30 | } 31 | 32 | return pointer; 33 | } 34 | 35 | // Function to generate our checkerboard, pixel by pixel 36 | #[wasm_bindgen] 37 | pub fn generate_checker_board( 38 | dark_value_red: u8, 39 | dark_value_green: u8, 40 | dark_value_blue: u8, 41 | light_value_red: u8, 42 | light_value_green: u8, 43 | light_value_blue: u8 44 | ) { 45 | 46 | // Since Linear memory is a 1 dimensional array, but we want a grid 47 | // we will be doing 2d to 1d mapping 48 | // https://softwareengineering.stackexchange.com/questions/212808/treating-a-1d-data-structure-as-2d-grid 49 | for y in 0..CHECKERBOARD_SIZE { 50 | for x in 0..CHECKERBOARD_SIZE { 51 | // Set our default case to be dark squares 52 | let mut is_dark_square: bool = true; 53 | 54 | // We should change our default case if 55 | // We are on an odd y 56 | if y % 2 == 0 { 57 | is_dark_square = false; 58 | } 59 | 60 | // Lastly, alternate on our x value 61 | if x % 2 == 0 { 62 | is_dark_square = !is_dark_square; 63 | } 64 | 65 | // Now that we determined if we are dark or light, 66 | // Let's set our square value 67 | let mut square_value_red: u8 = dark_value_red; 68 | let mut square_value_green: u8 = dark_value_green; 69 | let mut square_value_blue: u8 = dark_value_blue; 70 | if !is_dark_square { 71 | square_value_red = light_value_red; 72 | square_value_green = light_value_green; 73 | square_value_blue = light_value_blue; 74 | } 75 | 76 | // Let's calculate our index, using our 2d -> 1d mapping. 77 | // And then multiple by 4, for each pixel property (r,g,b,a). 78 | let square_number: usize = y * CHECKERBOARD_SIZE + x; 79 | let square_rgba_index: usize = square_number * 4; 80 | 81 | // Finally store the values. 82 | unsafe { 83 | OUTPUT_BUFFER[square_rgba_index + 0] = square_value_red; // Red 84 | OUTPUT_BUFFER[square_rgba_index + 1] = square_value_green; // Green 85 | OUTPUT_BUFFER[square_rgba_index + 2] = square_value_blue; // Blue 86 | OUTPUT_BUFFER[square_rgba_index + 3] = 255; // Alpha (Always Opaque) 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /examples/strings/demo/c/caesar.cpp: -------------------------------------------------------------------------------- 1 | typedef long int i32; 2 | 3 | extern "C" { 4 | void caesarEncrypt(i32 *plaintext, i32 plaintextLength, i32 key) { 5 | for (int i = 0; i < plaintextLength; i++) { 6 | plaintext[i] = (plaintext[i] + key) % 26; 7 | } 8 | } 9 | 10 | void caesarDecrypt(i32 *ciphertext, i32 ciphertextLength, i32 key) { 11 | for (int i = 0; i < ciphertextLength; i++) { 12 | ciphertext[i] = (ciphertext[i] - key) % 26; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/strings/demo/c/caesar.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/strings/demo/c/caesar.wasm -------------------------------------------------------------------------------- /examples/strings/demo/c/index.html: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/assemblyscript/assembly/index.ts: -------------------------------------------------------------------------------- 1 | // As of AssemblyScript 0.10.0, adding `import "wasi"`, will automatically 2 | // import WASI bindings, and add some nice defaults for compiling to WASI. 3 | import "wasi"; 4 | 5 | // Import Console (for writing to stdout), and FileSystem (for reading/writing files) 6 | // from "as-wasi". An API for working with WASI in AssemblyScript much easier. 7 | import { Console, FileSystem, Descriptor } from "as-wasi"; 8 | 9 | // Print out hello world! 10 | // This will handle writing to stdout for us using the WASI APIs (e.g fd_write) 11 | Console.log("Hello World!"); 12 | 13 | // We are creating/opening a `helloworld.txt` file 14 | // This code requires the Wasi host to provide a directory on the guest. 15 | // For example, in Wasmtime, if you want to access to the current directory, 16 | // invoke the wasmtime with the flag/argument: `--dir .` 17 | // FileSystem.open will return null if it fails to create/open the file 18 | let filePath: string = "helloworld.txt"; 19 | let fileOrNull: Descriptor | null = FileSystem.open(filePath, "w+"); 20 | 21 | // Check if the FileSystem.open() returned null. 22 | // If fileOrNull is null, that means we could not create/open the file 23 | // (Probably because we did not add the `--dir` flag) 24 | // Throw an error. 25 | if (fileOrNull == null) { 26 | throw new Error("Could not open the file " + filePath); 27 | } 28 | 29 | // Change our type from Descriptor | null, to Descriptor, as we checked above. 30 | // Meaning, we were able to successfully open/create the file 31 | let file = changetype(fileOrNull); 32 | 33 | // Write "Hello World!" to the file. 34 | file.writeStringLn("Hello World!"); 35 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/assemblyscript/build/index.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/wasi-hello-world/demo/assemblyscript/build/index.wasm -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/assemblyscript/helloworld.txt: -------------------------------------------------------------------------------- 1 | Hello World! 2 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/assemblyscript/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "assemblyscript", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "as-wasi": "^0.4.6", 9 | "assemblyscript": "^0.19.9" 10 | } 11 | }, 12 | "node_modules/as-wasi": { 13 | "version": "0.4.6", 14 | "resolved": "https://registry.npmjs.org/as-wasi/-/as-wasi-0.4.6.tgz", 15 | "integrity": "sha512-HFWdxLVHrOfchf/M+gE2IczsHBkWXqekZZfHYmDj6WP1UnpQC4k44OeyjqmSwC/db1tppEwCUssDCuFGnMdJZw==" 16 | }, 17 | "node_modules/assemblyscript": { 18 | "version": "0.19.9", 19 | "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.19.9.tgz", 20 | "integrity": "sha512-nVEg1bbGBegJp+UO9okNHgjCX6sri4OrIkl/LCaNWLIvioN2IjFeYt3R6ppZ6L813VYJxKhf0hr6lhXOXw3dvA==", 21 | "dependencies": { 22 | "binaryen": "101.0.0-nightly.20210723", 23 | "long": "^4.0.0" 24 | }, 25 | "bin": { 26 | "asc": "bin/asc", 27 | "asinit": "bin/asinit" 28 | }, 29 | "funding": { 30 | "type": "opencollective", 31 | "url": "https://opencollective.com/assemblyscript" 32 | } 33 | }, 34 | "node_modules/binaryen": { 35 | "version": "101.0.0-nightly.20210723", 36 | "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-101.0.0-nightly.20210723.tgz", 37 | "integrity": "sha512-eioJNqhHlkguVSbblHOtLqlhtC882SOEPKmNFZaDuz1hzQjolxZ+eu3/kaS10n3sGPONsIZsO7R9fR00UyhEUA==", 38 | "bin": { 39 | "wasm-opt": "bin/wasm-opt" 40 | } 41 | }, 42 | "node_modules/long": { 43 | "version": "4.0.0", 44 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 45 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 46 | } 47 | }, 48 | "dependencies": { 49 | "as-wasi": { 50 | "version": "0.4.6", 51 | "resolved": "https://registry.npmjs.org/as-wasi/-/as-wasi-0.4.6.tgz", 52 | "integrity": "sha512-HFWdxLVHrOfchf/M+gE2IczsHBkWXqekZZfHYmDj6WP1UnpQC4k44OeyjqmSwC/db1tppEwCUssDCuFGnMdJZw==" 53 | }, 54 | "assemblyscript": { 55 | "version": "0.19.9", 56 | "resolved": "https://registry.npmjs.org/assemblyscript/-/assemblyscript-0.19.9.tgz", 57 | "integrity": "sha512-nVEg1bbGBegJp+UO9okNHgjCX6sri4OrIkl/LCaNWLIvioN2IjFeYt3R6ppZ6L813VYJxKhf0hr6lhXOXw3dvA==", 58 | "requires": { 59 | "binaryen": "101.0.0-nightly.20210723", 60 | "long": "^4.0.0" 61 | } 62 | }, 63 | "binaryen": { 64 | "version": "101.0.0-nightly.20210723", 65 | "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-101.0.0-nightly.20210723.tgz", 66 | "integrity": "sha512-eioJNqhHlkguVSbblHOtLqlhtC882SOEPKmNFZaDuz1hzQjolxZ+eu3/kaS10n3sGPONsIZsO7R9fR00UyhEUA==" 67 | }, 68 | "long": { 69 | "version": "4.0.0", 70 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 71 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/assemblyscript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "asc assembly/index.ts -b build/index.wasm -t build/index.wat", 4 | "start": "wasmtime --dir . build/index.wasm" 5 | }, 6 | "dependencies": { 7 | "as-wasi": "^0.4.6", 8 | "assemblyscript": "^0.19.9" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/go/helloworld.txt: -------------------------------------------------------------------------------- 1 | Hello world! 2 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Import "fmt" from the Go Standard library to write to standard out 4 | // Import "io/ioutil" from the Go Standard library to write to the filesystem 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | ) 9 | 10 | func main() { 11 | // Print out hello world! 12 | // This will handle writing to stdout for us using the WASI APIs (e.g fd_write) 13 | fmt.Println("Hello world!") 14 | 15 | // Get our hello world string as bytes, so we can write the string using ioutil 16 | helloWorldAsBytes := []byte("Hello world!\n") 17 | 18 | // We are writing a `helloworld.txt` file 19 | // This code requires the Wasi host to provide a directory on the guest. 20 | // For example, in Wasmtime, if you want to access to the current directory, 21 | // invoke the wasmtime with the flag/argument: `--dir .` 22 | err := ioutil.WriteFile("./helloworld.txt", helloWorldAsBytes, 0644) 23 | 24 | // If err is not nil, that means we could not create/write the file 25 | // (Probably because we did not add the `--dir` flag on our wasmtime command) 26 | if err != nil { 27 | panic(err) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/wasi-hello-world/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/go/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Compile the TinyGo Wasm Module that targets WASI 4 | # Note, some features aren't fully supported by WASI. So if you hit nil pointer references 5 | # You may want to play around with the scheduler and gc flags. For example: 6 | # "-scheduler=none -gc=conservative" or "-scheduler=coroutines -gc=leaking" 7 | tinygo build -wasm-abi=generic -target=wasi -o main.wasm main.go 8 | 9 | # Run the Wasm module with wasmtime, 10 | # while passing in the capability to modify the filesytem of the current directory 11 | wasmtime --dir . main.wasm 12 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "wasi_hello_world" 5 | version = "0.1.0" 6 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasi_hello_world" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 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 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/rust/helloworld.txt: -------------------------------------------------------------------------------- 1 | Hello world! 2 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/demo/rust/src/main.rs: -------------------------------------------------------------------------------- 1 | // Import rust's io and filesystem module 2 | use std::io::prelude::*; 3 | use std::fs; 4 | 5 | // Entry point to our WASI applications 6 | fn main() { 7 | // Print out hello world! 8 | // This will handle writing to stdout for us using the WASI APIs (e.g fd_write) 9 | println!("Hello world!"); 10 | 11 | // Create a file 12 | // We are creating a `helloworld.txt` file in the `/helloworld` directory 13 | // This code requires the Wasi host to provide a `/helloworld` directory on the guest. 14 | // If the `/helloworld` directory is not available, the unwrap() will cause this program to panic. 15 | // For example, in Wasmtime, if you want to map the current directory to `/helloworld`, 16 | // invoke the runtime with the flag/argument: `--mapdir /helloworld::.` 17 | // This will map the `/helloworld` directory on the guest, to the current directory (`.`) on the host 18 | let mut file = fs::File::create("/helloworld/helloworld.txt").unwrap(); 19 | 20 | // Write the text to the file we created 21 | write!(file, "Hello world!\n").unwrap(); 22 | } 23 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/wasi-hello-world.go.en-us.md: -------------------------------------------------------------------------------- 1 | # WASI Hello World 2 | 3 | ## Overview 4 | 5 | In this example, We will be writing "Hello world!" to both the console (`stdout`), and a newly created file `helloworld.txt`. We highly reccomended that you have read the [WASI Introduction](/example-redirect?exampleName=wasi-introduction&programmingLanguage=all) before procedding with this example. You should install [wasmtime](https://wasmtime.dev/) as that is the WebAssembly runtime we will be using as our host. 6 | 7 | --- 8 | 9 | ## Implementation 10 | 11 | First, we will create a new `main.go` file, with the following code: 12 | 13 | ```go 14 | package main 15 | 16 | // Import "fmt" from the Go Standard library to write to standard out 17 | // Import "io/ioutil" from the Go Standard library to write to the filesystem 18 | import ( 19 | "fmt" 20 | "io/ioutil" 21 | ) 22 | 23 | func main() { 24 | // Print out hello world! 25 | // This will handle writing to stdout for us using the WASI APIs (e.g fd_write) 26 | fmt.Println("Hello world!") 27 | 28 | // Get our hello world string as bytes, so we can write the string using ioutil 29 | helloWorldAsBytes := []byte("Hello world!\n") 30 | 31 | // We are writing a `helloworld.txt` file 32 | // This code requires the Wasi host to provide a directory on the guest. 33 | // For example, in Wasmtime, if you want to access to the current directory, 34 | // invoke the wasmtime with the flag/argument: `--dir .` 35 | err := ioutil.WriteFile("./helloworld.txt", helloWorldAsBytes, 0644) 36 | 37 | // If err is not nil, that means we could not create/write the file 38 | // (Probably because we did not add the `--dir` flag on our wasmtime command) 39 | if err != nil { 40 | panic(err) 41 | } 42 | } 43 | ``` 44 | 45 | As mentioned in the code comments, even though the [WASI APIs](https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md) are not being used directly, when we compile our program to WASI, TinyGo will be calling the host functions for us through it's standard library functions. 46 | 47 | Next, Let's compile our `main.go` into a Wasm module that targets WASI! 48 | 49 | This can be down with the `-wasm-abi=generic` and `-target=wasi` flags when you run the TinyGo compiler: 50 | 51 | ```bash 52 | tinygo build -wasm-abi=generic -target=wasi -o main.wasm main.go 53 | ``` 54 | 55 | Which should output (`-o`) a `main.wasm` file that we can run in a WebAssembly runtime that supports WASI! 56 | 57 | > **NOTE:** As of July, 2021 goroutines and other language features may be in a funny place in terms of WASI support. Thus, if this is something you are trying to support it is worth playing around with the `-scheduler` and `-gc` compiler flags. For example, it may be worth adding the flags `"-scheduler=none -gc=conservative"` or `"-scheduler=coroutines -gc=leaking"` flag combination to a simple TinyGo compilation. (E.g `tinygo build -wasm-abi=generic -target=wasi -scheduler=coroutines -gc=leaking -o main.wasm main.go`). 58 | 59 | Now that we have our Wasm Module that targets WASI, we can run the module using the Wasmtime CLI. We mentioned wasmtime should be installed at the beginning of this tutorial. However, there is one thing to note that was mentioned in the code comments. **We need to give our program explicit access to create files on our host, because our program creates a new file**. As mentioned in the [WASI Introduction](/example-redirect?exampleName=wasi-introduction), our guest will not have this capability unless we give them the capability. 60 | 61 | Thus, when we use the Wasmtime CLI to run our wasm module, we should pass the `--dir .` flag. This grants wasmtime the capability to read/write files in the current directory (`.`). 62 | 63 | Finally, let's run our Wasm module with the Wasmtime CLI: 64 | 65 | ```bash 66 | wasmtime --dir . main.wasm 67 | ``` 68 | 69 | You should then see "Hello World!" logged in your terminal. You should also notice that a `helloworld.txt` file was created in your current directory, with the contents of "Hello World!". 70 | 71 | Yay! We have successfully written our first WASI module! 72 | 73 | --- 74 | 75 | WASI is still growing, and there are a lot of projects that are taking advantages of WASI to do interesting things! You can see some examples of projects written for, or ported to WebAssembly using WASI, by searching "WASI" on [Made with WebAssembly](https://madewithwebassembly.com/). 76 | 77 | Feel free to [fix, suggest, or contribute more examples](https://github.com/torch2424/wasm-by-example)! 78 | -------------------------------------------------------------------------------- /examples/wasi-hello-world/wasi-hello-world.rust.en-us.md: -------------------------------------------------------------------------------- 1 | # WASI Hello World 2 | 3 | ## Overview 4 | 5 | In this example, We will be writing "Hello world!" to both the console (`stdout`), and a newly created file `./hello-world.txt`. We highly reccomended that you have read the [WASI Introduction](/example-redirect?exampleName=wasi-introduction&programmingLanguage=all) before procedding with this example. You should install [wasmtime](https://wasmtime.dev/) as that is the WebAssembly runtime we will be using as our host. You should also ensure that Rust is installed using the rustup [rustup](https://rustup.rs/) tool. 6 | 7 | This example will be similar to [WASI Tutorial on the wasmtime repo](https://github.com/bytecodealliance/wasmtime/blob/master/docs/WASI-tutorial.md). 8 | 9 | --- 10 | 11 | ## Implementation 12 | 13 | First, we will generate a new executable with cargo: 14 | 15 | ```bash 16 | $ cargo new --bin wasi_hello_world 17 | $ cd wasi_hello_world 18 | ``` 19 | 20 | Then, we will open the `src/main.rs` and enter the following contents. Please see the comments to understand what our program will be doing: 21 | 22 | ```rust 23 | // Import rust's io and filesystem module 24 | use std::io::prelude::*; 25 | use std::fs; 26 | 27 | // Entry point to our WASI applications 28 | fn main() { 29 | 30 | // Print out hello world! 31 | // This will handle writing to stdout for us using the WASI APIs (e.g fd_write) 32 | println!("Hello world!"); 33 | 34 | // Create a file 35 | // We are creating a `helloworld.txt` file in the `/helloworld` directory 36 | // This code requires the Wasi host to provide a `/helloworld` directory on the guest. 37 | // If the `/helloworld` directory is not available, the unwrap() will cause this program to panic. 38 | // For example, in Wasmtime, if you want to map the current directory to `/helloworld`, 39 | // invoke the runtime with the flag/argument: `--mapdir /helloworld::.` 40 | // This will map the `/helloworld` directory on the guest, to the current directory (`.`) on the host 41 | let mut file = fs::File::create("/helloworld/helloworld.txt").unwrap(); 42 | 43 | // Write the text to the file we created 44 | write!(file, "Hello world!\n").unwrap(); 45 | } 46 | ``` 47 | 48 | As mentioned in the code comments, even though the [WASI APIs](https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md) are not being used directly, when we compile our program to WASI, the rust APIs will be using these WASI APIs under the hood for us. 49 | 50 | Next, we will want to add WASI as a target that we can compile to. We will ask the rustup tool to install support for WASI. Then, we will compile our program to WASI. To do this we will run: 51 | 52 | ```bash 53 | $ rustup target add wasm32-wasi 54 | $ cargo build --target wasm32-wasi 55 | ``` 56 | 57 | Our wasm file should be compiled to `target/wasm32-wasi/debug/wasi_hello_world.wasm`. And now we can actually run our program! 58 | 59 | To do this, we can use the Wasmtime CLI, which we mentioned should be installed at the beginning of this tutorial. However, there is one thing to note that was mentioned in the code comments. **We need to give our program explicit access to create files on our host, because our program creates a new file**. As mentioned in the [WASI Introduction](/example-redirect?exampleName=wasi-introduction), our guest will not have this capability unless we give them the capability. 60 | 61 | To grant the capability to write in a directory using the Wasmtime CLI, we need to use the `--mapdir` flag. `--mapdir` will allow us to map the `/helloworld` directory on the guest's virtual filesystem, to the current directory (`.`) on the host fileystem. For example: 62 | 63 | ```bash 64 | wasmtime --mapdir GUEST_DIRECTORY::HOST_DIRECTORY my-wasi-program.wasm 65 | ``` 66 | 67 | So, **to run our compiled WASI program, we will run**: 68 | 69 | ```bash 70 | wasmtime --mapdir /helloworld::. target/wasm32-wasi/debug/wasi_hello_world.wasm 71 | ``` 72 | 73 | You should then see "Hello World!" logged in your terminal. You should also notice that a `helloworld.txt` file was created in your current directory, with the contents of "Hello World!". 74 | 75 | Yay! We have successfully written our first WASI module. 76 | 77 | --- 78 | 79 | WASI is still growing, and there are a lot of projects that are taking advantages of WASI to do interesting things! You can see some examples of projects written for, or ported to WebAssembly using WASI, by searching "WASI" on [Made with WebAssembly](https://madewithwebassembly.com/). If you wanted to learn more about Rust and WASI at a hostcall level, here is a [great tutorial by Jakub Konka](http://www.jakubkonka.com/2020/04/28/rust-wasi-from-scratch.html). 80 | 81 | Feel free to [fix, suggest, or contribute more examples](https://github.com/torch2424/wasm-by-example)! 82 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/assemblyscript/README.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Linear Memory (Assemblyscript) 2 | 3 | Compile with `asc index.ts -b index.wasm -t index.wat` 4 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/assemblyscript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebAssembly Linear Memory - AssemblyScript 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/assemblyscript/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | 4 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 5 | import { domConsoleLog } from "/demo-util/domConsole.js"; 6 | 7 | const runWasmAdd = async () => { 8 | // Instantiate our wasm module 9 | const wasmModule = await wasmBrowserInstantiate("./index.wasm"); 10 | 11 | // Get our exports object, with all of our exported Wasm Properties 12 | const exports = wasmModule.instance.exports; 13 | 14 | // Get our memory object from the exports 15 | const memory = exports.memory; 16 | 17 | // Create a Uint8Array to give us access to Wasm Memory 18 | const wasmByteMemoryArray = new Uint8Array(memory.buffer); 19 | 20 | // Let's read index zero from JS, to make sure Wasm wrote to 21 | // wasm memory, and JS can read the "passed" value from Wasm 22 | domConsoleLog("Read from JS index Zero: " + wasmByteMemoryArray[0]); // Should Log "24". 23 | 24 | // Next let's write to index one, to make sure we can 25 | // write wasm memory, and Wasm can read the "passed" value from JS 26 | wasmByteMemoryArray[1] = 15; 27 | domConsoleLog( 28 | "Read from Wasm index one: " + exports.readWasmMemoryAndReturnIndexOne() 29 | ); // Should Log "15" 30 | }; 31 | runWasmAdd(); 32 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/assemblyscript/index.ts: -------------------------------------------------------------------------------- 1 | // Set up our memory 2 | // By growing our Wasm Memory by 1 page (64KB) 3 | memory.grow(1); 4 | 5 | // Store the value 24 at index 0 6 | const index = 0; 7 | const value = 24; 8 | store(index, value); 9 | 10 | // Export a function that will read wasm memory 11 | // and return the value at index 1 12 | export function readWasmMemoryAndReturnIndexOne(): i32 { 13 | // Read the value at indexOne 14 | let valueAtIndexOne = load(1); 15 | return valueAtIndexOne; 16 | } 17 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/assemblyscript/index.wasm: -------------------------------------------------------------------------------- 1 | asm``pA A A 4memorytablereadWasmMemoryAndReturnIndexOne A  2 | &A@##: A-!   -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/assemblyscript/index.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $FUNCSIG$v (func)) 3 | (type $FUNCSIG$i (func (result i32))) 4 | (memory $0 0) 5 | (table $0 1 funcref) 6 | (elem (i32.const 0) $null) 7 | (global $index/index i32 (i32.const 0)) 8 | (global $index/value i32 (i32.const 24)) 9 | (global $~lib/memory/HEAP_BASE i32 (i32.const 8)) 10 | (export "memory" (memory $0)) 11 | (export "table" (table $0)) 12 | (export "readWasmMemoryAndReturnIndexOne" (func $index/readWasmMemoryAndReturnIndexOne)) 13 | (start $start) 14 | (func $start:index (; 0 ;) (type $FUNCSIG$v) 15 | i32.const 1 16 | grow_memory 17 | drop 18 | global.get $index/index 19 | global.get $index/value 20 | i32.store8 21 | ) 22 | (func $index/readWasmMemoryAndReturnIndexOne (; 1 ;) (type $FUNCSIG$i) (result i32) 23 | (local $0 i32) 24 | i32.const 1 25 | i32.load8_u 26 | local.set $0 27 | local.get $0 28 | ) 29 | (func $start (; 2 ;) (type $FUNCSIG$v) 30 | call $start:index 31 | ) 32 | (func $null (; 3 ;) (type $FUNCSIG$v) 33 | ) 34 | ) 35 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/go/README.md: -------------------------------------------------------------------------------- 1 | Compile with TinyGo, by running: `tinygo build -o main.wasm -target wasm ./main.go` 2 | 3 | `wasm_exec.js` can be [copied from your TinyGo root](https://github.com/tinygo-org/tinygo/issues/1070). Which is [explained in the TinyGo Wasm Docs](https://tinygo.org/webassembly/webassembly/#how-it-works). 4 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebAssembly Linear Memory - Go 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/go/index.js: -------------------------------------------------------------------------------- 1 | // Imports are from the demo-util folder in the repo 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { wasmBrowserInstantiate } from "/demo-util/instantiateWasm.js"; 4 | import { domConsoleLog } from "/demo-util/domConsole.js"; 5 | 6 | const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html. 7 | 8 | const runWasm = async () => { 9 | const importObject = go.importObject; 10 | 11 | // Instantiate our wasm module 12 | const wasmModule = await wasmBrowserInstantiate("./main.wasm", importObject); 13 | 14 | // You have to run the go instance before doing anything else, or else println and things won't work 15 | go.run(wasmModule.instance); 16 | 17 | /** 18 | * Part one: Write in Wasm, Read in JS 19 | */ 20 | domConsoleLog("Write in Wasm, Read in JS, Index 0:"); 21 | 22 | // First, let's have wasm write to our buffer 23 | wasmModule.instance.exports.storeValueInWasmMemoryBufferIndexZero(24); 24 | 25 | // Next, let's create a Uint8Array of our wasm memory 26 | let wasmMemory = new Uint8Array(wasmModule.instance.exports.memory.buffer); 27 | 28 | // Then, let's get the pointer to our buffer that is within wasmMemory 29 | let bufferPointer = wasmModule.instance.exports.getWasmMemoryBufferPointer(); 30 | 31 | // Then, let's read the written value at index zero of the buffer, 32 | // by accessing the index of wasmMemory[bufferPointer + bufferIndex] 33 | domConsoleLog(wasmMemory[bufferPointer + 0]); // Should log "24" 34 | 35 | /** 36 | * Part two: Write in JS, Read in Wasm 37 | */ 38 | domConsoleLog("Write in JS, Read in Wasm, Index 1:"); 39 | 40 | // First, let's write to index one of our buffer 41 | wasmMemory[bufferPointer + 1] = 15; 42 | 43 | // Then, let's have wasm read index one of the buffer, 44 | // and return the result 45 | domConsoleLog( 46 | wasmModule.instance.exports.readWasmMemoryBufferAndReturnIndexOne() 47 | ); // Should log "15" 48 | 49 | /** 50 | * NOTE: if we were to continue reading and writing memory, 51 | * depending on how the memory is grown by rust, you may have 52 | * to re-create the Uint8Array since memory layout could change. 53 | * For example, `let wasmMemory = new Uint8Array(rustWasm.memory.buffer);` 54 | * In this example, we did not, but be aware this may happen :) 55 | */ 56 | }; 57 | runWasm(); 58 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Create a byte (uint8, not Go byte) buffer, which will be available in Wasm Memory. 4 | // We can then share this buffer with JS and Wasm. 5 | const BUFFER_SIZE int = 2; 6 | var buffer [BUFFER_SIZE]uint8; 7 | 8 | // Declare a main function, this is the entrypoint into our go module 9 | // That will be run. In our example, we won't need this 10 | func main() {} 11 | 12 | // Function to return a pointer (Index) to our buffer in wasm memory 13 | //export getWasmMemoryBufferPointer 14 | func getWasmMemoryBufferPointer() *[BUFFER_SIZE]uint8 { 15 | return &buffer 16 | } 17 | 18 | // Function to store the passed value at index 0, 19 | // in our buffer 20 | //go:export storeValueInWasmMemoryBufferIndexZero 21 | func storeValueInWasmMemoryBufferIndexZero(value uint8) { 22 | buffer[0] = value 23 | } 24 | 25 | // Function to read from index 1 of our buffer 26 | // And return the value at the index 27 | //go:export readWasmMemoryBufferAndReturnIndexOne 28 | func readWasmMemoryBufferAndReturnIndexOne() uint8 { 29 | return buffer[1] 30 | } 31 | 32 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/go/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/webassembly-linear-memory/demo/go/main.wasm -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webassembly-linear-memory" 3 | version = "0.1.0" 4 | authors = ["Aaron Turner "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = "0.2" 12 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/README.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Linear Memory (Rust) 2 | 3 | Compile with `wasm-pack build --target web` 4 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - Rust 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/index.js: -------------------------------------------------------------------------------- 1 | import wasmInit from "./pkg/webassembly_linear_memory.js"; 2 | // https://github.com/torch2424/wasm-by-example/blob/master/demo-util/ 3 | import { domConsoleLog } from "/demo-util/domConsole.js"; 4 | 5 | const runWasm = async () => { 6 | // Instantiate our wasm module 7 | const rustWasm = await wasmInit("./pkg/webassembly_linear_memory_bg.wasm"); 8 | 9 | /** 10 | * Part one: Write in Wasm, Read in JS 11 | */ 12 | domConsoleLog("Write in Wasm, Read in JS, Index 0:"); 13 | 14 | // First, let's have wasm write to our buffer 15 | rustWasm.store_value_in_wasm_memory_buffer_index_zero(24); 16 | 17 | // Next, let's create a Uint8Array of our wasm memory 18 | let wasmMemory = new Uint8Array(rustWasm.memory.buffer); 19 | 20 | // Then, let's get the pointer to our buffer that is within wasmMemory 21 | let bufferPointer = rustWasm.get_wasm_memory_buffer_pointer(); 22 | 23 | // Then, let's read the written value at index zero of the buffer, 24 | // by accessing the index of wasmMemory[bufferPointer + bufferIndex] 25 | domConsoleLog(wasmMemory[bufferPointer + 0]); // Should log "24" 26 | 27 | /** 28 | * Part two: Write in JS, Read in Wasm 29 | */ 30 | domConsoleLog("Write in JS, Read in Wasm, Index 1:"); 31 | 32 | // First, let's write to index one of our buffer 33 | wasmMemory[bufferPointer + 1] = 15; 34 | 35 | // Then, let's have wasm read index one of the buffer, 36 | // and return the result 37 | domConsoleLog(rustWasm.read_wasm_memory_buffer_and_return_index_one()); // Should log "15" 38 | 39 | /** 40 | * NOTE: if we were to continue reading and writing memory, 41 | * depending on how the memory is grown by rust, you may have 42 | * to re-create the Uint8Array since memory layout could change. 43 | * For example, `let wasmMemory = new Uint8Array(rustWasm.memory.buffer);` 44 | * In this example, we did not, but be aware this may happen :) 45 | */ 46 | }; 47 | runWasm(); 48 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Hello World (Assemblyscript) 2 | 3 | Compile with `asc hello-world.ts -b hello-world.wasm -t hello-world.wat` 4 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webassembly-linear-memory", 3 | "collaborators": [ 4 | "Aaron Turner " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "webassembly_linear_memory_bg.wasm", 9 | "webassembly_linear_memory.js", 10 | "webassembly_linear_memory.d.ts" 11 | ], 12 | "module": "webassembly_linear_memory.js", 13 | "types": "webassembly_linear_memory.d.ts", 14 | "sideEffects": "false" 15 | } 16 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/pkg/webassembly_linear_memory.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * @param {number} value 4 | * @returns {void} 5 | */ 6 | export function store_value_in_wasm_memory_buffer_index_zero( 7 | value: number 8 | ): void; 9 | /** 10 | * @returns {number} 11 | */ 12 | export function get_wasm_memory_buffer_pointer(): number; 13 | /** 14 | * @returns {number} 15 | */ 16 | export function read_wasm_memory_buffer_and_return_index_one(): number; 17 | 18 | /** 19 | * If `module_or_path` is {RequestInfo}, makes a request and 20 | * for everything else, calls `WebAssembly.instantiate` directly. 21 | * 22 | * @param {RequestInfo | BufferSource | WebAssembly.Module} module_or_path 23 | * 24 | * @returns {Promise} 25 | */ 26 | export default function init( 27 | module_or_path: RequestInfo | BufferSource | WebAssembly.Module 28 | ): Promise; 29 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/pkg/webassembly_linear_memory.js: -------------------------------------------------------------------------------- 1 | const __exports = {}; 2 | let wasm; 3 | 4 | /** 5 | * @param {number} value 6 | * @returns {void} 7 | */ 8 | export function store_value_in_wasm_memory_buffer_index_zero(value) { 9 | return wasm.store_value_in_wasm_memory_buffer_index_zero(value); 10 | } 11 | __exports.store_value_in_wasm_memory_buffer_index_zero = store_value_in_wasm_memory_buffer_index_zero; 12 | 13 | /** 14 | * @returns {number} 15 | */ 16 | export function get_wasm_memory_buffer_pointer() { 17 | return wasm.get_wasm_memory_buffer_pointer(); 18 | } 19 | __exports.get_wasm_memory_buffer_pointer = get_wasm_memory_buffer_pointer; 20 | 21 | /** 22 | * @returns {number} 23 | */ 24 | export function read_wasm_memory_buffer_and_return_index_one() { 25 | return wasm.read_wasm_memory_buffer_and_return_index_one(); 26 | } 27 | __exports.read_wasm_memory_buffer_and_return_index_one = read_wasm_memory_buffer_and_return_index_one; 28 | 29 | function init(module) { 30 | let result; 31 | const imports = { "./webassembly_linear_memory": __exports }; 32 | 33 | if ( 34 | module instanceof URL || 35 | typeof module === "string" || 36 | module instanceof Request 37 | ) { 38 | const response = fetch(module); 39 | if (typeof WebAssembly.instantiateStreaming === "function") { 40 | result = WebAssembly.instantiateStreaming(response, imports).catch(e => { 41 | console.warn( 42 | "`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", 43 | e 44 | ); 45 | return response 46 | .then(r => r.arrayBuffer()) 47 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 48 | }); 49 | } else { 50 | result = response 51 | .then(r => r.arrayBuffer()) 52 | .then(bytes => WebAssembly.instantiate(bytes, imports)); 53 | } 54 | } else { 55 | result = WebAssembly.instantiate(module, imports).then(result => { 56 | if (result instanceof WebAssembly.Instance) { 57 | return { instance: result, module }; 58 | } else { 59 | return result; 60 | } 61 | }); 62 | } 63 | return result.then(({ instance, module }) => { 64 | wasm = instance.exports; 65 | init.__wbindgen_wasm_module = module; 66 | 67 | return wasm; 68 | }); 69 | } 70 | 71 | export default init; 72 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/pkg/webassembly_linear_memory_bg.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | export const memory: WebAssembly.Memory; 3 | export function store_value_in_wasm_memory_buffer_index_zero(a: number): void; 4 | export function get_wasm_memory_buffer_pointer(): number; 5 | export function read_wasm_memory_buffer_and_return_index_one(): number; 6 | -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/pkg/webassembly_linear_memory_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torch2424/wasm-by-example/fce82ed5c4a30c4fe39317e59e354eb60552234c/examples/webassembly-linear-memory/demo/rust/pkg/webassembly_linear_memory_bg.wasm -------------------------------------------------------------------------------- /examples/webassembly-linear-memory/demo/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // The wasm-pack uses wasm-bindgen to build and generate JavaScript binding file. 2 | // Import the wasm-bindgen crate. 3 | use wasm_bindgen::prelude::*; 4 | 5 | // Create a static mutable byte buffer. 6 | // We will use for passing memory between js and wasm. 7 | // NOTE: global `static mut` means we will have "unsafe" code 8 | // but for passing memory between js and wasm should be fine. 9 | const WASM_MEMORY_BUFFER_SIZE: usize = 2; 10 | static mut WASM_MEMORY_BUFFER: [u8; WASM_MEMORY_BUFFER_SIZE] = [0; WASM_MEMORY_BUFFER_SIZE]; 11 | 12 | // Function to store the passed value at index 0, 13 | // in our buffer 14 | #[wasm_bindgen] 15 | pub fn store_value_in_wasm_memory_buffer_index_zero(value: u8) { 16 | unsafe { 17 | WASM_MEMORY_BUFFER[0] = value; 18 | } 19 | } 20 | 21 | // Function to return a pointer to our buffer 22 | // in wasm memory 23 | #[wasm_bindgen] 24 | pub fn get_wasm_memory_buffer_pointer() -> *const u8 { 25 | let pointer: *const u8; 26 | unsafe { 27 | pointer = WASM_MEMORY_BUFFER.as_ptr(); 28 | } 29 | 30 | return pointer; 31 | } 32 | 33 | // Function to read from index 1 of our buffer 34 | // And return the value at the index 35 | #[wasm_bindgen] 36 | pub fn read_wasm_memory_buffer_and_return_index_one() -> u8 { 37 | let value: u8; 38 | unsafe { 39 | value = WASM_MEMORY_BUFFER[1]; 40 | } 41 | return value; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wasm-by-example", 3 | "version": "0.2.0", 4 | "description": "A website of examples in how to do common things in WebAssembly", 5 | "main": "index.js", 6 | "directories": { 7 | "example": "examples" 8 | }, 9 | "scripts": { 10 | "dev": "npm-run-all build --parallel serve watch", 11 | "build": "node build-system/build.js", 12 | "serve": "serve ./dist -l 8080", 13 | "watch": "watch 'npm run build' ./examples ./shell ./build-system ./demo-util --interval=1", 14 | "lint": "prettier --write build-system/**/*.js shell/**/*.css shell/**/*.html examples/**/*.md examples/**/*.js examples/**/*.html examples/**/*.ts", 15 | "lint:ci": "prettier --list-different build-system/**/*.js shell/**/*.css shell/**/*.html examples/**/*.md examples/**/*.js examples/**/*.html examples/**/*.ts" 16 | }, 17 | "husky": { 18 | "hooks": { 19 | "pre-commit": "pretty-quick --staged" 20 | } 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/torch2424/wasm-by-example.git" 25 | }, 26 | "keywords": [ 27 | "WebAssembly", 28 | "Wasm", 29 | "Examples", 30 | "Example", 31 | "Documentation", 32 | "Demo", 33 | "Learning", 34 | "Tutorial" 35 | ], 36 | "author": "Aaron Turner", 37 | "license": "Creative Commons 4.0 Attribution", 38 | "bugs": { 39 | "url": "https://github.com/torch2424/wasm-by-example/issues" 40 | }, 41 | "homepage": "https://github.com/torch2424/wasm-by-example#readme", 42 | "devDependencies": { 43 | "clean-css": "^4.2.1", 44 | "cpy": "^6.0.0", 45 | "get-title-markdown": "^2.0.1", 46 | "highlight.js": "^10.4.1", 47 | "husky": "^2.3.0", 48 | "marked": "^0.8.0", 49 | "mkdirp": "^0.5.1", 50 | "mustache": "^3.0.1", 51 | "npm-run-all": "^4.1.5", 52 | "prettier": "1.17.1", 53 | "pretty-quick": "^1.11.0", 54 | "recursive-copy": "^2.0.10", 55 | "recursive-readdir": "^2.2.2", 56 | "serve": "^11.3.0", 57 | "terser": "^4.8.1", 58 | "watch": "^0.13.0", 59 | "workbox-build": "^5.1.2" 60 | }, 61 | "dependencies": { 62 | "normalize.css": "^8.0.1", 63 | "sakura.css": "^1.0.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /shell/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 13 | 14 | 15 | {{{partials.announcements}}} 16 |
17 | {{{partials.header}}} 18 | 19 |

20 | Wasm By Example is a concise, hands-on introduction to WebAssembly using 21 | code snippets and annotated WebAssembly example programs. If you "learn 22 | best by doing", or just need a good starting point for a concept, this 23 | is the place for you. Wasm By Example offers wasm examples in multiple 24 | programming / written languages, where the languages are available for 25 | the example. Browse the list of wasm examples below. 26 |

27 | 28 |

29 | Google Analytics is used on Wasm By Example, and is only used to record 30 | Basic visit data, as the script is only loaded. 35 |

36 | 37 |

38 | Just a quick shoutout to 39 | Carlos Baraza. Who created the 42 | WebAssembly Logo 48 | under a Creative Commons Universal license. The logo is used in the site 49 | favicon and title header. 50 |

51 | 52 |
53 |

Got stuck? Found a bug?

54 |

55 | If you can't find what you are looking for, feel free to 56 | open a request, or contribute back! 61 | 62 |

63 |
64 | 65 | {{{partials.footer}}} 66 |
67 | 68 | 69 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /shell/all-examples-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example - Examples Listing 7 | 8 | 13 | 14 | 15 | {{{partials.announcements}}} 16 |
17 | {{{partials.header}}} 18 | 19 |

All Examples List

20 | 21 |
22 |

23 | Below is a list of all available WebAssembly examples on Wasm by 24 | Example. Organized by their respective language. Currently, this 25 | will not switch your language preferences. But will allow you 26 | to see another WebAssembly example without having to set the default 27 | language. 28 |

29 |
30 | 31 | 32 | {{#examplesByLanguage}} 33 |

{{title}}

34 |
    35 | {{#examples}} 36 |
  • 37 | {{title}} 41 |
  • 42 | {{/examples}} 43 |
44 | {{/examplesByLanguage}} {{{partials.footer}}} 45 |
46 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /shell/demo-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /shell/example-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /shell/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 14 | 15 | 16 | {{{partials.announcements}}} 17 |
18 | {{{partials.header}}} {{{exampleHtml}}} {{{partials.footer}}} 19 |
20 | 21 | 22 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /shell/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 14 | 15 | 16 | {{{partials.announcements}}} 17 |
18 | {{{partials.header}}} {{{introductionHtml.inLanguage}}} 19 | 20 | 21 |

{{examplesTitle.inLanguage}}

22 | {{#categories}} 23 | 26 | 29 |
    30 | {{#examples}} 31 | 41 | {{/examples}} 42 |
43 | {{/categories}} {{{partials.footer}}} 44 |
45 | 46 | 47 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /shell/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /shell/js/demoRedirect.js: -------------------------------------------------------------------------------- 1 | // Initialization IIFE 2 | (() => { 3 | // Set our header langauge identifier 4 | let exampleName = window.WASM_BY_EXAMPLE.exampleName; 5 | let programmingLanguage = window.WASM_BY_EXAMPLE.programmingLanguage; 6 | let readingLanguage = window.WASM_BY_EXAMPLE.readingLanguage; 7 | 8 | // Grab any overrides from the query 9 | let params = new URLSearchParams(window.location.search); 10 | if (params.get("exampleName")) { 11 | exampleName = params.get("exampleName"); 12 | } 13 | if (params.get("programmingLanguage")) { 14 | programmingLanguage = params.get("programmingLanguage"); 15 | } 16 | if (params.get("readingLanguage")) { 17 | readingLanguage = params.get("readingLanguage"); 18 | } 19 | 20 | // Set the path, and clear the search 21 | if (exampleName) { 22 | window.location.href = `/examples/${exampleName}/demo/${programmingLanguage}/?version=${ 23 | WASM_BY_EXAMPLE.VERSION 24 | }`; 25 | } else { 26 | window.location.href = "/"; 27 | } 28 | })(); 29 | -------------------------------------------------------------------------------- /shell/js/examplesList.js: -------------------------------------------------------------------------------- 1 | const goToExample = ( 2 | parentPath, 3 | exampleName, 4 | programmingLanguage, 5 | readingLanguage 6 | ) => { 7 | location.pathname = `/${parentPath}/${exampleName}.${programmingLanguage}.${readingLanguage}.html`; 8 | }; 9 | 10 | // Initialization IIFE 11 | (() => { 12 | // Set our header langauge identifier 13 | const programmingLanguage = window.WASM_BY_EXAMPLE.programmingLanguage; 14 | const readingLanguage = window.WASM_BY_EXAMPLE.readingLanguage; 15 | 16 | // Only show the examples with the langauges in their class 17 | const css = ` 18 | .example-category-title.${programmingLanguage}.${readingLanguage}, 19 | .example-category-title.all.${readingLanguage}, 20 | .example-category-description.${programmingLanguage}.${readingLanguage}, 21 | .example-category-description.all.${readingLanguage} { 22 | display:block !important; 23 | } 24 | .${programmingLanguage}.${readingLanguage}, .all.${readingLanguage} { 25 | display: list-item !important; 26 | }`; 27 | const head = document.head || document.getElementsByTagName("head")[0]; 28 | const style = document.createElement("style"); 29 | 30 | head.appendChild(style); 31 | 32 | style.type = "text/css"; 33 | if (style.styleSheet) { 34 | // This is required for IE8 and below. 35 | style.styleSheet.cssText = css; 36 | } else { 37 | style.appendChild(document.createTextNode(css)); 38 | } 39 | })(); 40 | -------------------------------------------------------------------------------- /shell/js/examplesRedirect.js: -------------------------------------------------------------------------------- 1 | // Initialization IIFE 2 | (() => { 3 | // Set our header langauge identifier 4 | let exampleName = window.WASM_BY_EXAMPLE.exampleName; 5 | let programmingLanguage = window.WASM_BY_EXAMPLE.programmingLanguage; 6 | let readingLanguage = window.WASM_BY_EXAMPLE.readingLanguage; 7 | 8 | // Grab any overrides from the query 9 | let params = new URLSearchParams(window.location.search); 10 | if (params.get("exampleName")) { 11 | exampleName = params.get("exampleName"); 12 | } 13 | if (params.get("programmingLanguage")) { 14 | programmingLanguage = params.get("programmingLanguage"); 15 | } 16 | if (params.get("readingLanguage")) { 17 | readingLanguage = params.get("readingLanguage"); 18 | } 19 | 20 | // Set the path, and clear the search 21 | if (exampleName) { 22 | window.location.href = `/examples/${exampleName}/${exampleName}.${programmingLanguage}.${readingLanguage}.html`; 23 | } else { 24 | window.location.href = "/"; 25 | } 26 | })(); 27 | -------------------------------------------------------------------------------- /shell/js/indexRedirect.js: -------------------------------------------------------------------------------- 1 | // Initialization IIFE 2 | (() => { 3 | let readingLanguage = window.WASM_BY_EXAMPLE.readingLanguage; 4 | if (!readingLanguage) { 5 | readingLanguage = "en-us"; 6 | } 7 | 8 | let redirectUrl = `/home.${readingLanguage}.html${window.location.search}`; 9 | // console.log('Redirecting to homepage for reading language:', redirectUrl); 10 | 11 | window.location.href = redirectUrl; 12 | })(); 13 | -------------------------------------------------------------------------------- /shell/js/sourceRedirect.js: -------------------------------------------------------------------------------- 1 | const sourceBaseUrl = 2 | "https://github.com/torch2424/wasm-by-example/tree/master"; 3 | 4 | // Initialization IIFE 5 | (() => { 6 | let path = undefined; 7 | 8 | // Grab any overrides from the query 9 | let params = new URLSearchParams(window.location.search); 10 | if (params.get("path")) { 11 | path = params.get("path"); 12 | } 13 | 14 | // Set the path, and clear the search 15 | if (path) { 16 | // Remove leading and trailing slashes 17 | path = path.replace(/^\/|\/$/g, ""); 18 | window.location.href = `${sourceBaseUrl}/${path}`; 19 | } else { 20 | window.location.href = "/"; 21 | } 22 | })(); 23 | -------------------------------------------------------------------------------- /shell/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Wasm By Example", 3 | "short_name": "WasmByExample", 4 | "start_url": "/", 5 | "display": "standalone", 6 | "orientation": "portrait", 7 | "background_color": "#252830", 8 | "theme_color": "#654ff0", 9 | "icons": [ 10 | { 11 | "src": "/icon.png", 12 | "type": "image/png", 13 | "sizes": "512x512" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /shell/partials/announcements.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | The maintainer of this website has a 4 | Spotify Coding Playlist of their Lo-fi Hip Hop beats! 9 |

10 |
11 | 20 | -------------------------------------------------------------------------------- /shell/partials/footer.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 42 | -------------------------------------------------------------------------------- /shell/partials/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 61 | 62 | 66 | 74 | -------------------------------------------------------------------------------- /shell/partials/header.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | WebAssembly Logo 9 |

Wasm By Example

10 |
11 |
12 |
Language:
13 |
14 | 20 | 21 | 27 |
28 |
29 |
30 | 31 |
32 | -------------------------------------------------------------------------------- /shell/source-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{{partials.head}}} 5 | 6 | Wasm By Example 7 | 8 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /shell/styles/examples-list.css: -------------------------------------------------------------------------------- 1 | .example-category-title { 2 | margin-bottom: 5px; 3 | } 4 | 5 | .example-category-description { 6 | margin-top: 10px; 7 | font-size: 1.05em; 8 | } 9 | --------------------------------------------------------------------------------