├── .gitattributes ├── LICENSE ├── README.md ├── base64 ├── base64.html ├── base64.wasm ├── base64.wat ├── base64c.c ├── base64c.js ├── base64c.wasm ├── base64c.wat └── base64wat.wat ├── exported_func ├── exported.bat ├── exported.c ├── exported.html └── exported.wasm ├── hello_world ├── a.exe ├── a.out.html ├── a.out.js ├── a.out.wasm ├── hello_world.bat └── hello_world.c ├── memory ├── malloc.bat ├── malloc.c ├── malloc.html ├── malloc.js ├── malloc.wasm ├── memory.bat ├── memory.c ├── memory.html ├── memory.js └── memory.wasm ├── raw_wasm ├── add.wasm ├── add.wat ├── flow.wasm ├── flow.wat ├── func.wasm ├── func.wat ├── functable.wasm ├── functable.wat ├── mem.wasm ├── mem.wat └── raw.html ├── streaming ├── streaming.bat ├── streaming.c ├── streaming.html ├── streaming.wasm └── streaming_util.c ├── struct_framework ├── basic_framework.html ├── nested_struct.c ├── nested_struct.wasm ├── num_struct.c ├── num_struct.html ├── num_struct.wasm └── struct_framework.js └── wrapping ├── wrapping.bat ├── wrapping.c ├── wrapping.html ├── wrapping.js └── wrapping.wasm /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webassembly-tutorial 2 | Tutorial on using WebAssembly 3 | 4 | ## Installation 5 | [Installation guide](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install) 6 | 1. Run the following commands in the directory you want to store the library in (*This uses `C:\src` as my path*): 7 | ``` 8 | cd $LibraryDirectory # replace with your directory 9 | git clone https://github.com/emscripten-core/emsdk.git 10 | cd emsdk 11 | ./emsdk install latest 12 | ./emsdk activate latest 13 | ``` 14 | 2. Add `$LibraryDirectory\emsdk` to the `PATH` environment variable 15 | 3. Restart your terminal session 16 | 4. Run the command `emsdk --help` to ensure the library has been installed properly. 17 | ### Compiling 18 | 1. In a directory, create a c file (`test.c`) and write some code. 19 | 2. Open up the terminal to that directory and execute the following commands. 20 | ``` 21 | emsdk activate latest 22 | emcc test.c 23 | ``` 24 | 3. Open up the output `test.html` file in a browser and view the output. 25 | 26 | ## WebAssembly Tools Suite 27 | ### Wasm suite: [wabt](https://github.com/webassembly/wabt) 28 | ``` 29 | cd $LibraryDirectory # go to your target directory 30 | git clone --recursive https://github.com/WebAssembly/wabt 31 | cd wabt 32 | git submodule update --init 33 | ``` 34 | 35 | * Add the value: `$LibraryDirectory\wabt\bin` to your PATH environment variable. 36 | 37 | ### CMake: [download](https://cmake.org/download/) 38 | ``` 39 | cd $LibraryDirectory\wabt 40 | mkdir build 41 | cd build 42 | cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_INSTALL_PREFIX=..\ -G "Visual Studio 16 2019" 43 | cmake --build . --config DEBUG --target install 44 | ``` 45 | 46 | ### Testing 47 | * Ensure that the `bin` directory exists with a bunch of executable files. 48 | * Restart your terminal session, and navigate to a directory containing a .wasm file 49 | * Run the command `wasm2wat --help`, make sure it prints some output 50 | * Test the tool using a file (i.e. `wasm2wat exported.wasm`) 51 | 52 | ### Updating 53 | There may come a day when you get an error in using a wabt tool, something like `Bad magic value`. In this case, you need to update your toolset. To do this, we need to pull new code from GitHub then rebuild with CMake as follows: 54 | ``` 55 | cd $LibraryDirectory\wabt 56 | git pull 57 | cd build 58 | cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_INSTALL_PREFIX=..\ -G "Visual Studio 16 2019" 59 | cmake --build . --config DEBUG --target install 60 | ``` 61 | 62 | ## Helpful resources 63 | * [MDN handbook](https://developer.mozilla.org/en-US/docs/WebAssembly) 64 | ### Writing WebAssembly Text format (WAT) 65 | * [MDN](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format) 66 | * [MDN basic examples](https://github.com/mdn/webassembly-examples) 67 | * [Basic examples](https://blog.ttulka.com/learning-webassembly-3-wat-programming-basics/) 68 | * [Game of Life example](https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html) 69 | * [packthub](https://hub.packtpub.com/the-elements-of-webassembly-wat-and-wasm-explained-tutorial/) 70 | -------------------------------------------------------------------------------- /base64/base64.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Raw WAT 6 | 7 | 8 | 9 |

Hello, WebAssembly!

