├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── js.py ├── lib ├── firmware.wasm ├── micropython.binary └── micropython.js ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Farrell Raafi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MicroPython.js 2 | ============== 3 | 4 | MicroPython transmuted into Javascript (WASM) by Emscripten. 5 | 6 | Official Repo https://github.com/micropython/micropython/tree/master/ports/javascript 7 | 8 | Testing and Contribution Needed, feel free to make an issue or even better, a PR 9 | 10 | 11 | What's New on 1.1 12 | -------------------- 13 | 14 | - New Async/Await or Promise API 15 | - New Python classes to expose JS API and Objects like DOM API, XHR, Node.JS require, and etc 16 | - New Python promise class to wait promises with emscripten_sleep, using Emterpreter 17 | 18 | 19 | Running with Node.js 20 | -------------------- 21 | 22 | On Node.JS console 23 | 24 | ```javascript 25 | const mp_js = require('micropython'); 26 | 27 | mp_js.init(64 * 1024); 28 | mp_js.do_str("print('hello world')\n"); 29 | ``` 30 | 31 | On production/actual code use AsyncFunction or Promise to get the guaranteed result 32 | 33 | ```javascript 34 | (async () => { //AsyncFunction 35 | const mp_js = await require('micropython'); 36 | 37 | mp_js.init(64 * 1024); 38 | await mp_js.do_str("variable1 = {'data1': 1}"); 39 | await mp_js.do_str("variable1.get('data1')"); //Access variables from the previous event loop 40 | })(); 41 | ``` 42 | 43 | Running with Webpack 44 | ----------------- 45 | Running MicroPython on Webpack is a little bit tricky. It expects the firmware.wasm file at /static/js/firmware.wasm. So a simple solution is to make static and js folder on webpack's public directory and put firmware.wasm on it. (PR is accepted for a better solution) 46 | 47 | ``` 48 | mkdir -p public/static/js 49 | cp node_modules/micropython/lib/firmware.wasm public/static/js 50 | ``` 51 | 52 | And import it on your Javascript file 53 | 54 | ```javascript 55 | import mp_js from 'micropython'; 56 | 57 | (async () => { 58 | await mp_js; 59 | mp_js.init(64 * 1024); 60 | const stdout = await mp_js.do_str("print('hello world')\n"); 61 | console.log(stdout); 62 | })(); 63 | ``` 64 | 65 | 66 | Python API 67 | --- 68 | 69 | The following functions and classes is used to interact with Javascript. Load this API with ```mp_js.init_python(stack_size)``` 70 | 71 | ```python 72 | JS(variable_name) 73 | ``` 74 | Check for variable on Javascript's global and return the corresponding types, functions and Javascript objects instantiate JSFunction and JSObject class. Promise instantiate JSPromise class. 75 | 76 | ```python 77 | wait(promise) 78 | ``` 79 | Wait for a promise to be resolved on Javascript, and then returns the value. Uses emscripten_sleep. Also available as JSPromise class function: 80 | 81 | ```python 82 | fetch = JS('require')('node-fetch') 83 | response = fetch('https://github.com').wait() #Returns response object 84 | html = response.text().wait() #Returns HTML string 85 | ``` 86 | 87 | Javascript API 88 | --- 89 | 90 | The following functions have been exposed to Javascript. 91 | 92 | ``` 93 | init(stack_size) 94 | ``` 95 | 96 | Initialize MicroPython with the given stack size in bytes. This must be 97 | called before attempting to interact with MicroPython. 98 | 99 | ``` 100 | do_str(code) 101 | ``` 102 | 103 | Execute the input code. `code` must be a `string`. Returns a promise resulting an stdout. 104 | 105 | ``` 106 | init_repl() 107 | ``` 108 | 109 | Initialize MicroPython repl. Must be called before entering characters into 110 | the repl. 111 | 112 | ``` 113 | process_char(char) 114 | ``` 115 | 116 | Input character into MicroPython repl. `char` must be of type `number`. This 117 | will execute MicroPython code when necessary. 118 | 119 | ``` 120 | init_python(stack_size) 121 | ``` 122 | 123 | This function execute js.py to expose JS Objects to Python, Example: 124 | 125 | ```javascript 126 | mp_js = require('micropython'); 127 | 128 | (async () => { 129 | await mp_js; 130 | await mp_js.init_python(64 * 1024); 131 | await mp_js.do_str(` 132 | 133 | import js 134 | 135 | fetch = False 136 | if isbrowser: 137 | fetch = JS('fetch') 138 | else: 139 | require = JS('require') 140 | fetch = require('node-fetch') 141 | response = fetch('https://github.com').wait() 142 | result = response.text().wait() 143 | print(result) 144 | 145 | `); 146 | })(); 147 | ``` 148 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | global.mpjscache = {}; 2 | let pyjs; 3 | const browser = (typeof window || typeof importScripts) !== 'undefined'; 4 | let stdout_text = ''; 5 | let stdout_ready = false; 6 | let stdout_print = (stdout) => { 7 | if (browser) stdout = stdout.data; 8 | if (!browser) stdout = stdout.toString(); 9 | stdout_text += stdout; 10 | if (stdout_text.indexOf('mpjsendline') > -1) { 11 | stdout_text = stdout_text.replace('mpjsendline', ''); 12 | stdout_ready = true; 13 | //console.log(stdout_text); 14 | } 15 | } 16 | global.mpjsPrintStdout = stdout_print; 17 | global.formatString = (object) => object !== undefined ? JSON.stringify(object) : null 18 | 19 | const mp = require('./lib/micropython.js'); 20 | if (typeof webpackJsonp !== 'object') { 21 | pyjs = require('fs').readFileSync(__dirname + '/js.py').toString(); 22 | } 23 | else { 24 | pyjs = require('!raw-loader!' + './js.py').default; 25 | } 26 | 27 | function wait_exist(fn) { 28 | return new Promise((resolve, reject) => { 29 | const clear = (id) => { 30 | clearInterval(id); 31 | resolve(); 32 | } 33 | const interval = setInterval(() => {if (fn()) clear(interval)}, 0); 34 | }); 35 | } 36 | 37 | if (browser) { 38 | window.global = window; 39 | const stdout = document.createElement('div'); 40 | stdout.id = 'mp_js_stdout'; 41 | stdout.style.display = 'none'; 42 | stdout.addEventListener('print', stdout_print, false); 43 | document.body.append(stdout); 44 | } 45 | 46 | global.AsyncFunction = (async () => {}).constructor; 47 | 48 | let initiated; 49 | let pyjs_initiated; 50 | 51 | module.exports = (async () => { 52 | await wait_exist(() => global.mp_js_init); 53 | const methods = {} 54 | const init = global.mp_js_init; 55 | methods.init = (stack) => !initiated && (initiated = !init(stack)); 56 | const do_str = global.mp_js_do_str; 57 | global._mp_js_do_str = do_str; 58 | methods.do_str = async (code, module, initiated) => { 59 | const codes = code.split('\n'); 60 | let spaces = ''; 61 | for (let line of codes) { 62 | if (!line || !line.match(/[a-z]/i)) continue; 63 | let index = 0; 64 | for (let word of line) { 65 | if (index === 0 && word.match(/[a-z]/i)) break; 66 | if (word === ' ') spaces += ' '; 67 | index += 1; 68 | } 69 | break; 70 | } 71 | if (module) { 72 | if (!spaces) { 73 | code = code.replace(/^/gm, ' '); 74 | spaces = ' '; 75 | } 76 | code = 'def mpjs_module():\n' + code; 77 | code += '\n' + spaces + 'import sys'; 78 | code += '\n' + spaces + `sys.modules['${module}'] = type('${module}', (), globals())()`; 79 | code += '\nmpjs_module()'; 80 | if (!initiated) return code; 81 | spaces = ''; 82 | } 83 | if (spaces) { 84 | let index_split = 0; 85 | const new_code = []; 86 | for (let line of codes) { 87 | line = line.slice(spaces.length - 1); 88 | new_code.push(line); 89 | } 90 | code = new_code.join('\n'); 91 | } 92 | stdout_text = ''; 93 | stdout_ready = false; 94 | code += "\nprint('mpjsendline')"; 95 | if (global.promiseWaitInterval) await wait_exist(() => !global.promiseWaitInterval); 96 | do_str(code); 97 | await wait_exist(() => stdout_ready); 98 | return stdout_text; 99 | } 100 | methods.init_python = async (stack) => { 101 | if (pyjs_initiated) return; 102 | methods.init(stack); 103 | if (!pyjs_initiated) { 104 | await methods.do_str(` 105 | import json 106 | isbrowser = json.loads('${browser}') 107 | `); 108 | pyjs_initiated = true; 109 | } 110 | return await methods.do_str(pyjs); 111 | } 112 | methods.register_module = async (module, code) => { 113 | if (!pyjs_initiated) return pyjs += '\n' + await methods.do_str(code, module, false); 114 | return await methods.do_str(code, module, true); 115 | } 116 | global.mp_js_do_str = methods.do_str; 117 | methods.init_repl = global.mp_js_init_repl; 118 | methods.process_char = global.mp_js_process_char; 119 | return methods; 120 | })().then((methods) => { 121 | module.exports.init = methods.init; 122 | module.exports.do_str = methods.do_str; 123 | module.exports.init_python = methods.init_python; 124 | module.exports.init_repl = methods.init_repl; 125 | module.exports.process_char = methods.process_char; 126 | return methods; 127 | }); 128 | 129 | module.exports.init = mp._mp_js_init; 130 | module.exports.do_str = mp._mp_js_do_str; 131 | module.exports.init_repl = mp._mp_js_init_repl; 132 | module.exports.process_char = mp._mp_js_process_char; 133 | -------------------------------------------------------------------------------- /js.py: -------------------------------------------------------------------------------- 1 | import json 2 | import js 3 | 4 | def js_exec(code, *args): 5 | code = format(code, *args) 6 | result = js.exec('formatString((() => {\n' + code + '\n})());') 7 | return json.loads(result) 8 | 9 | def js_print(value): 10 | js.exec('console.log(%s)' % (json.dumps(str(value)))) 11 | 12 | py_print = print 13 | 14 | def format(string, *args): 15 | for index, arg in enumerate(args): 16 | string = string.replace('{%s}' % (index), str(arg)) 17 | return string 18 | 19 | def wait(promise): 20 | while not promise._resolved: 21 | js.sleep(250) 22 | result = js_exec(''' 23 | const object = {0}; 24 | if (object && object.constructor !== Promise) return true; 25 | ''', promise._name) 26 | if result: promise.resolve(JS(promise._name)) 27 | return promise._value 28 | 29 | class JSPromise(): 30 | 31 | def __init__(self, name): 32 | self._name = name 33 | self._resolved = False 34 | self._value = False 35 | 36 | def resolve(self, value): 37 | self._resolved = True 38 | self._value = value 39 | return value 40 | 41 | def wait(self): 42 | return wait(self) 43 | 44 | class JSObject(): 45 | 46 | def __init__(self, name): 47 | self._name = name 48 | 49 | def __len__(self): 50 | if self._name: 51 | return 1 52 | else: 53 | return 0 54 | 55 | def __dir__(self): 56 | if not self._name: return [] 57 | return js_exec(''' 58 | return Object.keys({0})); 59 | ''', self._name) 60 | 61 | def __getattr__(self, key): 62 | name = self._name + '.' + key if self._name else key 63 | result = js_exec(''' 64 | let object = {0}; 65 | if (object && object.constructor === Promise) { 66 | object.then((object) => global.mpjscache['{0}'] = object); 67 | return 'mpjspromiseobject:{0}'; 68 | } 69 | try { 70 | if (object && [Array, Object, Number, String, Boolean, Function, AsyncFunction].indexOf(object.constructor) < 0) throw Error('Not JSON Serializable'); 71 | if (object && object.constructor === Object) for (let key in Object.keys(object)) { 72 | if (object.indexOf(key) < 0) throw Error('Not a JSON'); 73 | } 74 | else if (object && (object.constructor === Function || object.constructor === AsyncFunction)) { 75 | delete global.mpjscache['{0}']; 76 | return 'mpjsfunctionobject:{0}'; 77 | } 78 | return object; 79 | } 80 | catch(error) { 81 | return 'mpjsjavascriptobject:{0}'; 82 | } 83 | ''', name) 84 | if type(result) != str: return result 85 | types = {'promise': JSPromise, 'function': JSFunction, 'javascript': JSObject} 86 | for object_type in types: 87 | if 'mpjs' + object_type + 'object' in result: 88 | result = types[object_type](result.split(':')[1]) 89 | break 90 | return result 91 | 92 | def __setattr__(self, key, value): 93 | if not self._name: return 94 | value = json.dumps(value) 95 | object_name = self._name + '.' + key 96 | js_exec(''' 97 | {0} = {1}; 98 | ''', object_name, value) 99 | 100 | def JSFunction(name): 101 | short_name = name.split('.')[-1] 102 | def function(*args): 103 | args = json.dumps(list(args)) 104 | cache_name = 'global.mpjscache' + ('.' + name if '.' not in name else json.dumps([name])) 105 | result = js_exec(''' 106 | let object; 107 | if (global.mpjscache['{0}']) { 108 | object = global.mpjscache['{0}'](...{1}); 109 | } 110 | else if ({0}) { 111 | object = {0}(...{1}); 112 | } 113 | global.mpjscache['{0}'] = object; 114 | if (object && object.constructor === Promise) { 115 | object.then((object) => global.mpjscache['{0}'] = object); 116 | return 'mpjspromiseobject'; 117 | } 118 | try { 119 | if (object && [Array, Object, Number, String, Boolean, Function, AsyncFunction].indexOf(object.constructor) < 0) throw Error('Not JSON Serializable'); 120 | if (object && object.constructor === Object) for (let key in Object.keys(object)) { 121 | if (object.indexOf(key) < 0) throw Error('Not a JSON'); 122 | } 123 | else if (object && (object.constructor === Function || object.constructor === AsyncFunction)) { 124 | return 'mpjsfunctionobject'; 125 | } 126 | return object; 127 | } 128 | catch(error) { 129 | return 'mpjsjavascriptobject'; 130 | } 131 | ''', name, args) 132 | if type(result) != str: return result 133 | types = {'promise': JSPromise, 'function': JSFunction, 'javascript': JSObject} 134 | for object_type in types: 135 | if 'mpjs' + object_type + 'object' in result: 136 | result = types[object_type](cache_name) 137 | break 138 | return result 139 | return function 140 | 141 | def JS(variable): 142 | empty = JSObject('') 143 | return getattr(empty, variable) 144 | 145 | #require = JS('require') 146 | #result = require('fs').readFileSync('./test.js').toString() 147 | #print(result) 148 | 149 | #New API promise.wait(), now works without skipping event loop using emscripten_sleep, requires emterpreter 150 | 151 | #require = JS('require') 152 | #response = require('node-fetch')('https://github.com/').wait() 153 | #print(response) 154 | #result = response.text().wait() 155 | #print(result) 156 | -------------------------------------------------------------------------------- /lib/firmware.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafi16jan/micropython-wasm/74d3da30dd9baa39aa1429bb1548d49b7a1662e1/lib/firmware.wasm -------------------------------------------------------------------------------- /lib/micropython.binary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rafi16jan/micropython-wasm/74d3da30dd9baa39aa1429bb1548d49b7a1662e1/lib/micropython.binary -------------------------------------------------------------------------------- /lib/micropython.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2017, 2018 Rami Ali 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | var Module = {}; 28 | 29 | var mainProgram = function() 30 | { 31 | mp_js_init = Module.cwrap('mp_js_init', 'null', ['number']); 32 | mp_js_do_str = Module.cwrap('mp_js_do_str', 'number', ['string'], {async: true}); 33 | mp_js_init_repl = Module.cwrap('mp_js_init_repl', 'null', ['null']); 34 | mp_js_process_char = Module.cwrap('mp_js_process_char', 'number', ['number']); 35 | 36 | MP_JS_EPOCH = (new Date()).getTime(); 37 | 38 | if (typeof window === 'undefined' && require.main === module) { 39 | var fs = require('fs'); 40 | var stack_size = 64 * 1024; 41 | var contents = ''; 42 | var repl = true; 43 | 44 | for (var i = 0; i < process.argv.length; i++) { 45 | if (process.argv[i] === '-X' && i < process.argv.length - 1) { 46 | if (process.argv[i + 1].includes('stack=')) { 47 | stack_size = parseInt(process.argv[i + 1].split('stack=')[1]); 48 | if (process.argv[i + 1].substr(-1).toLowerCase() === 'k') { 49 | stack_size *= 1024; 50 | } else if (process.argv[i + 1].substr(-1).toLowerCase() === 'm') { 51 | stack_size *= 1024 * 1024; 52 | } 53 | } 54 | } else if (process.argv[i].includes('.py')) { 55 | contents += fs.readFileSync(process.argv[i], 'utf8'); 56 | repl = false;; 57 | } 58 | } 59 | mp_js_init(stack_size); 60 | 61 | if (repl) { 62 | mp_js_init_repl(); 63 | process.stdin.setRawMode(true); 64 | process.stdin.on('data', function (data) { 65 | for (var i = 0; i < data.length; i++) { 66 | if (mp_js_process_char(data[i])) { 67 | process.exit() 68 | } 69 | } 70 | }); 71 | } else { 72 | process.exitCode = mp_js_do_str(contents); 73 | } 74 | } 75 | } 76 | 77 | Module["onRuntimeInitialized"] = mainProgram; 78 | 79 | if (typeof webpackJsonp !== 'object') { 80 | const fs = require('fs') 81 | const path = require('path') 82 | console.log(fs) 83 | const file = fs.readFileSync(__dirname + '/micropython.binary'); 84 | Module.emterpreterFile = file.buffer.slice(file.byteOffset, file.byteOffset + file.byteLength); 85 | } 86 | else { 87 | Module.emterpreterFile = require('!arraybuffer-loader!' + './micropython.binary'); 88 | } 89 | // Copyright 2010 The Emscripten Authors. All rights reserved. 90 | // Emscripten is available under two separate licenses, the MIT license and the 91 | // University of Illinois/NCSA Open Source License. Both these licenses can be 92 | // found in the LICENSE file. 93 | 94 | // The Module object: Our interface to the outside world. We import 95 | // and export values on it. There are various ways Module can be used: 96 | // 1. Not defined. We create it here 97 | // 2. A function parameter, function(Module) { ..generated code.. } 98 | // 3. pre-run appended it, var Module = {}; ..generated code.. 99 | // 4. External script tag defines var Module. 100 | // We need to check if Module already exists (e.g. case 3 above). 101 | // Substitution will be replaced with actual code on later stage of the build, 102 | // this way Closure Compiler will not mangle it (e.g. case 4. above). 103 | // Note that if you want to run closure, and also to use Module 104 | // after the generated code, you will need to define var Module = {}; 105 | // before the code. Then that object will be used in the code, and you 106 | // can continue to use Module afterwards as well. 107 | var Module = typeof Module !== 'undefined' ? Module : {}; 108 | 109 | // --pre-jses are emitted after the Module integration code, so that they can 110 | // refer to Module (if they choose; they can also define Module) 111 | // {{PRE_JSES}} 112 | 113 | // Sometimes an existing Module object exists with properties 114 | // meant to overwrite the default module functionality. Here 115 | // we collect those properties and reapply _after_ we configure 116 | // the current environment's defaults to avoid having to be so 117 | // defensive during initialization. 118 | var moduleOverrides = {}; 119 | var key; 120 | for (key in Module) { 121 | if (Module.hasOwnProperty(key)) { 122 | moduleOverrides[key] = Module[key]; 123 | } 124 | } 125 | 126 | Module['arguments'] = []; 127 | Module['thisProgram'] = './this.program'; 128 | Module['quit'] = function(status, toThrow) { 129 | throw toThrow; 130 | }; 131 | Module['preRun'] = []; 132 | Module['postRun'] = []; 133 | 134 | // Determine the runtime environment we are in. You can customize this by 135 | // setting the ENVIRONMENT setting at compile time (see settings.js). 136 | 137 | var ENVIRONMENT_IS_WEB = false; 138 | var ENVIRONMENT_IS_WORKER = false; 139 | var ENVIRONMENT_IS_NODE = false; 140 | var ENVIRONMENT_IS_SHELL = false; 141 | ENVIRONMENT_IS_WEB = typeof window === 'object'; 142 | ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; 143 | ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; 144 | ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; 145 | 146 | if (Module['ENVIRONMENT']) { 147 | throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)'); 148 | } 149 | 150 | 151 | // Three configurations we can be running in: 152 | // 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) 153 | // 2) We could be the application main() thread proxied to worker. (with Emscripten -s PROXY_TO_WORKER=1) (ENVIRONMENT_IS_WORKER == true, ENVIRONMENT_IS_PTHREAD == false) 154 | // 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) 155 | 156 | 157 | 158 | 159 | // `/` should be present at the end if `scriptDirectory` is not empty 160 | var scriptDirectory = ''; 161 | function locateFile(path) { 162 | if (Module['locateFile']) { 163 | return Module['locateFile'](path, scriptDirectory); 164 | } else { 165 | return scriptDirectory + path; 166 | } 167 | } 168 | 169 | if (ENVIRONMENT_IS_NODE) { 170 | scriptDirectory = __dirname + '/'; 171 | 172 | // Expose functionality in the same simple way that the shells work 173 | // Note that we pollute the global namespace here, otherwise we break in node 174 | var nodeFS; 175 | var nodePath; 176 | 177 | Module['read'] = function shell_read(filename, binary) { 178 | var ret; 179 | if (!nodeFS) nodeFS = require('fs'); 180 | if (!nodePath) nodePath = require('path'); 181 | filename = nodePath['normalize'](filename); 182 | ret = nodeFS['readFileSync'](filename); 183 | return binary ? ret : ret.toString(); 184 | }; 185 | 186 | Module['readBinary'] = function readBinary(filename) { 187 | var ret = Module['read'](filename, true); 188 | if (!ret.buffer) { 189 | ret = new Uint8Array(ret); 190 | } 191 | assert(ret.buffer); 192 | return ret; 193 | }; 194 | 195 | if (process['argv'].length > 1) { 196 | Module['thisProgram'] = process['argv'][1].replace(/\\/g, '/'); 197 | } 198 | 199 | Module['arguments'] = process['argv'].slice(2); 200 | 201 | if (typeof module !== 'undefined') { 202 | module['exports'] = Module; 203 | } 204 | 205 | process['on']('uncaughtException', function(ex) { 206 | // suppress ExitStatus exceptions from showing an error 207 | if (!(ex instanceof ExitStatus)) { 208 | throw ex; 209 | } 210 | }); 211 | // Currently node will swallow unhandled rejections, but this behavior is 212 | // deprecated, and in the future it will exit with error status. 213 | process['on']('unhandledRejection', abort); 214 | 215 | Module['quit'] = function(status) { 216 | process['exit'](status); 217 | }; 218 | 219 | Module['inspect'] = function () { return '[Emscripten Module object]'; }; 220 | } else 221 | if (ENVIRONMENT_IS_SHELL) { 222 | 223 | 224 | if (typeof read != 'undefined') { 225 | Module['read'] = function shell_read(f) { 226 | return read(f); 227 | }; 228 | } 229 | 230 | Module['readBinary'] = function readBinary(f) { 231 | var data; 232 | if (typeof readbuffer === 'function') { 233 | return new Uint8Array(readbuffer(f)); 234 | } 235 | data = read(f, 'binary'); 236 | assert(typeof data === 'object'); 237 | return data; 238 | }; 239 | 240 | if (typeof scriptArgs != 'undefined') { 241 | Module['arguments'] = scriptArgs; 242 | } else if (typeof arguments != 'undefined') { 243 | Module['arguments'] = arguments; 244 | } 245 | 246 | if (typeof quit === 'function') { 247 | Module['quit'] = function(status) { 248 | quit(status); 249 | } 250 | } 251 | } else 252 | if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { 253 | if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled 254 | scriptDirectory = self.location.href; 255 | } else if (document.currentScript) { // web 256 | scriptDirectory = document.currentScript.src; 257 | } 258 | // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them. 259 | // otherwise, slice off the final part of the url to find the script directory. 260 | // if scriptDirectory does not contain a slash, lastIndexOf will return -1, 261 | // and scriptDirectory will correctly be replaced with an empty string. 262 | if (scriptDirectory.indexOf('blob:') !== 0) { 263 | scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1); 264 | } else { 265 | scriptDirectory = ''; 266 | } 267 | 268 | 269 | Module['read'] = function shell_read(url) { 270 | var xhr = new XMLHttpRequest(); 271 | xhr.open('GET', url, false); 272 | xhr.send(null); 273 | return xhr.responseText; 274 | }; 275 | 276 | if (ENVIRONMENT_IS_WORKER) { 277 | Module['readBinary'] = function readBinary(url) { 278 | var xhr = new XMLHttpRequest(); 279 | xhr.open('GET', url, false); 280 | xhr.responseType = 'arraybuffer'; 281 | xhr.send(null); 282 | return new Uint8Array(xhr.response); 283 | }; 284 | } 285 | 286 | Module['readAsync'] = function readAsync(url, onload, onerror) { 287 | var xhr = new XMLHttpRequest(); 288 | xhr.open('GET', url, true); 289 | xhr.responseType = 'arraybuffer'; 290 | xhr.onload = function xhr_onload() { 291 | if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 292 | onload(xhr.response); 293 | return; 294 | } 295 | onerror(); 296 | }; 297 | xhr.onerror = onerror; 298 | xhr.send(null); 299 | }; 300 | 301 | Module['setWindowTitle'] = function(title) { document.title = title }; 302 | } else 303 | { 304 | throw new Error('environment detection error'); 305 | } 306 | 307 | // Set up the out() and err() hooks, which are how we can print to stdout or 308 | // stderr, respectively. 309 | // If the user provided Module.print or printErr, use that. Otherwise, 310 | // console.log is checked first, as 'print' on the web will open a print dialogue 311 | // printErr is preferable to console.warn (works better in shells) 312 | // bind(console) is necessary to fix IE/Edge closed dev tools panel behavior. 313 | var out = Module['print'] || (typeof console !== 'undefined' ? console.log.bind(console) : (typeof print !== 'undefined' ? print : null)); 314 | var err = Module['printErr'] || (typeof printErr !== 'undefined' ? printErr : ((typeof console !== 'undefined' && console.warn.bind(console)) || out)); 315 | 316 | // Merge back in the overrides 317 | for (key in moduleOverrides) { 318 | if (moduleOverrides.hasOwnProperty(key)) { 319 | Module[key] = moduleOverrides[key]; 320 | } 321 | } 322 | // Free the object hierarchy contained in the overrides, this lets the GC 323 | // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. 324 | moduleOverrides = undefined; 325 | 326 | // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message 327 | assert(typeof Module['memoryInitializerPrefixURL'] === 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead'); 328 | assert(typeof Module['pthreadMainPrefixURL'] === 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead'); 329 | assert(typeof Module['cdInitializerPrefixURL'] === 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead'); 330 | assert(typeof Module['filePackagePrefixURL'] === 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead'); 331 | 332 | 333 | 334 | // Copyright 2017 The Emscripten Authors. All rights reserved. 335 | // Emscripten is available under two separate licenses, the MIT license and the 336 | // University of Illinois/NCSA Open Source License. Both these licenses can be 337 | // found in the LICENSE file. 338 | 339 | // {{PREAMBLE_ADDITIONS}} 340 | 341 | var STACK_ALIGN = 16; 342 | 343 | // stack management, and other functionality that is provided by the compiled code, 344 | // should not be used before it is ready 345 | stackSave = stackRestore = stackAlloc = function() { 346 | abort('cannot use the stack before compiled code is ready to run, and has provided stack access'); 347 | }; 348 | 349 | function staticAlloc(size) { 350 | abort('staticAlloc is no longer available at runtime; instead, perform static allocations at compile time (using makeStaticAlloc)'); 351 | } 352 | 353 | function dynamicAlloc(size) { 354 | assert(DYNAMICTOP_PTR); 355 | var ret = HEAP32[DYNAMICTOP_PTR>>2]; 356 | var end = (ret + size + 15) & -16; 357 | if (end <= _emscripten_get_heap_size()) { 358 | HEAP32[DYNAMICTOP_PTR>>2] = end; 359 | } else { 360 | return 0; 361 | } 362 | return ret; 363 | } 364 | 365 | function alignMemory(size, factor) { 366 | if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default 367 | return Math.ceil(size / factor) * factor; 368 | } 369 | 370 | function getNativeTypeSize(type) { 371 | switch (type) { 372 | case 'i1': case 'i8': return 1; 373 | case 'i16': return 2; 374 | case 'i32': return 4; 375 | case 'i64': return 8; 376 | case 'float': return 4; 377 | case 'double': return 8; 378 | default: { 379 | if (type[type.length-1] === '*') { 380 | return 4; // A pointer 381 | } else if (type[0] === 'i') { 382 | var bits = parseInt(type.substr(1)); 383 | assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); 384 | return bits / 8; 385 | } else { 386 | return 0; 387 | } 388 | } 389 | } 390 | } 391 | 392 | function warnOnce(text) { 393 | if (!warnOnce.shown) warnOnce.shown = {}; 394 | if (!warnOnce.shown[text]) { 395 | warnOnce.shown[text] = 1; 396 | err(text); 397 | } 398 | } 399 | 400 | var asm2wasmImports = { // special asm2wasm imports 401 | "f64-rem": function(x, y) { 402 | return x % y; 403 | }, 404 | "debugger": function() { 405 | debugger; 406 | } 407 | }; 408 | 409 | 410 | 411 | var jsCallStartIndex = 1; 412 | var functionPointers = new Array(0); 413 | 414 | // Wraps a JS function as a wasm function with a given signature. 415 | // In the future, we may get a WebAssembly.Function constructor. Until then, 416 | // we create a wasm module that takes the JS function as an import with a given 417 | // signature, and re-exports that as a wasm function. 418 | function convertJsFunctionToWasm(func, sig) { 419 | // The module is static, with the exception of the type section, which is 420 | // generated based on the signature passed in. 421 | var typeSection = [ 422 | 0x01, // id: section, 423 | 0x00, // length: 0 (placeholder) 424 | 0x01, // count: 1 425 | 0x60, // form: func 426 | ]; 427 | var sigRet = sig.slice(0, 1); 428 | var sigParam = sig.slice(1); 429 | var typeCodes = { 430 | 'i': 0x7f, // i32 431 | 'j': 0x7e, // i64 432 | 'f': 0x7d, // f32 433 | 'd': 0x7c, // f64 434 | }; 435 | 436 | // Parameters, length + signatures 437 | typeSection.push(sigParam.length); 438 | for (var i = 0; i < sigParam.length; ++i) { 439 | typeSection.push(typeCodes[sigParam[i]]); 440 | } 441 | 442 | // Return values, length + signatures 443 | // With no multi-return in MVP, either 0 (void) or 1 (anything else) 444 | if (sigRet == 'v') { 445 | typeSection.push(0x00); 446 | } else { 447 | typeSection = typeSection.concat([0x01, typeCodes[sigRet]]); 448 | } 449 | 450 | // Write the overall length of the type section back into the section header 451 | // (excepting the 2 bytes for the section id and length) 452 | typeSection[1] = typeSection.length - 2; 453 | 454 | // Rest of the module is static 455 | var bytes = new Uint8Array([ 456 | 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") 457 | 0x01, 0x00, 0x00, 0x00, // version: 1 458 | ].concat(typeSection, [ 459 | 0x02, 0x07, // import section 460 | // (import "e" "f" (func 0 (type 0))) 461 | 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00, 462 | 0x07, 0x05, // export section 463 | // (export "f" (func 0 (type 0))) 464 | 0x01, 0x01, 0x66, 0x00, 0x00, 465 | ])); 466 | 467 | // We can compile this wasm module synchronously because it is very small. 468 | // This accepts an import (at "e.f"), that it reroutes to an export (at "f") 469 | var module = new WebAssembly.Module(bytes); 470 | var instance = new WebAssembly.Instance(module, { 471 | e: { 472 | f: func 473 | } 474 | }); 475 | var wrappedFunc = instance.exports.f; 476 | return wrappedFunc; 477 | } 478 | 479 | // Add a wasm function to the table. 480 | function addFunctionWasm(func, sig) { 481 | var table = wasmTable; 482 | var ret = table.length; 483 | 484 | // Grow the table 485 | try { 486 | table.grow(1); 487 | } catch (err) { 488 | if (!err instanceof RangeError) { 489 | throw err; 490 | } 491 | throw 'Unable to grow wasm table. Use a higher value for RESERVED_FUNCTION_POINTERS or set ALLOW_TABLE_GROWTH.'; 492 | } 493 | 494 | // Insert new element 495 | try { 496 | // Attempting to call this with JS function will cause of table.set() to fail 497 | table.set(ret, func); 498 | } catch (err) { 499 | if (!err instanceof TypeError) { 500 | throw err; 501 | } 502 | assert(typeof sig !== 'undefined', 'Missing signature argument to addFunction'); 503 | var wrapped = convertJsFunctionToWasm(func, sig); 504 | table.set(ret, wrapped); 505 | } 506 | 507 | return ret; 508 | } 509 | 510 | function removeFunctionWasm(index) { 511 | // TODO(sbc): Look into implementing this to allow re-using of table slots 512 | } 513 | 514 | // 'sig' parameter is required for the llvm backend but only when func is not 515 | // already a WebAssembly function. 516 | function addFunction(func, sig) { 517 | 518 | 519 | var base = 0; 520 | for (var i = base; i < base + 0; i++) { 521 | if (!functionPointers[i]) { 522 | functionPointers[i] = func; 523 | return jsCallStartIndex + i; 524 | } 525 | } 526 | throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; 527 | 528 | } 529 | 530 | function removeFunction(index) { 531 | 532 | functionPointers[index-jsCallStartIndex] = null; 533 | } 534 | 535 | var funcWrappers = {}; 536 | 537 | function getFuncWrapper(func, sig) { 538 | if (!func) return; // on null pointer, return undefined 539 | assert(sig); 540 | if (!funcWrappers[sig]) { 541 | funcWrappers[sig] = {}; 542 | } 543 | var sigCache = funcWrappers[sig]; 544 | if (!sigCache[func]) { 545 | // optimize away arguments usage in common cases 546 | if (sig.length === 1) { 547 | sigCache[func] = function dynCall_wrapper() { 548 | return dynCall(sig, func); 549 | }; 550 | } else if (sig.length === 2) { 551 | sigCache[func] = function dynCall_wrapper(arg) { 552 | return dynCall(sig, func, [arg]); 553 | }; 554 | } else { 555 | // general case 556 | sigCache[func] = function dynCall_wrapper() { 557 | return dynCall(sig, func, Array.prototype.slice.call(arguments)); 558 | }; 559 | } 560 | } 561 | return sigCache[func]; 562 | } 563 | 564 | 565 | function makeBigInt(low, high, unsigned) { 566 | return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0)); 567 | } 568 | 569 | function dynCall(sig, ptr, args) { 570 | if (args && args.length) { 571 | assert(args.length == sig.length-1); 572 | assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\''); 573 | return Module['dynCall_' + sig].apply(null, [ptr].concat(args)); 574 | } else { 575 | assert(sig.length == 1); 576 | assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\''); 577 | return Module['dynCall_' + sig].call(null, ptr); 578 | } 579 | } 580 | 581 | var tempRet0 = 0; 582 | 583 | var setTempRet0 = function(value) { 584 | tempRet0 = value; 585 | } 586 | 587 | var getTempRet0 = function() { 588 | return tempRet0; 589 | } 590 | 591 | function getCompilerSetting(name) { 592 | throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for getCompilerSetting or emscripten_get_compiler_setting to work'; 593 | } 594 | 595 | var Runtime = { 596 | // helpful errors 597 | getTempRet0: function() { abort('getTempRet0() is now a top-level function, after removing the Runtime object. Remove "Runtime."') }, 598 | staticAlloc: function() { abort('staticAlloc() is now a top-level function, after removing the Runtime object. Remove "Runtime."') }, 599 | stackAlloc: function() { abort('stackAlloc() is now a top-level function, after removing the Runtime object. Remove "Runtime."') }, 600 | }; 601 | 602 | // The address globals begin at. Very low in memory, for code size and optimization opportunities. 603 | // Above 0 is static memory, starting with globals. 604 | // Then the stack. 605 | // Then 'dynamic' memory for sbrk. 606 | var GLOBAL_BASE = 1024; 607 | 608 | 609 | 610 | 611 | // === Preamble library stuff === 612 | 613 | // Documentation for the public APIs defined in this file must be updated in: 614 | // site/source/docs/api_reference/preamble.js.rst 615 | // A prebuilt local version of the documentation is available at: 616 | // site/build/text/docs/api_reference/preamble.js.txt 617 | // You can also build docs locally as HTML or other formats in site/ 618 | // An online HTML version (which may be of a different version of Emscripten) 619 | // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html 620 | 621 | 622 | if (typeof WebAssembly !== 'object') { 623 | abort('No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.'); 624 | } 625 | 626 | 627 | /** @type {function(number, string, boolean=)} */ 628 | function getValue(ptr, type, noSafe) { 629 | type = type || 'i8'; 630 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit 631 | switch(type) { 632 | case 'i1': return HEAP8[((ptr)>>0)]; 633 | case 'i8': return HEAP8[((ptr)>>0)]; 634 | case 'i16': return HEAP16[((ptr)>>1)]; 635 | case 'i32': return HEAP32[((ptr)>>2)]; 636 | case 'i64': return HEAP32[((ptr)>>2)]; 637 | case 'float': return HEAPF32[((ptr)>>2)]; 638 | case 'double': return HEAPF64[((ptr)>>3)]; 639 | default: abort('invalid type for getValue: ' + type); 640 | } 641 | return null; 642 | } 643 | 644 | 645 | 646 | 647 | // Wasm globals 648 | 649 | var wasmMemory; 650 | 651 | // Potentially used for direct table calls. 652 | var wasmTable; 653 | 654 | 655 | //======================================== 656 | // Runtime essentials 657 | //======================================== 658 | 659 | // whether we are quitting the application. no code should run after this. 660 | // set in exit() and abort() 661 | var ABORT = false; 662 | 663 | // set by exit() and abort(). Passed to 'onExit' handler. 664 | // NOTE: This is also used as the process return code code in shell environments 665 | // but only when noExitRuntime is false. 666 | var EXITSTATUS = 0; 667 | 668 | /** @type {function(*, string=)} */ 669 | function assert(condition, text) { 670 | if (!condition) { 671 | abort('Assertion failed: ' + text); 672 | } 673 | } 674 | 675 | // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) 676 | function getCFunc(ident) { 677 | var func = Module['_' + ident]; // closure exported function 678 | assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); 679 | return func; 680 | } 681 | 682 | // C calling interface. 683 | function ccall(ident, returnType, argTypes, args, opts) { 684 | // For fast lookup of conversion functions 685 | var toC = { 686 | 'string': function(str) { 687 | var ret = 0; 688 | if (str !== null && str !== undefined && str !== 0) { // null string 689 | // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' 690 | var len = (str.length << 2) + 1; 691 | ret = stackAlloc(len); 692 | stringToUTF8(str, ret, len); 693 | } 694 | return ret; 695 | }, 696 | 'array': function(arr) { 697 | var ret = stackAlloc(arr.length); 698 | writeArrayToMemory(arr, ret); 699 | return ret; 700 | } 701 | }; 702 | 703 | function convertReturnValue(ret) { 704 | if (returnType === 'string') return UTF8ToString(ret); 705 | if (returnType === 'boolean') return Boolean(ret); 706 | return ret; 707 | } 708 | 709 | var func = getCFunc(ident); 710 | var cArgs = []; 711 | var stack = 0; 712 | assert(returnType !== 'array', 'Return type should not be "array".'); 713 | if (args) { 714 | for (var i = 0; i < args.length; i++) { 715 | var converter = toC[argTypes[i]]; 716 | if (converter) { 717 | if (stack === 0) stack = stackSave(); 718 | cArgs[i] = converter(args[i]); 719 | } else { 720 | cArgs[i] = args[i]; 721 | } 722 | } 723 | } 724 | var ret = func.apply(null, cArgs); 725 | if (typeof EmterpreterAsync === 'object' && EmterpreterAsync.state) { 726 | assert(opts && opts.async, 'The call to ' + ident + ' is running asynchronously. If this was intended, add the async option to the ccall/cwrap call.'); 727 | assert(!EmterpreterAsync.restartFunc, 'Cannot have multiple async ccalls in flight at once'); 728 | return new Promise(function(resolve) { 729 | EmterpreterAsync.restartFunc = func; 730 | EmterpreterAsync.asyncFinalizers.push(function(ret) { 731 | if (stack !== 0) stackRestore(stack); 732 | resolve(convertReturnValue(ret)); 733 | }); 734 | }); 735 | } 736 | ret = convertReturnValue(ret); 737 | if (stack !== 0) stackRestore(stack); 738 | // If this is an async ccall, ensure we return a promise 739 | if (opts && opts.async) return Promise.resolve(ret); 740 | return ret; 741 | } 742 | 743 | function cwrap(ident, returnType, argTypes, opts) { 744 | return function() { 745 | return ccall(ident, returnType, argTypes, arguments, opts); 746 | } 747 | } 748 | 749 | /** @type {function(number, number, string, boolean=)} */ 750 | function setValue(ptr, value, type, noSafe) { 751 | type = type || 'i8'; 752 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit 753 | switch(type) { 754 | case 'i1': HEAP8[((ptr)>>0)]=value; break; 755 | case 'i8': HEAP8[((ptr)>>0)]=value; break; 756 | case 'i16': HEAP16[((ptr)>>1)]=value; break; 757 | case 'i32': HEAP32[((ptr)>>2)]=value; break; 758 | case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; 759 | case 'float': HEAPF32[((ptr)>>2)]=value; break; 760 | case 'double': HEAPF64[((ptr)>>3)]=value; break; 761 | default: abort('invalid type for setValue: ' + type); 762 | } 763 | } 764 | 765 | var ALLOC_NORMAL = 0; // Tries to use _malloc() 766 | var ALLOC_STACK = 1; // Lives for the duration of the current function call 767 | var ALLOC_DYNAMIC = 2; // Cannot be freed except through sbrk 768 | var ALLOC_NONE = 3; // Do not allocate 769 | 770 | // allocate(): This is for internal use. You can use it yourself as well, but the interface 771 | // is a little tricky (see docs right below). The reason is that it is optimized 772 | // for multiple syntaxes to save space in generated code. So you should 773 | // normally not use allocate(), and instead allocate memory using _malloc(), 774 | // initialize it with setValue(), and so forth. 775 | // @slab: An array of data, or a number. If a number, then the size of the block to allocate, 776 | // in *bytes* (note that this is sometimes confusing: the next parameter does not 777 | // affect this!) 778 | // @types: Either an array of types, one for each byte (or 0 if no type at that position), 779 | // or a single type which is used for the entire block. This only matters if there 780 | // is initial data - if @slab is a number, then this does not matter at all and is 781 | // ignored. 782 | // @allocator: How to allocate memory, see ALLOC_* 783 | /** @type {function((TypedArray|Array|number), string, number, number=)} */ 784 | function allocate(slab, types, allocator, ptr) { 785 | var zeroinit, size; 786 | if (typeof slab === 'number') { 787 | zeroinit = true; 788 | size = slab; 789 | } else { 790 | zeroinit = false; 791 | size = slab.length; 792 | } 793 | 794 | var singleType = typeof types === 'string' ? types : null; 795 | 796 | var ret; 797 | if (allocator == ALLOC_NONE) { 798 | ret = ptr; 799 | } else { 800 | ret = [_malloc, 801 | stackAlloc, 802 | dynamicAlloc][allocator](Math.max(size, singleType ? 1 : types.length)); 803 | } 804 | 805 | if (zeroinit) { 806 | var stop; 807 | ptr = ret; 808 | assert((ret & 3) == 0); 809 | stop = ret + (size & ~3); 810 | for (; ptr < stop; ptr += 4) { 811 | HEAP32[((ptr)>>2)]=0; 812 | } 813 | stop = ret + size; 814 | while (ptr < stop) { 815 | HEAP8[((ptr++)>>0)]=0; 816 | } 817 | return ret; 818 | } 819 | 820 | if (singleType === 'i8') { 821 | if (slab.subarray || slab.slice) { 822 | HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret); 823 | } else { 824 | HEAPU8.set(new Uint8Array(slab), ret); 825 | } 826 | return ret; 827 | } 828 | 829 | var i = 0, type, typeSize, previousType; 830 | while (i < size) { 831 | var curr = slab[i]; 832 | 833 | type = singleType || types[i]; 834 | if (type === 0) { 835 | i++; 836 | continue; 837 | } 838 | assert(type, 'Must know what type to store in allocate!'); 839 | 840 | if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later 841 | 842 | setValue(ret+i, curr, type); 843 | 844 | // no need to look up size unless type changes, so cache it 845 | if (previousType !== type) { 846 | typeSize = getNativeTypeSize(type); 847 | previousType = type; 848 | } 849 | i += typeSize; 850 | } 851 | 852 | return ret; 853 | } 854 | 855 | // Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready 856 | function getMemory(size) { 857 | if (!runtimeInitialized) return dynamicAlloc(size); 858 | return _malloc(size); 859 | } 860 | 861 | 862 | 863 | 864 | /** @type {function(number, number=)} */ 865 | function Pointer_stringify(ptr, length) { 866 | abort("this function has been removed - you should use UTF8ToString(ptr, maxBytesToRead) instead!"); 867 | } 868 | 869 | // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns 870 | // a copy of that string as a Javascript String object. 871 | 872 | function AsciiToString(ptr) { 873 | var str = ''; 874 | while (1) { 875 | var ch = HEAPU8[((ptr++)>>0)]; 876 | if (!ch) return str; 877 | str += String.fromCharCode(ch); 878 | } 879 | } 880 | 881 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 882 | // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP. 883 | 884 | function stringToAscii(str, outPtr) { 885 | return writeAsciiToMemory(str, outPtr, false); 886 | } 887 | 888 | 889 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns 890 | // a copy of that string as a Javascript String object. 891 | 892 | var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined; 893 | 894 | /** 895 | * @param {number} idx 896 | * @param {number=} maxBytesToRead 897 | * @return {string} 898 | */ 899 | function UTF8ArrayToString(u8Array, idx, maxBytesToRead) { 900 | var endIdx = idx + maxBytesToRead; 901 | var endPtr = idx; 902 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 903 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 904 | // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity) 905 | while (u8Array[endPtr] && !(endPtr >= endIdx)) ++endPtr; 906 | 907 | if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { 908 | return UTF8Decoder.decode(u8Array.subarray(idx, endPtr)); 909 | } else { 910 | var str = ''; 911 | // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that 912 | while (idx < endPtr) { 913 | // For UTF8 byte structure, see: 914 | // http://en.wikipedia.org/wiki/UTF-8#Description 915 | // https://www.ietf.org/rfc/rfc2279.txt 916 | // https://tools.ietf.org/html/rfc3629 917 | var u0 = u8Array[idx++]; 918 | if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } 919 | var u1 = u8Array[idx++] & 63; 920 | if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } 921 | var u2 = u8Array[idx++] & 63; 922 | if ((u0 & 0xF0) == 0xE0) { 923 | u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; 924 | } else { 925 | if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!'); 926 | u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (u8Array[idx++] & 63); 927 | } 928 | 929 | if (u0 < 0x10000) { 930 | str += String.fromCharCode(u0); 931 | } else { 932 | var ch = u0 - 0x10000; 933 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 934 | } 935 | } 936 | } 937 | return str; 938 | } 939 | 940 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a 941 | // copy of that string as a Javascript String object. 942 | // maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit 943 | // this parameter to scan the string until the first \0 byte. If maxBytesToRead is 944 | // passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the 945 | // middle, then the string will cut short at that byte index (i.e. maxBytesToRead will 946 | // not produce a string of exact length [ptr, ptr+maxBytesToRead[) 947 | // N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may 948 | // throw JS JIT optimizations off, so it is worth to consider consistently using one 949 | // style or the other. 950 | /** 951 | * @param {number} ptr 952 | * @param {number=} maxBytesToRead 953 | * @return {string} 954 | */ 955 | function UTF8ToString(ptr, maxBytesToRead) { 956 | return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; 957 | } 958 | 959 | // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', 960 | // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP. 961 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 962 | // Parameters: 963 | // str: the Javascript string to copy. 964 | // outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element. 965 | // outIdx: The starting offset in the array to begin the copying. 966 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. 967 | // This count should include the null terminator, 968 | // i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else. 969 | // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator. 970 | // Returns the number of bytes written, EXCLUDING the null terminator. 971 | 972 | function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { 973 | if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. 974 | return 0; 975 | 976 | var startIdx = outIdx; 977 | var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. 978 | for (var i = 0; i < str.length; ++i) { 979 | // 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. 980 | // See http://unicode.org/faq/utf_bom.html#utf16-3 981 | // 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 982 | var u = str.charCodeAt(i); // possibly a lead surrogate 983 | if (u >= 0xD800 && u <= 0xDFFF) { 984 | var u1 = str.charCodeAt(++i); 985 | u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF); 986 | } 987 | if (u <= 0x7F) { 988 | if (outIdx >= endIdx) break; 989 | outU8Array[outIdx++] = u; 990 | } else if (u <= 0x7FF) { 991 | if (outIdx + 1 >= endIdx) break; 992 | outU8Array[outIdx++] = 0xC0 | (u >> 6); 993 | outU8Array[outIdx++] = 0x80 | (u & 63); 994 | } else if (u <= 0xFFFF) { 995 | if (outIdx + 2 >= endIdx) break; 996 | outU8Array[outIdx++] = 0xE0 | (u >> 12); 997 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 998 | outU8Array[outIdx++] = 0x80 | (u & 63); 999 | } else { 1000 | if (outIdx + 3 >= endIdx) break; 1001 | if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).'); 1002 | outU8Array[outIdx++] = 0xF0 | (u >> 18); 1003 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 1004 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 1005 | outU8Array[outIdx++] = 0x80 | (u & 63); 1006 | } 1007 | } 1008 | // Null-terminate the pointer to the buffer. 1009 | outU8Array[outIdx] = 0; 1010 | return outIdx - startIdx; 1011 | } 1012 | 1013 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 1014 | // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP. 1015 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 1016 | // Returns the number of bytes written, EXCLUDING the null terminator. 1017 | 1018 | function stringToUTF8(str, outPtr, maxBytesToWrite) { 1019 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); 1020 | return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); 1021 | } 1022 | 1023 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. 1024 | function lengthBytesUTF8(str) { 1025 | var len = 0; 1026 | for (var i = 0; i < str.length; ++i) { 1027 | // 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. 1028 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1029 | var u = str.charCodeAt(i); // possibly a lead surrogate 1030 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 1031 | if (u <= 0x7F) ++len; 1032 | else if (u <= 0x7FF) len += 2; 1033 | else if (u <= 0xFFFF) len += 3; 1034 | else len += 4; 1035 | } 1036 | return len; 1037 | } 1038 | 1039 | 1040 | // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns 1041 | // a copy of that string as a Javascript String object. 1042 | 1043 | var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; 1044 | function UTF16ToString(ptr) { 1045 | assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!'); 1046 | var endPtr = ptr; 1047 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 1048 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 1049 | var idx = endPtr >> 1; 1050 | while (HEAP16[idx]) ++idx; 1051 | endPtr = idx << 1; 1052 | 1053 | if (endPtr - ptr > 32 && UTF16Decoder) { 1054 | return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); 1055 | } else { 1056 | var i = 0; 1057 | 1058 | var str = ''; 1059 | while (1) { 1060 | var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; 1061 | if (codeUnit == 0) return str; 1062 | ++i; 1063 | // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. 1064 | str += String.fromCharCode(codeUnit); 1065 | } 1066 | } 1067 | } 1068 | 1069 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 1070 | // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP. 1071 | // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write. 1072 | // Parameters: 1073 | // str: the Javascript string to copy. 1074 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 1075 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 1076 | // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else. 1077 | // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator. 1078 | // Returns the number of bytes written, EXCLUDING the null terminator. 1079 | 1080 | function stringToUTF16(str, outPtr, maxBytesToWrite) { 1081 | assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!'); 1082 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); 1083 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 1084 | if (maxBytesToWrite === undefined) { 1085 | maxBytesToWrite = 0x7FFFFFFF; 1086 | } 1087 | if (maxBytesToWrite < 2) return 0; 1088 | maxBytesToWrite -= 2; // Null terminator. 1089 | var startPtr = outPtr; 1090 | var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; 1091 | for (var i = 0; i < numCharsToWrite; ++i) { 1092 | // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. 1093 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 1094 | HEAP16[((outPtr)>>1)]=codeUnit; 1095 | outPtr += 2; 1096 | } 1097 | // Null-terminate the pointer to the HEAP. 1098 | HEAP16[((outPtr)>>1)]=0; 1099 | return outPtr - startPtr; 1100 | } 1101 | 1102 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 1103 | 1104 | function lengthBytesUTF16(str) { 1105 | return str.length*2; 1106 | } 1107 | 1108 | function UTF32ToString(ptr) { 1109 | assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!'); 1110 | var i = 0; 1111 | 1112 | var str = ''; 1113 | while (1) { 1114 | var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; 1115 | if (utf32 == 0) 1116 | return str; 1117 | ++i; 1118 | // 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. 1119 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1120 | if (utf32 >= 0x10000) { 1121 | var ch = utf32 - 0x10000; 1122 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 1123 | } else { 1124 | str += String.fromCharCode(utf32); 1125 | } 1126 | } 1127 | } 1128 | 1129 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 1130 | // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP. 1131 | // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write. 1132 | // Parameters: 1133 | // str: the Javascript string to copy. 1134 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 1135 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 1136 | // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else. 1137 | // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator. 1138 | // Returns the number of bytes written, EXCLUDING the null terminator. 1139 | 1140 | function stringToUTF32(str, outPtr, maxBytesToWrite) { 1141 | assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!'); 1142 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); 1143 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 1144 | if (maxBytesToWrite === undefined) { 1145 | maxBytesToWrite = 0x7FFFFFFF; 1146 | } 1147 | if (maxBytesToWrite < 4) return 0; 1148 | var startPtr = outPtr; 1149 | var endPtr = startPtr + maxBytesToWrite - 4; 1150 | for (var i = 0; i < str.length; ++i) { 1151 | // 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. 1152 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1153 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 1154 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { 1155 | var trailSurrogate = str.charCodeAt(++i); 1156 | codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); 1157 | } 1158 | HEAP32[((outPtr)>>2)]=codeUnit; 1159 | outPtr += 4; 1160 | if (outPtr + 4 > endPtr) break; 1161 | } 1162 | // Null-terminate the pointer to the HEAP. 1163 | HEAP32[((outPtr)>>2)]=0; 1164 | return outPtr - startPtr; 1165 | } 1166 | 1167 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 1168 | 1169 | function lengthBytesUTF32(str) { 1170 | var len = 0; 1171 | for (var i = 0; i < str.length; ++i) { 1172 | // 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. 1173 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1174 | var codeUnit = str.charCodeAt(i); 1175 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. 1176 | len += 4; 1177 | } 1178 | 1179 | return len; 1180 | } 1181 | 1182 | // Allocate heap space for a JS string, and write it there. 1183 | // It is the responsibility of the caller to free() that memory. 1184 | function allocateUTF8(str) { 1185 | var size = lengthBytesUTF8(str) + 1; 1186 | var ret = _malloc(size); 1187 | if (ret) stringToUTF8Array(str, HEAP8, ret, size); 1188 | return ret; 1189 | } 1190 | 1191 | // Allocate stack space for a JS string, and write it there. 1192 | function allocateUTF8OnStack(str) { 1193 | var size = lengthBytesUTF8(str) + 1; 1194 | var ret = stackAlloc(size); 1195 | stringToUTF8Array(str, HEAP8, ret, size); 1196 | return ret; 1197 | } 1198 | 1199 | // Deprecated: This function should not be called because it is unsafe and does not provide 1200 | // a maximum length limit of how many bytes it is allowed to write. Prefer calling the 1201 | // function stringToUTF8Array() instead, which takes in a maximum length that can be used 1202 | // to be secure from out of bounds writes. 1203 | /** @deprecated */ 1204 | function writeStringToMemory(string, buffer, dontAddNull) { 1205 | warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); 1206 | 1207 | var /** @type {number} */ lastChar, /** @type {number} */ end; 1208 | if (dontAddNull) { 1209 | // stringToUTF8Array always appends null. If we don't want to do that, remember the 1210 | // character that existed at the location where the null will be placed, and restore 1211 | // that after the write (below). 1212 | end = buffer + lengthBytesUTF8(string); 1213 | lastChar = HEAP8[end]; 1214 | } 1215 | stringToUTF8(string, buffer, Infinity); 1216 | if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. 1217 | } 1218 | 1219 | function writeArrayToMemory(array, buffer) { 1220 | assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)') 1221 | HEAP8.set(array, buffer); 1222 | } 1223 | 1224 | function writeAsciiToMemory(str, buffer, dontAddNull) { 1225 | for (var i = 0; i < str.length; ++i) { 1226 | assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff); 1227 | HEAP8[((buffer++)>>0)]=str.charCodeAt(i); 1228 | } 1229 | // Null-terminate the pointer to the HEAP. 1230 | if (!dontAddNull) HEAP8[((buffer)>>0)]=0; 1231 | } 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | function demangle(func) { 1238 | warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling'); 1239 | return func; 1240 | } 1241 | 1242 | function demangleAll(text) { 1243 | var regex = 1244 | /__Z[\w\d_]+/g; 1245 | return text.replace(regex, 1246 | function(x) { 1247 | var y = demangle(x); 1248 | return x === y ? x : (y + ' [' + x + ']'); 1249 | }); 1250 | } 1251 | 1252 | function jsStackTrace() { 1253 | var err = new Error(); 1254 | if (!err.stack) { 1255 | // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown, 1256 | // so try that as a special-case. 1257 | try { 1258 | throw new Error(0); 1259 | } catch(e) { 1260 | err = e; 1261 | } 1262 | if (!err.stack) { 1263 | return '(no stack trace available)'; 1264 | } 1265 | } 1266 | return err.stack.toString(); 1267 | } 1268 | 1269 | function stackTrace() { 1270 | var js = jsStackTrace(); 1271 | if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); 1272 | return demangleAll(js); 1273 | } 1274 | 1275 | 1276 | 1277 | // Memory management 1278 | 1279 | var PAGE_SIZE = 16384; 1280 | var WASM_PAGE_SIZE = 65536; 1281 | var ASMJS_PAGE_SIZE = 16777216; 1282 | 1283 | function alignUp(x, multiple) { 1284 | if (x % multiple > 0) { 1285 | x += multiple - (x % multiple); 1286 | } 1287 | return x; 1288 | } 1289 | 1290 | var HEAP, 1291 | /** @type {ArrayBuffer} */ 1292 | buffer, 1293 | /** @type {Int8Array} */ 1294 | HEAP8, 1295 | /** @type {Uint8Array} */ 1296 | HEAPU8, 1297 | /** @type {Int16Array} */ 1298 | HEAP16, 1299 | /** @type {Uint16Array} */ 1300 | HEAPU16, 1301 | /** @type {Int32Array} */ 1302 | HEAP32, 1303 | /** @type {Uint32Array} */ 1304 | HEAPU32, 1305 | /** @type {Float32Array} */ 1306 | HEAPF32, 1307 | /** @type {Float64Array} */ 1308 | HEAPF64; 1309 | 1310 | function updateGlobalBufferViews() { 1311 | Module['HEAP8'] = HEAP8 = new Int8Array(buffer); 1312 | Module['HEAP16'] = HEAP16 = new Int16Array(buffer); 1313 | Module['HEAP32'] = HEAP32 = new Int32Array(buffer); 1314 | Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer); 1315 | Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer); 1316 | Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer); 1317 | Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer); 1318 | Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer); 1319 | } 1320 | 1321 | 1322 | var STATIC_BASE = 1024, 1323 | STACK_BASE = 42896, 1324 | STACKTOP = STACK_BASE, 1325 | STACK_MAX = 5285776, 1326 | DYNAMIC_BASE = 5285776, 1327 | DYNAMICTOP_PTR = 42864; 1328 | 1329 | assert(STACK_BASE % 16 === 0, 'stack must start aligned'); 1330 | assert(DYNAMIC_BASE % 16 === 0, 'heap must start aligned'); 1331 | 1332 | 1333 | function abortStackOverflowEmterpreter() { 1334 | abort("Emterpreter stack overflow! Decrease the recursion level or increase EMT_STACK_MAX in tools/emterpretify.py (current value " + EMT_STACK_MAX + ")."); 1335 | } 1336 | 1337 | var TOTAL_STACK = 5242880; 1338 | if (Module['TOTAL_STACK']) assert(TOTAL_STACK === Module['TOTAL_STACK'], 'the stack size can no longer be determined at runtime') 1339 | 1340 | var INITIAL_TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216; 1341 | if (INITIAL_TOTAL_MEMORY < TOTAL_STACK) err('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); 1342 | 1343 | // Initialize the runtime's memory 1344 | // check for full engine support (use string 'subarray' to avoid closure compiler confusion) 1345 | assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined, 1346 | 'JS engine does not provide full typed array support'); 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | // Use a provided buffer, if there is one, or else allocate a new one 1355 | if (Module['buffer']) { 1356 | buffer = Module['buffer']; 1357 | assert(buffer.byteLength === INITIAL_TOTAL_MEMORY, 'provided buffer should be ' + INITIAL_TOTAL_MEMORY + ' bytes, but it is ' + buffer.byteLength); 1358 | } else { 1359 | // Use a WebAssembly memory where available 1360 | if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { 1361 | assert(INITIAL_TOTAL_MEMORY % WASM_PAGE_SIZE === 0); 1362 | wasmMemory = new WebAssembly.Memory({ 'initial': INITIAL_TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': INITIAL_TOTAL_MEMORY / WASM_PAGE_SIZE }); 1363 | buffer = wasmMemory.buffer; 1364 | } else 1365 | { 1366 | buffer = new ArrayBuffer(INITIAL_TOTAL_MEMORY); 1367 | } 1368 | assert(buffer.byteLength === INITIAL_TOTAL_MEMORY); 1369 | } 1370 | updateGlobalBufferViews(); 1371 | 1372 | 1373 | HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; 1374 | 1375 | 1376 | // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. 1377 | function writeStackCookie() { 1378 | assert((STACK_MAX & 3) == 0); 1379 | HEAPU32[(STACK_MAX >> 2)-1] = 0x02135467; 1380 | HEAPU32[(STACK_MAX >> 2)-2] = 0x89BACDFE; 1381 | } 1382 | 1383 | function checkStackCookie() { 1384 | if (HEAPU32[(STACK_MAX >> 2)-1] != 0x02135467 || HEAPU32[(STACK_MAX >> 2)-2] != 0x89BACDFE) { 1385 | abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x02135467, but received 0x' + HEAPU32[(STACK_MAX >> 2)-2].toString(16) + ' ' + HEAPU32[(STACK_MAX >> 2)-1].toString(16)); 1386 | } 1387 | // Also test the global address 0 for integrity. 1388 | if (HEAP32[0] !== 0x63736d65 /* 'emsc' */) throw 'Runtime error: The application has corrupted its heap memory area (address zero)!'; 1389 | } 1390 | 1391 | function abortStackOverflow(allocSize) { 1392 | abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (STACK_MAX - stackSave() + allocSize) + ' bytes available!'); 1393 | } 1394 | 1395 | 1396 | HEAP32[0] = 0x63736d65; /* 'emsc' */ 1397 | 1398 | 1399 | 1400 | // Endianness check (note: assumes compiler arch was little-endian) 1401 | HEAP16[1] = 0x6373; 1402 | if (HEAPU8[2] !== 0x73 || HEAPU8[3] !== 0x63) throw 'Runtime error: expected the system to be little-endian!'; 1403 | 1404 | function callRuntimeCallbacks(callbacks) { 1405 | while(callbacks.length > 0) { 1406 | var callback = callbacks.shift(); 1407 | if (typeof callback == 'function') { 1408 | callback(); 1409 | continue; 1410 | } 1411 | var func = callback.func; 1412 | if (typeof func === 'number') { 1413 | if (callback.arg === undefined) { 1414 | Module['dynCall_v'](func); 1415 | } else { 1416 | Module['dynCall_vi'](func, callback.arg); 1417 | } 1418 | } else { 1419 | func(callback.arg === undefined ? null : callback.arg); 1420 | } 1421 | } 1422 | } 1423 | 1424 | var __ATPRERUN__ = []; // functions called before the runtime is initialized 1425 | var __ATINIT__ = []; // functions called during startup 1426 | var __ATMAIN__ = []; // functions called when main() is to be run 1427 | var __ATEXIT__ = []; // functions called during shutdown 1428 | var __ATPOSTRUN__ = []; // functions called after the main() is called 1429 | 1430 | var runtimeInitialized = false; 1431 | var runtimeExited = false; 1432 | 1433 | 1434 | function preRun() { 1435 | // compatibility - merge in anything from Module['preRun'] at this time 1436 | if (Module['preRun']) { 1437 | if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; 1438 | while (Module['preRun'].length) { 1439 | addOnPreRun(Module['preRun'].shift()); 1440 | } 1441 | } 1442 | callRuntimeCallbacks(__ATPRERUN__); 1443 | } 1444 | 1445 | function ensureInitRuntime() { 1446 | checkStackCookie(); 1447 | if (runtimeInitialized) return; 1448 | runtimeInitialized = true; 1449 | 1450 | callRuntimeCallbacks(__ATINIT__); 1451 | } 1452 | 1453 | function preMain() { 1454 | checkStackCookie(); 1455 | 1456 | callRuntimeCallbacks(__ATMAIN__); 1457 | } 1458 | 1459 | function exitRuntime() { 1460 | checkStackCookie(); 1461 | runtimeExited = true; 1462 | } 1463 | 1464 | function postRun() { 1465 | checkStackCookie(); 1466 | // compatibility - merge in anything from Module['postRun'] at this time 1467 | if (Module['postRun']) { 1468 | if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; 1469 | while (Module['postRun'].length) { 1470 | addOnPostRun(Module['postRun'].shift()); 1471 | } 1472 | } 1473 | callRuntimeCallbacks(__ATPOSTRUN__); 1474 | } 1475 | 1476 | function addOnPreRun(cb) { 1477 | __ATPRERUN__.unshift(cb); 1478 | } 1479 | 1480 | function addOnInit(cb) { 1481 | __ATINIT__.unshift(cb); 1482 | } 1483 | 1484 | function addOnPreMain(cb) { 1485 | __ATMAIN__.unshift(cb); 1486 | } 1487 | 1488 | function addOnExit(cb) { 1489 | } 1490 | 1491 | function addOnPostRun(cb) { 1492 | __ATPOSTRUN__.unshift(cb); 1493 | } 1494 | 1495 | function unSign(value, bits, ignore) { 1496 | if (value >= 0) { 1497 | return value; 1498 | } 1499 | return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts 1500 | : Math.pow(2, bits) + value; 1501 | } 1502 | function reSign(value, bits, ignore) { 1503 | if (value <= 0) { 1504 | return value; 1505 | } 1506 | var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 1507 | : Math.pow(2, bits-1); 1508 | if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that 1509 | // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors 1510 | // TODO: In i64 mode 1, resign the two parts separately and safely 1511 | value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts 1512 | } 1513 | return value; 1514 | } 1515 | 1516 | 1517 | 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'); 1518 | 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'); 1519 | 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'); 1520 | 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'); 1521 | 1522 | var Math_abs = Math.abs; 1523 | var Math_cos = Math.cos; 1524 | var Math_sin = Math.sin; 1525 | var Math_tan = Math.tan; 1526 | var Math_acos = Math.acos; 1527 | var Math_asin = Math.asin; 1528 | var Math_atan = Math.atan; 1529 | var Math_atan2 = Math.atan2; 1530 | var Math_exp = Math.exp; 1531 | var Math_log = Math.log; 1532 | var Math_sqrt = Math.sqrt; 1533 | var Math_ceil = Math.ceil; 1534 | var Math_floor = Math.floor; 1535 | var Math_pow = Math.pow; 1536 | var Math_imul = Math.imul; 1537 | var Math_fround = Math.fround; 1538 | var Math_round = Math.round; 1539 | var Math_min = Math.min; 1540 | var Math_max = Math.max; 1541 | var Math_clz32 = Math.clz32; 1542 | var Math_trunc = Math.trunc; 1543 | 1544 | 1545 | 1546 | // A counter of dependencies for calling run(). If we need to 1547 | // do asynchronous work before running, increment this and 1548 | // decrement it. Incrementing must happen in a place like 1549 | // Module.preRun (used by emcc to add file preloading). 1550 | // Note that you can add dependencies in preRun, even though 1551 | // it happens right before run - run will be postponed until 1552 | // the dependencies are met. 1553 | var runDependencies = 0; 1554 | var runDependencyWatcher = null; 1555 | var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled 1556 | var runDependencyTracking = {}; 1557 | 1558 | function getUniqueRunDependency(id) { 1559 | var orig = id; 1560 | while (1) { 1561 | if (!runDependencyTracking[id]) return id; 1562 | id = orig + Math.random(); 1563 | } 1564 | return id; 1565 | } 1566 | 1567 | function addRunDependency(id) { 1568 | runDependencies++; 1569 | if (Module['monitorRunDependencies']) { 1570 | Module['monitorRunDependencies'](runDependencies); 1571 | } 1572 | if (id) { 1573 | assert(!runDependencyTracking[id]); 1574 | runDependencyTracking[id] = 1; 1575 | if (runDependencyWatcher === null && typeof setInterval !== 'undefined') { 1576 | // Check for missing dependencies every few seconds 1577 | runDependencyWatcher = setInterval(function() { 1578 | if (ABORT) { 1579 | clearInterval(runDependencyWatcher); 1580 | runDependencyWatcher = null; 1581 | return; 1582 | } 1583 | var shown = false; 1584 | for (var dep in runDependencyTracking) { 1585 | if (!shown) { 1586 | shown = true; 1587 | err('still waiting on run dependencies:'); 1588 | } 1589 | err('dependency: ' + dep); 1590 | } 1591 | if (shown) { 1592 | err('(end of list)'); 1593 | } 1594 | }, 10000); 1595 | } 1596 | } else { 1597 | err('warning: run dependency added without ID'); 1598 | } 1599 | } 1600 | 1601 | function removeRunDependency(id) { 1602 | runDependencies--; 1603 | if (Module['monitorRunDependencies']) { 1604 | Module['monitorRunDependencies'](runDependencies); 1605 | } 1606 | if (id) { 1607 | assert(runDependencyTracking[id]); 1608 | delete runDependencyTracking[id]; 1609 | } else { 1610 | err('warning: run dependency removed without ID'); 1611 | } 1612 | if (runDependencies == 0) { 1613 | if (runDependencyWatcher !== null) { 1614 | clearInterval(runDependencyWatcher); 1615 | runDependencyWatcher = null; 1616 | } 1617 | if (dependenciesFulfilled) { 1618 | var callback = dependenciesFulfilled; 1619 | dependenciesFulfilled = null; 1620 | callback(); // can add another dependenciesFulfilled 1621 | } 1622 | } 1623 | } 1624 | 1625 | Module["preloadedImages"] = {}; // maps url to image data 1626 | Module["preloadedAudios"] = {}; // maps url to audio data 1627 | 1628 | 1629 | var memoryInitializer = null; 1630 | 1631 | 1632 | 1633 | // show errors on likely calls to FS when it was not included 1634 | var FS = { 1635 | error: function() { 1636 | 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 -s FORCE_FILESYSTEM=1'); 1637 | }, 1638 | init: function() { FS.error() }, 1639 | createDataFile: function() { FS.error() }, 1640 | createPreloadedFile: function() { FS.error() }, 1641 | createLazyFile: function() { FS.error() }, 1642 | open: function() { FS.error() }, 1643 | mkdev: function() { FS.error() }, 1644 | registerDevice: function() { FS.error() }, 1645 | analyzePath: function() { FS.error() }, 1646 | loadFilesFromDB: function() { FS.error() }, 1647 | 1648 | ErrnoError: function ErrnoError() { FS.error() }, 1649 | }; 1650 | Module['FS_createDataFile'] = FS.createDataFile; 1651 | Module['FS_createPreloadedFile'] = FS.createPreloadedFile; 1652 | 1653 | 1654 | 1655 | // Copyright 2017 The Emscripten Authors. All rights reserved. 1656 | // Emscripten is available under two separate licenses, the MIT license and the 1657 | // University of Illinois/NCSA Open Source License. Both these licenses can be 1658 | // found in the LICENSE file. 1659 | 1660 | // Prefix of data URIs emitted by SINGLE_FILE and related options. 1661 | var dataURIPrefix = 'data:application/octet-stream;base64,'; 1662 | 1663 | // Indicates whether filename is a base64 data URI. 1664 | function isDataURI(filename) { 1665 | return String.prototype.startsWith ? 1666 | filename.startsWith(dataURIPrefix) : 1667 | filename.indexOf(dataURIPrefix) === 0; 1668 | } 1669 | 1670 | 1671 | 1672 | 1673 | var wasmBinaryFile = 'firmware.wasm'; 1674 | if (!isDataURI(wasmBinaryFile)) { 1675 | wasmBinaryFile = locateFile(wasmBinaryFile); 1676 | } 1677 | 1678 | function getBinary() { 1679 | try { 1680 | if (Module['wasmBinary']) { 1681 | return new Uint8Array(Module['wasmBinary']); 1682 | } 1683 | if (Module['readBinary']) { 1684 | return Module['readBinary'](wasmBinaryFile); 1685 | } else { 1686 | throw "both async and sync fetching of the wasm failed"; 1687 | } 1688 | } 1689 | catch (err) { 1690 | abort(err); 1691 | } 1692 | } 1693 | 1694 | function getBinaryPromise() { 1695 | // if we don't have the binary yet, and have the Fetch api, use that 1696 | // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web 1697 | if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { 1698 | return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { 1699 | if (!response['ok']) { 1700 | throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; 1701 | } 1702 | return response['arrayBuffer'](); 1703 | }).catch(function () { 1704 | return getBinary(); 1705 | }); 1706 | } 1707 | // Otherwise, getBinary should be able to get it synchronously 1708 | return new Promise(function(resolve, reject) { 1709 | resolve(getBinary()); 1710 | }); 1711 | } 1712 | 1713 | // Create the wasm instance. 1714 | // Receives the wasm imports, returns the exports. 1715 | function createWasm(env) { 1716 | // prepare imports 1717 | var info = { 1718 | 'env': env 1719 | , 1720 | 'global': { 1721 | 'NaN': NaN, 1722 | 'Infinity': Infinity 1723 | }, 1724 | 'global.Math': Math, 1725 | 'asm2wasm': asm2wasmImports 1726 | }; 1727 | // Load the wasm module and create an instance of using native support in the JS engine. 1728 | // handle a generated wasm instance, receiving its exports and 1729 | // performing other necessary setup 1730 | function receiveInstance(instance, module) { 1731 | var exports = instance.exports; 1732 | Module['asm'] = exports; 1733 | removeRunDependency('wasm-instantiate'); 1734 | } 1735 | addRunDependency('wasm-instantiate'); 1736 | 1737 | // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback 1738 | // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel 1739 | // to any other async startup actions they are performing. 1740 | if (Module['instantiateWasm']) { 1741 | try { 1742 | return Module['instantiateWasm'](info, receiveInstance); 1743 | } catch(e) { 1744 | err('Module.instantiateWasm callback failed with error: ' + e); 1745 | return false; 1746 | } 1747 | } 1748 | 1749 | // Async compilation can be confusing when an error on the page overwrites Module 1750 | // (for example, if the order of elements is wrong, and the one defining Module is 1751 | // later), so we save Module and check it later. 1752 | var trueModule = Module; 1753 | function receiveInstantiatedSource(output) { 1754 | // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. 1755 | // receiveInstance() will swap in the exports (to Module.asm) so they can be called 1756 | assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); 1757 | trueModule = null; 1758 | // 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. 1759 | // When the regression is fixed, can restore the above USE_PTHREADS-enabled path. 1760 | receiveInstance(output['instance']); 1761 | } 1762 | function instantiateArrayBuffer(receiver) { 1763 | getBinaryPromise().then(function(binary) { 1764 | return WebAssembly.instantiate(binary, info); 1765 | }).then(receiver, function(reason) { 1766 | err('failed to asynchronously prepare wasm: ' + reason); 1767 | abort(reason); 1768 | }); 1769 | } 1770 | // Prefer streaming instantiation if available. 1771 | if (!Module['wasmBinary'] && 1772 | typeof WebAssembly.instantiateStreaming === 'function' && 1773 | !isDataURI(wasmBinaryFile) && 1774 | typeof fetch === 'function') { 1775 | WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info) 1776 | .then(receiveInstantiatedSource, function(reason) { 1777 | // We expect the most common failure cause to be a bad MIME type for the binary, 1778 | // in which case falling back to ArrayBuffer instantiation should work. 1779 | err('wasm streaming compile failed: ' + reason); 1780 | err('falling back to ArrayBuffer instantiation'); 1781 | instantiateArrayBuffer(receiveInstantiatedSource); 1782 | }); 1783 | } else { 1784 | instantiateArrayBuffer(receiveInstantiatedSource); 1785 | } 1786 | return {}; // no exports yet; we'll fill them in later 1787 | } 1788 | 1789 | // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate 1790 | // the wasm module at that time, and it receives imports and provides exports and so forth, the app 1791 | // doesn't need to care that it is wasm or asm.js. 1792 | 1793 | Module['asm'] = function(global, env, providedBuffer) { 1794 | // memory was already allocated (so js could use the buffer) 1795 | env['memory'] = wasmMemory 1796 | ; 1797 | // import table 1798 | env['table'] = wasmTable = new WebAssembly.Table({ 1799 | 'initial': 13824, 1800 | 'maximum': 13824, 1801 | 'element': 'anyfunc' 1802 | }); 1803 | // With the wasm backend __memory_base and __table_base and only needed for 1804 | // relocatable output. 1805 | env['__memory_base'] = 1024; // tell the memory segments where to place themselves 1806 | // table starts at 0 by default (even in dynamic linking, for the main module) 1807 | env['__table_base'] = 0; 1808 | 1809 | var exports = createWasm(env); 1810 | assert(exports, 'binaryen setup failed (no wasm support?)'); 1811 | return exports; 1812 | }; 1813 | 1814 | // === Body === 1815 | 1816 | var ASM_CONSTS = []; 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | // STATICTOP = STATIC_BASE + 41872; 1823 | /* global initializers */ /*__ATINIT__.push();*/ 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | /* no memory initializer */ 1833 | var tempDoublePtr = 42880 1834 | assert(tempDoublePtr % 8 == 0); 1835 | 1836 | function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much 1837 | HEAP8[tempDoublePtr] = HEAP8[ptr]; 1838 | HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; 1839 | HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; 1840 | HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; 1841 | } 1842 | 1843 | function copyTempDouble(ptr) { 1844 | HEAP8[tempDoublePtr] = HEAP8[ptr]; 1845 | HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; 1846 | HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; 1847 | HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; 1848 | HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; 1849 | HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; 1850 | HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; 1851 | HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; 1852 | } 1853 | 1854 | // {{PRE_LIBRARY}} 1855 | 1856 | var EMTSTACKTOP = getMemory(1048576); 1857 | var EMT_STACK_MAX = EMTSTACKTOP + 1048576; 1858 | 1859 | var eb = getMemory(580640); 1860 | assert(eb % 8 === 0); 1861 | __ATPRERUN__.push(function() { 1862 | 1863 | var bytecodeFile = Module['emterpreterFile']; 1864 | if (!(bytecodeFile instanceof ArrayBuffer)) { 1865 | throw "bad or missing emterpreter file. If you compiled to JS (and not HTML) make sure you set Module['emterpreterFile']"; 1866 | } 1867 | var codeSize = 580640; 1868 | HEAPU8.set(new Uint8Array(bytecodeFile).subarray(0, codeSize), eb); 1869 | assert(HEAPU8[eb] === 140); 1870 | assert(HEAPU8[eb+1] === 2); 1871 | assert(HEAPU8[eb+2] === 108); 1872 | assert(HEAPU8[eb+3] === 4); 1873 | var relocationsStart = (codeSize+3) >> 2; 1874 | var relocations = (new Uint32Array(bytecodeFile)).subarray(relocationsStart); 1875 | assert(relocations.length === 13769); 1876 | if (relocations.length > 0) { 1877 | assert(relocations[0] === 80); 1878 | } 1879 | 1880 | for (var i = 0; i < relocations.length; i++) { 1881 | assert(relocations[i] % 4 === 0); 1882 | assert(relocations[i] >= 0 && relocations[i] < eb + 580640); // in range 1883 | assert(HEAPU32[eb + relocations[i] >> 2] + eb < (-1 >>> 0), [i, relocations[i]]); // no overflows 1884 | HEAPU32[eb + relocations[i] >> 2] = HEAPU32[eb + relocations[i] >> 2] + eb; 1885 | } 1886 | }); 1887 | 1888 | 1889 | 1890 | function ___lock() {} 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | var SYSCALLS={buffers:[null,[],[]],printChar:function (stream, curr) { 1897 | var buffer = SYSCALLS.buffers[stream]; 1898 | assert(buffer); 1899 | if (curr === 0 || curr === 10) { 1900 | (stream === 1 ? out : err)(UTF8ArrayToString(buffer, 0)); 1901 | buffer.length = 0; 1902 | } else { 1903 | buffer.push(curr); 1904 | } 1905 | },varargs:0,get:function (varargs) { 1906 | SYSCALLS.varargs += 4; 1907 | var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; 1908 | return ret; 1909 | },getStr:function () { 1910 | var ret = UTF8ToString(SYSCALLS.get()); 1911 | return ret; 1912 | },get64:function () { 1913 | var low = SYSCALLS.get(), high = SYSCALLS.get(); 1914 | if (low >= 0) assert(high === 0); 1915 | else assert(high === -1); 1916 | return low; 1917 | },getZero:function () { 1918 | assert(SYSCALLS.get() === 0); 1919 | }};function ___syscall140(which, varargs) {SYSCALLS.varargs = varargs; 1920 | try { 1921 | // llseek 1922 | var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get(); 1923 | abort('it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM'); 1924 | return 0; 1925 | } catch (e) { 1926 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1927 | return -e.errno; 1928 | } 1929 | } 1930 | 1931 | 1932 | function flush_NO_FILESYSTEM() { 1933 | // flush anything remaining in the buffers during shutdown 1934 | var fflush = Module["_fflush"]; 1935 | if (fflush) fflush(0); 1936 | var buffers = SYSCALLS.buffers; 1937 | if (buffers[1].length) SYSCALLS.printChar(1, 10); 1938 | if (buffers[2].length) SYSCALLS.printChar(2, 10); 1939 | }function ___syscall146(which, varargs) {SYSCALLS.varargs = varargs; 1940 | try { 1941 | // writev 1942 | // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 1943 | var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get(); 1944 | var ret = 0; 1945 | for (var i = 0; i < iovcnt; i++) { 1946 | var ptr = HEAP32[(((iov)+(i*8))>>2)]; 1947 | var len = HEAP32[(((iov)+(i*8 + 4))>>2)]; 1948 | for (var j = 0; j < len; j++) { 1949 | SYSCALLS.printChar(stream, HEAPU8[ptr+j]); 1950 | } 1951 | ret += len; 1952 | } 1953 | return ret; 1954 | } catch (e) { 1955 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1956 | return -e.errno; 1957 | } 1958 | } 1959 | 1960 | function ___syscall54(which, varargs) {SYSCALLS.varargs = varargs; 1961 | try { 1962 | // ioctl 1963 | return 0; 1964 | } catch (e) { 1965 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1966 | return -e.errno; 1967 | } 1968 | } 1969 | 1970 | function ___syscall6(which, varargs) {SYSCALLS.varargs = varargs; 1971 | try { 1972 | // close 1973 | var stream = SYSCALLS.getStreamFromFD(); 1974 | abort('it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM'); 1975 | return 0; 1976 | } catch (e) { 1977 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1978 | return -e.errno; 1979 | } 1980 | } 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | function _llvm_cttz_i32(x) { // Note: Currently doesn't take isZeroUndef() 1989 | x = x | 0; 1990 | return (x ? (31 - (Math_clz32((x ^ (x - 1))) | 0) | 0) : 32) | 0; 1991 | } 1992 | 1993 | function ___unlock() {} 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | function _emscripten_get_heap_size() { 2002 | return HEAP8.length; 2003 | } 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | function _longjmp(env, value) { 2012 | _setThrew(env, value || 1); 2013 | throw 'longjmp'; 2014 | }function _emscripten_longjmp(env, value) { 2015 | _longjmp(env, value); 2016 | } 2017 | 2018 | 2019 | function abortOnCannotGrowMemory(requestedSize) { 2020 | abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); 2021 | }function _emscripten_resize_heap(requestedSize) { 2022 | abortOnCannotGrowMemory(requestedSize); 2023 | } 2024 | 2025 | function _emscripten_run_script_string(ptr) { 2026 | //console.log(UTF8ToString(ptr) + ''); 2027 | var s = eval(UTF8ToString(ptr)) + ''; 2028 | var me = _emscripten_run_script_string; 2029 | var len = lengthBytesUTF8(s); 2030 | if (!me.bufferSize || me.bufferSize < len+1) { 2031 | if (me.bufferSize) _free(me.buffer); 2032 | me.bufferSize = len+1; 2033 | me.buffer = _malloc(me.bufferSize); 2034 | } 2035 | stringToUTF8(s, me.buffer, me.bufferSize); 2036 | return me.buffer; 2037 | } 2038 | 2039 | 2040 | 2041 | 2042 | 2043 | function _emscripten_set_main_loop_timing(mode, value) { 2044 | Browser.mainLoop.timingMode = mode; 2045 | Browser.mainLoop.timingValue = value; 2046 | 2047 | if (!Browser.mainLoop.func) { 2048 | console.error('emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.'); 2049 | return 1; // Return non-zero on failure, can't set timing mode when there is no main loop. 2050 | } 2051 | 2052 | if (mode == 0 /*EM_TIMING_SETTIMEOUT*/) { 2053 | Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() { 2054 | var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now())|0; 2055 | setTimeout(Browser.mainLoop.runner, timeUntilNextTick); // doing this each time means that on exception, we stop 2056 | }; 2057 | Browser.mainLoop.method = 'timeout'; 2058 | } else if (mode == 1 /*EM_TIMING_RAF*/) { 2059 | Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() { 2060 | Browser.requestAnimationFrame(Browser.mainLoop.runner); 2061 | }; 2062 | Browser.mainLoop.method = 'rAF'; 2063 | } else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) { 2064 | if (typeof setImmediate === 'undefined') { 2065 | // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed) 2066 | var setImmediates = []; 2067 | var emscriptenMainLoopMessageId = 'setimmediate'; 2068 | var Browser_setImmediate_messageHandler = function(event) { 2069 | // When called in current thread or Worker, the main loop ID is structured slightly different to accommodate for --proxy-to-worker runtime listening to Worker events, 2070 | // so check for both cases. 2071 | if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) { 2072 | event.stopPropagation(); 2073 | setImmediates.shift()(); 2074 | } 2075 | } 2076 | addEventListener("message", Browser_setImmediate_messageHandler, true); 2077 | setImmediate = function Browser_emulated_setImmediate(func) { 2078 | setImmediates.push(func); 2079 | if (ENVIRONMENT_IS_WORKER) { 2080 | if (Module['setImmediates'] === undefined) Module['setImmediates'] = []; 2081 | Module['setImmediates'].push(func); 2082 | postMessage({target: emscriptenMainLoopMessageId}); // In --proxy-to-worker, route the message via proxyClient.js 2083 | } else postMessage(emscriptenMainLoopMessageId, "*"); // On the main thread, can just send the message to itself. 2084 | } 2085 | } 2086 | Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() { 2087 | setImmediate(Browser.mainLoop.runner); 2088 | }; 2089 | Browser.mainLoop.method = 'immediate'; 2090 | } 2091 | return 0; 2092 | } 2093 | 2094 | function _emscripten_get_now() { abort() }function _emscripten_set_main_loop(func, fps, simulateInfiniteLoop, arg, noSetTiming) { 2095 | Module['noExitRuntime'] = true; 2096 | 2097 | assert(!Browser.mainLoop.func, 'emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.'); 2098 | 2099 | Browser.mainLoop.func = func; 2100 | Browser.mainLoop.arg = arg; 2101 | 2102 | var browserIterationFunc; 2103 | if (typeof arg !== 'undefined') { 2104 | browserIterationFunc = function() { 2105 | Module['dynCall_vi'](func, arg); 2106 | }; 2107 | } else { 2108 | browserIterationFunc = function() { 2109 | Module['dynCall_v'](func); 2110 | }; 2111 | } 2112 | 2113 | var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop; 2114 | 2115 | Browser.mainLoop.runner = function Browser_mainLoop_runner() { 2116 | if (ABORT) return; 2117 | if (Browser.mainLoop.queue.length > 0) { 2118 | var start = Date.now(); 2119 | var blocker = Browser.mainLoop.queue.shift(); 2120 | blocker.func(blocker.arg); 2121 | if (Browser.mainLoop.remainingBlockers) { 2122 | var remaining = Browser.mainLoop.remainingBlockers; 2123 | var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining); 2124 | if (blocker.counted) { 2125 | Browser.mainLoop.remainingBlockers = next; 2126 | } else { 2127 | // not counted, but move the progress along a tiny bit 2128 | next = next + 0.5; // do not steal all the next one's progress 2129 | Browser.mainLoop.remainingBlockers = (8*remaining + next)/9; 2130 | } 2131 | } 2132 | console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers); 2133 | Browser.mainLoop.updateStatus(); 2134 | 2135 | // catches pause/resume main loop from blocker execution 2136 | if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return; 2137 | 2138 | setTimeout(Browser.mainLoop.runner, 0); 2139 | return; 2140 | } 2141 | 2142 | // catch pauses from non-main loop sources 2143 | if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return; 2144 | 2145 | // Implement very basic swap interval control 2146 | Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0; 2147 | if (Browser.mainLoop.timingMode == 1/*EM_TIMING_RAF*/ && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) { 2148 | // Not the scheduled time to render this frame - skip. 2149 | Browser.mainLoop.scheduler(); 2150 | return; 2151 | } else if (Browser.mainLoop.timingMode == 0/*EM_TIMING_SETTIMEOUT*/) { 2152 | Browser.mainLoop.tickStartTime = _emscripten_get_now(); 2153 | } 2154 | 2155 | // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize 2156 | // VBO double-buffering and reduce GPU stalls. 2157 | 2158 | 2159 | 2160 | if (Browser.mainLoop.method === 'timeout' && Module.ctx) { 2161 | err('Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!'); 2162 | Browser.mainLoop.method = ''; // just warn once per call to set main loop 2163 | } 2164 | 2165 | Browser.mainLoop.runIter(browserIterationFunc); 2166 | 2167 | checkStackCookie(); 2168 | 2169 | // catch pauses from the main loop itself 2170 | if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return; 2171 | 2172 | // Queue new audio data. This is important to be right after the main loop invocation, so that we will immediately be able 2173 | // to queue the newest produced audio samples. 2174 | // TODO: Consider adding pre- and post- rAF callbacks so that GL.newRenderingFrameStarted() and SDL.audio.queueNewAudioData() 2175 | // do not need to be hardcoded into this function, but can be more generic. 2176 | if (typeof SDL === 'object' && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData(); 2177 | 2178 | Browser.mainLoop.scheduler(); 2179 | } 2180 | 2181 | if (!noSetTiming) { 2182 | if (fps && fps > 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 1000.0 / fps); 2183 | else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, 1); // Do rAF by rendering each frame (no decimating) 2184 | 2185 | Browser.mainLoop.scheduler(); 2186 | } 2187 | 2188 | if (simulateInfiniteLoop) { 2189 | throw 'SimulateInfiniteLoop'; 2190 | } 2191 | }var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function () { 2192 | Browser.mainLoop.scheduler = null; 2193 | Browser.mainLoop.currentlyRunningMainloop++; // Incrementing this signals the previous main loop that it's now become old, and it must return. 2194 | },resume:function () { 2195 | Browser.mainLoop.currentlyRunningMainloop++; 2196 | var timingMode = Browser.mainLoop.timingMode; 2197 | var timingValue = Browser.mainLoop.timingValue; 2198 | var func = Browser.mainLoop.func; 2199 | Browser.mainLoop.func = null; 2200 | _emscripten_set_main_loop(func, 0, false, Browser.mainLoop.arg, true /* do not set timing and call scheduler, we will do it on the next lines */); 2201 | _emscripten_set_main_loop_timing(timingMode, timingValue); 2202 | Browser.mainLoop.scheduler(); 2203 | },updateStatus:function () { 2204 | if (Module['setStatus']) { 2205 | var message = Module['statusMessage'] || 'Please wait...'; 2206 | var remaining = Browser.mainLoop.remainingBlockers; 2207 | var expected = Browser.mainLoop.expectedBlockers; 2208 | if (remaining) { 2209 | if (remaining < expected) { 2210 | Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); 2211 | } else { 2212 | Module['setStatus'](message); 2213 | } 2214 | } else { 2215 | Module['setStatus'](''); 2216 | } 2217 | } 2218 | },runIter:function (func) { 2219 | if (ABORT) return; 2220 | if (Module['preMainLoop']) { 2221 | var preRet = Module['preMainLoop'](); 2222 | if (preRet === false) { 2223 | return; // |return false| skips a frame 2224 | } 2225 | } 2226 | try { 2227 | func(); 2228 | } catch (e) { 2229 | if (e instanceof ExitStatus) { 2230 | return; 2231 | } else { 2232 | if (e && typeof e === 'object' && e.stack) err('exception thrown: ' + [e, e.stack]); 2233 | throw e; 2234 | } 2235 | } 2236 | if (Module['postMainLoop']) Module['postMainLoop'](); 2237 | }},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () { 2238 | if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers 2239 | 2240 | if (Browser.initted) return; 2241 | Browser.initted = true; 2242 | 2243 | try { 2244 | new Blob(); 2245 | Browser.hasBlobConstructor = true; 2246 | } catch(e) { 2247 | Browser.hasBlobConstructor = false; 2248 | console.log("warning: no blob constructor, cannot create blobs with mimetypes"); 2249 | } 2250 | Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); 2251 | Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; 2252 | if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { 2253 | console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); 2254 | Module.noImageDecoding = true; 2255 | } 2256 | 2257 | // Support for plugins that can process preloaded files. You can add more of these to 2258 | // your app by creating and appending to Module.preloadPlugins. 2259 | // 2260 | // Each plugin is asked if it can handle a file based on the file's name. If it can, 2261 | // it is given the file's raw data. When it is done, it calls a callback with the file's 2262 | // (possibly modified) data. For example, a plugin might decompress a file, or it 2263 | // might create some side data structure for use later (like an Image element, etc.). 2264 | 2265 | var imagePlugin = {}; 2266 | imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { 2267 | return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); 2268 | }; 2269 | imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { 2270 | var b = null; 2271 | if (Browser.hasBlobConstructor) { 2272 | try { 2273 | b = new Blob([byteArray], { type: Browser.getMimetype(name) }); 2274 | if (b.size !== byteArray.length) { // Safari bug #118630 2275 | // Safari's Blob can only take an ArrayBuffer 2276 | b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); 2277 | } 2278 | } catch(e) { 2279 | warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); 2280 | } 2281 | } 2282 | if (!b) { 2283 | var bb = new Browser.BlobBuilder(); 2284 | bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range 2285 | b = bb.getBlob(); 2286 | } 2287 | var url = Browser.URLObject.createObjectURL(b); 2288 | assert(typeof url == 'string', 'createObjectURL must return a url as a string'); 2289 | var img = new Image(); 2290 | img.onload = function img_onload() { 2291 | assert(img.complete, 'Image ' + name + ' could not be decoded'); 2292 | var canvas = document.createElement('canvas'); 2293 | canvas.width = img.width; 2294 | canvas.height = img.height; 2295 | var ctx = canvas.getContext('2d'); 2296 | ctx.drawImage(img, 0, 0); 2297 | Module["preloadedImages"][name] = canvas; 2298 | Browser.URLObject.revokeObjectURL(url); 2299 | if (onload) onload(byteArray); 2300 | }; 2301 | img.onerror = function img_onerror(event) { 2302 | console.log('Image ' + url + ' could not be decoded'); 2303 | if (onerror) onerror(); 2304 | }; 2305 | img.src = url; 2306 | }; 2307 | Module['preloadPlugins'].push(imagePlugin); 2308 | 2309 | var audioPlugin = {}; 2310 | audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { 2311 | return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; 2312 | }; 2313 | audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { 2314 | var done = false; 2315 | function finish(audio) { 2316 | if (done) return; 2317 | done = true; 2318 | Module["preloadedAudios"][name] = audio; 2319 | if (onload) onload(byteArray); 2320 | } 2321 | function fail() { 2322 | if (done) return; 2323 | done = true; 2324 | Module["preloadedAudios"][name] = new Audio(); // empty shim 2325 | if (onerror) onerror(); 2326 | } 2327 | if (Browser.hasBlobConstructor) { 2328 | try { 2329 | var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); 2330 | } catch(e) { 2331 | return fail(); 2332 | } 2333 | var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! 2334 | assert(typeof url == 'string', 'createObjectURL must return a url as a string'); 2335 | var audio = new Audio(); 2336 | audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 2337 | audio.onerror = function audio_onerror(event) { 2338 | if (done) return; 2339 | console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); 2340 | function encode64(data) { 2341 | var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 2342 | var PAD = '='; 2343 | var ret = ''; 2344 | var leftchar = 0; 2345 | var leftbits = 0; 2346 | for (var i = 0; i < data.length; i++) { 2347 | leftchar = (leftchar << 8) | data[i]; 2348 | leftbits += 8; 2349 | while (leftbits >= 6) { 2350 | var curr = (leftchar >> (leftbits-6)) & 0x3f; 2351 | leftbits -= 6; 2352 | ret += BASE[curr]; 2353 | } 2354 | } 2355 | if (leftbits == 2) { 2356 | ret += BASE[(leftchar&3) << 4]; 2357 | ret += PAD + PAD; 2358 | } else if (leftbits == 4) { 2359 | ret += BASE[(leftchar&0xf) << 2]; 2360 | ret += PAD; 2361 | } 2362 | return ret; 2363 | } 2364 | audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); 2365 | finish(audio); // we don't wait for confirmation this worked - but it's worth trying 2366 | }; 2367 | audio.src = url; 2368 | // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror 2369 | Browser.safeSetTimeout(function() { 2370 | finish(audio); // try to use it even though it is not necessarily ready to play 2371 | }, 10000); 2372 | } else { 2373 | return fail(); 2374 | } 2375 | }; 2376 | Module['preloadPlugins'].push(audioPlugin); 2377 | 2378 | 2379 | // Canvas event setup 2380 | 2381 | function pointerLockChange() { 2382 | Browser.pointerLock = document['pointerLockElement'] === Module['canvas'] || 2383 | document['mozPointerLockElement'] === Module['canvas'] || 2384 | document['webkitPointerLockElement'] === Module['canvas'] || 2385 | document['msPointerLockElement'] === Module['canvas']; 2386 | } 2387 | var canvas = Module['canvas']; 2388 | if (canvas) { 2389 | // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module 2390 | // Module['forcedAspectRatio'] = 4 / 3; 2391 | 2392 | canvas.requestPointerLock = canvas['requestPointerLock'] || 2393 | canvas['mozRequestPointerLock'] || 2394 | canvas['webkitRequestPointerLock'] || 2395 | canvas['msRequestPointerLock'] || 2396 | function(){}; 2397 | canvas.exitPointerLock = document['exitPointerLock'] || 2398 | document['mozExitPointerLock'] || 2399 | document['webkitExitPointerLock'] || 2400 | document['msExitPointerLock'] || 2401 | function(){}; // no-op if function does not exist 2402 | canvas.exitPointerLock = canvas.exitPointerLock.bind(document); 2403 | 2404 | document.addEventListener('pointerlockchange', pointerLockChange, false); 2405 | document.addEventListener('mozpointerlockchange', pointerLockChange, false); 2406 | document.addEventListener('webkitpointerlockchange', pointerLockChange, false); 2407 | document.addEventListener('mspointerlockchange', pointerLockChange, false); 2408 | 2409 | if (Module['elementPointerLock']) { 2410 | canvas.addEventListener("click", function(ev) { 2411 | if (!Browser.pointerLock && Module['canvas'].requestPointerLock) { 2412 | Module['canvas'].requestPointerLock(); 2413 | ev.preventDefault(); 2414 | } 2415 | }, false); 2416 | } 2417 | } 2418 | },createContext:function (canvas, useWebGL, setInModule, webGLContextAttributes) { 2419 | if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas. 2420 | 2421 | var ctx; 2422 | var contextHandle; 2423 | if (useWebGL) { 2424 | // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults. 2425 | var contextAttributes = { 2426 | antialias: false, 2427 | alpha: false, 2428 | majorVersion: 1, 2429 | }; 2430 | 2431 | if (webGLContextAttributes) { 2432 | for (var attribute in webGLContextAttributes) { 2433 | contextAttributes[attribute] = webGLContextAttributes[attribute]; 2434 | } 2435 | } 2436 | 2437 | // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not 2438 | // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function 2439 | // Browser.createContext() should not even be emitted. 2440 | if (typeof GL !== 'undefined') { 2441 | contextHandle = GL.createContext(canvas, contextAttributes); 2442 | if (contextHandle) { 2443 | ctx = GL.getContext(contextHandle).GLctx; 2444 | } 2445 | } 2446 | } else { 2447 | ctx = canvas.getContext('2d'); 2448 | } 2449 | 2450 | if (!ctx) return null; 2451 | 2452 | if (setInModule) { 2453 | if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it'); 2454 | 2455 | Module.ctx = ctx; 2456 | if (useWebGL) GL.makeContextCurrent(contextHandle); 2457 | Module.useWebGL = useWebGL; 2458 | Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); 2459 | Browser.init(); 2460 | } 2461 | return ctx; 2462 | },destroyContext:function (canvas, useWebGL, setInModule) {},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function (lockPointer, resizeCanvas, vrDevice) { 2463 | Browser.lockPointer = lockPointer; 2464 | Browser.resizeCanvas = resizeCanvas; 2465 | Browser.vrDevice = vrDevice; 2466 | if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; 2467 | if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; 2468 | if (typeof Browser.vrDevice === 'undefined') Browser.vrDevice = null; 2469 | 2470 | var canvas = Module['canvas']; 2471 | function fullscreenChange() { 2472 | Browser.isFullscreen = false; 2473 | var canvasContainer = canvas.parentNode; 2474 | if ((document['fullscreenElement'] || document['mozFullScreenElement'] || 2475 | document['msFullscreenElement'] || document['webkitFullscreenElement'] || 2476 | document['webkitCurrentFullScreenElement']) === canvasContainer) { 2477 | canvas.exitFullscreen = Browser.exitFullscreen; 2478 | if (Browser.lockPointer) canvas.requestPointerLock(); 2479 | Browser.isFullscreen = true; 2480 | if (Browser.resizeCanvas) { 2481 | Browser.setFullscreenCanvasSize(); 2482 | } else { 2483 | Browser.updateCanvasDimensions(canvas); 2484 | } 2485 | } else { 2486 | // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen 2487 | canvasContainer.parentNode.insertBefore(canvas, canvasContainer); 2488 | canvasContainer.parentNode.removeChild(canvasContainer); 2489 | 2490 | if (Browser.resizeCanvas) { 2491 | Browser.setWindowedCanvasSize(); 2492 | } else { 2493 | Browser.updateCanvasDimensions(canvas); 2494 | } 2495 | } 2496 | if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen); 2497 | if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen); 2498 | } 2499 | 2500 | if (!Browser.fullscreenHandlersInstalled) { 2501 | Browser.fullscreenHandlersInstalled = true; 2502 | document.addEventListener('fullscreenchange', fullscreenChange, false); 2503 | document.addEventListener('mozfullscreenchange', fullscreenChange, false); 2504 | document.addEventListener('webkitfullscreenchange', fullscreenChange, false); 2505 | document.addEventListener('MSFullscreenChange', fullscreenChange, false); 2506 | } 2507 | 2508 | // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root 2509 | var canvasContainer = document.createElement("div"); 2510 | canvas.parentNode.insertBefore(canvasContainer, canvas); 2511 | canvasContainer.appendChild(canvas); 2512 | 2513 | // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) 2514 | canvasContainer.requestFullscreen = canvasContainer['requestFullscreen'] || 2515 | canvasContainer['mozRequestFullScreen'] || 2516 | canvasContainer['msRequestFullscreen'] || 2517 | (canvasContainer['webkitRequestFullscreen'] ? function() { canvasContainer['webkitRequestFullscreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null) || 2518 | (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); 2519 | 2520 | if (vrDevice) { 2521 | canvasContainer.requestFullscreen({ vrDisplay: vrDevice }); 2522 | } else { 2523 | canvasContainer.requestFullscreen(); 2524 | } 2525 | },requestFullScreen:function (lockPointer, resizeCanvas, vrDevice) { 2526 | err('Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.'); 2527 | Browser.requestFullScreen = function(lockPointer, resizeCanvas, vrDevice) { 2528 | return Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice); 2529 | } 2530 | return Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice); 2531 | },exitFullscreen:function () { 2532 | // This is workaround for chrome. Trying to exit from fullscreen 2533 | // not in fullscreen state will cause "TypeError: Document not active" 2534 | // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236 2535 | if (!Browser.isFullscreen) { 2536 | return false; 2537 | } 2538 | 2539 | var CFS = document['exitFullscreen'] || 2540 | document['cancelFullScreen'] || 2541 | document['mozCancelFullScreen'] || 2542 | document['msExitFullscreen'] || 2543 | document['webkitCancelFullScreen'] || 2544 | (function() {}); 2545 | CFS.apply(document, []); 2546 | return true; 2547 | },nextRAF:0,fakeRequestAnimationFrame:function (func) { 2548 | // try to keep 60fps between calls to here 2549 | var now = Date.now(); 2550 | if (Browser.nextRAF === 0) { 2551 | Browser.nextRAF = now + 1000/60; 2552 | } else { 2553 | while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0 2554 | Browser.nextRAF += 1000/60; 2555 | } 2556 | } 2557 | var delay = Math.max(Browser.nextRAF - now, 0); 2558 | setTimeout(func, delay); 2559 | },requestAnimationFrame:function requestAnimationFrame(func) { 2560 | if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) 2561 | Browser.fakeRequestAnimationFrame(func); 2562 | } else { 2563 | if (!window.requestAnimationFrame) { 2564 | window.requestAnimationFrame = window['requestAnimationFrame'] || 2565 | window['mozRequestAnimationFrame'] || 2566 | window['webkitRequestAnimationFrame'] || 2567 | window['msRequestAnimationFrame'] || 2568 | window['oRequestAnimationFrame'] || 2569 | Browser.fakeRequestAnimationFrame; 2570 | } 2571 | window.requestAnimationFrame(func); 2572 | } 2573 | },safeCallback:function (func) { 2574 | return function() { 2575 | if (!ABORT) return func.apply(null, arguments); 2576 | }; 2577 | },allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function () { 2578 | Browser.allowAsyncCallbacks = false; 2579 | },resumeAsyncCallbacks:function () { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now 2580 | Browser.allowAsyncCallbacks = true; 2581 | if (Browser.queuedAsyncCallbacks.length > 0) { 2582 | var callbacks = Browser.queuedAsyncCallbacks; 2583 | Browser.queuedAsyncCallbacks = []; 2584 | callbacks.forEach(function(func) { 2585 | func(); 2586 | }); 2587 | } 2588 | },safeRequestAnimationFrame:function (func) { 2589 | return Browser.requestAnimationFrame(function() { 2590 | if (ABORT) return; 2591 | if (Browser.allowAsyncCallbacks) { 2592 | func(); 2593 | } else { 2594 | Browser.queuedAsyncCallbacks.push(func); 2595 | } 2596 | }); 2597 | },safeSetTimeout:function (func, timeout) { 2598 | Module['noExitRuntime'] = true; 2599 | return setTimeout(function() { 2600 | if (ABORT) return; 2601 | if (Browser.allowAsyncCallbacks) { 2602 | func(); 2603 | } else { 2604 | Browser.queuedAsyncCallbacks.push(func); 2605 | } 2606 | }, timeout); 2607 | },safeSetInterval:function (func, timeout) { 2608 | Module['noExitRuntime'] = true; 2609 | return setInterval(function() { 2610 | if (ABORT) return; 2611 | if (Browser.allowAsyncCallbacks) { 2612 | func(); 2613 | } // drop it on the floor otherwise, next interval will kick in 2614 | }, timeout); 2615 | },getMimetype:function (name) { 2616 | return { 2617 | 'jpg': 'image/jpeg', 2618 | 'jpeg': 'image/jpeg', 2619 | 'png': 'image/png', 2620 | 'bmp': 'image/bmp', 2621 | 'ogg': 'audio/ogg', 2622 | 'wav': 'audio/wav', 2623 | 'mp3': 'audio/mpeg' 2624 | }[name.substr(name.lastIndexOf('.')+1)]; 2625 | },getUserMedia:function (func) { 2626 | if(!window.getUserMedia) { 2627 | window.getUserMedia = navigator['getUserMedia'] || 2628 | navigator['mozGetUserMedia']; 2629 | } 2630 | window.getUserMedia(func); 2631 | },getMovementX:function (event) { 2632 | return event['movementX'] || 2633 | event['mozMovementX'] || 2634 | event['webkitMovementX'] || 2635 | 0; 2636 | },getMovementY:function (event) { 2637 | return event['movementY'] || 2638 | event['mozMovementY'] || 2639 | event['webkitMovementY'] || 2640 | 0; 2641 | },getMouseWheelDelta:function (event) { 2642 | var delta = 0; 2643 | switch (event.type) { 2644 | case 'DOMMouseScroll': 2645 | // 3 lines make up a step 2646 | delta = event.detail / 3; 2647 | break; 2648 | case 'mousewheel': 2649 | // 120 units make up a step 2650 | delta = event.wheelDelta / 120; 2651 | break; 2652 | case 'wheel': 2653 | delta = event.deltaY 2654 | switch(event.deltaMode) { 2655 | case 0: 2656 | // DOM_DELTA_PIXEL: 100 pixels make up a step 2657 | delta /= 100; 2658 | break; 2659 | case 1: 2660 | // DOM_DELTA_LINE: 3 lines make up a step 2661 | delta /= 3; 2662 | break; 2663 | case 2: 2664 | // DOM_DELTA_PAGE: A page makes up 80 steps 2665 | delta *= 80; 2666 | break; 2667 | default: 2668 | throw 'unrecognized mouse wheel delta mode: ' + event.deltaMode; 2669 | } 2670 | break; 2671 | default: 2672 | throw 'unrecognized mouse wheel event: ' + event.type; 2673 | } 2674 | return delta; 2675 | },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function (event) { // event should be mousemove, mousedown or mouseup 2676 | if (Browser.pointerLock) { 2677 | // When the pointer is locked, calculate the coordinates 2678 | // based on the movement of the mouse. 2679 | // Workaround for Firefox bug 764498 2680 | if (event.type != 'mousemove' && 2681 | ('mozMovementX' in event)) { 2682 | Browser.mouseMovementX = Browser.mouseMovementY = 0; 2683 | } else { 2684 | Browser.mouseMovementX = Browser.getMovementX(event); 2685 | Browser.mouseMovementY = Browser.getMovementY(event); 2686 | } 2687 | 2688 | // check if SDL is available 2689 | if (typeof SDL != "undefined") { 2690 | Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; 2691 | Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; 2692 | } else { 2693 | // just add the mouse delta to the current absolut mouse position 2694 | // FIXME: ideally this should be clamped against the canvas size and zero 2695 | Browser.mouseX += Browser.mouseMovementX; 2696 | Browser.mouseY += Browser.mouseMovementY; 2697 | } 2698 | } else { 2699 | // Otherwise, calculate the movement based on the changes 2700 | // in the coordinates. 2701 | var rect = Module["canvas"].getBoundingClientRect(); 2702 | var cw = Module["canvas"].width; 2703 | var ch = Module["canvas"].height; 2704 | 2705 | // Neither .scrollX or .pageXOffset are defined in a spec, but 2706 | // we prefer .scrollX because it is currently in a spec draft. 2707 | // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) 2708 | var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); 2709 | var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); 2710 | // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset 2711 | // and we have no viable fallback. 2712 | assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.'); 2713 | 2714 | if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { 2715 | var touch = event.touch; 2716 | if (touch === undefined) { 2717 | return; // the "touch" property is only defined in SDL 2718 | 2719 | } 2720 | var adjustedX = touch.pageX - (scrollX + rect.left); 2721 | var adjustedY = touch.pageY - (scrollY + rect.top); 2722 | 2723 | adjustedX = adjustedX * (cw / rect.width); 2724 | adjustedY = adjustedY * (ch / rect.height); 2725 | 2726 | var coords = { x: adjustedX, y: adjustedY }; 2727 | 2728 | if (event.type === 'touchstart') { 2729 | Browser.lastTouches[touch.identifier] = coords; 2730 | Browser.touches[touch.identifier] = coords; 2731 | } else if (event.type === 'touchend' || event.type === 'touchmove') { 2732 | var last = Browser.touches[touch.identifier]; 2733 | if (!last) last = coords; 2734 | Browser.lastTouches[touch.identifier] = last; 2735 | Browser.touches[touch.identifier] = coords; 2736 | } 2737 | return; 2738 | } 2739 | 2740 | var x = event.pageX - (scrollX + rect.left); 2741 | var y = event.pageY - (scrollY + rect.top); 2742 | 2743 | // the canvas might be CSS-scaled compared to its backbuffer; 2744 | // SDL-using content will want mouse coordinates in terms 2745 | // of backbuffer units. 2746 | x = x * (cw / rect.width); 2747 | y = y * (ch / rect.height); 2748 | 2749 | Browser.mouseMovementX = x - Browser.mouseX; 2750 | Browser.mouseMovementY = y - Browser.mouseY; 2751 | Browser.mouseX = x; 2752 | Browser.mouseY = y; 2753 | } 2754 | },asyncLoad:function (url, onload, onerror, noRunDep) { 2755 | var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : ''; 2756 | Module['readAsync'](url, function(arrayBuffer) { 2757 | assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); 2758 | onload(new Uint8Array(arrayBuffer)); 2759 | if (dep) removeRunDependency(dep); 2760 | }, function(event) { 2761 | if (onerror) { 2762 | onerror(); 2763 | } else { 2764 | throw 'Loading data file "' + url + '" failed.'; 2765 | } 2766 | }); 2767 | if (dep) addRunDependency(dep); 2768 | },resizeListeners:[],updateResizeListeners:function () { 2769 | var canvas = Module['canvas']; 2770 | Browser.resizeListeners.forEach(function(listener) { 2771 | listener(canvas.width, canvas.height); 2772 | }); 2773 | },setCanvasSize:function (width, height, noUpdates) { 2774 | var canvas = Module['canvas']; 2775 | Browser.updateCanvasDimensions(canvas, width, height); 2776 | if (!noUpdates) Browser.updateResizeListeners(); 2777 | },windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function () { 2778 | // check if SDL is available 2779 | if (typeof SDL != "undefined") { 2780 | var flags = HEAPU32[((SDL.screen)>>2)]; 2781 | flags = flags | 0x00800000; // set SDL_FULLSCREEN flag 2782 | HEAP32[((SDL.screen)>>2)]=flags 2783 | } 2784 | Browser.updateCanvasDimensions(Module['canvas']); 2785 | Browser.updateResizeListeners(); 2786 | },setWindowedCanvasSize:function () { 2787 | // check if SDL is available 2788 | if (typeof SDL != "undefined") { 2789 | var flags = HEAPU32[((SDL.screen)>>2)]; 2790 | flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag 2791 | HEAP32[((SDL.screen)>>2)]=flags 2792 | } 2793 | Browser.updateCanvasDimensions(Module['canvas']); 2794 | Browser.updateResizeListeners(); 2795 | },updateCanvasDimensions:function (canvas, wNative, hNative) { 2796 | if (wNative && hNative) { 2797 | canvas.widthNative = wNative; 2798 | canvas.heightNative = hNative; 2799 | } else { 2800 | wNative = canvas.widthNative; 2801 | hNative = canvas.heightNative; 2802 | } 2803 | var w = wNative; 2804 | var h = hNative; 2805 | if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { 2806 | if (w/h < Module['forcedAspectRatio']) { 2807 | w = Math.round(h * Module['forcedAspectRatio']); 2808 | } else { 2809 | h = Math.round(w / Module['forcedAspectRatio']); 2810 | } 2811 | } 2812 | if (((document['fullscreenElement'] || document['mozFullScreenElement'] || 2813 | document['msFullscreenElement'] || document['webkitFullscreenElement'] || 2814 | document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { 2815 | var factor = Math.min(screen.width / w, screen.height / h); 2816 | w = Math.round(w * factor); 2817 | h = Math.round(h * factor); 2818 | } 2819 | if (Browser.resizeCanvas) { 2820 | if (canvas.width != w) canvas.width = w; 2821 | if (canvas.height != h) canvas.height = h; 2822 | if (typeof canvas.style != 'undefined') { 2823 | canvas.style.removeProperty( "width"); 2824 | canvas.style.removeProperty("height"); 2825 | } 2826 | } else { 2827 | if (canvas.width != wNative) canvas.width = wNative; 2828 | if (canvas.height != hNative) canvas.height = hNative; 2829 | if (typeof canvas.style != 'undefined') { 2830 | if (w != wNative || h != hNative) { 2831 | canvas.style.setProperty( "width", w + "px", "important"); 2832 | canvas.style.setProperty("height", h + "px", "important"); 2833 | } else { 2834 | canvas.style.removeProperty( "width"); 2835 | canvas.style.removeProperty("height"); 2836 | } 2837 | } 2838 | } 2839 | },wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function () { 2840 | var handle = Browser.nextWgetRequestHandle; 2841 | Browser.nextWgetRequestHandle++; 2842 | return handle; 2843 | }};var EmterpreterAsync={initted:false,state:0,saveStack:"",yieldCallbacks:[],postAsync:null,restartFunc:null,asyncFinalizers:[],ensureInit:function () { 2844 | if (this.initted) return; 2845 | this.initted = true; 2846 | abortDecorators.push(function(output, what) { 2847 | if (EmterpreterAsync.state === 1 || EmterpreterAsync.state === 2) { 2848 | return output + '\nThis error happened during an emterpreter-async operation. Was there non-emterpreted code on the stack during save (which is unallowed)? If so, you may want to adjust EMTERPRETIFY_BLACKLIST, EMTERPRETIFY_WHITELIST. For reference, this is what the stack looked like when we tried to save it: ' + [EmterpreterAsync.state, EmterpreterAsync.saveStack]; 2849 | } 2850 | return output; 2851 | }); 2852 | },setState:function (s) { 2853 | this.ensureInit(); 2854 | this.state = s; 2855 | Module['setAsyncState'](s); 2856 | },handle:function (doAsyncOp, yieldDuring) { 2857 | Module['noExitRuntime'] = true; 2858 | if (EmterpreterAsync.state === 0) { 2859 | // save the stack we want to resume. this lets other code run in between 2860 | // XXX this assumes that this stack top never ever leak! exceptions might violate that 2861 | var stack = new Int32Array(HEAP32.subarray(EMTSTACKTOP>>2, Module['emtStackSave']()>>2)); 2862 | var stacktop = Module['stackSave'](); 2863 | 2864 | var resumedCallbacksForYield = false; 2865 | function resumeCallbacksForYield() { 2866 | if (resumedCallbacksForYield) return; 2867 | resumedCallbacksForYield = true; 2868 | // allow async callbacks, and also make sure to call the specified yield callbacks. we must 2869 | // do this when nothing is on the stack, i.e. after it unwound 2870 | EmterpreterAsync.yieldCallbacks.forEach(function(func) { 2871 | func(); 2872 | }); 2873 | Browser.resumeAsyncCallbacks(); // if we were paused (e.g. we are after a sleep), then since we are now yielding, it is safe to call callbacks 2874 | } 2875 | 2876 | var callingDoAsyncOp = 1; // if resume is called synchronously - during the doAsyncOp - we must make it truly async, for consistency 2877 | 2878 | doAsyncOp(function resume(post) { 2879 | if (ABORT) { 2880 | return; 2881 | } 2882 | if (callingDoAsyncOp) { 2883 | assert(callingDoAsyncOp === 1); // avoid infinite recursion 2884 | callingDoAsyncOp++; 2885 | setTimeout(function() { 2886 | resume(post); 2887 | }, 0); 2888 | return; 2889 | } 2890 | 2891 | assert(EmterpreterAsync.state === 1 || EmterpreterAsync.state === 3); 2892 | EmterpreterAsync.setState(3); 2893 | if (yieldDuring) { 2894 | resumeCallbacksForYield(); 2895 | } 2896 | // copy the stack back in and resume 2897 | HEAP32.set(stack, EMTSTACKTOP>>2); 2898 | assert(stacktop === Module['stackSave']()); // nothing should have modified the stack meanwhile 2899 | // we are now starting to restore the stack 2900 | EmterpreterAsync.setState(2); 2901 | // Resume the main loop 2902 | if (Browser.mainLoop.func) { 2903 | Browser.mainLoop.resume(); 2904 | } 2905 | assert(!EmterpreterAsync.postAsync); 2906 | EmterpreterAsync.postAsync = post || null; 2907 | var asyncReturnValue; 2908 | if (!EmterpreterAsync.restartFunc) { 2909 | // pc of the first function, from which we can reconstruct the rest, is at position 0 on the stack 2910 | Module['emterpret'](stack[0]); 2911 | } else { 2912 | // the restartFunc knows how to emterpret the proper function, and also returns the return value 2913 | asyncReturnValue = EmterpreterAsync.restartFunc(); 2914 | } 2915 | if (!yieldDuring && EmterpreterAsync.state === 0) { 2916 | // if we did *not* do another async operation, then we know that nothing is conceptually on the stack now, and we can re-allow async callbacks as well as run the queued ones right now 2917 | Browser.resumeAsyncCallbacks(); 2918 | } 2919 | if (EmterpreterAsync.state === 0) { 2920 | // All async operations have concluded. 2921 | // In particular, if we were in an async ccall, we have 2922 | // consumed the restartFunc and can reset it to null. 2923 | EmterpreterAsync.restartFunc = null; 2924 | // The async finalizers can run now, after all async operations. 2925 | var asyncFinalizers = EmterpreterAsync.asyncFinalizers; 2926 | EmterpreterAsync.asyncFinalizers = []; 2927 | asyncFinalizers.forEach(function(func) { 2928 | func(asyncReturnValue); 2929 | }); 2930 | } 2931 | }); 2932 | 2933 | callingDoAsyncOp = 0; 2934 | 2935 | EmterpreterAsync.setState(1); 2936 | EmterpreterAsync.saveStack = new Error().stack; // we can't call stackTrace() as it calls compiled code 2937 | // Pause the main loop, until we resume 2938 | if (Browser.mainLoop.func) { 2939 | Browser.mainLoop.pause(); 2940 | } 2941 | if (yieldDuring) { 2942 | // do this when we are not on the stack, i.e., the stack unwound. we might be too late, in which case we do it in resume() 2943 | setTimeout(function() { 2944 | resumeCallbacksForYield(); 2945 | }, 0); 2946 | } else { 2947 | Browser.pauseAsyncCallbacks(); 2948 | } 2949 | } else { 2950 | // nothing to do here, the stack was just recreated. reset the state. 2951 | assert(EmterpreterAsync.state === 2); 2952 | EmterpreterAsync.setState(0); 2953 | 2954 | if (EmterpreterAsync.postAsync) { 2955 | var ret = EmterpreterAsync.postAsync(); 2956 | EmterpreterAsync.postAsync = null; 2957 | return ret; 2958 | } 2959 | } 2960 | }};function _emscripten_sleep_with_yield(ms) { 2961 | EmterpreterAsync.handle(function(resume) { 2962 | Browser.safeSetTimeout(resume, ms); 2963 | }, true); 2964 | } 2965 | 2966 | 2967 | 2968 | function _llvm_copysign_f64(x, y) { 2969 | return y < 0 || (y === 0 && 1/y < 0) ? -Math_abs(x) : Math_abs(x); 2970 | } 2971 | 2972 | var _llvm_cos_f64=Math_cos; 2973 | 2974 | 2975 | function _llvm_log10_f32(x) { 2976 | return Math.log(x) / Math.LN10; // TODO: Math.log10, when browser support is there 2977 | }function _llvm_log10_f64(a0 2978 | /*``*/) { 2979 | return _llvm_log10_f32(a0); 2980 | } 2981 | 2982 | 2983 | 2984 | 2985 | 2986 | var _llvm_sin_f64=Math_sin; 2987 | 2988 | var _llvm_trunc_f64=Math_trunc; 2989 | 2990 | 2991 | 2992 | function _emscripten_memcpy_big(dest, src, num) { 2993 | HEAPU8.set(HEAPU8.subarray(src, src+num), dest); 2994 | } 2995 | 2996 | 2997 | 2998 | 2999 | 3000 | 3001 | 3002 | function _mp_js_hook() { 3003 | if (typeof window === 'undefined') { 3004 | var mp_interrupt_char = Module.ccall('mp_hal_get_interrupt_char', 'number', ['number'], ['null']); 3005 | var fs = require('fs'); 3006 | 3007 | var buf = Buffer.alloc(1); 3008 | try { 3009 | var n = fs.readSync(process.stdin.fd, buf, 0, 1); 3010 | if (n > 0) { 3011 | if (buf[0] == mp_interrupt_char) { 3012 | Module.ccall('mp_keyboard_interrupt', 'null', ['null'], ['null']); 3013 | } else { 3014 | process.stdout.write(String.fromCharCode(buf[0])); 3015 | } 3016 | } 3017 | } catch (e) { 3018 | if (e.code === 'EAGAIN') { 3019 | } else { 3020 | throw e; 3021 | } 3022 | } 3023 | } 3024 | } 3025 | 3026 | function _mp_js_ticks_ms() { 3027 | return (new Date()).getTime() - MP_JS_EPOCH; 3028 | } 3029 | 3030 | function _mp_js_write(ptr, len) { 3031 | for (var i = 0; i < len; ++i) { 3032 | if (typeof window === 'undefined') { 3033 | var b = Buffer.alloc(1); 3034 | b.writeInt8(getValue(ptr + i, 'i8')); 3035 | //process.stdout.write(b); 3036 | global.mpjsPrintStdout(b); 3037 | } else { 3038 | var c = String.fromCharCode(getValue(ptr + i, 'i8')); 3039 | var mp_js_stdout = document.getElementById('mp_js_stdout'); 3040 | var print = new Event('print'); 3041 | print.data = c; 3042 | mp_js_stdout.dispatchEvent(print); 3043 | } 3044 | } 3045 | } 3046 | 3047 | 3048 | 3049 | function ___setErrNo(value) { 3050 | if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value; 3051 | else err('failed to set errno from JS'); 3052 | return value; 3053 | } 3054 | 3055 | var _sqrt=Math_sqrt; 3056 | 3057 | Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas, vrDevice) { err("Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead."); Module["requestFullScreen"] = Module["requestFullscreen"]; Browser.requestFullScreen(lockPointer, resizeCanvas, vrDevice) }; 3058 | Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas, vrDevice) { Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice) }; 3059 | Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) }; 3060 | Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) }; 3061 | Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() }; 3062 | Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() }; 3063 | Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() } 3064 | Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) }; 3065 | if (ENVIRONMENT_IS_NODE) { 3066 | _emscripten_get_now = function _emscripten_get_now_actual() { 3067 | var t = process['hrtime'](); 3068 | return t[0] * 1e3 + t[1] / 1e6; 3069 | }; 3070 | } else if (typeof dateNow !== 'undefined') { 3071 | _emscripten_get_now = dateNow; 3072 | } else if (typeof performance === 'object' && performance && typeof performance['now'] === 'function') { 3073 | _emscripten_get_now = function() { return performance['now'](); }; 3074 | } else { 3075 | _emscripten_get_now = Date.now; 3076 | }; 3077 | var ASSERTIONS = true; 3078 | 3079 | // Copyright 2017 The Emscripten Authors. All rights reserved. 3080 | // Emscripten is available under two separate licenses, the MIT license and the 3081 | // University of Illinois/NCSA Open Source License. Both these licenses can be 3082 | // found in the LICENSE file. 3083 | 3084 | /** @type {function(string, boolean=, number=)} */ 3085 | function intArrayFromString(stringy, dontAddNull, length) { 3086 | var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; 3087 | var u8array = new Array(len); 3088 | var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); 3089 | if (dontAddNull) u8array.length = numBytesWritten; 3090 | return u8array; 3091 | } 3092 | 3093 | function intArrayToString(array) { 3094 | var ret = []; 3095 | for (var i = 0; i < array.length; i++) { 3096 | var chr = array[i]; 3097 | if (chr > 0xFF) { 3098 | if (ASSERTIONS) { 3099 | assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.'); 3100 | } 3101 | chr &= 0xFF; 3102 | } 3103 | ret.push(String.fromCharCode(chr)); 3104 | } 3105 | return ret.join(''); 3106 | } 3107 | 3108 | 3109 | // ASM_LIBRARY EXTERN PRIMITIVES: Math_imul,Math_clz32,Math_floor,Math_ceil,Int8Array,Int32Array 3110 | 3111 | 3112 | function nullFunc_dd(x) { err("Invalid function pointer called with signature 'dd'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3113 | 3114 | function nullFunc_ddd(x) { err("Invalid function pointer called with signature 'ddd'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3115 | 3116 | function nullFunc_i(x) { err("Invalid function pointer called with signature 'i'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3117 | 3118 | function nullFunc_ii(x) { err("Invalid function pointer called with signature 'ii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3119 | 3120 | function nullFunc_iidiiii(x) { err("Invalid function pointer called with signature 'iidiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3121 | 3122 | function nullFunc_iii(x) { err("Invalid function pointer called with signature 'iii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3123 | 3124 | function nullFunc_iiii(x) { err("Invalid function pointer called with signature 'iiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3125 | 3126 | function nullFunc_iiiii(x) { err("Invalid function pointer called with signature 'iiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3127 | 3128 | function nullFunc_v(x) { err("Invalid function pointer called with signature 'v'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3129 | 3130 | function nullFunc_vi(x) { err("Invalid function pointer called with signature 'vi'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3131 | 3132 | function nullFunc_vii(x) { err("Invalid function pointer called with signature 'vii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3133 | 3134 | function nullFunc_viii(x) { err("Invalid function pointer called with signature 'viii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3135 | 3136 | function nullFunc_viiii(x) { err("Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3137 | 3138 | function nullFunc_viiiiii(x) { err("Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); err("Build with ASSERTIONS=2 for more info.");abort(x) } 3139 | 3140 | function invoke_i(index) { 3141 | var sp = stackSave(); 3142 | try { 3143 | return dynCall_i(index); 3144 | } catch(e) { 3145 | stackRestore(sp); 3146 | if (e !== e+0 && e !== 'longjmp') throw e; 3147 | _setThrew(1, 0); 3148 | } 3149 | } 3150 | 3151 | function invoke_ii(index,a1) { 3152 | var sp = stackSave(); 3153 | try { 3154 | return dynCall_ii(index,a1); 3155 | } catch(e) { 3156 | stackRestore(sp); 3157 | if (e !== e+0 && e !== 'longjmp') throw e; 3158 | _setThrew(1, 0); 3159 | } 3160 | } 3161 | 3162 | function invoke_iii(index,a1,a2) { 3163 | var sp = stackSave(); 3164 | try { 3165 | return dynCall_iii(index,a1,a2); 3166 | } catch(e) { 3167 | stackRestore(sp); 3168 | if (e !== e+0 && e !== 'longjmp') throw e; 3169 | _setThrew(1, 0); 3170 | } 3171 | } 3172 | 3173 | function invoke_iiii(index,a1,a2,a3) { 3174 | var sp = stackSave(); 3175 | try { 3176 | return dynCall_iiii(index,a1,a2,a3); 3177 | } catch(e) { 3178 | stackRestore(sp); 3179 | if (e !== e+0 && e !== 'longjmp') throw e; 3180 | _setThrew(1, 0); 3181 | } 3182 | } 3183 | 3184 | function invoke_iiiii(index,a1,a2,a3,a4) { 3185 | var sp = stackSave(); 3186 | try { 3187 | return dynCall_iiiii(index,a1,a2,a3,a4); 3188 | } catch(e) { 3189 | stackRestore(sp); 3190 | if (e !== e+0 && e !== 'longjmp') throw e; 3191 | _setThrew(1, 0); 3192 | } 3193 | } 3194 | 3195 | function invoke_v(index) { 3196 | var sp = stackSave(); 3197 | try { 3198 | dynCall_v(index); 3199 | } catch(e) { 3200 | stackRestore(sp); 3201 | if (e !== e+0 && e !== 'longjmp') throw e; 3202 | _setThrew(1, 0); 3203 | } 3204 | } 3205 | 3206 | function invoke_vi(index,a1) { 3207 | var sp = stackSave(); 3208 | try { 3209 | dynCall_vi(index,a1); 3210 | } catch(e) { 3211 | stackRestore(sp); 3212 | if (e !== e+0 && e !== 'longjmp') throw e; 3213 | _setThrew(1, 0); 3214 | } 3215 | } 3216 | 3217 | function invoke_vii(index,a1,a2) { 3218 | var sp = stackSave(); 3219 | try { 3220 | dynCall_vii(index,a1,a2); 3221 | } catch(e) { 3222 | stackRestore(sp); 3223 | if (e !== e+0 && e !== 'longjmp') throw e; 3224 | _setThrew(1, 0); 3225 | } 3226 | } 3227 | 3228 | function invoke_viii(index,a1,a2,a3) { 3229 | var sp = stackSave(); 3230 | try { 3231 | dynCall_viii(index,a1,a2,a3); 3232 | } catch(e) { 3233 | stackRestore(sp); 3234 | if (e !== e+0 && e !== 'longjmp') throw e; 3235 | _setThrew(1, 0); 3236 | } 3237 | } 3238 | 3239 | function invoke_viiii(index,a1,a2,a3,a4) { 3240 | var sp = stackSave(); 3241 | try { 3242 | dynCall_viiii(index,a1,a2,a3,a4); 3243 | } catch(e) { 3244 | stackRestore(sp); 3245 | if (e !== e+0 && e !== 'longjmp') throw e; 3246 | _setThrew(1, 0); 3247 | } 3248 | } 3249 | 3250 | var asmGlobalArg = {} 3251 | 3252 | var asmLibraryArg = { 3253 | "abort": abort, 3254 | "setTempRet0": setTempRet0, 3255 | "getTempRet0": getTempRet0, 3256 | "abortStackOverflow": abortStackOverflow, 3257 | "abortStackOverflowEmterpreter": abortStackOverflowEmterpreter, 3258 | "nullFunc_dd": nullFunc_dd, 3259 | "nullFunc_ddd": nullFunc_ddd, 3260 | "nullFunc_i": nullFunc_i, 3261 | "nullFunc_ii": nullFunc_ii, 3262 | "nullFunc_iidiiii": nullFunc_iidiiii, 3263 | "nullFunc_iii": nullFunc_iii, 3264 | "nullFunc_iiii": nullFunc_iiii, 3265 | "nullFunc_iiiii": nullFunc_iiiii, 3266 | "nullFunc_v": nullFunc_v, 3267 | "nullFunc_vi": nullFunc_vi, 3268 | "nullFunc_vii": nullFunc_vii, 3269 | "nullFunc_viii": nullFunc_viii, 3270 | "nullFunc_viiii": nullFunc_viiii, 3271 | "nullFunc_viiiiii": nullFunc_viiiiii, 3272 | "invoke_i": invoke_i, 3273 | "invoke_ii": invoke_ii, 3274 | "invoke_iii": invoke_iii, 3275 | "invoke_iiii": invoke_iiii, 3276 | "invoke_iiiii": invoke_iiiii, 3277 | "invoke_v": invoke_v, 3278 | "invoke_vi": invoke_vi, 3279 | "invoke_vii": invoke_vii, 3280 | "invoke_viii": invoke_viii, 3281 | "invoke_viiii": invoke_viiii, 3282 | "___lock": ___lock, 3283 | "___setErrNo": ___setErrNo, 3284 | "___syscall140": ___syscall140, 3285 | "___syscall146": ___syscall146, 3286 | "___syscall54": ___syscall54, 3287 | "___syscall6": ___syscall6, 3288 | "___unlock": ___unlock, 3289 | "_emscripten_get_heap_size": _emscripten_get_heap_size, 3290 | "_emscripten_get_now": _emscripten_get_now, 3291 | "_emscripten_longjmp": _emscripten_longjmp, 3292 | "_emscripten_memcpy_big": _emscripten_memcpy_big, 3293 | "_emscripten_resize_heap": _emscripten_resize_heap, 3294 | "_emscripten_run_script_string": _emscripten_run_script_string, 3295 | "_emscripten_set_main_loop": _emscripten_set_main_loop, 3296 | "_emscripten_set_main_loop_timing": _emscripten_set_main_loop_timing, 3297 | "_emscripten_sleep_with_yield": _emscripten_sleep_with_yield, 3298 | "_llvm_copysign_f64": _llvm_copysign_f64, 3299 | "_llvm_cos_f64": _llvm_cos_f64, 3300 | "_llvm_cttz_i32": _llvm_cttz_i32, 3301 | "_llvm_log10_f32": _llvm_log10_f32, 3302 | "_llvm_log10_f64": _llvm_log10_f64, 3303 | "_llvm_sin_f64": _llvm_sin_f64, 3304 | "_llvm_trunc_f64": _llvm_trunc_f64, 3305 | "_longjmp": _longjmp, 3306 | "_mp_js_hook": _mp_js_hook, 3307 | "_mp_js_ticks_ms": _mp_js_ticks_ms, 3308 | "_mp_js_write": _mp_js_write, 3309 | "_sqrt": _sqrt, 3310 | "abortOnCannotGrowMemory": abortOnCannotGrowMemory, 3311 | "flush_NO_FILESYSTEM": flush_NO_FILESYSTEM, 3312 | "tempDoublePtr": tempDoublePtr, 3313 | "DYNAMICTOP_PTR": DYNAMICTOP_PTR, 3314 | "EMTSTACKTOP": EMTSTACKTOP, 3315 | "EMT_STACK_MAX": EMT_STACK_MAX, 3316 | "eb": eb 3317 | } 3318 | // EMSCRIPTEN_START_ASM 3319 | var asm =Module["asm"]// EMSCRIPTEN_END_ASM 3320 | (asmGlobalArg, asmLibraryArg, buffer); 3321 | 3322 | var real____errno_location = asm["___errno_location"]; asm["___errno_location"] = function() { 3323 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3324 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3325 | return real____errno_location.apply(null, arguments); 3326 | }; 3327 | 3328 | var real____muldi3 = asm["___muldi3"]; asm["___muldi3"] = function() { 3329 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3330 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3331 | return real____muldi3.apply(null, arguments); 3332 | }; 3333 | 3334 | var real____udivdi3 = asm["___udivdi3"]; asm["___udivdi3"] = function() { 3335 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3336 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3337 | return real____udivdi3.apply(null, arguments); 3338 | }; 3339 | 3340 | var real__bitshift64Ashr = asm["_bitshift64Ashr"]; asm["_bitshift64Ashr"] = function() { 3341 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3342 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3343 | return real__bitshift64Ashr.apply(null, arguments); 3344 | }; 3345 | 3346 | var real__bitshift64Lshr = asm["_bitshift64Lshr"]; asm["_bitshift64Lshr"] = function() { 3347 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3348 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3349 | return real__bitshift64Lshr.apply(null, arguments); 3350 | }; 3351 | 3352 | var real__bitshift64Shl = asm["_bitshift64Shl"]; asm["_bitshift64Shl"] = function() { 3353 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3354 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3355 | return real__bitshift64Shl.apply(null, arguments); 3356 | }; 3357 | 3358 | var real__fflush = asm["_fflush"]; asm["_fflush"] = function() { 3359 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3360 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3361 | return real__fflush.apply(null, arguments); 3362 | }; 3363 | 3364 | var real__free = asm["_free"]; asm["_free"] = function() { 3365 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3366 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3367 | return real__free.apply(null, arguments); 3368 | }; 3369 | 3370 | var real__i64Add = asm["_i64Add"]; asm["_i64Add"] = function() { 3371 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3372 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3373 | return real__i64Add.apply(null, arguments); 3374 | }; 3375 | 3376 | var real__i64Subtract = asm["_i64Subtract"]; asm["_i64Subtract"] = function() { 3377 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3378 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3379 | return real__i64Subtract.apply(null, arguments); 3380 | }; 3381 | 3382 | var real__llvm_nearbyint_f64 = asm["_llvm_nearbyint_f64"]; asm["_llvm_nearbyint_f64"] = function() { 3383 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3384 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3385 | return real__llvm_nearbyint_f64.apply(null, arguments); 3386 | }; 3387 | 3388 | var real__malloc = asm["_malloc"]; asm["_malloc"] = function() { 3389 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3390 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3391 | return real__malloc.apply(null, arguments); 3392 | }; 3393 | 3394 | var real__memmove = asm["_memmove"]; asm["_memmove"] = function() { 3395 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3396 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3397 | return real__memmove.apply(null, arguments); 3398 | }; 3399 | 3400 | var real__mp_hal_get_interrupt_char = asm["_mp_hal_get_interrupt_char"]; asm["_mp_hal_get_interrupt_char"] = function() { 3401 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3402 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3403 | return real__mp_hal_get_interrupt_char.apply(null, arguments); 3404 | }; 3405 | 3406 | var real__mp_js_do_str = asm["_mp_js_do_str"]; asm["_mp_js_do_str"] = function() { 3407 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3408 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3409 | return real__mp_js_do_str.apply(null, arguments); 3410 | }; 3411 | 3412 | var real__mp_js_init = asm["_mp_js_init"]; asm["_mp_js_init"] = function() { 3413 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3414 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3415 | return real__mp_js_init.apply(null, arguments); 3416 | }; 3417 | 3418 | var real__mp_js_init_repl = asm["_mp_js_init_repl"]; asm["_mp_js_init_repl"] = function() { 3419 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3420 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3421 | return real__mp_js_init_repl.apply(null, arguments); 3422 | }; 3423 | 3424 | var real__mp_js_process_char = asm["_mp_js_process_char"]; asm["_mp_js_process_char"] = function() { 3425 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3426 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3427 | return real__mp_js_process_char.apply(null, arguments); 3428 | }; 3429 | 3430 | var real__mp_keyboard_interrupt = asm["_mp_keyboard_interrupt"]; asm["_mp_keyboard_interrupt"] = function() { 3431 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3432 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3433 | return real__mp_keyboard_interrupt.apply(null, arguments); 3434 | }; 3435 | 3436 | var real__realloc = asm["_realloc"]; asm["_realloc"] = function() { 3437 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3438 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3439 | return real__realloc.apply(null, arguments); 3440 | }; 3441 | 3442 | var real__saveSetjmp = asm["_saveSetjmp"]; asm["_saveSetjmp"] = function() { 3443 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3444 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3445 | return real__saveSetjmp.apply(null, arguments); 3446 | }; 3447 | 3448 | var real__sbrk = asm["_sbrk"]; asm["_sbrk"] = function() { 3449 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3450 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3451 | return real__sbrk.apply(null, arguments); 3452 | }; 3453 | 3454 | var real__setThrew = asm["_setThrew"]; asm["_setThrew"] = function() { 3455 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3456 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3457 | return real__setThrew.apply(null, arguments); 3458 | }; 3459 | 3460 | var real__testSetjmp = asm["_testSetjmp"]; asm["_testSetjmp"] = function() { 3461 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3462 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3463 | return real__testSetjmp.apply(null, arguments); 3464 | }; 3465 | 3466 | var real_emtStackRestore = asm["emtStackRestore"]; asm["emtStackRestore"] = function() { 3467 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3468 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3469 | return real_emtStackRestore.apply(null, arguments); 3470 | }; 3471 | 3472 | var real_emtStackSave = asm["emtStackSave"]; asm["emtStackSave"] = function() { 3473 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3474 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3475 | return real_emtStackSave.apply(null, arguments); 3476 | }; 3477 | 3478 | var real_emterpret = asm["emterpret"]; asm["emterpret"] = function() { 3479 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3480 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3481 | return real_emterpret.apply(null, arguments); 3482 | }; 3483 | 3484 | var real_establishStackSpace = asm["establishStackSpace"]; asm["establishStackSpace"] = function() { 3485 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3486 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3487 | return real_establishStackSpace.apply(null, arguments); 3488 | }; 3489 | 3490 | var real_getEmtStackMax = asm["getEmtStackMax"]; asm["getEmtStackMax"] = function() { 3491 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3492 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3493 | return real_getEmtStackMax.apply(null, arguments); 3494 | }; 3495 | 3496 | var real_setAsyncState = asm["setAsyncState"]; asm["setAsyncState"] = function() { 3497 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3498 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3499 | return real_setAsyncState.apply(null, arguments); 3500 | }; 3501 | 3502 | var real_setEmtStackMax = asm["setEmtStackMax"]; asm["setEmtStackMax"] = function() { 3503 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3504 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3505 | return real_setEmtStackMax.apply(null, arguments); 3506 | }; 3507 | 3508 | var real_stackAlloc = asm["stackAlloc"]; asm["stackAlloc"] = function() { 3509 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3510 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3511 | return real_stackAlloc.apply(null, arguments); 3512 | }; 3513 | 3514 | var real_stackRestore = asm["stackRestore"]; asm["stackRestore"] = function() { 3515 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3516 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3517 | return real_stackRestore.apply(null, arguments); 3518 | }; 3519 | 3520 | var real_stackSave = asm["stackSave"]; asm["stackSave"] = function() { 3521 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3522 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3523 | return real_stackSave.apply(null, arguments); 3524 | }; 3525 | Module["asm"] = asm; 3526 | var ___errno_location = Module["___errno_location"] = function() { 3527 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3528 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3529 | return Module["asm"]["___errno_location"].apply(null, arguments) }; 3530 | var ___muldi3 = Module["___muldi3"] = function() { 3531 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3532 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3533 | return Module["asm"]["___muldi3"].apply(null, arguments) }; 3534 | var ___udivdi3 = Module["___udivdi3"] = function() { 3535 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3536 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3537 | return Module["asm"]["___udivdi3"].apply(null, arguments) }; 3538 | var _bitshift64Ashr = Module["_bitshift64Ashr"] = function() { 3539 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3540 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3541 | return Module["asm"]["_bitshift64Ashr"].apply(null, arguments) }; 3542 | var _bitshift64Lshr = Module["_bitshift64Lshr"] = function() { 3543 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3544 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3545 | return Module["asm"]["_bitshift64Lshr"].apply(null, arguments) }; 3546 | var _bitshift64Shl = Module["_bitshift64Shl"] = function() { 3547 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3548 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3549 | return Module["asm"]["_bitshift64Shl"].apply(null, arguments) }; 3550 | var _fflush = Module["_fflush"] = function() { 3551 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3552 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3553 | return Module["asm"]["_fflush"].apply(null, arguments) }; 3554 | var _free = Module["_free"] = function() { 3555 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3556 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3557 | return Module["asm"]["_free"].apply(null, arguments) }; 3558 | var _i64Add = Module["_i64Add"] = function() { 3559 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3560 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3561 | return Module["asm"]["_i64Add"].apply(null, arguments) }; 3562 | var _i64Subtract = Module["_i64Subtract"] = function() { 3563 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3564 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3565 | return Module["asm"]["_i64Subtract"].apply(null, arguments) }; 3566 | var _llvm_nearbyint_f64 = Module["_llvm_nearbyint_f64"] = function() { 3567 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3568 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3569 | return Module["asm"]["_llvm_nearbyint_f64"].apply(null, arguments) }; 3570 | var _malloc = Module["_malloc"] = function() { 3571 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3572 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3573 | return Module["asm"]["_malloc"].apply(null, arguments) }; 3574 | var _memcpy = Module["_memcpy"] = function() { 3575 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3576 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3577 | return Module["asm"]["_memcpy"].apply(null, arguments) }; 3578 | var _memmove = Module["_memmove"] = function() { 3579 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3580 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3581 | return Module["asm"]["_memmove"].apply(null, arguments) }; 3582 | var _memset = Module["_memset"] = function() { 3583 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3584 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3585 | return Module["asm"]["_memset"].apply(null, arguments) }; 3586 | var _mp_hal_get_interrupt_char = Module["_mp_hal_get_interrupt_char"] = function() { 3587 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3588 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3589 | return Module["asm"]["_mp_hal_get_interrupt_char"].apply(null, arguments) }; 3590 | var _mp_js_do_str = Module["_mp_js_do_str"] = function() { 3591 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3592 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3593 | return Module["asm"]["_mp_js_do_str"].apply(null, arguments) }; 3594 | var _mp_js_init = Module["_mp_js_init"] = function() { 3595 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3596 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3597 | return Module["asm"]["_mp_js_init"].apply(null, arguments) }; 3598 | var _mp_js_init_repl = Module["_mp_js_init_repl"] = function() { 3599 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3600 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3601 | return Module["asm"]["_mp_js_init_repl"].apply(null, arguments) }; 3602 | var _mp_js_process_char = Module["_mp_js_process_char"] = function() { 3603 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3604 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3605 | return Module["asm"]["_mp_js_process_char"].apply(null, arguments) }; 3606 | var _mp_keyboard_interrupt = Module["_mp_keyboard_interrupt"] = function() { 3607 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3608 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3609 | return Module["asm"]["_mp_keyboard_interrupt"].apply(null, arguments) }; 3610 | var _realloc = Module["_realloc"] = function() { 3611 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3612 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3613 | return Module["asm"]["_realloc"].apply(null, arguments) }; 3614 | var _saveSetjmp = Module["_saveSetjmp"] = function() { 3615 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3616 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3617 | return Module["asm"]["_saveSetjmp"].apply(null, arguments) }; 3618 | var _sbrk = Module["_sbrk"] = function() { 3619 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3620 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3621 | return Module["asm"]["_sbrk"].apply(null, arguments) }; 3622 | var _setThrew = Module["_setThrew"] = function() { 3623 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3624 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3625 | return Module["asm"]["_setThrew"].apply(null, arguments) }; 3626 | var _testSetjmp = Module["_testSetjmp"] = function() { 3627 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3628 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3629 | return Module["asm"]["_testSetjmp"].apply(null, arguments) }; 3630 | var emtStackRestore = Module["emtStackRestore"] = function() { 3631 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3632 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3633 | return Module["asm"]["emtStackRestore"].apply(null, arguments) }; 3634 | var emtStackSave = Module["emtStackSave"] = function() { 3635 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3636 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3637 | return Module["asm"]["emtStackSave"].apply(null, arguments) }; 3638 | var emterpret = Module["emterpret"] = function() { 3639 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3640 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3641 | return Module["asm"]["emterpret"].apply(null, arguments) }; 3642 | var establishStackSpace = Module["establishStackSpace"] = function() { 3643 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3644 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3645 | return Module["asm"]["establishStackSpace"].apply(null, arguments) }; 3646 | var getEmtStackMax = Module["getEmtStackMax"] = function() { 3647 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3648 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3649 | return Module["asm"]["getEmtStackMax"].apply(null, arguments) }; 3650 | var setAsyncState = Module["setAsyncState"] = function() { 3651 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3652 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3653 | return Module["asm"]["setAsyncState"].apply(null, arguments) }; 3654 | var setEmtStackMax = Module["setEmtStackMax"] = function() { 3655 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3656 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3657 | return Module["asm"]["setEmtStackMax"].apply(null, arguments) }; 3658 | var stackAlloc = Module["stackAlloc"] = function() { 3659 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3660 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3661 | return Module["asm"]["stackAlloc"].apply(null, arguments) }; 3662 | var stackRestore = Module["stackRestore"] = function() { 3663 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3664 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3665 | return Module["asm"]["stackRestore"].apply(null, arguments) }; 3666 | var stackSave = Module["stackSave"] = function() { 3667 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3668 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3669 | return Module["asm"]["stackSave"].apply(null, arguments) }; 3670 | var dynCall_dd = Module["dynCall_dd"] = function() { 3671 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3672 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3673 | return Module["asm"]["dynCall_dd"].apply(null, arguments) }; 3674 | var dynCall_ddd = Module["dynCall_ddd"] = function() { 3675 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3676 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3677 | return Module["asm"]["dynCall_ddd"].apply(null, arguments) }; 3678 | var dynCall_i = Module["dynCall_i"] = function() { 3679 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3680 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3681 | return Module["asm"]["dynCall_i"].apply(null, arguments) }; 3682 | var dynCall_ii = Module["dynCall_ii"] = function() { 3683 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3684 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3685 | return Module["asm"]["dynCall_ii"].apply(null, arguments) }; 3686 | var dynCall_iidiiii = Module["dynCall_iidiiii"] = function() { 3687 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3688 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3689 | return Module["asm"]["dynCall_iidiiii"].apply(null, arguments) }; 3690 | var dynCall_iii = Module["dynCall_iii"] = function() { 3691 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3692 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3693 | return Module["asm"]["dynCall_iii"].apply(null, arguments) }; 3694 | var dynCall_iiii = Module["dynCall_iiii"] = function() { 3695 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3696 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3697 | return Module["asm"]["dynCall_iiii"].apply(null, arguments) }; 3698 | var dynCall_iiiii = Module["dynCall_iiiii"] = function() { 3699 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3700 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3701 | return Module["asm"]["dynCall_iiiii"].apply(null, arguments) }; 3702 | var dynCall_v = Module["dynCall_v"] = function() { 3703 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3704 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3705 | return Module["asm"]["dynCall_v"].apply(null, arguments) }; 3706 | var dynCall_vi = Module["dynCall_vi"] = function() { 3707 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3708 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3709 | return Module["asm"]["dynCall_vi"].apply(null, arguments) }; 3710 | var dynCall_vii = Module["dynCall_vii"] = function() { 3711 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3712 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3713 | return Module["asm"]["dynCall_vii"].apply(null, arguments) }; 3714 | var dynCall_viii = Module["dynCall_viii"] = function() { 3715 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3716 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3717 | return Module["asm"]["dynCall_viii"].apply(null, arguments) }; 3718 | var dynCall_viiii = Module["dynCall_viiii"] = function() { 3719 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3720 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3721 | return Module["asm"]["dynCall_viiii"].apply(null, arguments) }; 3722 | var dynCall_viiiiii = Module["dynCall_viiiiii"] = function() { 3723 | assert(runtimeInitialized, 'you need to wait for the runtime to be ready (e.g. wait for main() to be called)'); 3724 | assert(!runtimeExited, 'the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)'); 3725 | return Module["asm"]["dynCall_viiiiii"].apply(null, arguments) }; 3726 | ; 3727 | 3728 | 3729 | 3730 | // === Auto-generated postamble setup entry stuff === 3731 | 3732 | Module['asm'] = asm; 3733 | 3734 | if (!Module["intArrayFromString"]) Module["intArrayFromString"] = function() { abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3735 | if (!Module["intArrayToString"]) Module["intArrayToString"] = function() { abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3736 | Module["ccall"] = ccall; 3737 | Module["cwrap"] = cwrap; 3738 | if (!Module["setValue"]) Module["setValue"] = function() { abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3739 | if (!Module["getValue"]) Module["getValue"] = function() { abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3740 | if (!Module["allocate"]) Module["allocate"] = function() { abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3741 | if (!Module["getMemory"]) Module["getMemory"] = function() { abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3742 | if (!Module["AsciiToString"]) Module["AsciiToString"] = function() { abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3743 | if (!Module["stringToAscii"]) Module["stringToAscii"] = function() { abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3744 | if (!Module["UTF8ArrayToString"]) Module["UTF8ArrayToString"] = function() { abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3745 | if (!Module["UTF8ToString"]) Module["UTF8ToString"] = function() { abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3746 | if (!Module["stringToUTF8Array"]) Module["stringToUTF8Array"] = function() { abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3747 | if (!Module["stringToUTF8"]) Module["stringToUTF8"] = function() { abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3748 | if (!Module["lengthBytesUTF8"]) Module["lengthBytesUTF8"] = function() { abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3749 | if (!Module["UTF16ToString"]) Module["UTF16ToString"] = function() { abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3750 | if (!Module["stringToUTF16"]) Module["stringToUTF16"] = function() { abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3751 | if (!Module["lengthBytesUTF16"]) Module["lengthBytesUTF16"] = function() { abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3752 | if (!Module["UTF32ToString"]) Module["UTF32ToString"] = function() { abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3753 | if (!Module["stringToUTF32"]) Module["stringToUTF32"] = function() { abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3754 | if (!Module["lengthBytesUTF32"]) Module["lengthBytesUTF32"] = function() { abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3755 | if (!Module["allocateUTF8"]) Module["allocateUTF8"] = function() { abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3756 | if (!Module["stackTrace"]) Module["stackTrace"] = function() { abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3757 | if (!Module["addOnPreRun"]) Module["addOnPreRun"] = function() { abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3758 | if (!Module["addOnInit"]) Module["addOnInit"] = function() { abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3759 | if (!Module["addOnPreMain"]) Module["addOnPreMain"] = function() { abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3760 | if (!Module["addOnExit"]) Module["addOnExit"] = function() { abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3761 | if (!Module["addOnPostRun"]) Module["addOnPostRun"] = function() { abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3762 | if (!Module["writeStringToMemory"]) Module["writeStringToMemory"] = function() { abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3763 | if (!Module["writeArrayToMemory"]) Module["writeArrayToMemory"] = function() { abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3764 | if (!Module["writeAsciiToMemory"]) Module["writeAsciiToMemory"] = function() { abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3765 | if (!Module["addRunDependency"]) Module["addRunDependency"] = function() { abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3766 | if (!Module["removeRunDependency"]) Module["removeRunDependency"] = function() { abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3767 | if (!Module["ENV"]) Module["ENV"] = function() { abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3768 | if (!Module["FS"]) Module["FS"] = function() { abort("'FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3769 | if (!Module["FS_createFolder"]) Module["FS_createFolder"] = function() { abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3770 | if (!Module["FS_createPath"]) Module["FS_createPath"] = function() { abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3771 | if (!Module["FS_createDataFile"]) Module["FS_createDataFile"] = function() { abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3772 | if (!Module["FS_createPreloadedFile"]) Module["FS_createPreloadedFile"] = function() { abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3773 | if (!Module["FS_createLazyFile"]) Module["FS_createLazyFile"] = function() { abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3774 | if (!Module["FS_createLink"]) Module["FS_createLink"] = function() { abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3775 | if (!Module["FS_createDevice"]) Module["FS_createDevice"] = function() { abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3776 | if (!Module["FS_unlink"]) Module["FS_unlink"] = function() { abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you") }; 3777 | if (!Module["GL"]) Module["GL"] = function() { abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3778 | if (!Module["dynamicAlloc"]) Module["dynamicAlloc"] = function() { abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3779 | if (!Module["warnOnce"]) Module["warnOnce"] = function() { abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3780 | if (!Module["loadDynamicLibrary"]) Module["loadDynamicLibrary"] = function() { abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3781 | if (!Module["loadWebAssemblyModule"]) Module["loadWebAssemblyModule"] = function() { abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3782 | if (!Module["getLEB"]) Module["getLEB"] = function() { abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3783 | if (!Module["getFunctionTables"]) Module["getFunctionTables"] = function() { abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3784 | if (!Module["alignFunctionTables"]) Module["alignFunctionTables"] = function() { abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3785 | if (!Module["registerFunctions"]) Module["registerFunctions"] = function() { abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3786 | if (!Module["addFunction"]) Module["addFunction"] = function() { abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3787 | if (!Module["removeFunction"]) Module["removeFunction"] = function() { abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3788 | if (!Module["getFuncWrapper"]) Module["getFuncWrapper"] = function() { abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3789 | if (!Module["prettyPrint"]) Module["prettyPrint"] = function() { abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3790 | if (!Module["makeBigInt"]) Module["makeBigInt"] = function() { abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3791 | if (!Module["dynCall"]) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3792 | if (!Module["getCompilerSetting"]) Module["getCompilerSetting"] = function() { abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3793 | if (!Module["stackSave"]) Module["stackSave"] = function() { abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3794 | if (!Module["stackRestore"]) Module["stackRestore"] = function() { abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3795 | if (!Module["stackAlloc"]) Module["stackAlloc"] = function() { abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3796 | if (!Module["establishStackSpace"]) Module["establishStackSpace"] = function() { abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3797 | if (!Module["print"]) Module["print"] = function() { abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3798 | if (!Module["printErr"]) Module["printErr"] = function() { abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3799 | if (!Module["getTempRet0"]) Module["getTempRet0"] = function() { abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3800 | if (!Module["setTempRet0"]) Module["setTempRet0"] = function() { abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") }; 3801 | if (!Module["Pointer_stringify"]) Module["Pointer_stringify"] = function() { abort("'Pointer_stringify' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };if (!Module["ALLOC_NORMAL"]) Object.defineProperty(Module, "ALLOC_NORMAL", { get: function() { abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } }); 3802 | if (!Module["ALLOC_STACK"]) Object.defineProperty(Module, "ALLOC_STACK", { get: function() { abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } }); 3803 | if (!Module["ALLOC_DYNAMIC"]) Object.defineProperty(Module, "ALLOC_DYNAMIC", { get: function() { abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } }); 3804 | if (!Module["ALLOC_NONE"]) Object.defineProperty(Module, "ALLOC_NONE", { get: function() { abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } }); 3805 | 3806 | 3807 | 3808 | 3809 | /** 3810 | * @constructor 3811 | * @extends {Error} 3812 | * @this {ExitStatus} 3813 | */ 3814 | function ExitStatus(status) { 3815 | this.name = "ExitStatus"; 3816 | this.message = "Program terminated with exit(" + status + ")"; 3817 | this.status = status; 3818 | }; 3819 | ExitStatus.prototype = new Error(); 3820 | ExitStatus.prototype.constructor = ExitStatus; 3821 | 3822 | var calledMain = false; 3823 | 3824 | dependenciesFulfilled = function runCaller() { 3825 | // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) 3826 | if (!Module['calledRun']) run(); 3827 | if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled 3828 | } 3829 | 3830 | 3831 | 3832 | 3833 | 3834 | /** @type {function(Array=)} */ 3835 | function run(args) { 3836 | args = args || Module['arguments']; 3837 | 3838 | if (runDependencies > 0) { 3839 | return; 3840 | } 3841 | 3842 | writeStackCookie(); 3843 | 3844 | preRun(); 3845 | 3846 | if (runDependencies > 0) return; // a preRun added a dependency, run will be called later 3847 | if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame 3848 | 3849 | function doRun() { 3850 | if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening 3851 | Module['calledRun'] = true; 3852 | 3853 | if (ABORT) return; 3854 | 3855 | ensureInitRuntime(); 3856 | 3857 | preMain(); 3858 | 3859 | if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); 3860 | 3861 | assert(!Module['_main'], 'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'); 3862 | 3863 | postRun(); 3864 | } 3865 | 3866 | if (Module['setStatus']) { 3867 | Module['setStatus']('Running...'); 3868 | setTimeout(function() { 3869 | setTimeout(function() { 3870 | Module['setStatus'](''); 3871 | }, 1); 3872 | doRun(); 3873 | }, 1); 3874 | } else { 3875 | doRun(); 3876 | } 3877 | checkStackCookie(); 3878 | } 3879 | Module['run'] = run; 3880 | 3881 | function checkUnflushedContent() { 3882 | // Compiler settings do not allow exiting the runtime, so flushing 3883 | // the streams is not possible. but in ASSERTIONS mode we check 3884 | // if there was something to flush, and if so tell the user they 3885 | // should request that the runtime be exitable. 3886 | // Normally we would not even include flush() at all, but in ASSERTIONS 3887 | // builds we do so just for this check, and here we see if there is any 3888 | // content to flush, that is, we check if there would have been 3889 | // something a non-ASSERTIONS build would have not seen. 3890 | // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0 3891 | // mode (which has its own special function for this; otherwise, all 3892 | // the code is inside libc) 3893 | var print = out; 3894 | var printErr = err; 3895 | var has = false; 3896 | out = err = function(x) { 3897 | has = true; 3898 | } 3899 | try { // it doesn't matter if it fails 3900 | var flush = flush_NO_FILESYSTEM; 3901 | if (flush) flush(0); 3902 | } catch(e) {} 3903 | out = print; 3904 | err = printErr; 3905 | if (has) { 3906 | 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.'); 3907 | warnOnce('(this may also be due to not including full filesystem support - try building with -s FORCE_FILESYSTEM=1)'); 3908 | } 3909 | } 3910 | 3911 | function exit(status, implicit) { 3912 | checkUnflushedContent(); 3913 | 3914 | // if this is just main exit-ing implicitly, and the status is 0, then we 3915 | // don't need to do anything here and can just leave. if the status is 3916 | // non-zero, though, then we need to report it. 3917 | // (we may have warned about this earlier, if a situation justifies doing so) 3918 | if (implicit && Module['noExitRuntime'] && status === 0) { 3919 | return; 3920 | } 3921 | 3922 | if (Module['noExitRuntime']) { 3923 | // if exit() was called, we may warn the user if the runtime isn't actually being shut down 3924 | if (!implicit) { 3925 | err('exit(' + status + ') called, 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)'); 3926 | } 3927 | } else { 3928 | 3929 | ABORT = true; 3930 | EXITSTATUS = status; 3931 | 3932 | exitRuntime(); 3933 | 3934 | if (Module['onExit']) Module['onExit'](status); 3935 | } 3936 | 3937 | Module['quit'](status, new ExitStatus(status)); 3938 | } 3939 | 3940 | var abortDecorators = []; 3941 | 3942 | function abort(what) { 3943 | if (Module['onAbort']) { 3944 | Module['onAbort'](what); 3945 | } 3946 | 3947 | if (what !== undefined) { 3948 | out(what); 3949 | err(what); 3950 | what = JSON.stringify(what) 3951 | } else { 3952 | what = ''; 3953 | } 3954 | 3955 | ABORT = true; 3956 | EXITSTATUS = 1; 3957 | 3958 | var extra = ''; 3959 | var output = 'abort(' + what + ') at ' + stackTrace() + extra; 3960 | if (abortDecorators) { 3961 | abortDecorators.forEach(function(decorator) { 3962 | output = decorator(output, what); 3963 | }); 3964 | } 3965 | throw output; 3966 | } 3967 | Module['abort'] = abort; 3968 | 3969 | if (Module['preInit']) { 3970 | if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; 3971 | while (Module['preInit'].length > 0) { 3972 | Module['preInit'].pop()(); 3973 | } 3974 | } 3975 | 3976 | 3977 | Module["noExitRuntime"] = true; 3978 | 3979 | run(); 3980 | 3981 | 3982 | 3983 | 3984 | 3985 | // {{MODULE_ADDITIONS}} 3986 | 3987 | 3988 | 3989 | 3990 | 3991 | 3992 | 3993 | 3994 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "micropython", 3 | "version": "1.1.8", 4 | "description": "A WASM module built from the official MicroPython port", 5 | "main": "index.js", 6 | "directories": { 7 | "lib": "lib" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/rafi16jan/micropython-wasm.git" 15 | }, 16 | "keywords": [ 17 | "python", 18 | "micropython", 19 | "wasm", 20 | "webassembly" 21 | ], 22 | "author": "MicroPython", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/rafi16jan/micropython-wasm/issues" 26 | }, 27 | "homepage": "https://github.com/rafi16jan/micropython-wasm#readme", 28 | "dependencies": { 29 | "arraybuffer-loader": "^1.0.7", 30 | "node-fetch": "^2.6.0", 31 | "raw-loader": "^2.0.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | (async () => { 2 | 3 | const jspy = require('fs').readFileSync('js.py').toString() 4 | const micropython = await require('./index.js') 5 | console.log(micropython) 6 | micropython.init(64 * 100000) 7 | micropython.do_str(jspy) 8 | 9 | //Testing JS event loop, works 10 | /*await micropython.do_str('c = False') 11 | global.interval = setInterval(() => { 12 | micropython.do_str(` 13 | import js 14 | if not c: 15 | js.exec("console.log('wait')") 16 | else: 17 | js.exec("clearInterval(interval)") 18 | `) 19 | }, 500) 20 | setTimeout(() => { 21 | micropython.do_str(` 22 | import js 23 | c = True 24 | js.exec("console.log('done')") 25 | `) 26 | }, 5000)*/ 27 | 28 | //Testing tick skipping, works, but only on higher level (not possible on functions, or class) 29 | /*await micropython.do_str("require = JS('require')") 30 | await micropython.do_str("fetch = require('node-fetch')") 31 | await micropython.do_str("result = fetch('https://google.com')") 32 | await micropython.do_str("result = wait(result)") 33 | await micropython.do_str("result = result._value") 34 | await micropython.do_str("result = result.text()") 35 | await micropython.do_str("result = wait(result)") 36 | await micropython.do_str("result = result._value") 37 | await micropython.do_str("print(result)")*/ 38 | 39 | })() 40 | --------------------------------------------------------------------------------