10 | 11 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /base64/base64.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/base64/base64.wasm -------------------------------------------------------------------------------- /base64/base64.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "console" "logNum" (func $logNum (param i32))) 3 | 4 | (memory $exported_memory 10 100) 5 | (export "memory" (memory $exported_memory)) 6 | 7 | ;; b64 encoding table 8 | (data (;0;) (i32.const 0) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") 9 | 10 | ;; b64 encode function 11 | (func $b64encode (export "b64encode") 12 | (param $str i32) 13 | (param $strlen i32) 14 | (param $out i32) 15 | (result i32) 16 | 17 | (local $len i32) ;; output string length 18 | (local $val i32) ;; temporary value 19 | (local $shiftAmt i32) ;; amount to shift by 20 | (local $minShiftAmt i32) 21 | 22 | i32.const 0 23 | local.set $len 24 | 25 | ;; main loop 26 | (block $encodeBlock 27 | ;; set input cursor upper bound 28 | local.get $str 29 | local.get $strlen 30 | i32.add 31 | local.set $strlen 32 | 33 | ;; iterate through three octets, output four base64 characters 34 | (loop $encodeLoop 35 | local.get $str 36 | local.get $strlen 37 | i32.ge_s 38 | br_if $encodeBlock 39 | 40 | i32.const 18 41 | local.set $minShiftAmt 42 | 43 | ;; load three octets 44 | (block $readOctetsBlock 45 | i32.const 0 46 | local.set $val 47 | 48 | i32.const 16 49 | local.set $shiftAmt 50 | 51 | (loop $readOctetsLoop 52 | local.get $str 53 | local.get $strlen 54 | i32.ge_s 55 | br_if $readOctetsBlock 56 | 57 | local.get $str ;; input cursor 58 | i32.load8_u ;; load in byte (stack = byte) 59 | local.get $shiftAmt ;; (stack = byte, shiftAmt) 60 | i32.shl ;; shift octet into position (stack = byte << shiftAmt) 61 | local.get $val ;; (stack = byte', $val) 62 | i32.or ;; combine octet with existing concatenation 63 | local.set $val 64 | 65 | ;; increment step ;; 66 | 67 | ;; decrease shift amount 68 | local.get $shiftAmt 69 | i32.const 8 70 | i32.sub 71 | local.set $shiftAmt 72 | 73 | ;; decrease minimum shift amount for next step 74 | local.get $minShiftAmt 75 | i32.const 6 76 | i32.sub 77 | local.set $minShiftAmt 78 | 79 | ;; advance input cursor 80 | local.get $str 81 | i32.const 1 82 | i32.add 83 | local.set $str 84 | 85 | ;; loop if shift amount is not -8 86 | local.get $shiftAmt 87 | i32.const -8 88 | i32.ne 89 | br_if $readOctetsLoop 90 | ) 91 | ) 92 | 93 | ;; write four base64 characters 94 | (block $outputBlock 95 | i32.const 18 96 | local.set $shiftAmt 97 | 98 | (loop $outputLoop 99 | local.get $out ;; output cursor 100 | local.get $val ;; (stack = $val) 101 | local.get $shiftAmt ;; (stack = $val, $shiftAmt) 102 | i32.shr_u ;; shift to position (stack = $val') 103 | i32.const 63 ;; bit mask 0x3f (stack = $val', 63) 104 | i32.and ;; apply bit mask (stack = $val' & 0x3f) 105 | i32.load8_u ;; encode character (stack = $out, $char) 106 | i32.store8 ;; store character 107 | 108 | ;; increment step ;; 109 | local.get $shiftAmt 110 | i32.const 6 111 | i32.sub 112 | local.set $shiftAmt 113 | 114 | ;; increment length 115 | local.get $len 116 | i32.const 1 117 | i32.add 118 | local.set $len 119 | 120 | ;; increment cursor 121 | local.get $out 122 | i32.const 1 123 | i32.add 124 | local.set $out 125 | 126 | ;; loop if shift amount is above the minimum 127 | local.get $shiftAmt 128 | local.get $minShiftAmt 129 | i32.ge_s 130 | br_if $outputLoop 131 | ;; br $outputBlock 132 | ) 133 | ) 134 | 135 | br $encodeLoop 136 | ) 137 | ) 138 | 139 | ;; padding 140 | (block $padBlock 141 | (loop $padLoop 142 | ;; break if no more characters to pad 143 | local.get $len 144 | i32.const 3 ;; bit mask 145 | i32.and 146 | i32.const 0 147 | i32.eq 148 | br_if $padBlock ;; break if divisible by 4 149 | 150 | ;; store padding character 151 | local.get $out ;; cursor 152 | i32.const 61 ;; padding character '=' 153 | i32.store8 154 | 155 | ;; increment step ;; 156 | 157 | local.get $len 158 | i32.const 1 159 | i32.add 160 | local.set $len 161 | 162 | local.get $out 163 | i32.const 1 164 | i32.add 165 | local.set $out 166 | 167 | br $padLoop 168 | ) 169 | ) 170 | 171 | ;; terminator character 172 | local.get $out ;; cursor 173 | i32.const 0 174 | i32.store8 175 | 176 | ;; return length 177 | local.get $len 178 | ) 179 | ) 180 | -------------------------------------------------------------------------------- /base64/base64c.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char b64table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 4 | 5 | EMSCRIPTEN_KEEPALIVE 6 | int b64encode(unsigned char *data, int length, unsigned char *out) 7 | { 8 | int outLength = 4 * ((length + 2) / 3); 9 | 10 | // iterate through three octets, output four base64 characters 11 | for (int i = 0, j = 0; i < length;) 12 | { 13 | unsigned int octet1 = i < length ? data[i++] : 0; 14 | unsigned int octet2 = i < length ? data[i++] : 0; 15 | unsigned int octet3 = i < length ? data[i++] : 0; 16 | 17 | // concatenate to get 24b = octet1 | octet2 | octet3 18 | unsigned int concat = (octet1 << 16) | (octet2 << 8) | (octet3); 19 | 20 | out[j++] = b64table[(concat >> 18) & 0x3f]; 21 | out[j++] = b64table[(concat >> 12) & 0x3f]; 22 | out[j++] = b64table[(concat >> 6) & 0x3f]; 23 | out[j++] = b64table[(concat >> 0) & 0x3f]; 24 | } 25 | 26 | int padding; 27 | switch (length % 3) 28 | { 29 | case 0: 30 | padding = 0; 31 | break; 32 | case 1: 33 | padding = 2; 34 | break; 35 | case 2: 36 | padding = 1; 37 | break; 38 | } 39 | for (int i = 0; i < padding; i++) 40 | { 41 | out[outLength - 1 - i] = '='; 42 | } 43 | 44 | return outLength; 45 | } -------------------------------------------------------------------------------- /base64/base64c.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | // The Module object: Our interface to the outside world. We import 4 | // and export values on it. There are various ways Module can be used: 5 | // 1. Not defined. We create it here 6 | // 2. A function parameter, function(Module) { ..generated code.. } 7 | // 3. pre-run appended it, var Module = {}; ..generated code.. 8 | // 4. External script tag defines var Module. 9 | // We need to check if Module already exists (e.g. case 3 above). 10 | // Substitution will be replaced with actual code on later stage of the build, 11 | // this way Closure Compiler will not mangle it (e.g. case 4. above). 12 | // Note that if you want to run closure, and also to use Module 13 | // after the generated code, you will need to define var Module = {}; 14 | // before the code. Then that object will be used in the code, and you 15 | // can continue to use Module afterwards as well. 16 | var Module = typeof Module != 'undefined' ? Module : {}; 17 | 18 | // See https://caniuse.com/mdn-javascript_builtins_object_assign 19 | 20 | // --pre-jses are emitted after the Module integration code, so that they can 21 | // refer to Module (if they choose; they can also define Module) 22 | // {{PRE_JSES}} 23 | 24 | // Sometimes an existing Module object exists with properties 25 | // meant to overwrite the default module functionality. Here 26 | // we collect those properties and reapply _after_ we configure 27 | // the current environment's defaults to avoid having to be so 28 | // defensive during initialization. 29 | var moduleOverrides = Object.assign({}, Module); 30 | 31 | var arguments_ = []; 32 | var thisProgram = './this.program'; 33 | var quit_ = (status, toThrow) => { 34 | throw toThrow; 35 | }; 36 | 37 | // Determine the runtime environment we are in. You can customize this by 38 | // setting the ENVIRONMENT setting at compile time (see settings.js). 39 | 40 | // Attempt to auto-detect the environment 41 | var ENVIRONMENT_IS_WEB = typeof window == 'object'; 42 | var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function'; 43 | // N.b. Electron.js environment is simultaneously a NODE-environment, but 44 | // also a web environment. 45 | var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string'; 46 | var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; 47 | 48 | if (Module['ENVIRONMENT']) { 49 | throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)'); 50 | } 51 | 52 | // `/` should be present at the end if `scriptDirectory` is not empty 53 | var scriptDirectory = ''; 54 | function locateFile(path) { 55 | if (Module['locateFile']) { 56 | return Module['locateFile'](path, scriptDirectory); 57 | } 58 | return scriptDirectory + path; 59 | } 60 | 61 | // Hooks that are implemented differently in different runtime environments. 62 | var read_, 63 | readAsync, 64 | readBinary, 65 | setWindowTitle; 66 | 67 | // Normally we don't log exceptions but instead let them bubble out the top 68 | // level where the embedding environment (e.g. the browser) can handle 69 | // them. 70 | // However under v8 and node we sometimes exit the process direcly in which case 71 | // its up to use us to log the exception before exiting. 72 | // If we fix https://github.com/emscripten-core/emscripten/issues/15080 73 | // this may no longer be needed under node. 74 | function logExceptionOnExit(e) { 75 | if (e instanceof ExitStatus) return; 76 | let toLog = e; 77 | if (e && typeof e == 'object' && e.stack) { 78 | toLog = [e, e.stack]; 79 | } 80 | err('exiting due to exception: ' + toLog); 81 | } 82 | 83 | var fs; 84 | var nodePath; 85 | var requireNodeFS; 86 | 87 | if (ENVIRONMENT_IS_NODE) { 88 | if (!(typeof process == 'object' && typeof require == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); 89 | if (ENVIRONMENT_IS_WORKER) { 90 | scriptDirectory = require('path').dirname(scriptDirectory) + '/'; 91 | } else { 92 | scriptDirectory = __dirname + '/'; 93 | } 94 | 95 | // include: node_shell_read.js 96 | 97 | 98 | requireNodeFS = () => { 99 | // Use nodePath as the indicator for these not being initialized, 100 | // since in some environments a global fs may have already been 101 | // created. 102 | if (!nodePath) { 103 | fs = require('fs'); 104 | nodePath = require('path'); 105 | } 106 | }; 107 | 108 | read_ = function shell_read(filename, binary) { 109 | requireNodeFS(); 110 | filename = nodePath['normalize'](filename); 111 | return fs.readFileSync(filename, binary ? undefined : 'utf8'); 112 | }; 113 | 114 | readBinary = (filename) => { 115 | var ret = read_(filename, true); 116 | if (!ret.buffer) { 117 | ret = new Uint8Array(ret); 118 | } 119 | assert(ret.buffer); 120 | return ret; 121 | }; 122 | 123 | readAsync = (filename, onload, onerror) => { 124 | requireNodeFS(); 125 | filename = nodePath['normalize'](filename); 126 | fs.readFile(filename, function(err, data) { 127 | if (err) onerror(err); 128 | else onload(data.buffer); 129 | }); 130 | }; 131 | 132 | // end include: node_shell_read.js 133 | if (process['argv'].length > 1) { 134 | thisProgram = process['argv'][1].replace(/\\/g, '/'); 135 | } 136 | 137 | arguments_ = process['argv'].slice(2); 138 | 139 | if (typeof module != 'undefined') { 140 | module['exports'] = Module; 141 | } 142 | 143 | process['on']('uncaughtException', function(ex) { 144 | // suppress ExitStatus exceptions from showing an error 145 | if (!(ex instanceof ExitStatus)) { 146 | throw ex; 147 | } 148 | }); 149 | 150 | // Without this older versions of node (< v15) will log unhandled rejections 151 | // but return 0, which is not normally the desired behaviour. This is 152 | // not be needed with node v15 and about because it is now the default 153 | // behaviour: 154 | // See https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode 155 | process['on']('unhandledRejection', function(reason) { throw reason; }); 156 | 157 | quit_ = (status, toThrow) => { 158 | if (keepRuntimeAlive()) { 159 | process['exitCode'] = status; 160 | throw toThrow; 161 | } 162 | logExceptionOnExit(toThrow); 163 | process['exit'](status); 164 | }; 165 | 166 | Module['inspect'] = function () { return '[Emscripten Module object]'; }; 167 | 168 | } else 169 | if (ENVIRONMENT_IS_SHELL) { 170 | 171 | if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); 172 | 173 | if (typeof read != 'undefined') { 174 | read_ = function shell_read(f) { 175 | return read(f); 176 | }; 177 | } 178 | 179 | readBinary = function readBinary(f) { 180 | let data; 181 | if (typeof readbuffer == 'function') { 182 | return new Uint8Array(readbuffer(f)); 183 | } 184 | data = read(f, 'binary'); 185 | assert(typeof data == 'object'); 186 | return data; 187 | }; 188 | 189 | readAsync = function readAsync(f, onload, onerror) { 190 | setTimeout(() => onload(readBinary(f)), 0); 191 | }; 192 | 193 | if (typeof scriptArgs != 'undefined') { 194 | arguments_ = scriptArgs; 195 | } else if (typeof arguments != 'undefined') { 196 | arguments_ = arguments; 197 | } 198 | 199 | if (typeof quit == 'function') { 200 | quit_ = (status, toThrow) => { 201 | logExceptionOnExit(toThrow); 202 | quit(status); 203 | }; 204 | } 205 | 206 | if (typeof print != 'undefined') { 207 | // Prefer to use print/printErr where they exist, as they usually work better. 208 | if (typeof console == 'undefined') console = /** @type{!Console} */({}); 209 | console.log = /** @type{!function(this:Console, ...*): undefined} */ (print); 210 | console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print); 211 | } 212 | 213 | } else 214 | 215 | // Note that this includes Node.js workers when relevant (pthreads is enabled). 216 | // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and 217 | // ENVIRONMENT_IS_NODE. 218 | if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { 219 | if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled 220 | scriptDirectory = self.location.href; 221 | } else if (typeof document != 'undefined' && document.currentScript) { // web 222 | scriptDirectory = document.currentScript.src; 223 | } 224 | // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. 225 | // otherwise, slice off the final part of the url to find the script directory. 226 | // if scriptDirectory does not contain a slash, lastIndexOf will return -1, 227 | // and scriptDirectory will correctly be replaced with an empty string. 228 | // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #), 229 | // they are removed because they could contain a slash. 230 | if (scriptDirectory.indexOf('blob:') !== 0) { 231 | scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf('/')+1); 232 | } else { 233 | scriptDirectory = ''; 234 | } 235 | 236 | if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); 237 | 238 | // Differentiate the Web Worker from the Node Worker case, as reading must 239 | // be done differently. 240 | { 241 | // include: web_or_worker_shell_read.js 242 | 243 | 244 | read_ = (url) => { 245 | var xhr = new XMLHttpRequest(); 246 | xhr.open('GET', url, false); 247 | xhr.send(null); 248 | return xhr.responseText; 249 | } 250 | 251 | if (ENVIRONMENT_IS_WORKER) { 252 | readBinary = (url) => { 253 | var xhr = new XMLHttpRequest(); 254 | xhr.open('GET', url, false); 255 | xhr.responseType = 'arraybuffer'; 256 | xhr.send(null); 257 | return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response)); 258 | }; 259 | } 260 | 261 | readAsync = (url, onload, onerror) => { 262 | var xhr = new XMLHttpRequest(); 263 | xhr.open('GET', url, true); 264 | xhr.responseType = 'arraybuffer'; 265 | xhr.onload = () => { 266 | if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 267 | onload(xhr.response); 268 | return; 269 | } 270 | onerror(); 271 | }; 272 | xhr.onerror = onerror; 273 | xhr.send(null); 274 | } 275 | 276 | // end include: web_or_worker_shell_read.js 277 | } 278 | 279 | setWindowTitle = (title) => document.title = title; 280 | } else 281 | { 282 | throw new Error('environment detection error'); 283 | } 284 | 285 | var out = Module['print'] || console.log.bind(console); 286 | var err = Module['printErr'] || console.warn.bind(console); 287 | 288 | // Merge back in the overrides 289 | Object.assign(Module, moduleOverrides); 290 | // Free the object hierarchy contained in the overrides, this lets the GC 291 | // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. 292 | moduleOverrides = null; 293 | checkIncomingModuleAPI(); 294 | 295 | // Emit code to handle expected values on the Module object. This applies Module.x 296 | // to the proper local x. This has two benefits: first, we only emit it if it is 297 | // expected to arrive, and second, by using a local everywhere else that can be 298 | // minified. 299 | 300 | if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_'); 301 | 302 | if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram'); 303 | 304 | if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_'); 305 | 306 | // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message 307 | // Assertions on removed incoming Module JS APIs. 308 | assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); 309 | assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); 310 | assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); 311 | assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); 312 | assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); 313 | assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); 314 | assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); 315 | assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)'); 316 | assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); 317 | legacyModuleProp('read', 'read_'); 318 | legacyModuleProp('readAsync', 'readAsync'); 319 | legacyModuleProp('readBinary', 'readBinary'); 320 | legacyModuleProp('setWindowTitle', 'setWindowTitle'); 321 | var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; 322 | var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; 323 | var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; 324 | var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; 325 | function alignMemory() { abort('`alignMemory` is now a library function and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line'); } 326 | 327 | assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."); 328 | 329 | 330 | 331 | 332 | var STACK_ALIGN = 16; 333 | var POINTER_SIZE = 4; 334 | 335 | function getNativeTypeSize(type) { 336 | switch (type) { 337 | case 'i1': case 'i8': case 'u8': return 1; 338 | case 'i16': case 'u16': return 2; 339 | case 'i32': case 'u32': return 4; 340 | case 'i64': case 'u64': return 8; 341 | case 'float': return 4; 342 | case 'double': return 8; 343 | default: { 344 | if (type[type.length - 1] === '*') { 345 | return POINTER_SIZE; 346 | } else if (type[0] === 'i') { 347 | const bits = Number(type.substr(1)); 348 | assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); 349 | return bits / 8; 350 | } else { 351 | return 0; 352 | } 353 | } 354 | } 355 | } 356 | 357 | function warnOnce(text) { 358 | if (!warnOnce.shown) warnOnce.shown = {}; 359 | if (!warnOnce.shown[text]) { 360 | warnOnce.shown[text] = 1; 361 | err(text); 362 | } 363 | } 364 | 365 | // include: runtime_functions.js 366 | 367 | 368 | // This gives correct answers for everything less than 2^{14} = 16384 369 | // I hope nobody is contemplating functions with 16384 arguments... 370 | function uleb128Encode(n) { 371 | assert(n < 16384); 372 | if (n < 128) { 373 | return [n]; 374 | } 375 | return [(n % 128) | 128, n >> 7]; 376 | } 377 | 378 | // Converts a signature like 'vii' into a description of the wasm types, like 379 | // { parameters: ['i32', 'i32'], results: [] }. 380 | function sigToWasmTypes(sig) { 381 | var typeNames = { 382 | 'i': 'i32', 383 | 'j': 'i64', 384 | 'f': 'f32', 385 | 'd': 'f64', 386 | 'p': 'i32', 387 | }; 388 | var type = { 389 | parameters: [], 390 | results: sig[0] == 'v' ? [] : [typeNames[sig[0]]] 391 | }; 392 | for (var i = 1; i < sig.length; ++i) { 393 | assert(sig[i] in typeNames, 'invalid signature char: ' + sig[i]); 394 | type.parameters.push(typeNames[sig[i]]); 395 | } 396 | return type; 397 | } 398 | 399 | // Wraps a JS function as a wasm function with a given signature. 400 | function convertJsFunctionToWasm(func, sig) { 401 | 402 | // If the type reflection proposal is available, use the new 403 | // "WebAssembly.Function" constructor. 404 | // Otherwise, construct a minimal wasm module importing the JS function and 405 | // re-exporting it. 406 | if (typeof WebAssembly.Function == "function") { 407 | return new WebAssembly.Function(sigToWasmTypes(sig), func); 408 | } 409 | 410 | // The module is static, with the exception of the type section, which is 411 | // generated based on the signature passed in. 412 | var typeSection = [ 413 | 0x01, // count: 1 414 | 0x60, // form: func 415 | ]; 416 | var sigRet = sig.slice(0, 1); 417 | var sigParam = sig.slice(1); 418 | var typeCodes = { 419 | 'i': 0x7f, // i32 420 | 'p': 0x7f, // i32 421 | 'j': 0x7e, // i64 422 | 'f': 0x7d, // f32 423 | 'd': 0x7c, // f64 424 | }; 425 | 426 | // Parameters, length + signatures 427 | typeSection = typeSection.concat(uleb128Encode(sigParam.length)); 428 | for (var i = 0; i < sigParam.length; ++i) { 429 | assert(sigParam[i] in typeCodes, 'invalid signature char: ' + sigParam[i]); 430 | typeSection.push(typeCodes[sigParam[i]]); 431 | } 432 | 433 | // Return values, length + signatures 434 | // With no multi-return in MVP, either 0 (void) or 1 (anything else) 435 | if (sigRet == 'v') { 436 | typeSection.push(0x00); 437 | } else { 438 | typeSection = typeSection.concat([0x01, typeCodes[sigRet]]); 439 | } 440 | 441 | // Write the section code and overall length of the type section into the 442 | // section header 443 | typeSection = [0x01 /* Type section code */].concat( 444 | uleb128Encode(typeSection.length), 445 | typeSection 446 | ); 447 | 448 | // Rest of the module is static 449 | var bytes = new Uint8Array([ 450 | 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") 451 | 0x01, 0x00, 0x00, 0x00, // version: 1 452 | ].concat(typeSection, [ 453 | 0x02, 0x07, // import section 454 | // (import "e" "f" (func 0 (type 0))) 455 | 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00, 456 | 0x07, 0x05, // export section 457 | // (export "f" (func 0 (type 0))) 458 | 0x01, 0x01, 0x66, 0x00, 0x00, 459 | ])); 460 | 461 | // We can compile this wasm module synchronously because it is very small. 462 | // This accepts an import (at "e.f"), that it reroutes to an export (at "f") 463 | var module = new WebAssembly.Module(bytes); 464 | var instance = new WebAssembly.Instance(module, { 465 | 'e': { 466 | 'f': func 467 | } 468 | }); 469 | var wrappedFunc = instance.exports['f']; 470 | return wrappedFunc; 471 | } 472 | 473 | var freeTableIndexes = []; 474 | 475 | // Weak map of functions in the table to their indexes, created on first use. 476 | var functionsInTableMap; 477 | 478 | function getEmptyTableSlot() { 479 | // Reuse a free index if there is one, otherwise grow. 480 | if (freeTableIndexes.length) { 481 | return freeTableIndexes.pop(); 482 | } 483 | // Grow the table 484 | try { 485 | wasmTable.grow(1); 486 | } catch (err) { 487 | if (!(err instanceof RangeError)) { 488 | throw err; 489 | } 490 | throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.'; 491 | } 492 | return wasmTable.length - 1; 493 | } 494 | 495 | function updateTableMap(offset, count) { 496 | for (var i = offset; i < offset + count; i++) { 497 | var item = getWasmTableEntry(i); 498 | // Ignore null values. 499 | if (item) { 500 | functionsInTableMap.set(item, i); 501 | } 502 | } 503 | } 504 | 505 | /** 506 | * Add a function to the table. 507 | * 'sig' parameter is required if the function being added is a JS function. 508 | * @param {string=} sig 509 | */ 510 | function addFunction(func, sig) { 511 | assert(typeof func != 'undefined'); 512 | 513 | // Check if the function is already in the table, to ensure each function 514 | // gets a unique index. First, create the map if this is the first use. 515 | if (!functionsInTableMap) { 516 | functionsInTableMap = new WeakMap(); 517 | updateTableMap(0, wasmTable.length); 518 | } 519 | if (functionsInTableMap.has(func)) { 520 | return functionsInTableMap.get(func); 521 | } 522 | 523 | // It's not in the table, add it now. 524 | 525 | var ret = getEmptyTableSlot(); 526 | 527 | // Set the new value. 528 | try { 529 | // Attempting to call this with JS function will cause of table.set() to fail 530 | setWasmTableEntry(ret, func); 531 | } catch (err) { 532 | if (!(err instanceof TypeError)) { 533 | throw err; 534 | } 535 | assert(typeof sig != 'undefined', 'Missing signature argument to addFunction: ' + func); 536 | var wrapped = convertJsFunctionToWasm(func, sig); 537 | setWasmTableEntry(ret, wrapped); 538 | } 539 | 540 | functionsInTableMap.set(func, ret); 541 | 542 | return ret; 543 | } 544 | 545 | function removeFunction(index) { 546 | functionsInTableMap.delete(getWasmTableEntry(index)); 547 | freeTableIndexes.push(index); 548 | } 549 | 550 | // end include: runtime_functions.js 551 | // include: runtime_debug.js 552 | 553 | 554 | function legacyModuleProp(prop, newName) { 555 | if (!Object.getOwnPropertyDescriptor(Module, prop)) { 556 | Object.defineProperty(Module, prop, { 557 | configurable: true, 558 | get: function() { 559 | abort('Module.' + prop + ' has been replaced with plain ' + newName + ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)'); 560 | } 561 | }); 562 | } 563 | } 564 | 565 | function ignoredModuleProp(prop) { 566 | if (Object.getOwnPropertyDescriptor(Module, prop)) { 567 | abort('`Module.' + prop + '` was supplied but `' + prop + '` not included in INCOMING_MODULE_JS_API'); 568 | } 569 | } 570 | 571 | function unexportedMessage(sym, isFSSybol) { 572 | var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)"; 573 | if (isFSSybol) { 574 | msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; 575 | } 576 | return msg; 577 | } 578 | 579 | function unexportedRuntimeSymbol(sym, isFSSybol) { 580 | if (!Object.getOwnPropertyDescriptor(Module, sym)) { 581 | Object.defineProperty(Module, sym, { 582 | configurable: true, 583 | get: function() { 584 | abort(unexportedMessage(sym, isFSSybol)); 585 | } 586 | }); 587 | } 588 | } 589 | 590 | function unexportedRuntimeFunction(sym, isFSSybol) { 591 | if (!Object.getOwnPropertyDescriptor(Module, sym)) { 592 | Module[sym] = () => abort(unexportedMessage(sym, isFSSybol)); 593 | } 594 | } 595 | 596 | // end include: runtime_debug.js 597 | var tempRet0 = 0; 598 | var setTempRet0 = (value) => { tempRet0 = value; }; 599 | var getTempRet0 = () => tempRet0; 600 | 601 | 602 | 603 | // === Preamble library stuff === 604 | 605 | // Documentation for the public APIs defined in this file must be updated in: 606 | // site/source/docs/api_reference/preamble.js.rst 607 | // A prebuilt local version of the documentation is available at: 608 | // site/build/text/docs/api_reference/preamble.js.txt 609 | // You can also build docs locally as HTML or other formats in site/ 610 | // An online HTML version (which may be of a different version of Emscripten) 611 | // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html 612 | 613 | var wasmBinary; 614 | if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); 615 | var noExitRuntime = Module['noExitRuntime'] || true;legacyModuleProp('noExitRuntime', 'noExitRuntime'); 616 | 617 | if (typeof WebAssembly != 'object') { 618 | abort('no native wasm support detected'); 619 | } 620 | 621 | // Wasm globals 622 | 623 | var wasmMemory; 624 | 625 | //======================================== 626 | // Runtime essentials 627 | //======================================== 628 | 629 | // whether we are quitting the application. no code should run after this. 630 | // set in exit() and abort() 631 | var ABORT = false; 632 | 633 | // set by exit() and abort(). Passed to 'onExit' handler. 634 | // NOTE: This is also used as the process return code code in shell environments 635 | // but only when noExitRuntime is false. 636 | var EXITSTATUS; 637 | 638 | /** @type {function(*, string=)} */ 639 | function assert(condition, text) { 640 | if (!condition) { 641 | abort('Assertion failed' + (text ? ': ' + text : '')); 642 | } 643 | } 644 | 645 | // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) 646 | function getCFunc(ident) { 647 | var func = Module['_' + ident]; // closure exported function 648 | assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); 649 | return func; 650 | } 651 | 652 | // C calling interface. 653 | /** @param {string|null=} returnType 654 | @param {Array=} argTypes 655 | @param {Arguments|Array=} args 656 | @param {Object=} opts */ 657 | function ccall(ident, returnType, argTypes, args, opts) { 658 | // For fast lookup of conversion functions 659 | var toC = { 660 | 'string': function(str) { 661 | var ret = 0; 662 | if (str !== null && str !== undefined && str !== 0) { // null string 663 | // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' 664 | var len = (str.length << 2) + 1; 665 | ret = stackAlloc(len); 666 | stringToUTF8(str, ret, len); 667 | } 668 | return ret; 669 | }, 670 | 'array': function(arr) { 671 | var ret = stackAlloc(arr.length); 672 | writeArrayToMemory(arr, ret); 673 | return ret; 674 | } 675 | }; 676 | 677 | function convertReturnValue(ret) { 678 | if (returnType === 'string') { 679 | 680 | return UTF8ToString(ret); 681 | } 682 | if (returnType === 'boolean') return Boolean(ret); 683 | return ret; 684 | } 685 | 686 | var func = getCFunc(ident); 687 | var cArgs = []; 688 | var stack = 0; 689 | assert(returnType !== 'array', 'Return type should not be "array".'); 690 | if (args) { 691 | for (var i = 0; i < args.length; i++) { 692 | var converter = toC[argTypes[i]]; 693 | if (converter) { 694 | if (stack === 0) stack = stackSave(); 695 | cArgs[i] = converter(args[i]); 696 | } else { 697 | cArgs[i] = args[i]; 698 | } 699 | } 700 | } 701 | var ret = func.apply(null, cArgs); 702 | function onDone(ret) { 703 | if (stack !== 0) stackRestore(stack); 704 | return convertReturnValue(ret); 705 | } 706 | 707 | ret = onDone(ret); 708 | return ret; 709 | } 710 | 711 | /** @param {string=} returnType 712 | @param {Array=} argTypes 713 | @param {Object=} opts */ 714 | function cwrap(ident, returnType, argTypes, opts) { 715 | return function() { 716 | return ccall(ident, returnType, argTypes, arguments, opts); 717 | } 718 | } 719 | 720 | // We used to include malloc/free by default in the past. Show a helpful error in 721 | // builds with assertions. 722 | function _malloc() { 723 | abort("malloc() called but not included in the build - add '_malloc' to EXPORTED_FUNCTIONS"); 724 | } 725 | function _free() { 726 | // Show a helpful error since we used to include free by default in the past. 727 | abort("free() called but not included in the build - add '_free' to EXPORTED_FUNCTIONS"); 728 | } 729 | 730 | // include: runtime_legacy.js 731 | 732 | 733 | var ALLOC_NORMAL = 0; // Tries to use _malloc() 734 | var ALLOC_STACK = 1; // Lives for the duration of the current function call 735 | 736 | /** 737 | * allocate(): This function is no longer used by emscripten but is kept around to avoid 738 | * breaking external users. 739 | * You should normally not use allocate(), and instead allocate 740 | * memory using _malloc()/stackAlloc(), initialize it with 741 | * setValue(), and so forth. 742 | * @param {(Uint8Array|Array)} slab: An array of data. 743 | * @param {number=} allocator : How to allocate memory, see ALLOC_* 744 | */ 745 | function allocate(slab, allocator) { 746 | var ret; 747 | assert(typeof allocator == 'number', 'allocate no longer takes a type argument') 748 | assert(typeof slab != 'number', 'allocate no longer takes a number as arg0') 749 | 750 | if (allocator == ALLOC_STACK) { 751 | ret = stackAlloc(slab.length); 752 | } else { 753 | ret = abort('malloc was not included, but is needed in allocate. Adding "_malloc" to EXPORTED_FUNCTIONS should fix that. This may be a bug in the compiler, please file an issue.');; 754 | } 755 | 756 | if (!slab.subarray && !slab.slice) { 757 | slab = new Uint8Array(slab); 758 | } 759 | HEAPU8.set(slab, ret); 760 | return ret; 761 | } 762 | 763 | // end include: runtime_legacy.js 764 | // include: runtime_strings.js 765 | 766 | 767 | // runtime_strings.js: Strings related runtime functions that are part of both MINIMAL_RUNTIME and regular runtime. 768 | 769 | var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined; 770 | 771 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns 772 | // a copy of that string as a Javascript String object. 773 | /** 774 | * heapOrArray is either a regular array, or a JavaScript typed array view. 775 | * @param {number} idx 776 | * @param {number=} maxBytesToRead 777 | * @return {string} 778 | */ 779 | function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { 780 | var endIdx = idx + maxBytesToRead; 781 | var endPtr = idx; 782 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 783 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 784 | // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity) 785 | while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; 786 | 787 | if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { 788 | return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); 789 | } else { 790 | var str = ''; 791 | // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that 792 | while (idx < endPtr) { 793 | // For UTF8 byte structure, see: 794 | // http://en.wikipedia.org/wiki/UTF-8#Description 795 | // https://www.ietf.org/rfc/rfc2279.txt 796 | // https://tools.ietf.org/html/rfc3629 797 | var u0 = heapOrArray[idx++]; 798 | if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } 799 | var u1 = heapOrArray[idx++] & 63; 800 | if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } 801 | var u2 = heapOrArray[idx++] & 63; 802 | if ((u0 & 0xF0) == 0xE0) { 803 | u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; 804 | } else { 805 | if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!'); 806 | u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heapOrArray[idx++] & 63); 807 | } 808 | 809 | if (u0 < 0x10000) { 810 | str += String.fromCharCode(u0); 811 | } else { 812 | var ch = u0 - 0x10000; 813 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 814 | } 815 | } 816 | } 817 | return str; 818 | } 819 | 820 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a 821 | // copy of that string as a Javascript String object. 822 | // maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit 823 | // this parameter to scan the string until the first \0 byte. If maxBytesToRead is 824 | // passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the 825 | // middle, then the string will cut short at that byte index (i.e. maxBytesToRead will 826 | // not produce a string of exact length [ptr, ptr+maxBytesToRead[) 827 | // N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may 828 | // throw JS JIT optimizations off, so it is worth to consider consistently using one 829 | // style or the other. 830 | /** 831 | * @param {number} ptr 832 | * @param {number=} maxBytesToRead 833 | * @return {string} 834 | */ 835 | function UTF8ToString(ptr, maxBytesToRead) { 836 | return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; 837 | } 838 | 839 | // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', 840 | // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP. 841 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 842 | // Parameters: 843 | // str: the Javascript string to copy. 844 | // heap: the array to copy to. Each index in this array is assumed to be one 8-byte element. 845 | // outIdx: The starting offset in the array to begin the copying. 846 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. 847 | // This count should include the null terminator, 848 | // i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else. 849 | // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator. 850 | // Returns the number of bytes written, EXCLUDING the null terminator. 851 | 852 | function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { 853 | if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. 854 | return 0; 855 | 856 | var startIdx = outIdx; 857 | var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. 858 | for (var i = 0; i < str.length; ++i) { 859 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 860 | // See http://unicode.org/faq/utf_bom.html#utf16-3 861 | // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 862 | var u = str.charCodeAt(i); // possibly a lead surrogate 863 | if (u >= 0xD800 && u <= 0xDFFF) { 864 | var u1 = str.charCodeAt(++i); 865 | u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); 866 | } 867 | if (u <= 0x7F) { 868 | if (outIdx >= endIdx) break; 869 | heap[outIdx++] = u; 870 | } else if (u <= 0x7FF) { 871 | if (outIdx + 1 >= endIdx) break; 872 | heap[outIdx++] = 0xC0 | (u >> 6); 873 | heap[outIdx++] = 0x80 | (u & 63); 874 | } else if (u <= 0xFFFF) { 875 | if (outIdx + 2 >= endIdx) break; 876 | heap[outIdx++] = 0xE0 | (u >> 12); 877 | heap[outIdx++] = 0x80 | ((u >> 6) & 63); 878 | heap[outIdx++] = 0x80 | (u & 63); 879 | } else { 880 | if (outIdx + 3 >= endIdx) break; 881 | if (u > 0x10FFFF) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).'); 882 | heap[outIdx++] = 0xF0 | (u >> 18); 883 | heap[outIdx++] = 0x80 | ((u >> 12) & 63); 884 | heap[outIdx++] = 0x80 | ((u >> 6) & 63); 885 | heap[outIdx++] = 0x80 | (u & 63); 886 | } 887 | } 888 | // Null-terminate the pointer to the buffer. 889 | heap[outIdx] = 0; 890 | return outIdx - startIdx; 891 | } 892 | 893 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 894 | // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP. 895 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 896 | // Returns the number of bytes written, EXCLUDING the null terminator. 897 | 898 | function stringToUTF8(str, outPtr, maxBytesToWrite) { 899 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); 900 | return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); 901 | } 902 | 903 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. 904 | function lengthBytesUTF8(str) { 905 | var len = 0; 906 | for (var i = 0; i < str.length; ++i) { 907 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 908 | // See http://unicode.org/faq/utf_bom.html#utf16-3 909 | var u = str.charCodeAt(i); // possibly a lead surrogate 910 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 911 | if (u <= 0x7F) ++len; 912 | else if (u <= 0x7FF) len += 2; 913 | else if (u <= 0xFFFF) len += 3; 914 | else len += 4; 915 | } 916 | return len; 917 | } 918 | 919 | // end include: runtime_strings.js 920 | // include: runtime_strings_extra.js 921 | 922 | 923 | // runtime_strings_extra.js: Strings related runtime functions that are available only in regular runtime. 924 | 925 | // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns 926 | // a copy of that string as a Javascript String object. 927 | 928 | function AsciiToString(ptr) { 929 | var str = ''; 930 | while (1) { 931 | var ch = HEAPU8[((ptr++)>>0)]; 932 | if (!ch) return str; 933 | str += String.fromCharCode(ch); 934 | } 935 | } 936 | 937 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 938 | // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP. 939 | 940 | function stringToAscii(str, outPtr) { 941 | return writeAsciiToMemory(str, outPtr, false); 942 | } 943 | 944 | // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns 945 | // a copy of that string as a Javascript String object. 946 | 947 | var UTF16Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf-16le') : undefined; 948 | 949 | function UTF16ToString(ptr, maxBytesToRead) { 950 | assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!'); 951 | var endPtr = ptr; 952 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 953 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 954 | var idx = endPtr >> 1; 955 | var maxIdx = idx + maxBytesToRead / 2; 956 | // If maxBytesToRead is not passed explicitly, it will be undefined, and this 957 | // will always evaluate to true. This saves on code size. 958 | while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx; 959 | endPtr = idx << 1; 960 | 961 | if (endPtr - ptr > 32 && UTF16Decoder) { 962 | return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); 963 | } else { 964 | var str = ''; 965 | 966 | // If maxBytesToRead is not passed explicitly, it will be undefined, and the for-loop's condition 967 | // will always evaluate to true. The loop is then terminated on the first null char. 968 | for (var i = 0; !(i >= maxBytesToRead / 2); ++i) { 969 | var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; 970 | if (codeUnit == 0) break; 971 | // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. 972 | str += String.fromCharCode(codeUnit); 973 | } 974 | 975 | return str; 976 | } 977 | } 978 | 979 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 980 | // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP. 981 | // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write. 982 | // Parameters: 983 | // str: the Javascript string to copy. 984 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 985 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 986 | // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else. 987 | // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator. 988 | // Returns the number of bytes written, EXCLUDING the null terminator. 989 | 990 | function stringToUTF16(str, outPtr, maxBytesToWrite) { 991 | assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!'); 992 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); 993 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 994 | if (maxBytesToWrite === undefined) { 995 | maxBytesToWrite = 0x7FFFFFFF; 996 | } 997 | if (maxBytesToWrite < 2) return 0; 998 | maxBytesToWrite -= 2; // Null terminator. 999 | var startPtr = outPtr; 1000 | var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; 1001 | for (var i = 0; i < numCharsToWrite; ++i) { 1002 | // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. 1003 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 1004 | HEAP16[((outPtr)>>1)] = codeUnit; 1005 | outPtr += 2; 1006 | } 1007 | // Null-terminate the pointer to the HEAP. 1008 | HEAP16[((outPtr)>>1)] = 0; 1009 | return outPtr - startPtr; 1010 | } 1011 | 1012 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 1013 | 1014 | function lengthBytesUTF16(str) { 1015 | return str.length*2; 1016 | } 1017 | 1018 | function UTF32ToString(ptr, maxBytesToRead) { 1019 | assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!'); 1020 | var i = 0; 1021 | 1022 | var str = ''; 1023 | // If maxBytesToRead is not passed explicitly, it will be undefined, and this 1024 | // will always evaluate to true. This saves on code size. 1025 | while (!(i >= maxBytesToRead / 4)) { 1026 | var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; 1027 | if (utf32 == 0) break; 1028 | ++i; 1029 | // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. 1030 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1031 | if (utf32 >= 0x10000) { 1032 | var ch = utf32 - 0x10000; 1033 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 1034 | } else { 1035 | str += String.fromCharCode(utf32); 1036 | } 1037 | } 1038 | return str; 1039 | } 1040 | 1041 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 1042 | // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP. 1043 | // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write. 1044 | // Parameters: 1045 | // str: the Javascript string to copy. 1046 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 1047 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 1048 | // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else. 1049 | // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator. 1050 | // Returns the number of bytes written, EXCLUDING the null terminator. 1051 | 1052 | function stringToUTF32(str, outPtr, maxBytesToWrite) { 1053 | assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!'); 1054 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); 1055 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 1056 | if (maxBytesToWrite === undefined) { 1057 | maxBytesToWrite = 0x7FFFFFFF; 1058 | } 1059 | if (maxBytesToWrite < 4) return 0; 1060 | var startPtr = outPtr; 1061 | var endPtr = startPtr + maxBytesToWrite - 4; 1062 | for (var i = 0; i < str.length; ++i) { 1063 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. 1064 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1065 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 1066 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { 1067 | var trailSurrogate = str.charCodeAt(++i); 1068 | codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); 1069 | } 1070 | HEAP32[((outPtr)>>2)] = codeUnit; 1071 | outPtr += 4; 1072 | if (outPtr + 4 > endPtr) break; 1073 | } 1074 | // Null-terminate the pointer to the HEAP. 1075 | HEAP32[((outPtr)>>2)] = 0; 1076 | return outPtr - startPtr; 1077 | } 1078 | 1079 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 1080 | 1081 | function lengthBytesUTF32(str) { 1082 | var len = 0; 1083 | for (var i = 0; i < str.length; ++i) { 1084 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. 1085 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1086 | var codeUnit = str.charCodeAt(i); 1087 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. 1088 | len += 4; 1089 | } 1090 | 1091 | return len; 1092 | } 1093 | 1094 | // Allocate heap space for a JS string, and write it there. 1095 | // It is the responsibility of the caller to free() that memory. 1096 | function allocateUTF8(str) { 1097 | var size = lengthBytesUTF8(str) + 1; 1098 | var ret = abort('malloc was not included, but is needed in allocateUTF8. Adding "_malloc" to EXPORTED_FUNCTIONS should fix that. This may be a bug in the compiler, please file an issue.');; 1099 | if (ret) stringToUTF8Array(str, HEAP8, ret, size); 1100 | return ret; 1101 | } 1102 | 1103 | // Allocate stack space for a JS string, and write it there. 1104 | function allocateUTF8OnStack(str) { 1105 | var size = lengthBytesUTF8(str) + 1; 1106 | var ret = stackAlloc(size); 1107 | stringToUTF8Array(str, HEAP8, ret, size); 1108 | return ret; 1109 | } 1110 | 1111 | // Deprecated: This function should not be called because it is unsafe and does not provide 1112 | // a maximum length limit of how many bytes it is allowed to write. Prefer calling the 1113 | // function stringToUTF8Array() instead, which takes in a maximum length that can be used 1114 | // to be secure from out of bounds writes. 1115 | /** @deprecated 1116 | @param {boolean=} dontAddNull */ 1117 | function writeStringToMemory(string, buffer, dontAddNull) { 1118 | warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); 1119 | 1120 | var /** @type {number} */ lastChar, /** @type {number} */ end; 1121 | if (dontAddNull) { 1122 | // stringToUTF8Array always appends null. If we don't want to do that, remember the 1123 | // character that existed at the location where the null will be placed, and restore 1124 | // that after the write (below). 1125 | end = buffer + lengthBytesUTF8(string); 1126 | lastChar = HEAP8[end]; 1127 | } 1128 | stringToUTF8(string, buffer, Infinity); 1129 | if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. 1130 | } 1131 | 1132 | function writeArrayToMemory(array, buffer) { 1133 | assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)') 1134 | HEAP8.set(array, buffer); 1135 | } 1136 | 1137 | /** @param {boolean=} dontAddNull */ 1138 | function writeAsciiToMemory(str, buffer, dontAddNull) { 1139 | for (var i = 0; i < str.length; ++i) { 1140 | assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff)); 1141 | HEAP8[((buffer++)>>0)] = str.charCodeAt(i); 1142 | } 1143 | // Null-terminate the pointer to the HEAP. 1144 | if (!dontAddNull) HEAP8[((buffer)>>0)] = 0; 1145 | } 1146 | 1147 | // end include: runtime_strings_extra.js 1148 | // Memory management 1149 | 1150 | var HEAP, 1151 | /** @type {!ArrayBuffer} */ 1152 | buffer, 1153 | /** @type {!Int8Array} */ 1154 | HEAP8, 1155 | /** @type {!Uint8Array} */ 1156 | HEAPU8, 1157 | /** @type {!Int16Array} */ 1158 | HEAP16, 1159 | /** @type {!Uint16Array} */ 1160 | HEAPU16, 1161 | /** @type {!Int32Array} */ 1162 | HEAP32, 1163 | /** @type {!Uint32Array} */ 1164 | HEAPU32, 1165 | /** @type {!Float32Array} */ 1166 | HEAPF32, 1167 | /** @type {!Float64Array} */ 1168 | HEAPF64; 1169 | 1170 | function updateGlobalBufferAndViews(buf) { 1171 | buffer = buf; 1172 | Module['HEAP8'] = HEAP8 = new Int8Array(buf); 1173 | Module['HEAP16'] = HEAP16 = new Int16Array(buf); 1174 | Module['HEAP32'] = HEAP32 = new Int32Array(buf); 1175 | Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf); 1176 | Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf); 1177 | Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf); 1178 | Module['HEAPF32'] = HEAPF32 = new Float32Array(buf); 1179 | Module['HEAPF64'] = HEAPF64 = new Float64Array(buf); 1180 | } 1181 | 1182 | var TOTAL_STACK = 5242880; 1183 | if (Module['TOTAL_STACK']) assert(TOTAL_STACK === Module['TOTAL_STACK'], 'the stack size can no longer be determined at runtime') 1184 | 1185 | var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY'); 1186 | 1187 | assert(INITIAL_MEMORY >= TOTAL_STACK, 'INITIAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); 1188 | 1189 | // check for full engine support (use string 'subarray' to avoid closure compiler confusion) 1190 | assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined, 1191 | 'JS engine does not provide full typed array support'); 1192 | 1193 | // If memory is defined in wasm, the user can't provide it. 1194 | assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); 1195 | assert(INITIAL_MEMORY == 16777216, 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); 1196 | 1197 | // include: runtime_init_table.js 1198 | // In regular non-RELOCATABLE mode the table is exported 1199 | // from the wasm module and this will be assigned once 1200 | // the exports are available. 1201 | var wasmTable; 1202 | 1203 | // end include: runtime_init_table.js 1204 | // include: runtime_stack_check.js 1205 | 1206 | 1207 | // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. 1208 | function writeStackCookie() { 1209 | var max = _emscripten_stack_get_end(); 1210 | assert((max & 3) == 0); 1211 | // The stack grow downwards towards _emscripten_stack_get_end. 1212 | // We write cookies to the final two words in the stack and detect if they are 1213 | // ever overwritten. 1214 | HEAP32[((max)>>2)] = 0x2135467; 1215 | HEAP32[(((max)+(4))>>2)] = 0x89BACDFE; 1216 | // Also test the global address 0 for integrity. 1217 | HEAPU32[0] = 0x63736d65; /* 'emsc' */ 1218 | } 1219 | 1220 | function checkStackCookie() { 1221 | if (ABORT) return; 1222 | var max = _emscripten_stack_get_end(); 1223 | var cookie1 = HEAPU32[((max)>>2)]; 1224 | var cookie2 = HEAPU32[(((max)+(4))>>2)]; 1225 | if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) { 1226 | abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x' + cookie2.toString(16) + ' 0x' + cookie1.toString(16)); 1227 | } 1228 | // Also test the global address 0 for integrity. 1229 | if (HEAPU32[0] !== 0x63736d65 /* 'emsc' */) abort('Runtime error: The application has corrupted its heap memory area (address zero)!'); 1230 | } 1231 | 1232 | // end include: runtime_stack_check.js 1233 | // include: runtime_assertions.js 1234 | 1235 | 1236 | // Endianness check 1237 | (function() { 1238 | var h16 = new Int16Array(1); 1239 | var h8 = new Int8Array(h16.buffer); 1240 | h16[0] = 0x6373; 1241 | if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)'; 1242 | })(); 1243 | 1244 | // end include: runtime_assertions.js 1245 | var __ATPRERUN__ = []; // functions called before the runtime is initialized 1246 | var __ATINIT__ = []; // functions called during startup 1247 | var __ATEXIT__ = []; // functions called during shutdown 1248 | var __ATPOSTRUN__ = []; // functions called after the main() is called 1249 | 1250 | var runtimeInitialized = false; 1251 | 1252 | function keepRuntimeAlive() { 1253 | return noExitRuntime; 1254 | } 1255 | 1256 | function preRun() { 1257 | 1258 | if (Module['preRun']) { 1259 | if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; 1260 | while (Module['preRun'].length) { 1261 | addOnPreRun(Module['preRun'].shift()); 1262 | } 1263 | } 1264 | 1265 | callRuntimeCallbacks(__ATPRERUN__); 1266 | } 1267 | 1268 | function initRuntime() { 1269 | assert(!runtimeInitialized); 1270 | runtimeInitialized = true; 1271 | 1272 | checkStackCookie(); 1273 | 1274 | 1275 | callRuntimeCallbacks(__ATINIT__); 1276 | } 1277 | 1278 | function postRun() { 1279 | checkStackCookie(); 1280 | 1281 | if (Module['postRun']) { 1282 | if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; 1283 | while (Module['postRun'].length) { 1284 | addOnPostRun(Module['postRun'].shift()); 1285 | } 1286 | } 1287 | 1288 | callRuntimeCallbacks(__ATPOSTRUN__); 1289 | } 1290 | 1291 | function addOnPreRun(cb) { 1292 | __ATPRERUN__.unshift(cb); 1293 | } 1294 | 1295 | function addOnInit(cb) { 1296 | __ATINIT__.unshift(cb); 1297 | } 1298 | 1299 | function addOnExit(cb) { 1300 | } 1301 | 1302 | function addOnPostRun(cb) { 1303 | __ATPOSTRUN__.unshift(cb); 1304 | } 1305 | 1306 | // include: runtime_math.js 1307 | 1308 | 1309 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul 1310 | 1311 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround 1312 | 1313 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 1314 | 1315 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc 1316 | 1317 | assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); 1318 | assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); 1319 | assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); 1320 | assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill'); 1321 | 1322 | // end include: runtime_math.js 1323 | // A counter of dependencies for calling run(). If we need to 1324 | // do asynchronous work before running, increment this and 1325 | // decrement it. Incrementing must happen in a place like 1326 | // Module.preRun (used by emcc to add file preloading). 1327 | // Note that you can add dependencies in preRun, even though 1328 | // it happens right before run - run will be postponed until 1329 | // the dependencies are met. 1330 | var runDependencies = 0; 1331 | var runDependencyWatcher = null; 1332 | var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled 1333 | var runDependencyTracking = {}; 1334 | 1335 | function getUniqueRunDependency(id) { 1336 | var orig = id; 1337 | while (1) { 1338 | if (!runDependencyTracking[id]) return id; 1339 | id = orig + Math.random(); 1340 | } 1341 | } 1342 | 1343 | function addRunDependency(id) { 1344 | runDependencies++; 1345 | 1346 | if (Module['monitorRunDependencies']) { 1347 | Module['monitorRunDependencies'](runDependencies); 1348 | } 1349 | 1350 | if (id) { 1351 | assert(!runDependencyTracking[id]); 1352 | runDependencyTracking[id] = 1; 1353 | if (runDependencyWatcher === null && typeof setInterval != 'undefined') { 1354 | // Check for missing dependencies every few seconds 1355 | runDependencyWatcher = setInterval(function() { 1356 | if (ABORT) { 1357 | clearInterval(runDependencyWatcher); 1358 | runDependencyWatcher = null; 1359 | return; 1360 | } 1361 | var shown = false; 1362 | for (var dep in runDependencyTracking) { 1363 | if (!shown) { 1364 | shown = true; 1365 | err('still waiting on run dependencies:'); 1366 | } 1367 | err('dependency: ' + dep); 1368 | } 1369 | if (shown) { 1370 | err('(end of list)'); 1371 | } 1372 | }, 10000); 1373 | } 1374 | } else { 1375 | err('warning: run dependency added without ID'); 1376 | } 1377 | } 1378 | 1379 | function removeRunDependency(id) { 1380 | runDependencies--; 1381 | 1382 | if (Module['monitorRunDependencies']) { 1383 | Module['monitorRunDependencies'](runDependencies); 1384 | } 1385 | 1386 | if (id) { 1387 | assert(runDependencyTracking[id]); 1388 | delete runDependencyTracking[id]; 1389 | } else { 1390 | err('warning: run dependency removed without ID'); 1391 | } 1392 | if (runDependencies == 0) { 1393 | if (runDependencyWatcher !== null) { 1394 | clearInterval(runDependencyWatcher); 1395 | runDependencyWatcher = null; 1396 | } 1397 | if (dependenciesFulfilled) { 1398 | var callback = dependenciesFulfilled; 1399 | dependenciesFulfilled = null; 1400 | callback(); // can add another dependenciesFulfilled 1401 | } 1402 | } 1403 | } 1404 | 1405 | /** @param {string|number=} what */ 1406 | function abort(what) { 1407 | { 1408 | if (Module['onAbort']) { 1409 | Module['onAbort'](what); 1410 | } 1411 | } 1412 | 1413 | what = 'Aborted(' + what + ')'; 1414 | // TODO(sbc): Should we remove printing and leave it up to whoever 1415 | // catches the exception? 1416 | err(what); 1417 | 1418 | ABORT = true; 1419 | EXITSTATUS = 1; 1420 | 1421 | // Use a wasm runtime error, because a JS error might be seen as a foreign 1422 | // exception, which means we'd run destructors on it. We need the error to 1423 | // simply make the program stop. 1424 | // FIXME This approach does not work in Wasm EH because it currently does not assume 1425 | // all RuntimeErrors are from traps; it decides whether a RuntimeError is from 1426 | // a trap or not based on a hidden field within the object. So at the moment 1427 | // we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that 1428 | // allows this in the wasm spec. 1429 | 1430 | // Suppress closure compiler warning here. Closure compiler's builtin extern 1431 | // defintion for WebAssembly.RuntimeError claims it takes no arguments even 1432 | // though it can. 1433 | // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed. 1434 | /** @suppress {checkTypes} */ 1435 | var e = new WebAssembly.RuntimeError(what); 1436 | 1437 | // Throw the error whether or not MODULARIZE is set because abort is used 1438 | // in code paths apart from instantiation where an exception is expected 1439 | // to be thrown when abort is called. 1440 | throw e; 1441 | } 1442 | 1443 | // {{MEM_INITIALIZER}} 1444 | 1445 | // include: memoryprofiler.js 1446 | 1447 | 1448 | // end include: memoryprofiler.js 1449 | // show errors on likely calls to FS when it was not included 1450 | var FS = { 1451 | error: function() { 1452 | abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -sFORCE_FILESYSTEM'); 1453 | }, 1454 | init: function() { FS.error() }, 1455 | createDataFile: function() { FS.error() }, 1456 | createPreloadedFile: function() { FS.error() }, 1457 | createLazyFile: function() { FS.error() }, 1458 | open: function() { FS.error() }, 1459 | mkdev: function() { FS.error() }, 1460 | registerDevice: function() { FS.error() }, 1461 | analyzePath: function() { FS.error() }, 1462 | loadFilesFromDB: function() { FS.error() }, 1463 | 1464 | ErrnoError: function ErrnoError() { FS.error() }, 1465 | }; 1466 | Module['FS_createDataFile'] = FS.createDataFile; 1467 | Module['FS_createPreloadedFile'] = FS.createPreloadedFile; 1468 | 1469 | // include: URIUtils.js 1470 | 1471 | 1472 | // Prefix of data URIs emitted by SINGLE_FILE and related options. 1473 | var dataURIPrefix = 'data:application/octet-stream;base64,'; 1474 | 1475 | // Indicates whether filename is a base64 data URI. 1476 | function isDataURI(filename) { 1477 | // Prefix of data URIs emitted by SINGLE_FILE and related options. 1478 | return filename.startsWith(dataURIPrefix); 1479 | } 1480 | 1481 | // Indicates whether filename is delivered via file protocol (as opposed to http/https) 1482 | function isFileURI(filename) { 1483 | return filename.startsWith('file://'); 1484 | } 1485 | 1486 | // end include: URIUtils.js 1487 | /** @param {boolean=} fixedasm */ 1488 | function createExportWrapper(name, fixedasm) { 1489 | return function() { 1490 | var displayName = name; 1491 | var asm = fixedasm; 1492 | if (!fixedasm) { 1493 | asm = Module['asm']; 1494 | } 1495 | assert(runtimeInitialized, 'native function `' + displayName + '` called before runtime initialization'); 1496 | if (!asm[name]) { 1497 | assert(asm[name], 'exported native function `' + displayName + '` not found'); 1498 | } 1499 | return asm[name].apply(null, arguments); 1500 | }; 1501 | } 1502 | 1503 | var wasmBinaryFile; 1504 | wasmBinaryFile = 'base64c.wasm'; 1505 | if (!isDataURI(wasmBinaryFile)) { 1506 | wasmBinaryFile = locateFile(wasmBinaryFile); 1507 | } 1508 | 1509 | function getBinary(file) { 1510 | try { 1511 | if (file == wasmBinaryFile && wasmBinary) { 1512 | return new Uint8Array(wasmBinary); 1513 | } 1514 | if (readBinary) { 1515 | return readBinary(file); 1516 | } else { 1517 | throw "both async and sync fetching of the wasm failed"; 1518 | } 1519 | } 1520 | catch (err) { 1521 | abort(err); 1522 | } 1523 | } 1524 | 1525 | function getBinaryPromise() { 1526 | // If we don't have the binary yet, try to to load it asynchronously. 1527 | // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url. 1528 | // See https://github.com/github/fetch/pull/92#issuecomment-140665932 1529 | // Cordova or Electron apps are typically loaded from a file:// url. 1530 | // So use fetch if it is available and the url is not a file, otherwise fall back to XHR. 1531 | if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { 1532 | if (typeof fetch == 'function' 1533 | && !isFileURI(wasmBinaryFile) 1534 | ) { 1535 | return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { 1536 | if (!response['ok']) { 1537 | throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; 1538 | } 1539 | return response['arrayBuffer'](); 1540 | }).catch(function () { 1541 | return getBinary(wasmBinaryFile); 1542 | }); 1543 | } 1544 | else { 1545 | if (readAsync) { 1546 | // fetch is not available or url is file => try XHR (readAsync uses XHR internally) 1547 | return new Promise(function(resolve, reject) { 1548 | readAsync(wasmBinaryFile, function(response) { resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))) }, reject) 1549 | }); 1550 | } 1551 | } 1552 | } 1553 | 1554 | // Otherwise, getBinary should be able to get it synchronously 1555 | return Promise.resolve().then(function() { return getBinary(wasmBinaryFile); }); 1556 | } 1557 | 1558 | // Create the wasm instance. 1559 | // Receives the wasm imports, returns the exports. 1560 | function createWasm() { 1561 | // prepare imports 1562 | var info = { 1563 | 'env': asmLibraryArg, 1564 | 'wasi_snapshot_preview1': asmLibraryArg, 1565 | }; 1566 | // Load the wasm module and create an instance of using native support in the JS engine. 1567 | // handle a generated wasm instance, receiving its exports and 1568 | // performing other necessary setup 1569 | /** @param {WebAssembly.Module=} module*/ 1570 | function receiveInstance(instance, module) { 1571 | var exports = instance.exports; 1572 | 1573 | Module['asm'] = exports; 1574 | 1575 | wasmMemory = Module['asm']['memory']; 1576 | assert(wasmMemory, "memory not found in wasm exports"); 1577 | // This assertion doesn't hold when emscripten is run in --post-link 1578 | // mode. 1579 | // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode. 1580 | //assert(wasmMemory.buffer.byteLength === 16777216); 1581 | updateGlobalBufferAndViews(wasmMemory.buffer); 1582 | 1583 | wasmTable = Module['asm']['__indirect_function_table']; 1584 | assert(wasmTable, "table not found in wasm exports"); 1585 | 1586 | addOnInit(Module['asm']['__wasm_call_ctors']); 1587 | 1588 | removeRunDependency('wasm-instantiate'); 1589 | 1590 | } 1591 | // we can't run yet (except in a pthread, where we have a custom sync instantiator) 1592 | addRunDependency('wasm-instantiate'); 1593 | 1594 | // Prefer streaming instantiation if available. 1595 | // Async compilation can be confusing when an error on the page overwrites Module 1596 | // (for example, if the order of elements is wrong, and the one defining Module is 1597 | // later), so we save Module and check it later. 1598 | var trueModule = Module; 1599 | function receiveInstantiationResult(result) { 1600 | // 'result' is a ResultObject object which has both the module and instance. 1601 | // receiveInstance() will swap in the exports (to Module.asm) so they can be called 1602 | assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); 1603 | trueModule = null; 1604 | // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line. 1605 | // When the regression is fixed, can restore the above USE_PTHREADS-enabled path. 1606 | receiveInstance(result['instance']); 1607 | } 1608 | 1609 | function instantiateArrayBuffer(receiver) { 1610 | return getBinaryPromise().then(function(binary) { 1611 | return WebAssembly.instantiate(binary, info); 1612 | }).then(function (instance) { 1613 | return instance; 1614 | }).then(receiver, function(reason) { 1615 | err('failed to asynchronously prepare wasm: ' + reason); 1616 | 1617 | // Warn on some common problems. 1618 | if (isFileURI(wasmBinaryFile)) { 1619 | err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing'); 1620 | } 1621 | abort(reason); 1622 | }); 1623 | } 1624 | 1625 | function instantiateAsync() { 1626 | if (!wasmBinary && 1627 | typeof WebAssembly.instantiateStreaming == 'function' && 1628 | !isDataURI(wasmBinaryFile) && 1629 | // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously. 1630 | !isFileURI(wasmBinaryFile) && 1631 | // Avoid instantiateStreaming() on Node.js environment for now, as while 1632 | // Node.js v18.1.0 implements it, it does not have a full fetch() 1633 | // implementation yet. 1634 | // 1635 | // Reference: 1636 | // https://github.com/emscripten-core/emscripten/pull/16917 1637 | !ENVIRONMENT_IS_NODE && 1638 | typeof fetch == 'function') { 1639 | return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { 1640 | // Suppress closure warning here since the upstream definition for 1641 | // instantiateStreaming only allows Promise rather than 1642 | // an actual Response. 1643 | // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed. 1644 | /** @suppress {checkTypes} */ 1645 | var result = WebAssembly.instantiateStreaming(response, info); 1646 | 1647 | return result.then( 1648 | receiveInstantiationResult, 1649 | function(reason) { 1650 | // We expect the most common failure cause to be a bad MIME type for the binary, 1651 | // in which case falling back to ArrayBuffer instantiation should work. 1652 | err('wasm streaming compile failed: ' + reason); 1653 | err('falling back to ArrayBuffer instantiation'); 1654 | return instantiateArrayBuffer(receiveInstantiationResult); 1655 | }); 1656 | }); 1657 | } else { 1658 | return instantiateArrayBuffer(receiveInstantiationResult); 1659 | } 1660 | } 1661 | 1662 | // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback 1663 | // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel 1664 | // to any other async startup actions they are performing. 1665 | // Also pthreads and wasm workers initialize the wasm instance through this path. 1666 | if (Module['instantiateWasm']) { 1667 | try { 1668 | var exports = Module['instantiateWasm'](info, receiveInstance); 1669 | return exports; 1670 | } catch(e) { 1671 | err('Module.instantiateWasm callback failed with error: ' + e); 1672 | return false; 1673 | } 1674 | } 1675 | 1676 | instantiateAsync(); 1677 | return {}; // no exports yet; we'll fill them in later 1678 | } 1679 | 1680 | // Globals used by JS i64 conversions (see makeSetValue) 1681 | var tempDouble; 1682 | var tempI64; 1683 | 1684 | // === Body === 1685 | 1686 | var ASM_CONSTS = { 1687 | 1688 | }; 1689 | 1690 | 1691 | 1692 | 1693 | 1694 | 1695 | function callRuntimeCallbacks(callbacks) { 1696 | while (callbacks.length > 0) { 1697 | var callback = callbacks.shift(); 1698 | if (typeof callback == 'function') { 1699 | callback(Module); // Pass the module as the first argument. 1700 | continue; 1701 | } 1702 | var func = callback.func; 1703 | if (typeof func == 'number') { 1704 | if (callback.arg === undefined) { 1705 | // Run the wasm function ptr with signature 'v'. If no function 1706 | // with such signature was exported, this call does not need 1707 | // to be emitted (and would confuse Closure) 1708 | getWasmTableEntry(func)(); 1709 | } else { 1710 | // If any function with signature 'vi' was exported, run 1711 | // the callback with that signature. 1712 | getWasmTableEntry(func)(callback.arg); 1713 | } 1714 | } else { 1715 | func(callback.arg === undefined ? null : callback.arg); 1716 | } 1717 | } 1718 | } 1719 | 1720 | function withStackSave(f) { 1721 | var stack = stackSave(); 1722 | var ret = f(); 1723 | stackRestore(stack); 1724 | return ret; 1725 | } 1726 | function demangle(func) { 1727 | warnOnce('warning: build with -sDEMANGLE_SUPPORT to link in libcxxabi demangling'); 1728 | return func; 1729 | } 1730 | 1731 | function demangleAll(text) { 1732 | var regex = 1733 | /\b_Z[\w\d_]+/g; 1734 | return text.replace(regex, 1735 | function(x) { 1736 | var y = demangle(x); 1737 | return x === y ? x : (y + ' [' + x + ']'); 1738 | }); 1739 | } 1740 | 1741 | 1742 | /** 1743 | * @param {number} ptr 1744 | * @param {string} type 1745 | */ 1746 | function getValue(ptr, type = 'i8') { 1747 | if (type.endsWith('*')) type = 'i32'; 1748 | switch (type) { 1749 | case 'i1': return HEAP8[((ptr)>>0)]; 1750 | case 'i8': return HEAP8[((ptr)>>0)]; 1751 | case 'i16': return HEAP16[((ptr)>>1)]; 1752 | case 'i32': return HEAP32[((ptr)>>2)]; 1753 | case 'i64': return HEAP32[((ptr)>>2)]; 1754 | case 'float': return HEAPF32[((ptr)>>2)]; 1755 | case 'double': return Number(HEAPF64[((ptr)>>3)]); 1756 | default: abort('invalid type for getValue: ' + type); 1757 | } 1758 | return null; 1759 | } 1760 | 1761 | var wasmTableMirror = []; 1762 | function getWasmTableEntry(funcPtr) { 1763 | var func = wasmTableMirror[funcPtr]; 1764 | if (!func) { 1765 | if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; 1766 | wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr); 1767 | } 1768 | assert(wasmTable.get(funcPtr) == func, "JavaScript-side Wasm function table mirror is out of date!"); 1769 | return func; 1770 | } 1771 | 1772 | function handleException(e) { 1773 | // Certain exception types we do not treat as errors since they are used for 1774 | // internal control flow. 1775 | // 1. ExitStatus, which is thrown by exit() 1776 | // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others 1777 | // that wish to return to JS event loop. 1778 | if (e instanceof ExitStatus || e == 'unwind') { 1779 | return EXITSTATUS; 1780 | } 1781 | quit_(1, e); 1782 | } 1783 | 1784 | function jsStackTrace() { 1785 | var error = new Error(); 1786 | if (!error.stack) { 1787 | // IE10+ special cases: It does have callstack info, but it is only 1788 | // populated if an Error object is thrown, so try that as a special-case. 1789 | try { 1790 | throw new Error(); 1791 | } catch(e) { 1792 | error = e; 1793 | } 1794 | if (!error.stack) { 1795 | return '(no stack trace available)'; 1796 | } 1797 | } 1798 | return error.stack.toString(); 1799 | } 1800 | 1801 | 1802 | /** 1803 | * @param {number} ptr 1804 | * @param {number} value 1805 | * @param {string} type 1806 | */ 1807 | function setValue(ptr, value, type = 'i8') { 1808 | if (type.endsWith('*')) type = 'i32'; 1809 | switch (type) { 1810 | case 'i1': HEAP8[((ptr)>>0)] = value; break; 1811 | case 'i8': HEAP8[((ptr)>>0)] = value; break; 1812 | case 'i16': HEAP16[((ptr)>>1)] = value; break; 1813 | case 'i32': HEAP32[((ptr)>>2)] = value; break; 1814 | case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math.min((+(Math.floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)] = tempI64[0],HEAP32[(((ptr)+(4))>>2)] = tempI64[1]); break; 1815 | case 'float': HEAPF32[((ptr)>>2)] = value; break; 1816 | case 'double': HEAPF64[((ptr)>>3)] = value; break; 1817 | default: abort('invalid type for setValue: ' + type); 1818 | } 1819 | } 1820 | 1821 | function setWasmTableEntry(idx, func) { 1822 | wasmTable.set(idx, func); 1823 | // With ABORT_ON_WASM_EXCEPTIONS wasmTable.get is overriden to return wrapped 1824 | // functions so we need to call it here to retrieve the potential wrapper correctly 1825 | // instead of just storing 'func' directly into wasmTableMirror 1826 | wasmTableMirror[idx] = wasmTable.get(idx); 1827 | } 1828 | 1829 | function stackTrace() { 1830 | var js = jsStackTrace(); 1831 | if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); 1832 | return demangleAll(js); 1833 | } 1834 | var ASSERTIONS = true; 1835 | 1836 | 1837 | 1838 | /** @type {function(string, boolean=, number=)} */ 1839 | function intArrayFromString(stringy, dontAddNull, length) { 1840 | var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; 1841 | var u8array = new Array(len); 1842 | var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); 1843 | if (dontAddNull) u8array.length = numBytesWritten; 1844 | return u8array; 1845 | } 1846 | 1847 | function intArrayToString(array) { 1848 | var ret = []; 1849 | for (var i = 0; i < array.length; i++) { 1850 | var chr = array[i]; 1851 | if (chr > 0xFF) { 1852 | if (ASSERTIONS) { 1853 | assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.'); 1854 | } 1855 | chr &= 0xFF; 1856 | } 1857 | ret.push(String.fromCharCode(chr)); 1858 | } 1859 | return ret.join(''); 1860 | } 1861 | 1862 | 1863 | function checkIncomingModuleAPI() { 1864 | ignoredModuleProp('fetchSettings'); 1865 | } 1866 | var asmLibraryArg = { 1867 | 1868 | }; 1869 | var asm = createWasm(); 1870 | /** @type {function(...*):?} */ 1871 | var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__wasm_call_ctors"); 1872 | 1873 | /** @type {function(...*):?} */ 1874 | var _b64encode = Module["_b64encode"] = createExportWrapper("b64encode"); 1875 | 1876 | /** @type {function(...*):?} */ 1877 | var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location"); 1878 | 1879 | /** @type {function(...*):?} */ 1880 | var _fflush = Module["_fflush"] = createExportWrapper("fflush"); 1881 | 1882 | /** @type {function(...*):?} */ 1883 | var _emscripten_stack_init = Module["_emscripten_stack_init"] = function() { 1884 | return (_emscripten_stack_init = Module["_emscripten_stack_init"] = Module["asm"]["emscripten_stack_init"]).apply(null, arguments); 1885 | }; 1886 | 1887 | /** @type {function(...*):?} */ 1888 | var _emscripten_stack_get_free = Module["_emscripten_stack_get_free"] = function() { 1889 | return (_emscripten_stack_get_free = Module["_emscripten_stack_get_free"] = Module["asm"]["emscripten_stack_get_free"]).apply(null, arguments); 1890 | }; 1891 | 1892 | /** @type {function(...*):?} */ 1893 | var _emscripten_stack_get_base = Module["_emscripten_stack_get_base"] = function() { 1894 | return (_emscripten_stack_get_base = Module["_emscripten_stack_get_base"] = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments); 1895 | }; 1896 | 1897 | /** @type {function(...*):?} */ 1898 | var _emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = function() { 1899 | return (_emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments); 1900 | }; 1901 | 1902 | /** @type {function(...*):?} */ 1903 | var stackSave = Module["stackSave"] = createExportWrapper("stackSave"); 1904 | 1905 | /** @type {function(...*):?} */ 1906 | var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore"); 1907 | 1908 | /** @type {function(...*):?} */ 1909 | var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc"); 1910 | 1911 | 1912 | 1913 | 1914 | 1915 | // === Auto-generated postamble setup entry stuff === 1916 | 1917 | unexportedRuntimeFunction('ccall', false); 1918 | unexportedRuntimeFunction('cwrap', false); 1919 | unexportedRuntimeFunction('allocate', false); 1920 | unexportedRuntimeFunction('UTF8ArrayToString', false); 1921 | unexportedRuntimeFunction('UTF8ToString', false); 1922 | unexportedRuntimeFunction('stringToUTF8Array', false); 1923 | unexportedRuntimeFunction('stringToUTF8', false); 1924 | unexportedRuntimeFunction('lengthBytesUTF8', false); 1925 | unexportedRuntimeFunction('addOnPreRun', false); 1926 | unexportedRuntimeFunction('addOnInit', false); 1927 | unexportedRuntimeFunction('addOnPreMain', false); 1928 | unexportedRuntimeFunction('addOnExit', false); 1929 | unexportedRuntimeFunction('addOnPostRun', false); 1930 | unexportedRuntimeFunction('addRunDependency', true); 1931 | unexportedRuntimeFunction('removeRunDependency', true); 1932 | unexportedRuntimeFunction('FS_createFolder', false); 1933 | unexportedRuntimeFunction('FS_createPath', true); 1934 | unexportedRuntimeFunction('FS_createDataFile', true); 1935 | unexportedRuntimeFunction('FS_createPreloadedFile', true); 1936 | unexportedRuntimeFunction('FS_createLazyFile', true); 1937 | unexportedRuntimeFunction('FS_createLink', false); 1938 | unexportedRuntimeFunction('FS_createDevice', true); 1939 | unexportedRuntimeFunction('FS_unlink', true); 1940 | unexportedRuntimeFunction('getLEB', false); 1941 | unexportedRuntimeFunction('getFunctionTables', false); 1942 | unexportedRuntimeFunction('alignFunctionTables', false); 1943 | unexportedRuntimeFunction('registerFunctions', false); 1944 | unexportedRuntimeFunction('addFunction', false); 1945 | unexportedRuntimeFunction('removeFunction', false); 1946 | unexportedRuntimeFunction('prettyPrint', false); 1947 | unexportedRuntimeFunction('getCompilerSetting', false); 1948 | unexportedRuntimeFunction('print', false); 1949 | unexportedRuntimeFunction('printErr', false); 1950 | unexportedRuntimeFunction('getTempRet0', false); 1951 | unexportedRuntimeFunction('setTempRet0', false); 1952 | unexportedRuntimeFunction('callMain', false); 1953 | unexportedRuntimeFunction('abort', false); 1954 | unexportedRuntimeFunction('keepRuntimeAlive', false); 1955 | unexportedRuntimeFunction('wasmMemory', false); 1956 | unexportedRuntimeFunction('warnOnce', false); 1957 | unexportedRuntimeFunction('stackSave', false); 1958 | unexportedRuntimeFunction('stackRestore', false); 1959 | unexportedRuntimeFunction('stackAlloc', false); 1960 | unexportedRuntimeFunction('AsciiToString', false); 1961 | unexportedRuntimeFunction('stringToAscii', false); 1962 | unexportedRuntimeFunction('UTF16ToString', false); 1963 | unexportedRuntimeFunction('stringToUTF16', false); 1964 | unexportedRuntimeFunction('lengthBytesUTF16', false); 1965 | unexportedRuntimeFunction('UTF32ToString', false); 1966 | unexportedRuntimeFunction('stringToUTF32', false); 1967 | unexportedRuntimeFunction('lengthBytesUTF32', false); 1968 | unexportedRuntimeFunction('allocateUTF8', false); 1969 | unexportedRuntimeFunction('allocateUTF8OnStack', false); 1970 | unexportedRuntimeFunction('ExitStatus', false); 1971 | unexportedRuntimeFunction('intArrayFromString', false); 1972 | unexportedRuntimeFunction('intArrayToString', false); 1973 | unexportedRuntimeFunction('writeStringToMemory', false); 1974 | unexportedRuntimeFunction('writeArrayToMemory', false); 1975 | unexportedRuntimeFunction('writeAsciiToMemory', false); 1976 | Module["writeStackCookie"] = writeStackCookie; 1977 | Module["checkStackCookie"] = checkStackCookie; 1978 | unexportedRuntimeFunction('ptrToString', false); 1979 | unexportedRuntimeFunction('zeroMemory', false); 1980 | unexportedRuntimeFunction('stringToNewUTF8', false); 1981 | unexportedRuntimeFunction('getHeapMax', false); 1982 | unexportedRuntimeFunction('abortOnCannotGrowMemory', false); 1983 | unexportedRuntimeFunction('emscripten_realloc_buffer', false); 1984 | unexportedRuntimeFunction('ENV', false); 1985 | unexportedRuntimeFunction('ERRNO_CODES', false); 1986 | unexportedRuntimeFunction('ERRNO_MESSAGES', false); 1987 | unexportedRuntimeFunction('setErrNo', false); 1988 | unexportedRuntimeFunction('inetPton4', false); 1989 | unexportedRuntimeFunction('inetNtop4', false); 1990 | unexportedRuntimeFunction('inetPton6', false); 1991 | unexportedRuntimeFunction('inetNtop6', false); 1992 | unexportedRuntimeFunction('readSockaddr', false); 1993 | unexportedRuntimeFunction('writeSockaddr', false); 1994 | unexportedRuntimeFunction('DNS', false); 1995 | unexportedRuntimeFunction('getHostByName', false); 1996 | unexportedRuntimeFunction('Protocols', false); 1997 | unexportedRuntimeFunction('Sockets', false); 1998 | unexportedRuntimeFunction('getRandomDevice', false); 1999 | unexportedRuntimeFunction('traverseStack', false); 2000 | unexportedRuntimeFunction('UNWIND_CACHE', false); 2001 | unexportedRuntimeFunction('convertPCtoSourceLocation', false); 2002 | unexportedRuntimeFunction('readAsmConstArgsArray', false); 2003 | unexportedRuntimeFunction('readAsmConstArgs', false); 2004 | unexportedRuntimeFunction('mainThreadEM_ASM', false); 2005 | unexportedRuntimeFunction('jstoi_q', false); 2006 | unexportedRuntimeFunction('jstoi_s', false); 2007 | unexportedRuntimeFunction('getExecutableName', false); 2008 | unexportedRuntimeFunction('listenOnce', false); 2009 | unexportedRuntimeFunction('autoResumeAudioContext', false); 2010 | unexportedRuntimeFunction('dynCallLegacy', false); 2011 | unexportedRuntimeFunction('getDynCaller', false); 2012 | unexportedRuntimeFunction('dynCall', false); 2013 | unexportedRuntimeFunction('handleException', false); 2014 | unexportedRuntimeFunction('runtimeKeepalivePush', false); 2015 | unexportedRuntimeFunction('runtimeKeepalivePop', false); 2016 | unexportedRuntimeFunction('callUserCallback', false); 2017 | unexportedRuntimeFunction('maybeExit', false); 2018 | unexportedRuntimeFunction('safeSetTimeout', false); 2019 | unexportedRuntimeFunction('asmjsMangle', false); 2020 | unexportedRuntimeFunction('asyncLoad', false); 2021 | unexportedRuntimeFunction('alignMemory', false); 2022 | unexportedRuntimeFunction('mmapAlloc', false); 2023 | unexportedRuntimeFunction('writeI53ToI64', false); 2024 | unexportedRuntimeFunction('writeI53ToI64Clamped', false); 2025 | unexportedRuntimeFunction('writeI53ToI64Signaling', false); 2026 | unexportedRuntimeFunction('writeI53ToU64Clamped', false); 2027 | unexportedRuntimeFunction('writeI53ToU64Signaling', false); 2028 | unexportedRuntimeFunction('readI53FromI64', false); 2029 | unexportedRuntimeFunction('readI53FromU64', false); 2030 | unexportedRuntimeFunction('convertI32PairToI53', false); 2031 | unexportedRuntimeFunction('convertI32PairToI53Checked', false); 2032 | unexportedRuntimeFunction('convertU32PairToI53', false); 2033 | unexportedRuntimeFunction('reallyNegative', false); 2034 | unexportedRuntimeFunction('unSign', false); 2035 | unexportedRuntimeFunction('strLen', false); 2036 | unexportedRuntimeFunction('reSign', false); 2037 | unexportedRuntimeFunction('formatString', false); 2038 | unexportedRuntimeFunction('setValue', false); 2039 | unexportedRuntimeFunction('getValue', false); 2040 | unexportedRuntimeFunction('PATH', false); 2041 | unexportedRuntimeFunction('PATH_FS', false); 2042 | unexportedRuntimeFunction('SYSCALLS', false); 2043 | unexportedRuntimeFunction('getSocketFromFD', false); 2044 | unexportedRuntimeFunction('getSocketAddress', false); 2045 | unexportedRuntimeFunction('JSEvents', false); 2046 | unexportedRuntimeFunction('registerKeyEventCallback', false); 2047 | unexportedRuntimeFunction('specialHTMLTargets', false); 2048 | unexportedRuntimeFunction('maybeCStringToJsString', false); 2049 | unexportedRuntimeFunction('findEventTarget', false); 2050 | unexportedRuntimeFunction('findCanvasEventTarget', false); 2051 | unexportedRuntimeFunction('getBoundingClientRect', false); 2052 | unexportedRuntimeFunction('fillMouseEventData', false); 2053 | unexportedRuntimeFunction('registerMouseEventCallback', false); 2054 | unexportedRuntimeFunction('registerWheelEventCallback', false); 2055 | unexportedRuntimeFunction('registerUiEventCallback', false); 2056 | unexportedRuntimeFunction('registerFocusEventCallback', false); 2057 | unexportedRuntimeFunction('fillDeviceOrientationEventData', false); 2058 | unexportedRuntimeFunction('registerDeviceOrientationEventCallback', false); 2059 | unexportedRuntimeFunction('fillDeviceMotionEventData', false); 2060 | unexportedRuntimeFunction('registerDeviceMotionEventCallback', false); 2061 | unexportedRuntimeFunction('screenOrientation', false); 2062 | unexportedRuntimeFunction('fillOrientationChangeEventData', false); 2063 | unexportedRuntimeFunction('registerOrientationChangeEventCallback', false); 2064 | unexportedRuntimeFunction('fillFullscreenChangeEventData', false); 2065 | unexportedRuntimeFunction('registerFullscreenChangeEventCallback', false); 2066 | unexportedRuntimeFunction('JSEvents_requestFullscreen', false); 2067 | unexportedRuntimeFunction('JSEvents_resizeCanvasForFullscreen', false); 2068 | unexportedRuntimeFunction('registerRestoreOldStyle', false); 2069 | unexportedRuntimeFunction('hideEverythingExceptGivenElement', false); 2070 | unexportedRuntimeFunction('restoreHiddenElements', false); 2071 | unexportedRuntimeFunction('setLetterbox', false); 2072 | unexportedRuntimeFunction('currentFullscreenStrategy', false); 2073 | unexportedRuntimeFunction('restoreOldWindowedStyle', false); 2074 | unexportedRuntimeFunction('softFullscreenResizeWebGLRenderTarget', false); 2075 | unexportedRuntimeFunction('doRequestFullscreen', false); 2076 | unexportedRuntimeFunction('fillPointerlockChangeEventData', false); 2077 | unexportedRuntimeFunction('registerPointerlockChangeEventCallback', false); 2078 | unexportedRuntimeFunction('registerPointerlockErrorEventCallback', false); 2079 | unexportedRuntimeFunction('requestPointerLock', false); 2080 | unexportedRuntimeFunction('fillVisibilityChangeEventData', false); 2081 | unexportedRuntimeFunction('registerVisibilityChangeEventCallback', false); 2082 | unexportedRuntimeFunction('registerTouchEventCallback', false); 2083 | unexportedRuntimeFunction('fillGamepadEventData', false); 2084 | unexportedRuntimeFunction('registerGamepadEventCallback', false); 2085 | unexportedRuntimeFunction('registerBeforeUnloadEventCallback', false); 2086 | unexportedRuntimeFunction('fillBatteryEventData', false); 2087 | unexportedRuntimeFunction('battery', false); 2088 | unexportedRuntimeFunction('registerBatteryEventCallback', false); 2089 | unexportedRuntimeFunction('setCanvasElementSize', false); 2090 | unexportedRuntimeFunction('getCanvasElementSize', false); 2091 | unexportedRuntimeFunction('demangle', false); 2092 | unexportedRuntimeFunction('demangleAll', false); 2093 | unexportedRuntimeFunction('jsStackTrace', false); 2094 | unexportedRuntimeFunction('stackTrace', false); 2095 | unexportedRuntimeFunction('getEnvStrings', false); 2096 | unexportedRuntimeFunction('checkWasiClock', false); 2097 | unexportedRuntimeFunction('flush_NO_FILESYSTEM', false); 2098 | unexportedRuntimeFunction('dlopenMissingError', false); 2099 | unexportedRuntimeFunction('setImmediateWrapped', false); 2100 | unexportedRuntimeFunction('clearImmediateWrapped', false); 2101 | unexportedRuntimeFunction('polyfillSetImmediate', false); 2102 | unexportedRuntimeFunction('uncaughtExceptionCount', false); 2103 | unexportedRuntimeFunction('exceptionLast', false); 2104 | unexportedRuntimeFunction('exceptionCaught', false); 2105 | unexportedRuntimeFunction('ExceptionInfo', false); 2106 | unexportedRuntimeFunction('exception_addRef', false); 2107 | unexportedRuntimeFunction('exception_decRef', false); 2108 | unexportedRuntimeFunction('Browser', false); 2109 | unexportedRuntimeFunction('setMainLoop', false); 2110 | unexportedRuntimeFunction('wget', false); 2111 | unexportedRuntimeFunction('FS', false); 2112 | unexportedRuntimeFunction('MEMFS', false); 2113 | unexportedRuntimeFunction('TTY', false); 2114 | unexportedRuntimeFunction('PIPEFS', false); 2115 | unexportedRuntimeFunction('SOCKFS', false); 2116 | unexportedRuntimeFunction('_setNetworkCallback', false); 2117 | unexportedRuntimeFunction('tempFixedLengthArray', false); 2118 | unexportedRuntimeFunction('miniTempWebGLFloatBuffers', false); 2119 | unexportedRuntimeFunction('heapObjectForWebGLType', false); 2120 | unexportedRuntimeFunction('heapAccessShiftForWebGLHeap', false); 2121 | unexportedRuntimeFunction('GL', false); 2122 | unexportedRuntimeFunction('emscriptenWebGLGet', false); 2123 | unexportedRuntimeFunction('computeUnpackAlignedImageSize', false); 2124 | unexportedRuntimeFunction('emscriptenWebGLGetTexPixelData', false); 2125 | unexportedRuntimeFunction('emscriptenWebGLGetUniform', false); 2126 | unexportedRuntimeFunction('webglGetUniformLocation', false); 2127 | unexportedRuntimeFunction('webglPrepareUniformLocationsBeforeFirstUse', false); 2128 | unexportedRuntimeFunction('webglGetLeftBracePos', false); 2129 | unexportedRuntimeFunction('emscriptenWebGLGetVertexAttrib', false); 2130 | unexportedRuntimeFunction('writeGLArray', false); 2131 | unexportedRuntimeFunction('AL', false); 2132 | unexportedRuntimeFunction('SDL_unicode', false); 2133 | unexportedRuntimeFunction('SDL_ttfContext', false); 2134 | unexportedRuntimeFunction('SDL_audio', false); 2135 | unexportedRuntimeFunction('SDL', false); 2136 | unexportedRuntimeFunction('SDL_gfx', false); 2137 | unexportedRuntimeFunction('GLUT', false); 2138 | unexportedRuntimeFunction('EGL', false); 2139 | unexportedRuntimeFunction('GLFW_Window', false); 2140 | unexportedRuntimeFunction('GLFW', false); 2141 | unexportedRuntimeFunction('GLEW', false); 2142 | unexportedRuntimeFunction('IDBStore', false); 2143 | unexportedRuntimeFunction('runAndAbortIfError', false); 2144 | unexportedRuntimeSymbol('ALLOC_NORMAL', false); 2145 | unexportedRuntimeSymbol('ALLOC_STACK', false); 2146 | 2147 | var calledRun; 2148 | 2149 | /** 2150 | * @constructor 2151 | * @this {ExitStatus} 2152 | */ 2153 | function ExitStatus(status) { 2154 | this.name = "ExitStatus"; 2155 | this.message = "Program terminated with exit(" + status + ")"; 2156 | this.status = status; 2157 | } 2158 | 2159 | var calledMain = false; 2160 | 2161 | dependenciesFulfilled = function runCaller() { 2162 | // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) 2163 | if (!calledRun) run(); 2164 | if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled 2165 | }; 2166 | 2167 | function stackCheckInit() { 2168 | // This is normally called automatically during __wasm_call_ctors but need to 2169 | // get these values before even running any of the ctors so we call it redundantly 2170 | // here. 2171 | _emscripten_stack_init(); 2172 | // TODO(sbc): Move writeStackCookie to native to to avoid this. 2173 | writeStackCookie(); 2174 | } 2175 | 2176 | /** @type {function(Array=)} */ 2177 | function run(args) { 2178 | args = args || arguments_; 2179 | 2180 | if (runDependencies > 0) { 2181 | return; 2182 | } 2183 | 2184 | stackCheckInit(); 2185 | 2186 | preRun(); 2187 | 2188 | // a preRun added a dependency, run will be called later 2189 | if (runDependencies > 0) { 2190 | return; 2191 | } 2192 | 2193 | function doRun() { 2194 | // run may have just been called through dependencies being fulfilled just in this very frame, 2195 | // or while the async setStatus time below was happening 2196 | if (calledRun) return; 2197 | calledRun = true; 2198 | Module['calledRun'] = true; 2199 | 2200 | if (ABORT) return; 2201 | 2202 | initRuntime(); 2203 | 2204 | if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); 2205 | 2206 | assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); 2207 | 2208 | postRun(); 2209 | } 2210 | 2211 | if (Module['setStatus']) { 2212 | Module['setStatus']('Running...'); 2213 | setTimeout(function() { 2214 | setTimeout(function() { 2215 | Module['setStatus'](''); 2216 | }, 1); 2217 | doRun(); 2218 | }, 1); 2219 | } else 2220 | { 2221 | doRun(); 2222 | } 2223 | checkStackCookie(); 2224 | } 2225 | Module['run'] = run; 2226 | 2227 | function checkUnflushedContent() { 2228 | // Compiler settings do not allow exiting the runtime, so flushing 2229 | // the streams is not possible. but in ASSERTIONS mode we check 2230 | // if there was something to flush, and if so tell the user they 2231 | // should request that the runtime be exitable. 2232 | // Normally we would not even include flush() at all, but in ASSERTIONS 2233 | // builds we do so just for this check, and here we see if there is any 2234 | // content to flush, that is, we check if there would have been 2235 | // something a non-ASSERTIONS build would have not seen. 2236 | // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 2237 | // mode (which has its own special function for this; otherwise, all 2238 | // the code is inside libc) 2239 | var oldOut = out; 2240 | var oldErr = err; 2241 | var has = false; 2242 | out = err = (x) => { 2243 | has = true; 2244 | } 2245 | try { // it doesn't matter if it fails 2246 | _fflush(0); 2247 | } catch(e) {} 2248 | out = oldOut; 2249 | err = oldErr; 2250 | if (has) { 2251 | warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline when you printf etc.'); 2252 | warnOnce('(this may also be due to not including full filesystem support - try building with -sFORCE_FILESYSTEM)'); 2253 | } 2254 | } 2255 | 2256 | /** @param {boolean|number=} implicit */ 2257 | function exit(status, implicit) { 2258 | EXITSTATUS = status; 2259 | 2260 | checkUnflushedContent(); 2261 | 2262 | // if exit() was called explicitly, warn the user if the runtime isn't actually being shut down 2263 | if (keepRuntimeAlive() && !implicit) { 2264 | var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)'; 2265 | err(msg); 2266 | } 2267 | 2268 | procExit(status); 2269 | } 2270 | 2271 | function procExit(code) { 2272 | EXITSTATUS = code; 2273 | if (!keepRuntimeAlive()) { 2274 | if (Module['onExit']) Module['onExit'](code); 2275 | ABORT = true; 2276 | } 2277 | quit_(code, new ExitStatus(code)); 2278 | } 2279 | 2280 | if (Module['preInit']) { 2281 | if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; 2282 | while (Module['preInit'].length > 0) { 2283 | Module['preInit'].pop()(); 2284 | } 2285 | } 2286 | 2287 | run(); 2288 | 2289 | 2290 | 2291 | 2292 | 2293 | -------------------------------------------------------------------------------- /base64/base64c.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/base64/base64c.wasm -------------------------------------------------------------------------------- /base64/base64c.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (result i32))) 3 | (type (;1;) (func (param i32))) 4 | (type (;2;) (func)) 5 | (type (;3;) (func (param i32) (result i32))) 6 | (type (;4;) (func (param i32 i32 i32) (result i32))) 7 | (type (;5;) (func (param i32 i64 i32) (result i64))) 8 | (func (;0;) (type 2) 9 | call 5) 10 | (func (;1;) (type 4) (param i32 i32 i32) (result i32) 11 | (local i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) 12 | global.get 0 13 | local.set 3 14 | i32.const 48 15 | local.set 4 16 | local.get 3 17 | local.get 4 18 | i32.sub 19 | local.set 5 20 | local.get 5 21 | local.get 0 22 | i32.store offset=44 23 | local.get 5 24 | local.get 1 25 | i32.store offset=40 26 | local.get 5 27 | local.get 2 28 | i32.store offset=36 29 | local.get 5 30 | i32.load offset=40 31 | local.set 6 32 | i32.const 2 33 | local.set 7 34 | local.get 6 35 | local.get 7 36 | i32.add 37 | local.set 8 38 | i32.const 3 39 | local.set 9 40 | local.get 8 41 | local.get 9 42 | i32.div_s 43 | local.set 10 44 | i32.const 2 45 | local.set 11 46 | local.get 10 47 | local.get 11 48 | i32.shl 49 | local.set 12 50 | local.get 5 51 | local.get 12 52 | i32.store offset=32 53 | i32.const 0 54 | local.set 13 55 | local.get 5 56 | local.get 13 57 | i32.store offset=28 58 | i32.const 0 59 | local.set 14 60 | local.get 5 61 | local.get 14 62 | i32.store offset=24 63 | block ;; label = @1 64 | loop ;; label = @2 65 | local.get 5 66 | i32.load offset=28 67 | local.set 15 68 | local.get 5 69 | i32.load offset=40 70 | local.set 16 71 | local.get 15 72 | local.set 17 73 | local.get 16 74 | local.set 18 75 | local.get 17 76 | local.get 18 77 | i32.lt_s 78 | local.set 19 79 | i32.const 1 80 | local.set 20 81 | local.get 19 82 | local.get 20 83 | i32.and 84 | local.set 21 85 | local.get 21 86 | i32.eqz 87 | br_if 1 (;@1;) 88 | local.get 5 89 | i32.load offset=28 90 | local.set 22 91 | local.get 5 92 | i32.load offset=40 93 | local.set 23 94 | local.get 22 95 | local.set 24 96 | local.get 23 97 | local.set 25 98 | local.get 24 99 | local.get 25 100 | i32.lt_s 101 | local.set 26 102 | i32.const 1 103 | local.set 27 104 | local.get 26 105 | local.get 27 106 | i32.and 107 | local.set 28 108 | block ;; label = @3 109 | block ;; label = @4 110 | local.get 28 111 | i32.eqz 112 | br_if 0 (;@4;) 113 | local.get 5 114 | i32.load offset=44 115 | local.set 29 116 | local.get 5 117 | i32.load offset=28 118 | local.set 30 119 | i32.const 1 120 | local.set 31 121 | local.get 30 122 | local.get 31 123 | i32.add 124 | local.set 32 125 | local.get 5 126 | local.get 32 127 | i32.store offset=28 128 | local.get 29 129 | local.get 30 130 | i32.add 131 | local.set 33 132 | local.get 33 133 | i32.load8_u 134 | local.set 34 135 | i32.const 255 136 | local.set 35 137 | local.get 34 138 | local.get 35 139 | i32.and 140 | local.set 36 141 | local.get 36 142 | local.set 37 143 | br 1 (;@3;) 144 | end 145 | i32.const 0 146 | local.set 38 147 | local.get 38 148 | local.set 37 149 | end 150 | local.get 37 151 | local.set 39 152 | local.get 5 153 | local.get 39 154 | i32.store offset=20 155 | local.get 5 156 | i32.load offset=28 157 | local.set 40 158 | local.get 5 159 | i32.load offset=40 160 | local.set 41 161 | local.get 40 162 | local.set 42 163 | local.get 41 164 | local.set 43 165 | local.get 42 166 | local.get 43 167 | i32.lt_s 168 | local.set 44 169 | i32.const 1 170 | local.set 45 171 | local.get 44 172 | local.get 45 173 | i32.and 174 | local.set 46 175 | block ;; label = @3 176 | block ;; label = @4 177 | local.get 46 178 | i32.eqz 179 | br_if 0 (;@4;) 180 | local.get 5 181 | i32.load offset=44 182 | local.set 47 183 | local.get 5 184 | i32.load offset=28 185 | local.set 48 186 | i32.const 1 187 | local.set 49 188 | local.get 48 189 | local.get 49 190 | i32.add 191 | local.set 50 192 | local.get 5 193 | local.get 50 194 | i32.store offset=28 195 | local.get 47 196 | local.get 48 197 | i32.add 198 | local.set 51 199 | local.get 51 200 | i32.load8_u 201 | local.set 52 202 | i32.const 255 203 | local.set 53 204 | local.get 52 205 | local.get 53 206 | i32.and 207 | local.set 54 208 | local.get 54 209 | local.set 55 210 | br 1 (;@3;) 211 | end 212 | i32.const 0 213 | local.set 56 214 | local.get 56 215 | local.set 55 216 | end 217 | local.get 55 218 | local.set 57 219 | local.get 5 220 | local.get 57 221 | i32.store offset=16 222 | local.get 5 223 | i32.load offset=28 224 | local.set 58 225 | local.get 5 226 | i32.load offset=40 227 | local.set 59 228 | local.get 58 229 | local.set 60 230 | local.get 59 231 | local.set 61 232 | local.get 60 233 | local.get 61 234 | i32.lt_s 235 | local.set 62 236 | i32.const 1 237 | local.set 63 238 | local.get 62 239 | local.get 63 240 | i32.and 241 | local.set 64 242 | block ;; label = @3 243 | block ;; label = @4 244 | local.get 64 245 | i32.eqz 246 | br_if 0 (;@4;) 247 | local.get 5 248 | i32.load offset=44 249 | local.set 65 250 | local.get 5 251 | i32.load offset=28 252 | local.set 66 253 | i32.const 1 254 | local.set 67 255 | local.get 66 256 | local.get 67 257 | i32.add 258 | local.set 68 259 | local.get 5 260 | local.get 68 261 | i32.store offset=28 262 | local.get 65 263 | local.get 66 264 | i32.add 265 | local.set 69 266 | local.get 69 267 | i32.load8_u 268 | local.set 70 269 | i32.const 255 270 | local.set 71 271 | local.get 70 272 | local.get 71 273 | i32.and 274 | local.set 72 275 | local.get 72 276 | local.set 73 277 | br 1 (;@3;) 278 | end 279 | i32.const 0 280 | local.set 74 281 | local.get 74 282 | local.set 73 283 | end 284 | local.get 73 285 | local.set 75 286 | local.get 5 287 | local.get 75 288 | i32.store offset=12 289 | local.get 5 290 | i32.load offset=20 291 | local.set 76 292 | i32.const 16 293 | local.set 77 294 | local.get 76 295 | local.get 77 296 | i32.shl 297 | local.set 78 298 | local.get 5 299 | i32.load offset=16 300 | local.set 79 301 | i32.const 8 302 | local.set 80 303 | local.get 79 304 | local.get 80 305 | i32.shl 306 | local.set 81 307 | local.get 78 308 | local.get 81 309 | i32.or 310 | local.set 82 311 | local.get 5 312 | i32.load offset=12 313 | local.set 83 314 | local.get 82 315 | local.get 83 316 | i32.or 317 | local.set 84 318 | local.get 5 319 | local.get 84 320 | i32.store offset=8 321 | local.get 5 322 | i32.load offset=8 323 | local.set 85 324 | i32.const 18 325 | local.set 86 326 | local.get 85 327 | local.get 86 328 | i32.shr_u 329 | local.set 87 330 | i32.const 63 331 | local.set 88 332 | local.get 87 333 | local.get 88 334 | i32.and 335 | local.set 89 336 | local.get 89 337 | i32.load8_u offset=1024 338 | local.set 90 339 | local.get 5 340 | i32.load offset=36 341 | local.set 91 342 | local.get 5 343 | i32.load offset=24 344 | local.set 92 345 | i32.const 1 346 | local.set 93 347 | local.get 92 348 | local.get 93 349 | i32.add 350 | local.set 94 351 | local.get 5 352 | local.get 94 353 | i32.store offset=24 354 | local.get 91 355 | local.get 92 356 | i32.add 357 | local.set 95 358 | local.get 95 359 | local.get 90 360 | i32.store8 361 | local.get 5 362 | i32.load offset=8 363 | local.set 96 364 | i32.const 12 365 | local.set 97 366 | local.get 96 367 | local.get 97 368 | i32.shr_u 369 | local.set 98 370 | i32.const 63 371 | local.set 99 372 | local.get 98 373 | local.get 99 374 | i32.and 375 | local.set 100 376 | local.get 100 377 | i32.load8_u offset=1024 378 | local.set 101 379 | local.get 5 380 | i32.load offset=36 381 | local.set 102 382 | local.get 5 383 | i32.load offset=24 384 | local.set 103 385 | i32.const 1 386 | local.set 104 387 | local.get 103 388 | local.get 104 389 | i32.add 390 | local.set 105 391 | local.get 5 392 | local.get 105 393 | i32.store offset=24 394 | local.get 102 395 | local.get 103 396 | i32.add 397 | local.set 106 398 | local.get 106 399 | local.get 101 400 | i32.store8 401 | local.get 5 402 | i32.load offset=8 403 | local.set 107 404 | i32.const 6 405 | local.set 108 406 | local.get 107 407 | local.get 108 408 | i32.shr_u 409 | local.set 109 410 | i32.const 63 411 | local.set 110 412 | local.get 109 413 | local.get 110 414 | i32.and 415 | local.set 111 416 | local.get 111 417 | i32.load8_u offset=1024 418 | local.set 112 419 | local.get 5 420 | i32.load offset=36 421 | local.set 113 422 | local.get 5 423 | i32.load offset=24 424 | local.set 114 425 | i32.const 1 426 | local.set 115 427 | local.get 114 428 | local.get 115 429 | i32.add 430 | local.set 116 431 | local.get 5 432 | local.get 116 433 | i32.store offset=24 434 | local.get 113 435 | local.get 114 436 | i32.add 437 | local.set 117 438 | local.get 117 439 | local.get 112 440 | i32.store8 441 | local.get 5 442 | i32.load offset=8 443 | local.set 118 444 | i32.const 0 445 | local.set 119 446 | local.get 118 447 | local.get 119 448 | i32.shr_u 449 | local.set 120 450 | i32.const 63 451 | local.set 121 452 | local.get 120 453 | local.get 121 454 | i32.and 455 | local.set 122 456 | local.get 122 457 | i32.load8_u offset=1024 458 | local.set 123 459 | local.get 5 460 | i32.load offset=36 461 | local.set 124 462 | local.get 5 463 | i32.load offset=24 464 | local.set 125 465 | i32.const 1 466 | local.set 126 467 | local.get 125 468 | local.get 126 469 | i32.add 470 | local.set 127 471 | local.get 5 472 | local.get 127 473 | i32.store offset=24 474 | local.get 124 475 | local.get 125 476 | i32.add 477 | local.set 128 478 | local.get 128 479 | local.get 123 480 | i32.store8 481 | br 0 (;@2;) 482 | end 483 | unreachable 484 | end 485 | local.get 5 486 | i32.load offset=40 487 | local.set 129 488 | i32.const 3 489 | local.set 130 490 | local.get 129 491 | local.get 130 492 | i32.rem_s 493 | local.set 131 494 | i32.const 2 495 | local.set 132 496 | local.get 131 497 | local.get 132 498 | i32.gt_u 499 | drop 500 | block ;; label = @1 501 | block ;; label = @2 502 | block ;; label = @3 503 | block ;; label = @4 504 | local.get 131 505 | br_table 0 (;@4;) 1 (;@3;) 2 (;@2;) 3 (;@1;) 506 | end 507 | i32.const 0 508 | local.set 133 509 | local.get 5 510 | local.get 133 511 | i32.store offset=4 512 | br 2 (;@1;) 513 | end 514 | i32.const 2 515 | local.set 134 516 | local.get 5 517 | local.get 134 518 | i32.store offset=4 519 | br 1 (;@1;) 520 | end 521 | i32.const 1 522 | local.set 135 523 | local.get 5 524 | local.get 135 525 | i32.store offset=4 526 | end 527 | i32.const 0 528 | local.set 136 529 | local.get 5 530 | local.get 136 531 | i32.store 532 | block ;; label = @1 533 | loop ;; label = @2 534 | local.get 5 535 | i32.load 536 | local.set 137 537 | local.get 5 538 | i32.load offset=4 539 | local.set 138 540 | local.get 137 541 | local.set 139 542 | local.get 138 543 | local.set 140 544 | local.get 139 545 | local.get 140 546 | i32.lt_s 547 | local.set 141 548 | i32.const 1 549 | local.set 142 550 | local.get 141 551 | local.get 142 552 | i32.and 553 | local.set 143 554 | local.get 143 555 | i32.eqz 556 | br_if 1 (;@1;) 557 | local.get 5 558 | i32.load offset=36 559 | local.set 144 560 | local.get 5 561 | i32.load offset=32 562 | local.set 145 563 | i32.const 1 564 | local.set 146 565 | local.get 145 566 | local.get 146 567 | i32.sub 568 | local.set 147 569 | local.get 5 570 | i32.load 571 | local.set 148 572 | local.get 147 573 | local.get 148 574 | i32.sub 575 | local.set 149 576 | local.get 144 577 | local.get 149 578 | i32.add 579 | local.set 150 580 | i32.const 61 581 | local.set 151 582 | local.get 150 583 | local.get 151 584 | i32.store8 585 | local.get 5 586 | i32.load 587 | local.set 152 588 | i32.const 1 589 | local.set 153 590 | local.get 152 591 | local.get 153 592 | i32.add 593 | local.set 154 594 | local.get 5 595 | local.get 154 596 | i32.store 597 | br 0 (;@2;) 598 | end 599 | unreachable 600 | end 601 | local.get 5 602 | i32.load offset=32 603 | local.set 155 604 | local.get 155 605 | return) 606 | (func (;2;) (type 0) (result i32) 607 | global.get 0) 608 | (func (;3;) (type 1) (param i32) 609 | local.get 0 610 | global.set 0) 611 | (func (;4;) (type 3) (param i32) (result i32) 612 | (local i32 i32) 613 | global.get 0 614 | local.get 0 615 | i32.sub 616 | i32.const -16 617 | i32.and 618 | local.tee 1 619 | global.set 0 620 | local.get 1) 621 | (func (;5;) (type 2) 622 | i32.const 5244000 623 | global.set 2 624 | i32.const 1108 625 | i32.const 15 626 | i32.add 627 | i32.const -16 628 | i32.and 629 | global.set 1) 630 | (func (;6;) (type 0) (result i32) 631 | global.get 0 632 | global.get 1 633 | i32.sub) 634 | (func (;7;) (type 0) (result i32) 635 | global.get 2) 636 | (func (;8;) (type 0) (result i32) 637 | global.get 1) 638 | (func (;9;) (type 1) (param i32)) 639 | (func (;10;) (type 1) (param i32)) 640 | (func (;11;) (type 0) (result i32) 641 | i32.const 1092 642 | call 9 643 | i32.const 1096) 644 | (func (;12;) (type 2) 645 | i32.const 1092 646 | call 10) 647 | (func (;13;) (type 3) (param i32) (result i32) 648 | i32.const 1) 649 | (func (;14;) (type 1) (param i32)) 650 | (func (;15;) (type 3) (param i32) (result i32) 651 | (local i32 i32 i32) 652 | block ;; label = @1 653 | local.get 0 654 | br_if 0 (;@1;) 655 | i32.const 0 656 | local.set 1 657 | block ;; label = @2 658 | i32.const 0 659 | i32.load offset=1100 660 | i32.eqz 661 | br_if 0 (;@2;) 662 | i32.const 0 663 | i32.load offset=1100 664 | call 15 665 | local.set 1 666 | end 667 | block ;; label = @2 668 | i32.const 0 669 | i32.load offset=1100 670 | i32.eqz 671 | br_if 0 (;@2;) 672 | i32.const 0 673 | i32.load offset=1100 674 | call 15 675 | local.get 1 676 | i32.or 677 | local.set 1 678 | end 679 | block ;; label = @2 680 | call 11 681 | i32.load 682 | local.tee 0 683 | i32.eqz 684 | br_if 0 (;@2;) 685 | loop ;; label = @3 686 | i32.const 0 687 | local.set 2 688 | block ;; label = @4 689 | local.get 0 690 | i32.load offset=76 691 | i32.const 0 692 | i32.lt_s 693 | br_if 0 (;@4;) 694 | local.get 0 695 | call 13 696 | local.set 2 697 | end 698 | block ;; label = @4 699 | local.get 0 700 | i32.load offset=20 701 | local.get 0 702 | i32.load offset=28 703 | i32.eq 704 | br_if 0 (;@4;) 705 | local.get 0 706 | call 15 707 | local.get 1 708 | i32.or 709 | local.set 1 710 | end 711 | block ;; label = @4 712 | local.get 2 713 | i32.eqz 714 | br_if 0 (;@4;) 715 | local.get 0 716 | call 14 717 | end 718 | local.get 0 719 | i32.load offset=56 720 | local.tee 0 721 | br_if 0 (;@3;) 722 | end 723 | end 724 | call 12 725 | local.get 1 726 | return 727 | end 728 | i32.const 0 729 | local.set 2 730 | block ;; label = @1 731 | local.get 0 732 | i32.load offset=76 733 | i32.const 0 734 | i32.lt_s 735 | br_if 0 (;@1;) 736 | local.get 0 737 | call 13 738 | local.set 2 739 | end 740 | block ;; label = @1 741 | block ;; label = @2 742 | block ;; label = @3 743 | local.get 0 744 | i32.load offset=20 745 | local.get 0 746 | i32.load offset=28 747 | i32.eq 748 | br_if 0 (;@3;) 749 | local.get 0 750 | i32.const 0 751 | i32.const 0 752 | local.get 0 753 | i32.load offset=36 754 | call_indirect (type 4) 755 | drop 756 | local.get 0 757 | i32.load offset=20 758 | br_if 0 (;@3;) 759 | i32.const -1 760 | local.set 1 761 | local.get 2 762 | br_if 1 (;@2;) 763 | br 2 (;@1;) 764 | end 765 | block ;; label = @3 766 | local.get 0 767 | i32.load offset=4 768 | local.tee 1 769 | local.get 0 770 | i32.load offset=8 771 | local.tee 3 772 | i32.eq 773 | br_if 0 (;@3;) 774 | local.get 0 775 | local.get 1 776 | local.get 3 777 | i32.sub 778 | i64.extend_i32_s 779 | i32.const 1 780 | local.get 0 781 | i32.load offset=40 782 | call_indirect (type 5) 783 | drop 784 | end 785 | i32.const 0 786 | local.set 1 787 | local.get 0 788 | i32.const 0 789 | i32.store offset=28 790 | local.get 0 791 | i64.const 0 792 | i64.store offset=16 793 | local.get 0 794 | i64.const 0 795 | i64.store offset=4 align=4 796 | local.get 2 797 | i32.eqz 798 | br_if 1 (;@1;) 799 | end 800 | local.get 0 801 | call 14 802 | end 803 | local.get 1) 804 | (func (;16;) (type 0) (result i32) 805 | i32.const 1104) 806 | (table (;0;) 1 1 funcref) 807 | (memory (;0;) 256 256) 808 | (global (;0;) (mut i32) (i32.const 5244000)) 809 | (global (;1;) (mut i32) (i32.const 0)) 810 | (global (;2;) (mut i32) (i32.const 0)) 811 | (export "memory" (memory 0)) 812 | (export "__wasm_call_ctors" (func 0)) 813 | (export "b64encode" (func 1)) 814 | (export "__indirect_function_table" (table 0)) 815 | (export "__errno_location" (func 16)) 816 | (export "fflush" (func 15)) 817 | (export "emscripten_stack_init" (func 5)) 818 | (export "emscripten_stack_get_free" (func 6)) 819 | (export "emscripten_stack_get_base" (func 7)) 820 | (export "emscripten_stack_get_end" (func 8)) 821 | (export "stackSave" (func 2)) 822 | (export "stackRestore" (func 3)) 823 | (export "stackAlloc" (func 4)) 824 | (data (;0;) (i32.const 1024) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\00")) 825 | -------------------------------------------------------------------------------- /base64/base64wat.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32))) 3 | (type (;1;) (func (param i32 i32 i32) (result i32))) 4 | (import "console" "logNum" (func (;0;) (type 0))) 5 | (func (;1;) (type 1) (param i32 i32 i32) (result i32) 6 | (local i32 i32 i32 i32) 7 | i32.const 0 8 | local.set 3 9 | block ;; label = @1 10 | local.get 0 11 | local.get 1 12 | i32.add 13 | local.set 1 14 | loop ;; label = @2 15 | local.get 0 16 | local.get 1 17 | i32.ge_s 18 | br_if 1 (;@1;) 19 | i32.const 18 20 | local.set 6 21 | block ;; label = @3 22 | i32.const 0 23 | local.set 4 24 | i32.const 16 25 | local.set 5 26 | loop ;; label = @4 27 | local.get 0 28 | local.get 1 29 | i32.ge_s 30 | br_if 1 (;@3;) 31 | local.get 0 32 | i32.load8_u 33 | local.get 5 34 | i32.shl 35 | local.get 4 36 | i32.or 37 | local.set 4 38 | local.get 5 39 | i32.const 8 40 | i32.sub 41 | local.set 5 42 | local.get 6 43 | i32.const 6 44 | i32.sub 45 | local.set 6 46 | local.get 0 47 | i32.const 1 48 | i32.add 49 | local.set 0 50 | local.get 5 51 | i32.const -8 52 | i32.ne 53 | br_if 0 (;@4;) 54 | end 55 | end 56 | block ;; label = @3 57 | i32.const 18 58 | local.set 5 59 | loop ;; label = @4 60 | local.get 2 61 | local.get 4 62 | local.get 5 63 | i32.shr_u 64 | i32.const 63 65 | i32.and 66 | i32.load8_u 67 | i32.store8 68 | local.get 5 69 | i32.const 6 70 | i32.sub 71 | local.set 5 72 | local.get 3 73 | i32.const 1 74 | i32.add 75 | local.set 3 76 | local.get 2 77 | i32.const 1 78 | i32.add 79 | local.set 2 80 | local.get 5 81 | local.get 6 82 | i32.ge_s 83 | br_if 0 (;@4;) 84 | end 85 | end 86 | br 0 (;@2;) 87 | end 88 | end 89 | block ;; label = @1 90 | loop ;; label = @2 91 | local.get 3 92 | i32.const 3 93 | i32.and 94 | i32.const 0 95 | i32.eq 96 | br_if 1 (;@1;) 97 | local.get 2 98 | i32.const 61 99 | i32.store8 100 | local.get 3 101 | i32.const 1 102 | i32.add 103 | local.set 3 104 | local.get 2 105 | i32.const 1 106 | i32.add 107 | local.set 2 108 | br 0 (;@2;) 109 | end 110 | end 111 | local.get 2 112 | i32.const 0 113 | i32.store8 114 | local.get 3) 115 | (memory (;0;) 10 100) 116 | (export "memory" (memory 0)) 117 | (export "b64encode" (func 1)) 118 | (data (;0;) (i32.const 0) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")) 119 | -------------------------------------------------------------------------------- /exported_func/exported.bat: -------------------------------------------------------------------------------- 1 | emcc exported.c -o exported.js -------------------------------------------------------------------------------- /exported_func/exported.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern unsigned int curTime(); 5 | extern void logProgress(float progress); 6 | 7 | int main() { return 0; } 8 | 9 | EMSCRIPTEN_KEEPALIVE 10 | unsigned char *randString(int len) 11 | { 12 | unsigned char *str = malloc(len + 1); 13 | 14 | srand(curTime()); 15 | 16 | for (int i = 0; i < len; i++) 17 | { 18 | // generate a printable character 19 | str[i] = rand() % (127 - 33) + 33; 20 | logProgress((float)(i + 1) / (float)len); 21 | for (int j = 0; j < 100000000; j++) 22 | { 23 | } 24 | } 25 | 26 | str[len] = 0; 27 | return str; 28 | } -------------------------------------------------------------------------------- /exported_func/exported.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Streaming 8 | 9 | 17 | 18 | 19 | 20 |

Hello, WebAssembly!

21 | 22 | 63 | 64 | 65 | 66 |
67 |

68 | 69 | 70 | -------------------------------------------------------------------------------- /exported_func/exported.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/exported_func/exported.wasm -------------------------------------------------------------------------------- /hello_world/a.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/hello_world/a.exe -------------------------------------------------------------------------------- /hello_world/a.out.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello, WebAssembly! 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /hello_world/a.out.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/hello_world/a.out.wasm -------------------------------------------------------------------------------- /hello_world/hello_world.bat: -------------------------------------------------------------------------------- 1 | emcc hello_world.c 2 | gcc hello_world.c -------------------------------------------------------------------------------- /hello_world/hello_world.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Hello, world!\n"); 6 | 7 | return 0; 8 | } -------------------------------------------------------------------------------- /memory/malloc.bat: -------------------------------------------------------------------------------- 1 | emcc malloc.c -o malloc.js -------------------------------------------------------------------------------- /memory/malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { return 0; } 5 | 6 | EMSCRIPTEN_KEEPALIVE 7 | int accumulate(int *arr, int n) 8 | { 9 | int sum = 0; 10 | while (n) 11 | { 12 | sum += arr[--n]; 13 | } 14 | return sum; 15 | } 16 | 17 | EMSCRIPTEN_KEEPALIVE 18 | const char *getString() 19 | { 20 | return "Hello, asdfasdfgagyhaqwetrqew!"; 21 | } 22 | 23 | EMSCRIPTEN_KEEPALIVE 24 | void *wasmmalloc(size_t n) 25 | { 26 | return malloc(n); 27 | } 28 | 29 | EMSCRIPTEN_KEEPALIVE 30 | void wasmfree(void *ptr) 31 | { 32 | free(ptr); 33 | } -------------------------------------------------------------------------------- /memory/malloc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Streaming 8 | 9 | 10 | 11 |

Hello, WebAssembly!

12 | 13 | 89 | 90 | 91 | 92 | 93 |

94 | 95 | 96 | -------------------------------------------------------------------------------- /memory/malloc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/memory/malloc.wasm -------------------------------------------------------------------------------- /memory/memory.bat: -------------------------------------------------------------------------------- 1 | emcc memory.c -o memory.js -------------------------------------------------------------------------------- /memory/memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { return 0; } 4 | 5 | EMSCRIPTEN_KEEPALIVE 6 | int accumulate(int *arr, int n) 7 | { 8 | int sum = 0; 9 | while (n) 10 | { 11 | sum += arr[--n]; 12 | } 13 | return sum; 14 | } 15 | 16 | EMSCRIPTEN_KEEPALIVE 17 | const char *getString() 18 | { 19 | return "Hello, asdfasdfgagyhaqwetrqew!"; 20 | } -------------------------------------------------------------------------------- /memory/memory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Streaming 8 | 9 | 10 | 11 |

Hello, WebAssembly!

12 | 13 | 54 | 55 | 56 | 57 | 58 |

59 | 60 | 61 | -------------------------------------------------------------------------------- /memory/memory.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/memory/memory.wasm -------------------------------------------------------------------------------- /raw_wasm/add.wasm: -------------------------------------------------------------------------------- 1 | asm`add 2 |  j -------------------------------------------------------------------------------- /raw_wasm/add.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (func $add (param $lhs i32) (param $rhs i32) (result i32) 3 | local.get $lhs ;; put lhs on the stack 4 | local.get $rhs ;; put rhs on the stack 5 | i32.add ;; pop from stack and compute 6 | ) 7 | (export "add" (func $add)) 8 | ) 9 | -------------------------------------------------------------------------------- /raw_wasm/flow.wasm: -------------------------------------------------------------------------------- 1 | asm ``consolelogNum!memory 2 | accumulateaverage 3 | B4A!@@  ( j! Aj! Ak! AJ   m -------------------------------------------------------------------------------- /raw_wasm/flow.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "console" "logNum" (func $logNum (param i32))) 3 | (memory $mem 1) 4 | (export "memory" (memory $mem)) 5 | 6 | (func $accumulate (export "accumulate") 7 | (param $addr i32) ;; 0: address of array 8 | (param $n i32) ;; 1: number of ints in the array 9 | (result i32) ;; sum of elements 10 | 11 | (local $sum i32) ;; 2: sum to store 12 | i32.const 0 ;; initial value 13 | local.set $sum 14 | 15 | (block 16 | (loop $inc 17 | local.get $n 18 | call $logNum 19 | 20 | ;; get element 21 | local.get $addr ;; S: addr 22 | i32.load ;; S: elem 23 | local.get $sum ;; S: elem, sum 24 | i32.add ;; S: sum' 25 | local.set $sum ;; S: - 26 | 27 | ;; increment step 28 | 29 | ;; increment address 30 | local.get $addr ;; S: addr 31 | i32.const 4 ;; S: addr, 4 32 | i32.add ;; S: addr' 33 | local.set $addr ;; S: - 34 | 35 | ;; decrement counter 36 | local.get $n ;; S: n 37 | i32.const 1 ;; S: n, 1 38 | i32.sub ;; S: n' 39 | local.set $n ;; S: - 40 | 41 | ;; loop or break 42 | local.get $n ;; S: n' 43 | i32.const 0 ;; S: n', 0 44 | i32.gt_s ;; S: true 45 | br_if $inc 46 | ) 47 | ) 48 | 49 | ;; return 50 | local.get $sum 51 | return 52 | ) 53 | 54 | (func $average (export "average") (param i32 i32) (result i32) 55 | local.get 0 ;; S: addr 56 | local.get 1 ;; S: addr, n 57 | call $accumulate ;; S: sum 58 | local.get 1 ;; S: sum, n 59 | i32.div_s ;; S: sum/n 60 | ) 61 | ) 62 | -------------------------------------------------------------------------------- /raw_wasm/func.wasm: -------------------------------------------------------------------------------- 1 | asm````consolelogNumgetValcompute 2 |  Aj A*A2 A j -------------------------------------------------------------------------------- /raw_wasm/func.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "console" "logNum" (func $logNum (param i32))) 3 | 4 | (func $someFunc (param i32) (result i32) 5 | local.get 0 6 | i32.const 20 7 | i32.add 8 | ) 9 | (func $getVal (export "getVal") (result i32 i32) 10 | i32.const 42 ;; 42 11 | i32.const 50 ;; 42, 50 12 | call $someFunc ;; 42, 70 13 | ) 14 | 15 | (func $compute (export "compute") (result i32) 16 | i32.const 13 ;; 13 17 | call $logNum ;; - 18 | 19 | call $getVal ;; 42, 70 20 | i32.add ;; 112 21 | ) 22 | ) -------------------------------------------------------------------------------- /raw_wasm/functable.wasm: -------------------------------------------------------------------------------- 1 | asm````%consolelogNumconsolelogThreep 2 | dtbleval A A A A A  3 | X   j  k  l  m 1A!@@ AN  - F  Aj!    A =+-/* -------------------------------------------------------------------------------- /raw_wasm/functable.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type $OPERATION (func (param i32) (param i32) (result i32))) 3 | 4 | (import "console" "logNum" (func $logNum (param i32))) 5 | (import "console" "logThree" (func $logThree (param i32 i32 i32))) 6 | 7 | (func $set (type $OPERATION) 8 | local.get 1 9 | ) 10 | (func $add (type $OPERATION) 11 | local.get 0 12 | local.get 1 13 | i32.add 14 | ) 15 | (func $sub (type $OPERATION) 16 | local.get 0 17 | local.get 1 18 | i32.sub 19 | ) 20 | (func $mul (type $OPERATION) 21 | local.get 0 22 | local.get 1 23 | i32.mul 24 | ) 25 | (func $div (type $OPERATION) 26 | local.get 0 27 | local.get 1 28 | i32.div_s 29 | ) 30 | 31 | (memory $key_memory 10 100) 32 | (data 0 33 | (i32.const 0) ;; address 34 | "=+-/*" 35 | ) 36 | 37 | (table $tbl (export "tbl") 5 funcref) 38 | (elem (i32.const 0) $set) 39 | (elem (i32.const 1) $add) 40 | (elem (i32.const 2) $sub) 41 | (elem (i32.const 3) $div) 42 | (elem (i32.const 4) $mul) 43 | 44 | (func $eval (export "eval") 45 | (param $op i32) (param $res i32) (param $num i32) 46 | (result i32) 47 | 48 | (local $idx i32) 49 | i32.const 0 50 | local.set $idx 51 | 52 | ;; find operator index 53 | (block $scanBlock 54 | (loop $scanLoop 55 | ;; condition 56 | local.get $idx 57 | i32.const 5 58 | i32.ge_s 59 | br_if $scanBlock 60 | 61 | ;; test character 62 | local.get $idx 63 | i32.load8_u 64 | local.get $op 65 | i32.eq 66 | br_if $scanBlock 67 | 68 | ;; increment 69 | local.get $idx 70 | i32.const 1 71 | i32.add 72 | local.set $idx 73 | 74 | br $scanLoop 75 | ) 76 | ) 77 | 78 | ;; index into the function table 79 | (call_indirect 80 | (type $OPERATION) 81 | (local.get $res) (local.get $num) 82 | (local.get $idx) 83 | ) 84 | ) 85 | ) -------------------------------------------------------------------------------- /raw_wasm/mem.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/raw_wasm/mem.wasm -------------------------------------------------------------------------------- /raw_wasm/mem.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "console" "logStrLen" (func $logStrLen (param i32 i32))) 3 | (import "console" "logStr" (func $logStr (param i32))) 4 | 5 | (memory $exported_memory 10 100) 6 | (export "memory" (memory $exported_memory)) 7 | (data 0 8 | (i32.const 0) ;; address 9 | "wasd" 10 | "2345" 11 | "\00\00\00\00" 12 | ) 13 | 14 | (data 0 15 | (i32.const 48) ;; address 16 | "asd\00" 17 | ) 18 | 19 | (func $print (export "print") (result i32) 20 | i32.const 0 ;; offset 21 | i32.const 8 ;; length 22 | call $logStrLen 23 | 24 | i32.const 48 ;; offset 25 | call $logStr 26 | 27 | i32.const 51 ;; offset 28 | i32.const 102 ;; utf-8 char code 29 | i32.store8 30 | 31 | i32.const 52 ;; offset 32 | i32.const 0 ;; terminator character 33 | i32.store 34 | 35 | i32.const 48 ;; offset 36 | call $logStr 37 | 38 | i32.const 0 ;; return 39 | ) 40 | ) 41 | -------------------------------------------------------------------------------- /raw_wasm/raw.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Raw WAT 6 | 7 | 8 | 9 |

Hello, WebAssembly!

10 | 11 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /streaming/streaming.bat: -------------------------------------------------------------------------------- 1 | emcc streaming.c streaming_util.c -o streaming.js 2 | del -f streaming.js -------------------------------------------------------------------------------- /streaming/streaming.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int add(int a, int b); 4 | int sub(int a, int b); 5 | int mul(int a, int b); 6 | int div(int a, int b); 7 | 8 | EMSCRIPTEN_KEEPALIVE 9 | int sumOfNInts(int n) 10 | { 11 | // return n * (n + 1) / 2; 12 | return div(mul(n, add(n, 1)), 2); 13 | } -------------------------------------------------------------------------------- /streaming/streaming.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Streaming 8 | 9 | 10 | 11 |

Hello, WebAssembly!

12 | 13 | 27 | 28 | 29 | 30 |

31 | 32 | 33 | -------------------------------------------------------------------------------- /streaming/streaming.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/streaming/streaming.wasm -------------------------------------------------------------------------------- /streaming/streaming_util.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | EMSCRIPTEN_KEEPALIVE 4 | int add(int a, int b) 5 | { 6 | return a + b; 7 | } 8 | 9 | EMSCRIPTEN_KEEPALIVE 10 | int sub(int a, int b) 11 | { 12 | return a - b; 13 | } 14 | 15 | EMSCRIPTEN_KEEPALIVE 16 | int mul(int a, int b) 17 | { 18 | return a * b; 19 | } 20 | 21 | EMSCRIPTEN_KEEPALIVE 22 | int div(int a, int b) 23 | { 24 | return a / b; 25 | } -------------------------------------------------------------------------------- /struct_framework/basic_framework.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Streaming 8 | 9 | 10 | 11 |

Hello, WebAssembly!

12 | 13 | 14 | 103 | 104 | 105 | 106 | 107 | 108 | 109 |

110 | 111 | 112 | -------------------------------------------------------------------------------- /struct_framework/nested_struct.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern void printNameToConsole(char *str); 5 | 6 | typedef struct 7 | { 8 | int val; 9 | int a; 10 | } sub_s; 11 | 12 | typedef struct 13 | { 14 | int a; 15 | int b; 16 | sub_s structure; 17 | int **ptr; 18 | int *int_arr; 19 | int arr_size; 20 | char *name; 21 | } s; 22 | 23 | int main() { return 0; } 24 | 25 | EMSCRIPTEN_KEEPALIVE 26 | s *createStruct(int a, int b, int l, int c) 27 | { 28 | s *ret = malloc(sizeof(s)); 29 | ret->a = a; 30 | ret->b = b; 31 | ret->structure.val = l; 32 | ret->structure.a = c; 33 | return ret; 34 | } 35 | 36 | EMSCRIPTEN_KEEPALIVE 37 | int computeSum(s *obj) 38 | { 39 | return obj->a * obj->b + obj->structure.val / obj->structure.a; 40 | } 41 | 42 | EMSCRIPTEN_KEEPALIVE 43 | int getPtr(s *obj) 44 | { 45 | return obj->ptr[0][0]; 46 | } 47 | 48 | EMSCRIPTEN_KEEPALIVE 49 | int compSumTerminator(s *obj) 50 | { 51 | int sum = 0; 52 | int i = 0; 53 | while (obj->int_arr[i]) 54 | { 55 | sum += obj->int_arr[i++]; 56 | } 57 | return sum; 58 | } 59 | 60 | EMSCRIPTEN_KEEPALIVE 61 | int compSumSize(s *obj) 62 | { 63 | int sum = 0; 64 | for (int i = 0; i < obj->arr_size; i++) 65 | { 66 | sum += obj->int_arr[i]; 67 | } 68 | return sum; 69 | } 70 | 71 | EMSCRIPTEN_KEEPALIVE 72 | void printName(s *obj) 73 | { 74 | printNameToConsole(obj->name); 75 | } 76 | 77 | EMSCRIPTEN_KEEPALIVE 78 | void *wasmmalloc(int size) 79 | { 80 | return malloc(size); 81 | } 82 | 83 | EMSCRIPTEN_KEEPALIVE 84 | void wasmfree(void *ptr) 85 | { 86 | free(ptr); 87 | } -------------------------------------------------------------------------------- /struct_framework/nested_struct.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/struct_framework/nested_struct.wasm -------------------------------------------------------------------------------- /struct_framework/num_struct.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef struct 5 | { 6 | int a; 7 | int b; 8 | } pair; 9 | 10 | int main() { return 0; } 11 | 12 | EMSCRIPTEN_KEEPALIVE 13 | float computeSum(pair *p) 14 | { 15 | return p->a + p->b; 16 | } 17 | 18 | EMSCRIPTEN_KEEPALIVE 19 | pair *createPair(int a, int b) 20 | { 21 | pair *p = malloc(sizeof(pair)); 22 | p->a = a; 23 | p->b = b; 24 | return p; 25 | } 26 | 27 | EMSCRIPTEN_KEEPALIVE 28 | void *wasmmalloc(int size) 29 | { 30 | return malloc(size); 31 | } 32 | 33 | EMSCRIPTEN_KEEPALIVE 34 | void wasmfree(void *ptr) 35 | { 36 | free(ptr); 37 | } -------------------------------------------------------------------------------- /struct_framework/num_struct.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Streaming 8 | 9 | 10 | 11 |

Hello, WebAssembly!

12 | 13 | 14 | 57 | 58 | 59 | 60 | 61 | 62 |

63 | 64 | 65 | -------------------------------------------------------------------------------- /struct_framework/num_struct.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/struct_framework/num_struct.wasm -------------------------------------------------------------------------------- /struct_framework/struct_framework.js: -------------------------------------------------------------------------------- 1 | let types = { 2 | char: 1, 3 | int: 4, 4 | float: 4, 5 | } 6 | 7 | let primitives = ["char", "int", "float"]; 8 | 9 | let structs = {}; 10 | 11 | function registerStruct(name, structFormat) { 12 | types[name] = computeStructSize(structFormat); 13 | structs[name] = structFormat; 14 | } 15 | 16 | function getElemSize(type) { 17 | if (type.endsWith('*') || type.endsWith('[]')) { 18 | return 4; 19 | } else { 20 | return types[type]; 21 | } 22 | } 23 | 24 | function computeStructSize(structFormat) { 25 | let size = 0; 26 | 27 | for (const type of Object.values(structFormat)) { 28 | size += getElemSize(type); 29 | } 30 | 31 | return size; 32 | } 33 | 34 | function encodeInt(num, n, buffer, offset = 0) { 35 | for (var i = 0; i < n; i++) { 36 | buffer[i + offset] = num & 0xff; 37 | num >>= 8; 38 | } 39 | } 40 | 41 | function encodeStruct(type, obj, buffer, memory, malloc, cursor = 0, pointer = 0) { 42 | for (const [name, elemType] of Object.entries(structs[type])) { 43 | encodeElem(elemType, obj[name], buffer, memory, malloc, cursor, pointer); 44 | 45 | cursor += getElemSize(elemType); 46 | } 47 | } 48 | 49 | function encodePointer(type, obj, memory, malloc) { 50 | if (!obj) { 51 | return 0; // NULL 52 | } 53 | 54 | const n = getElemSize(type); 55 | const ptr = malloc(n); 56 | const buf = new Uint8Array(memory.buffer, ptr, n); 57 | 58 | encodeElem(type, obj, buf, memory, malloc, 0, ptr); 59 | return ptr; 60 | } 61 | 62 | function encodeArray(type, obj, memory, malloc) { 63 | if (!obj) { 64 | return 0; // NULL 65 | } 66 | 67 | const nIndividual = getElemSize(type); 68 | const n = (obj.length + 1) * nIndividual; 69 | const ptr = malloc(n); 70 | const buf = new Uint8Array(memory.buffer, ptr, n); 71 | if (type === 'char') { 72 | for (var i = 0; i < obj.length; i++) { 73 | buf[i] = obj.charCodeAt(i); 74 | } 75 | buf[obj.length] = 0; 76 | } else { 77 | let cursor = 0; 78 | for (var i = 0; i < obj.length; i++) { 79 | encodeElem(type, obj[i], buf, memory, malloc, cursor, ptr); 80 | cursor += nIndividual; 81 | } 82 | encodeInt(0, nIndividual, buf, cursor); // terminator element 83 | } 84 | 85 | return ptr; 86 | } 87 | 88 | function encodeElem(type, obj, buffer, memory, malloc, cursor = 0, pointer = 0) { 89 | if (type.endsWith('*')) { 90 | const ptr = encodePointer(type.substring(0, type.length - 1), obj, memory, malloc); 91 | encodeInt(ptr, 4, buffer, cursor); 92 | } else if (type.endsWith('[]')) { 93 | const ptr = encodeArray(type.substring(0, type.length - 2), obj, memory, malloc); 94 | encodeInt(ptr, 4, buffer, cursor); 95 | } else if (primitives.includes(type)) { 96 | if (type !== 'float') { 97 | encodeInt(obj ?? 0, types[type], buffer, cursor); 98 | } else { 99 | const floatBuf = new Float32Array(memory.buffer, pointer + cursor); 100 | floatBuf[0] = obj ?? 0.0; 101 | } 102 | } else { 103 | encodeStruct(type, obj, buffer, memory, malloc, cursor, pointer); 104 | } 105 | } 106 | 107 | function decodeNum(n, memory, offset = 0) { 108 | let ret = 0; 109 | for (var i = n - 1; i >= 0; i--) { 110 | ret <<= 8; 111 | ret |= memory[i + offset]; 112 | } 113 | return ret; 114 | } 115 | 116 | function decodeStruct(name, memory, offset = 0) { 117 | var ret = {}; 118 | let cursor = offset; 119 | for (const [key, type] of Object.entries(structs[name])) { 120 | if (primitives.includes(type)) { 121 | ret[key] = decodeNum(types[type], memory, cursor); 122 | } else { 123 | ret[key] = decodeStruct(type, memory, cursor); 124 | } 125 | 126 | cursor += types[type]; 127 | } 128 | return ret; 129 | } 130 | 131 | function startDecodeStruct(name, ptr, memory) { 132 | return decodeStruct(name, new Uint8Array(memory.buffer, ptr, types[name])); 133 | } -------------------------------------------------------------------------------- /wrapping/wrapping.bat: -------------------------------------------------------------------------------- 1 | emcc wrapping.c -o wrapping.js -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=ccall,cwrap -------------------------------------------------------------------------------- /wrapping/wrapping.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | EMSCRIPTEN_KEEPALIVE 5 | int addNums(int a, int b) 6 | { 7 | return a + b; 8 | } 9 | 10 | EMSCRIPTEN_KEEPALIVE 11 | int subtractNums(int a, int b) 12 | { 13 | return a - b; 14 | } 15 | 16 | EMSCRIPTEN_KEEPALIVE 17 | int main() 18 | { 19 | printf("Hello, world, %d\n", addNums(3, 5)); 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /wrapping/wrapping.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CCall and CWrap 8 | 9 | 10 | 11 | 12 | 13 |

Hello, WebAssembly!

14 | 15 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /wrapping/wrapping.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelg29/webassembly-tutorial/7c2b81cb6b069c7fe3e4b49e203c976e3f2a3558/wrapping/wrapping.wasm --------------------------------------------------------------------------------