├── .gitignore ├── js ├── wasm_dsp_module.wasm ├── dsp_worker.js ├── dsp.js ├── utils.js ├── wasm_dsp.js ├── vendor │ └── AudioContextMonkeyPatch.js └── wasm_dsp_module.js ├── wasm_dsp ├── compile.sh └── wasm_dsp.cpp ├── README.md ├── benchmarks ├── osc_webAudio.js ├── osc_workerJsDsp.js ├── osc_wasmDsp.js ├── osc_jsDsp.js └── osc_MultipleWorkersJsDsp.js └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | build/ -------------------------------------------------------------------------------- /js/wasm_dsp_module.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sebpiq/waa-benchmarks/HEAD/js/wasm_dsp_module.wasm -------------------------------------------------------------------------------- /wasm_dsp/compile.sh: -------------------------------------------------------------------------------- 1 | mkdir -p build 2 | rm -f build/* 3 | 4 | if emcc wasm_dsp.cpp -O2 -s WASM=1 \ 5 | -s "MODULARIZE=1" -s "EXPORT_NAME='WasmDspModule'" -s "BINARYEN_METHOD='native-wasm'" \ 6 | -s "EXPORTED_FUNCTIONS=['_sum_osc_static']" \ 7 | -o build/wasm_dsp_module.js ; 8 | then 9 | echo "compilation succeeded" 10 | echo "copying to js/wasm_dsp_module.js" 11 | cp build/wasm_dsp_module.js ../js/ 12 | echo "copying to js/wasm_dsp_module.wasm" 13 | cp build/wasm_dsp_module.wasm ../js/ 14 | fi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Web Audio API benchmarks 2 | ========================= 3 | 4 | [GO GO](https://sebpiq.github.io/waa-benchmarks/) 5 | 6 | A series of (not)automated benchmarks for testing the performance of different options of doing sound synthesis in the browser : 7 | 8 | - Using native Web Audio API nodes 9 | - ScriptProcessorNode and JavaScript DSP in the main thread 10 | - ScriptProcessorNode and JavaScript DSP in one web worker 11 | - ScriptProcessorNode and JavaScript DSP in several web workers 12 | - ScriptProcessorNode and WebAssembly DSP in the main thread 13 | 14 | At the moment there are only tests with oscillators, and it would be interesting to try different operations, such as interpolated buffer playback, etc ... 15 | 16 | To build the web assembly code, install the compiler and run: 17 | 18 | ``` 19 | cd wasm_dsp 20 | ./compile.sh 21 | ``` 22 | -------------------------------------------------------------------------------- /benchmarks/osc_webAudio.js: -------------------------------------------------------------------------------- 1 | window.osc_webAudio = { 2 | 3 | context: null, 4 | mainGain: null, 5 | oscNodes: [], 6 | 7 | addNode: function(count) { 8 | for (var i = 0; i < count; i++) { 9 | var osc = this.context.createOscillator() 10 | osc.frequency.value = 220 + Math.random() * 660 11 | osc.connect(this.mainGain) 12 | this.oscNodes.push(osc) 13 | this.mainGain.gain.value = 1 / this.oscNodes.length 14 | osc.start(0) 15 | } 16 | UI.updateNodeCount(this.oscNodes.length) 17 | }, 18 | 19 | removeNode: function(count) { 20 | for (var i = 0; i < count; i++) { 21 | var osc = this.oscNodes.pop() 22 | osc.stop(0) 23 | osc.disconnect() 24 | this.mainGain.gain.value = 1 / this.oscNodes.length 25 | } 26 | UI.updateNodeCount(this.oscNodes.length) 27 | }, 28 | 29 | start: function(context) { 30 | UI.setTitle('Oscillator benchmark : Web Audio native nodes') 31 | this.context = context 32 | this.mainGain = context.createGain() 33 | this.mainGain.connect(this.context.destination) 34 | } 35 | } -------------------------------------------------------------------------------- /wasm_dsp/wasm_dsp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define PI 3.141592653589793 5 | #define BLOCK_SIZE 4096 6 | 7 | // We need 2 floats to store 1 oscillator [ phase, K ]. 8 | // K = 2 * PI / sample_rate * freq 9 | int OSC_LEN = 2; 10 | 11 | extern "C" { 12 | 13 | void sum_osc_static(float* out_block, double* oscillators, int osc_count) { 14 | double phase, K; 15 | double gain = 1.0 / osc_count; 16 | 17 | // Reset `out_block` with zeros 18 | for (int j=0; j= (this._oscListLen - 1)) { 51 | realloc = true 52 | this._oscListLen += 100 53 | } 54 | 55 | if (realloc) { 56 | // TODO : DEALLOC 57 | var bytesLength = this._oscListLen * 8 * OSC_LEN 58 | var ptr = this._wasm_module._malloc(bytesLength) 59 | var start = ptr / 8 60 | var newOscList = this._wasm_module.HEAPF64.subarray(start, start + this._oscListLen * OSC_LEN) 61 | if (this._oscList) 62 | newOscList.set(this._oscList) 63 | this._oscList = newOscList 64 | this._oscListPtr = ptr 65 | } 66 | } 67 | 68 | WasmDsp.prototype.computeNext = function() { 69 | this._wasm_oscSum(this._oscOutBlockPtr, this._oscListPtr, this.getOscCount()) 70 | return this.getSubarray(this._oscOutBlockPtr, BLOCK_SIZE) 71 | } 72 | 73 | // Takes an Float32Array, copies it to the heap and returns a pointer 74 | WasmDsp.prototype.arrayToPtr = function(array) { 75 | var ptr = this._wasm_module._malloc(array.length * BYTES_PER_ELEMENT) 76 | this._wasm_module.HEAPF32.set(array, ptr / BYTES_PER_ELEMENT) 77 | return ptr 78 | } 79 | 80 | // Takes a pointer and array length, and returns a Float32Array from the heap 81 | WasmDsp.prototype.ptrToArray = function(ptr, array) { 82 | var pos = ptr / BYTES_PER_ELEMENT 83 | array.set(this._wasm_module.HEAPF32.subarray(pos, pos + array.length)) 84 | return array 85 | } 86 | 87 | // Takes a pointer and array length, and returns a Float32Array from the heap 88 | WasmDsp.prototype.getSubarray = function(ptr, length) { 89 | var pos = ptr / BYTES_PER_ELEMENT 90 | return this._wasm_module.HEAPF32.subarray(pos, pos + length) 91 | } 92 | 93 | function load(opts, done) { 94 | if (!opts.blockSize || !opts.sampleRate) 95 | throw new Error('missing initialization parameters') 96 | BLOCK_SIZE = opts.blockSize 97 | SAMPLE_RATE = opts.sampleRate 98 | 99 | var oReq = new XMLHttpRequest() 100 | oReq.responseType = 'arraybuffer' 101 | oReq.addEventListener('load', function reqListener () { 102 | // Loading wasm module 103 | var arrayBuffer = oReq.response 104 | var wasmDspModule = WasmDspModule({ wasmBinary: arrayBuffer }) 105 | done(null, new WasmDsp(wasmDspModule)) 106 | }) 107 | oReq.open('GET', 'js/wasm_dsp_module.wasm') 108 | oReq.send() 109 | } 110 | 111 | this.wasmDsp = { 112 | load: load 113 | } 114 | 115 | }).apply(this) -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 64 | 65 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /js/vendor/AudioContextMonkeyPatch.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2013 Chris Wilson 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | /* 17 | 18 | This monkeypatch library is intended to be included in projects that are 19 | written to the proper AudioContext spec (instead of webkitAudioContext), 20 | and that use the new naming and proper bits of the Web Audio API (e.g. 21 | using BufferSourceNode.start() instead of BufferSourceNode.noteOn()), but may 22 | have to run on systems that only support the deprecated bits. 23 | 24 | This library should be harmless to include if the browser supports 25 | unprefixed "AudioContext", and/or if it supports the new names. 26 | 27 | The patches this library handles: 28 | if window.AudioContext is unsupported, it will be aliased to webkitAudioContext(). 29 | if AudioBufferSourceNode.start() is unimplemented, it will be routed to noteOn() or 30 | noteGrainOn(), depending on parameters. 31 | 32 | The following aliases only take effect if the new names are not already in place: 33 | 34 | AudioBufferSourceNode.stop() is aliased to noteOff() 35 | AudioContext.createGain() is aliased to createGainNode() 36 | AudioContext.createDelay() is aliased to createDelayNode() 37 | AudioContext.createScriptProcessor() is aliased to createJavaScriptNode() 38 | AudioContext.createPeriodicWave() is aliased to createWaveTable() 39 | OscillatorNode.start() is aliased to noteOn() 40 | OscillatorNode.stop() is aliased to noteOff() 41 | OscillatorNode.setPeriodicWave() is aliased to setWaveTable() 42 | AudioParam.setTargetAtTime() is aliased to setTargetValueAtTime() 43 | 44 | This library does NOT patch the enumerated type changes, as it is 45 | recommended in the specification that implementations support both integer 46 | and string types for AudioPannerNode.panningModel, AudioPannerNode.distanceModel 47 | BiquadFilterNode.type and OscillatorNode.type. 48 | 49 | */ 50 | (function (global, exports, perf) { 51 | 'use strict'; 52 | 53 | function fixSetTarget(param) { 54 | if (!param) // if NYI, just return 55 | return; 56 | if (!param.setTargetAtTime) 57 | param.setTargetAtTime = param.setTargetValueAtTime; 58 | } 59 | 60 | if (window.hasOwnProperty('webkitAudioContext') && 61 | !window.hasOwnProperty('AudioContext')) { 62 | window.AudioContext = webkitAudioContext; 63 | 64 | if (!AudioContext.prototype.hasOwnProperty('createGain')) 65 | AudioContext.prototype.createGain = AudioContext.prototype.createGainNode; 66 | if (!AudioContext.prototype.hasOwnProperty('createDelay')) 67 | AudioContext.prototype.createDelay = AudioContext.prototype.createDelayNode; 68 | if (!AudioContext.prototype.hasOwnProperty('createScriptProcessor')) 69 | AudioContext.prototype.createScriptProcessor = AudioContext.prototype.createJavaScriptNode; 70 | if (!AudioContext.prototype.hasOwnProperty('createPeriodicWave')) 71 | AudioContext.prototype.createPeriodicWave = AudioContext.prototype.createWaveTable; 72 | 73 | 74 | AudioContext.prototype.internal_createGain = AudioContext.prototype.createGain; 75 | AudioContext.prototype.createGain = function() { 76 | var node = this.internal_createGain(); 77 | fixSetTarget(node.gain); 78 | return node; 79 | }; 80 | 81 | AudioContext.prototype.internal_createDelay = AudioContext.prototype.createDelay; 82 | AudioContext.prototype.createDelay = function(maxDelayTime) { 83 | var node = maxDelayTime ? this.internal_createDelay(maxDelayTime) : this.internal_createDelay(); 84 | fixSetTarget(node.delayTime); 85 | return node; 86 | }; 87 | 88 | AudioContext.prototype.internal_createBufferSource = AudioContext.prototype.createBufferSource; 89 | AudioContext.prototype.createBufferSource = function() { 90 | var node = this.internal_createBufferSource(); 91 | if (!node.start) { 92 | node.start = function ( when, offset, duration ) { 93 | if ( offset || duration ) 94 | this.noteGrainOn( when || 0, offset, duration ); 95 | else 96 | this.noteOn( when || 0 ); 97 | }; 98 | } else { 99 | node.internal_start = node.start; 100 | node.start = function( when, offset, duration ) { 101 | if( typeof duration !== 'undefined' ) 102 | node.internal_start( when || 0, offset, duration ); 103 | else 104 | node.internal_start( when || 0, offset || 0 ); 105 | }; 106 | } 107 | if (!node.stop) { 108 | node.stop = function ( when ) { 109 | this.noteOff( when || 0 ); 110 | }; 111 | } else { 112 | node.internal_stop = node.stop; 113 | node.stop = function( when ) { 114 | node.internal_stop( when || 0 ); 115 | }; 116 | } 117 | fixSetTarget(node.playbackRate); 118 | return node; 119 | }; 120 | 121 | AudioContext.prototype.internal_createDynamicsCompressor = AudioContext.prototype.createDynamicsCompressor; 122 | AudioContext.prototype.createDynamicsCompressor = function() { 123 | var node = this.internal_createDynamicsCompressor(); 124 | fixSetTarget(node.threshold); 125 | fixSetTarget(node.knee); 126 | fixSetTarget(node.ratio); 127 | fixSetTarget(node.reduction); 128 | fixSetTarget(node.attack); 129 | fixSetTarget(node.release); 130 | return node; 131 | }; 132 | 133 | AudioContext.prototype.internal_createBiquadFilter = AudioContext.prototype.createBiquadFilter; 134 | AudioContext.prototype.createBiquadFilter = function() { 135 | var node = this.internal_createBiquadFilter(); 136 | fixSetTarget(node.frequency); 137 | fixSetTarget(node.detune); 138 | fixSetTarget(node.Q); 139 | fixSetTarget(node.gain); 140 | return node; 141 | }; 142 | 143 | if (AudioContext.prototype.hasOwnProperty( 'createOscillator' )) { 144 | AudioContext.prototype.internal_createOscillator = AudioContext.prototype.createOscillator; 145 | AudioContext.prototype.createOscillator = function() { 146 | var node = this.internal_createOscillator(); 147 | if (!node.start) { 148 | node.start = function ( when ) { 149 | this.noteOn( when || 0 ); 150 | }; 151 | } else { 152 | node.internal_start = node.start; 153 | node.start = function ( when ) { 154 | node.internal_start( when || 0); 155 | }; 156 | } 157 | if (!node.stop) { 158 | node.stop = function ( when ) { 159 | this.noteOff( when || 0 ); 160 | }; 161 | } else { 162 | node.internal_stop = node.stop; 163 | node.stop = function( when ) { 164 | node.internal_stop( when || 0 ); 165 | }; 166 | } 167 | if (!node.setPeriodicWave) 168 | node.setPeriodicWave = node.setWaveTable; 169 | fixSetTarget(node.frequency); 170 | fixSetTarget(node.detune); 171 | return node; 172 | }; 173 | } 174 | } 175 | 176 | if (window.hasOwnProperty('webkitOfflineAudioContext') && 177 | !window.hasOwnProperty('OfflineAudioContext')) { 178 | window.OfflineAudioContext = webkitOfflineAudioContext; 179 | } 180 | 181 | }(window)); 182 | 183 | -------------------------------------------------------------------------------- /js/wasm_dsp_module.js: -------------------------------------------------------------------------------- 1 | var WasmDspModule = function(WasmDspModule) { 2 | WasmDspModule = WasmDspModule || {}; 3 | var Module = WasmDspModule; 4 | 5 | // The Module object: Our interface to the outside world. We import 6 | // and export values on it, and do the work to get that through 7 | // closure compiler if necessary. There are various ways Module can be used: 8 | // 1. Not defined. We create it here 9 | // 2. A function parameter, function(Module) { ..generated code.. } 10 | // 3. pre-run appended it, var Module = {}; ..generated code.. 11 | // 4. External script tag defines var Module. 12 | // We need to do an eval in order to handle the closure compiler 13 | // case, where this code here is minified but Module was defined 14 | // elsewhere (e.g. case 4 above). We also need to check if Module 15 | // already exists (e.g. case 3 above). 16 | // Note that if you want to run closure, and also to use Module 17 | // after the generated code, you will need to define var Module = {}; 18 | // before the code. Then that object will be used in the code, and you 19 | // can continue to use Module afterwards as well. 20 | var Module; 21 | if (!Module) Module = (typeof WasmDspModule !== 'undefined' ? WasmDspModule : null) || {}; 22 | 23 | // Sometimes an existing Module object exists with properties 24 | // meant to overwrite the default module functionality. Here 25 | // we collect those properties and reapply _after_ we configure 26 | // the current environment's defaults to avoid having to be so 27 | // defensive during initialization. 28 | var moduleOverrides = {}; 29 | for (var key in Module) { 30 | if (Module.hasOwnProperty(key)) { 31 | moduleOverrides[key] = Module[key]; 32 | } 33 | } 34 | 35 | // The environment setup code below is customized to use Module. 36 | // *** Environment setup code *** 37 | var ENVIRONMENT_IS_WEB = false; 38 | var ENVIRONMENT_IS_WORKER = false; 39 | var ENVIRONMENT_IS_NODE = false; 40 | var ENVIRONMENT_IS_SHELL = false; 41 | 42 | // Three configurations we can be running in: 43 | // 1) We could be the application main() thread running in the main JS UI thread. (ENVIRONMENT_IS_WORKER == false and ENVIRONMENT_IS_PTHREAD == false) 44 | // 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) 45 | // 3) We could be an application pthread running in a worker. (ENVIRONMENT_IS_WORKER == true and ENVIRONMENT_IS_PTHREAD == true) 46 | 47 | if (Module['ENVIRONMENT']) { 48 | if (Module['ENVIRONMENT'] === 'WEB') { 49 | ENVIRONMENT_IS_WEB = true; 50 | } else if (Module['ENVIRONMENT'] === 'WORKER') { 51 | ENVIRONMENT_IS_WORKER = true; 52 | } else if (Module['ENVIRONMENT'] === 'NODE') { 53 | ENVIRONMENT_IS_NODE = true; 54 | } else if (Module['ENVIRONMENT'] === 'SHELL') { 55 | ENVIRONMENT_IS_SHELL = true; 56 | } else { 57 | throw new Error('The provided Module[\'ENVIRONMENT\'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.'); 58 | } 59 | } else { 60 | ENVIRONMENT_IS_WEB = typeof window === 'object'; 61 | ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; 62 | ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function' && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER; 63 | ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; 64 | } 65 | 66 | 67 | if (ENVIRONMENT_IS_NODE) { 68 | // Expose functionality in the same simple way that the shells work 69 | // Note that we pollute the global namespace here, otherwise we break in node 70 | if (!Module['print']) Module['print'] = console.log; 71 | if (!Module['printErr']) Module['printErr'] = console.warn; 72 | 73 | var nodeFS; 74 | var nodePath; 75 | 76 | Module['read'] = function read(filename, binary) { 77 | if (!nodeFS) nodeFS = require('fs'); 78 | if (!nodePath) nodePath = require('path'); 79 | filename = nodePath['normalize'](filename); 80 | var ret = nodeFS['readFileSync'](filename); 81 | return binary ? ret : ret.toString(); 82 | }; 83 | 84 | Module['readBinary'] = function readBinary(filename) { 85 | var ret = Module['read'](filename, true); 86 | if (!ret.buffer) { 87 | ret = new Uint8Array(ret); 88 | } 89 | assert(ret.buffer); 90 | return ret; 91 | }; 92 | 93 | Module['load'] = function load(f) { 94 | globalEval(read(f)); 95 | }; 96 | 97 | if (!Module['thisProgram']) { 98 | if (process['argv'].length > 1) { 99 | Module['thisProgram'] = process['argv'][1].replace(/\\/g, '/'); 100 | } else { 101 | Module['thisProgram'] = 'unknown-program'; 102 | } 103 | } 104 | 105 | Module['arguments'] = process['argv'].slice(2); 106 | 107 | if (typeof module !== 'undefined') { 108 | module['exports'] = Module; 109 | } 110 | 111 | process['on']('uncaughtException', function(ex) { 112 | // suppress ExitStatus exceptions from showing an error 113 | if (!(ex instanceof ExitStatus)) { 114 | throw ex; 115 | } 116 | }); 117 | 118 | Module['inspect'] = function () { return '[Emscripten Module object]'; }; 119 | } 120 | else if (ENVIRONMENT_IS_SHELL) { 121 | if (!Module['print']) Module['print'] = print; 122 | if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm 123 | 124 | if (typeof read != 'undefined') { 125 | Module['read'] = read; 126 | } else { 127 | Module['read'] = function read() { throw 'no read() available' }; 128 | } 129 | 130 | Module['readBinary'] = function readBinary(f) { 131 | if (typeof readbuffer === 'function') { 132 | return new Uint8Array(readbuffer(f)); 133 | } 134 | var data = read(f, 'binary'); 135 | assert(typeof data === 'object'); 136 | return data; 137 | }; 138 | 139 | if (typeof scriptArgs != 'undefined') { 140 | Module['arguments'] = scriptArgs; 141 | } else if (typeof arguments != 'undefined') { 142 | Module['arguments'] = arguments; 143 | } 144 | 145 | } 146 | else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { 147 | Module['read'] = function read(url) { 148 | var xhr = new XMLHttpRequest(); 149 | xhr.open('GET', url, false); 150 | xhr.send(null); 151 | return xhr.responseText; 152 | }; 153 | 154 | Module['readAsync'] = function readAsync(url, onload, onerror) { 155 | var xhr = new XMLHttpRequest(); 156 | xhr.open('GET', url, true); 157 | xhr.responseType = 'arraybuffer'; 158 | xhr.onload = function xhr_onload() { 159 | if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 160 | onload(xhr.response); 161 | } else { 162 | onerror(); 163 | } 164 | }; 165 | xhr.onerror = onerror; 166 | xhr.send(null); 167 | }; 168 | 169 | if (typeof arguments != 'undefined') { 170 | Module['arguments'] = arguments; 171 | } 172 | 173 | if (typeof console !== 'undefined') { 174 | if (!Module['print']) Module['print'] = function print(x) { 175 | console.log(x); 176 | }; 177 | if (!Module['printErr']) Module['printErr'] = function printErr(x) { 178 | console.warn(x); 179 | }; 180 | } else { 181 | // Probably a worker, and without console.log. We can do very little here... 182 | var TRY_USE_DUMP = false; 183 | if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) { 184 | dump(x); 185 | }) : (function(x) { 186 | // self.postMessage(x); // enable this if you want stdout to be sent as messages 187 | })); 188 | } 189 | 190 | if (ENVIRONMENT_IS_WORKER) { 191 | Module['load'] = importScripts; 192 | } 193 | 194 | if (typeof Module['setWindowTitle'] === 'undefined') { 195 | Module['setWindowTitle'] = function(title) { document.title = title }; 196 | } 197 | } 198 | else { 199 | // Unreachable because SHELL is dependant on the others 200 | throw 'Unknown runtime environment. Where are we?'; 201 | } 202 | 203 | function globalEval(x) { 204 | eval.call(null, x); 205 | } 206 | if (!Module['load'] && Module['read']) { 207 | Module['load'] = function load(f) { 208 | globalEval(Module['read'](f)); 209 | }; 210 | } 211 | if (!Module['print']) { 212 | Module['print'] = function(){}; 213 | } 214 | if (!Module['printErr']) { 215 | Module['printErr'] = Module['print']; 216 | } 217 | if (!Module['arguments']) { 218 | Module['arguments'] = []; 219 | } 220 | if (!Module['thisProgram']) { 221 | Module['thisProgram'] = './this.program'; 222 | } 223 | 224 | // *** Environment setup code *** 225 | 226 | // Closure helpers 227 | Module.print = Module['print']; 228 | Module.printErr = Module['printErr']; 229 | 230 | // Callbacks 231 | Module['preRun'] = []; 232 | Module['postRun'] = []; 233 | 234 | // Merge back in the overrides 235 | for (var key in moduleOverrides) { 236 | if (moduleOverrides.hasOwnProperty(key)) { 237 | Module[key] = moduleOverrides[key]; 238 | } 239 | } 240 | // Free the object hierarchy contained in the overrides, this lets the GC 241 | // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. 242 | moduleOverrides = undefined; 243 | 244 | 245 | 246 | // {{PREAMBLE_ADDITIONS}} 247 | 248 | // === Preamble library stuff === 249 | 250 | // Documentation for the public APIs defined in this file must be updated in: 251 | // site/source/docs/api_reference/preamble.js.rst 252 | // A prebuilt local version of the documentation is available at: 253 | // site/build/text/docs/api_reference/preamble.js.txt 254 | // You can also build docs locally as HTML or other formats in site/ 255 | // An online HTML version (which may be of a different version of Emscripten) 256 | // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html 257 | 258 | //======================================== 259 | // Runtime code shared with compiler 260 | //======================================== 261 | 262 | var Runtime = { 263 | setTempRet0: function (value) { 264 | tempRet0 = value; 265 | }, 266 | getTempRet0: function () { 267 | return tempRet0; 268 | }, 269 | stackSave: function () { 270 | return STACKTOP; 271 | }, 272 | stackRestore: function (stackTop) { 273 | STACKTOP = stackTop; 274 | }, 275 | getNativeTypeSize: function (type) { 276 | switch (type) { 277 | case 'i1': case 'i8': return 1; 278 | case 'i16': return 2; 279 | case 'i32': return 4; 280 | case 'i64': return 8; 281 | case 'float': return 4; 282 | case 'double': return 8; 283 | default: { 284 | if (type[type.length-1] === '*') { 285 | return Runtime.QUANTUM_SIZE; // A pointer 286 | } else if (type[0] === 'i') { 287 | var bits = parseInt(type.substr(1)); 288 | assert(bits % 8 === 0); 289 | return bits/8; 290 | } else { 291 | return 0; 292 | } 293 | } 294 | } 295 | }, 296 | getNativeFieldSize: function (type) { 297 | return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE); 298 | }, 299 | STACK_ALIGN: 16, 300 | prepVararg: function (ptr, type) { 301 | if (type === 'double' || type === 'i64') { 302 | // move so the load is aligned 303 | if (ptr & 7) { 304 | assert((ptr & 7) === 4); 305 | ptr += 4; 306 | } 307 | } else { 308 | assert((ptr & 3) === 0); 309 | } 310 | return ptr; 311 | }, 312 | getAlignSize: function (type, size, vararg) { 313 | // we align i64s and doubles on 64-bit boundaries, unlike x86 314 | if (!vararg && (type == 'i64' || type == 'double')) return 8; 315 | if (!type) return Math.min(size, 8); // align structures internally to 64 bits 316 | return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE); 317 | }, 318 | dynCall: function (sig, ptr, args) { 319 | if (args && args.length) { 320 | return Module['dynCall_' + sig].apply(null, [ptr].concat(args)); 321 | } else { 322 | return Module['dynCall_' + sig].call(null, ptr); 323 | } 324 | }, 325 | functionPointers: [], 326 | addFunction: function (func) { 327 | for (var i = 0; i < Runtime.functionPointers.length; i++) { 328 | if (!Runtime.functionPointers[i]) { 329 | Runtime.functionPointers[i] = func; 330 | return 2*(1 + i); 331 | } 332 | } 333 | throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; 334 | }, 335 | removeFunction: function (index) { 336 | Runtime.functionPointers[(index-2)/2] = null; 337 | }, 338 | warnOnce: function (text) { 339 | if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; 340 | if (!Runtime.warnOnce.shown[text]) { 341 | Runtime.warnOnce.shown[text] = 1; 342 | Module.printErr(text); 343 | } 344 | }, 345 | funcWrappers: {}, 346 | getFuncWrapper: function (func, sig) { 347 | assert(sig); 348 | if (!Runtime.funcWrappers[sig]) { 349 | Runtime.funcWrappers[sig] = {}; 350 | } 351 | var sigCache = Runtime.funcWrappers[sig]; 352 | if (!sigCache[func]) { 353 | // optimize away arguments usage in common cases 354 | if (sig.length === 1) { 355 | sigCache[func] = function dynCall_wrapper() { 356 | return Runtime.dynCall(sig, func); 357 | }; 358 | } else if (sig.length === 2) { 359 | sigCache[func] = function dynCall_wrapper(arg) { 360 | return Runtime.dynCall(sig, func, [arg]); 361 | }; 362 | } else { 363 | // general case 364 | sigCache[func] = function dynCall_wrapper() { 365 | return Runtime.dynCall(sig, func, Array.prototype.slice.call(arguments)); 366 | }; 367 | } 368 | } 369 | return sigCache[func]; 370 | }, 371 | getCompilerSetting: function (name) { 372 | throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work'; 373 | }, 374 | stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+15)&-16); return ret; }, 375 | staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+15)&-16); return ret; }, 376 | dynamicAlloc: function (size) { var ret = HEAP32[DYNAMICTOP_PTR>>2];var end = (((ret + size + 15)|0) & -16);HEAP32[DYNAMICTOP_PTR>>2] = end;if (end >= TOTAL_MEMORY) {var success = enlargeMemory();if (!success) {HEAP32[DYNAMICTOP_PTR>>2] = ret;return 0;}}return ret;}, 377 | alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 16))*(quantum ? quantum : 16); return ret; }, 378 | makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0))); return ret; }, 379 | GLOBAL_BASE: 1024, 380 | QUANTUM_SIZE: 4, 381 | __dummy__: 0 382 | } 383 | 384 | 385 | 386 | Module["Runtime"] = Runtime; 387 | 388 | 389 | 390 | //======================================== 391 | // Runtime essentials 392 | //======================================== 393 | 394 | var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort() 395 | var EXITSTATUS = 0; 396 | 397 | function assert(condition, text) { 398 | if (!condition) { 399 | abort('Assertion failed: ' + text); 400 | } 401 | } 402 | 403 | var globalScope = this; 404 | 405 | // Returns the C function with a specified identifier (for C++, you need to do manual name mangling) 406 | function getCFunc(ident) { 407 | var func = Module['_' + ident]; // closure exported function 408 | if (!func) { 409 | try { func = eval('_' + ident); } catch(e) {} 410 | } 411 | assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)'); 412 | return func; 413 | } 414 | 415 | var cwrap, ccall; 416 | (function(){ 417 | var JSfuncs = { 418 | // Helpers for cwrap -- it can't refer to Runtime directly because it might 419 | // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find 420 | // out what the minified function name is. 421 | 'stackSave': function() { 422 | Runtime.stackSave() 423 | }, 424 | 'stackRestore': function() { 425 | Runtime.stackRestore() 426 | }, 427 | // type conversion from js to c 428 | 'arrayToC' : function(arr) { 429 | var ret = Runtime.stackAlloc(arr.length); 430 | writeArrayToMemory(arr, ret); 431 | return ret; 432 | }, 433 | 'stringToC' : function(str) { 434 | var ret = 0; 435 | if (str !== null && str !== undefined && str !== 0) { // null string 436 | // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' 437 | var len = (str.length << 2) + 1; 438 | ret = Runtime.stackAlloc(len); 439 | stringToUTF8(str, ret, len); 440 | } 441 | return ret; 442 | } 443 | }; 444 | // For fast lookup of conversion functions 445 | var toC = {'string' : JSfuncs['stringToC'], 'array' : JSfuncs['arrayToC']}; 446 | 447 | // C calling interface. 448 | ccall = function ccallFunc(ident, returnType, argTypes, args, opts) { 449 | var func = getCFunc(ident); 450 | var cArgs = []; 451 | var stack = 0; 452 | if (args) { 453 | for (var i = 0; i < args.length; i++) { 454 | var converter = toC[argTypes[i]]; 455 | if (converter) { 456 | if (stack === 0) stack = Runtime.stackSave(); 457 | cArgs[i] = converter(args[i]); 458 | } else { 459 | cArgs[i] = args[i]; 460 | } 461 | } 462 | } 463 | var ret = func.apply(null, cArgs); 464 | if (returnType === 'string') ret = Pointer_stringify(ret); 465 | if (stack !== 0) { 466 | if (opts && opts.async) { 467 | EmterpreterAsync.asyncFinalizers.push(function() { 468 | Runtime.stackRestore(stack); 469 | }); 470 | return; 471 | } 472 | Runtime.stackRestore(stack); 473 | } 474 | return ret; 475 | } 476 | 477 | var sourceRegex = /^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/; 478 | function parseJSFunc(jsfunc) { 479 | // Match the body and the return value of a javascript function source 480 | var parsed = jsfunc.toString().match(sourceRegex).slice(1); 481 | return {arguments : parsed[0], body : parsed[1], returnValue: parsed[2]} 482 | } 483 | 484 | // sources of useful functions. we create this lazily as it can trigger a source decompression on this entire file 485 | var JSsource = null; 486 | function ensureJSsource() { 487 | if (!JSsource) { 488 | JSsource = {}; 489 | for (var fun in JSfuncs) { 490 | if (JSfuncs.hasOwnProperty(fun)) { 491 | // Elements of toCsource are arrays of three items: 492 | // the code, and the return value 493 | JSsource[fun] = parseJSFunc(JSfuncs[fun]); 494 | } 495 | } 496 | } 497 | } 498 | 499 | cwrap = function cwrap(ident, returnType, argTypes) { 500 | argTypes = argTypes || []; 501 | var cfunc = getCFunc(ident); 502 | // When the function takes numbers and returns a number, we can just return 503 | // the original function 504 | var numericArgs = argTypes.every(function(type){ return type === 'number'}); 505 | var numericRet = (returnType !== 'string'); 506 | if ( numericRet && numericArgs) { 507 | return cfunc; 508 | } 509 | // Creation of the arguments list (["$1","$2",...,"$nargs"]) 510 | var argNames = argTypes.map(function(x,i){return '$'+i}); 511 | var funcstr = "(function(" + argNames.join(',') + ") {"; 512 | var nargs = argTypes.length; 513 | if (!numericArgs) { 514 | // Generate the code needed to convert the arguments from javascript 515 | // values to pointers 516 | ensureJSsource(); 517 | funcstr += 'var stack = ' + JSsource['stackSave'].body + ';'; 518 | for (var i = 0; i < nargs; i++) { 519 | var arg = argNames[i], type = argTypes[i]; 520 | if (type === 'number') continue; 521 | var convertCode = JSsource[type + 'ToC']; // [code, return] 522 | funcstr += 'var ' + convertCode.arguments + ' = ' + arg + ';'; 523 | funcstr += convertCode.body + ';'; 524 | funcstr += arg + '=(' + convertCode.returnValue + ');'; 525 | } 526 | } 527 | 528 | // When the code is compressed, the name of cfunc is not literally 'cfunc' anymore 529 | var cfuncname = parseJSFunc(function(){return cfunc}).returnValue; 530 | // Call the function 531 | funcstr += 'var ret = ' + cfuncname + '(' + argNames.join(',') + ');'; 532 | if (!numericRet) { // Return type can only by 'string' or 'number' 533 | // Convert the result to a string 534 | var strgfy = parseJSFunc(function(){return Pointer_stringify}).returnValue; 535 | funcstr += 'ret = ' + strgfy + '(ret);'; 536 | } 537 | if (!numericArgs) { 538 | // If we had a stack, restore it 539 | ensureJSsource(); 540 | funcstr += JSsource['stackRestore'].body.replace('()', '(stack)') + ';'; 541 | } 542 | funcstr += 'return ret})'; 543 | return eval(funcstr); 544 | }; 545 | })(); 546 | Module["ccall"] = ccall; 547 | Module["cwrap"] = cwrap; 548 | 549 | function setValue(ptr, value, type, noSafe) { 550 | type = type || 'i8'; 551 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit 552 | switch(type) { 553 | case 'i1': HEAP8[((ptr)>>0)]=value; break; 554 | case 'i8': HEAP8[((ptr)>>0)]=value; break; 555 | case 'i16': HEAP16[((ptr)>>1)]=value; break; 556 | case 'i32': HEAP32[((ptr)>>2)]=value; break; 557 | case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break; 558 | case 'float': HEAPF32[((ptr)>>2)]=value; break; 559 | case 'double': HEAPF64[((ptr)>>3)]=value; break; 560 | default: abort('invalid type for setValue: ' + type); 561 | } 562 | } 563 | Module["setValue"] = setValue; 564 | 565 | 566 | function getValue(ptr, type, noSafe) { 567 | type = type || 'i8'; 568 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit 569 | switch(type) { 570 | case 'i1': return HEAP8[((ptr)>>0)]; 571 | case 'i8': return HEAP8[((ptr)>>0)]; 572 | case 'i16': return HEAP16[((ptr)>>1)]; 573 | case 'i32': return HEAP32[((ptr)>>2)]; 574 | case 'i64': return HEAP32[((ptr)>>2)]; 575 | case 'float': return HEAPF32[((ptr)>>2)]; 576 | case 'double': return HEAPF64[((ptr)>>3)]; 577 | default: abort('invalid type for setValue: ' + type); 578 | } 579 | return null; 580 | } 581 | Module["getValue"] = getValue; 582 | 583 | var ALLOC_NORMAL = 0; // Tries to use _malloc() 584 | var ALLOC_STACK = 1; // Lives for the duration of the current function call 585 | var ALLOC_STATIC = 2; // Cannot be freed 586 | var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk 587 | var ALLOC_NONE = 4; // Do not allocate 588 | Module["ALLOC_NORMAL"] = ALLOC_NORMAL; 589 | Module["ALLOC_STACK"] = ALLOC_STACK; 590 | Module["ALLOC_STATIC"] = ALLOC_STATIC; 591 | Module["ALLOC_DYNAMIC"] = ALLOC_DYNAMIC; 592 | Module["ALLOC_NONE"] = ALLOC_NONE; 593 | 594 | // allocate(): This is for internal use. You can use it yourself as well, but the interface 595 | // is a little tricky (see docs right below). The reason is that it is optimized 596 | // for multiple syntaxes to save space in generated code. So you should 597 | // normally not use allocate(), and instead allocate memory using _malloc(), 598 | // initialize it with setValue(), and so forth. 599 | // @slab: An array of data, or a number. If a number, then the size of the block to allocate, 600 | // in *bytes* (note that this is sometimes confusing: the next parameter does not 601 | // affect this!) 602 | // @types: Either an array of types, one for each byte (or 0 if no type at that position), 603 | // or a single type which is used for the entire block. This only matters if there 604 | // is initial data - if @slab is a number, then this does not matter at all and is 605 | // ignored. 606 | // @allocator: How to allocate memory, see ALLOC_* 607 | function allocate(slab, types, allocator, ptr) { 608 | var zeroinit, size; 609 | if (typeof slab === 'number') { 610 | zeroinit = true; 611 | size = slab; 612 | } else { 613 | zeroinit = false; 614 | size = slab.length; 615 | } 616 | 617 | var singleType = typeof types === 'string' ? types : null; 618 | 619 | var ret; 620 | if (allocator == ALLOC_NONE) { 621 | ret = ptr; 622 | } else { 623 | ret = [typeof _malloc === 'function' ? _malloc : Runtime.staticAlloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); 624 | } 625 | 626 | if (zeroinit) { 627 | var ptr = ret, stop; 628 | assert((ret & 3) == 0); 629 | stop = ret + (size & ~3); 630 | for (; ptr < stop; ptr += 4) { 631 | HEAP32[((ptr)>>2)]=0; 632 | } 633 | stop = ret + size; 634 | while (ptr < stop) { 635 | HEAP8[((ptr++)>>0)]=0; 636 | } 637 | return ret; 638 | } 639 | 640 | if (singleType === 'i8') { 641 | if (slab.subarray || slab.slice) { 642 | HEAPU8.set(slab, ret); 643 | } else { 644 | HEAPU8.set(new Uint8Array(slab), ret); 645 | } 646 | return ret; 647 | } 648 | 649 | var i = 0, type, typeSize, previousType; 650 | while (i < size) { 651 | var curr = slab[i]; 652 | 653 | if (typeof curr === 'function') { 654 | curr = Runtime.getFunctionIndex(curr); 655 | } 656 | 657 | type = singleType || types[i]; 658 | if (type === 0) { 659 | i++; 660 | continue; 661 | } 662 | 663 | if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later 664 | 665 | setValue(ret+i, curr, type); 666 | 667 | // no need to look up size unless type changes, so cache it 668 | if (previousType !== type) { 669 | typeSize = Runtime.getNativeTypeSize(type); 670 | previousType = type; 671 | } 672 | i += typeSize; 673 | } 674 | 675 | return ret; 676 | } 677 | Module["allocate"] = allocate; 678 | 679 | // Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready 680 | function getMemory(size) { 681 | if (!staticSealed) return Runtime.staticAlloc(size); 682 | if (!runtimeInitialized) return Runtime.dynamicAlloc(size); 683 | return _malloc(size); 684 | } 685 | Module["getMemory"] = getMemory; 686 | 687 | function Pointer_stringify(ptr, /* optional */ length) { 688 | if (length === 0 || !ptr) return ''; 689 | // TODO: use TextDecoder 690 | // Find the length, and check for UTF while doing so 691 | var hasUtf = 0; 692 | var t; 693 | var i = 0; 694 | while (1) { 695 | t = HEAPU8[(((ptr)+(i))>>0)]; 696 | hasUtf |= t; 697 | if (t == 0 && !length) break; 698 | i++; 699 | if (length && i == length) break; 700 | } 701 | if (!length) length = i; 702 | 703 | var ret = ''; 704 | 705 | if (hasUtf < 128) { 706 | var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack 707 | var curr; 708 | while (length > 0) { 709 | curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); 710 | ret = ret ? ret + curr : curr; 711 | ptr += MAX_CHUNK; 712 | length -= MAX_CHUNK; 713 | } 714 | return ret; 715 | } 716 | return Module['UTF8ToString'](ptr); 717 | } 718 | Module["Pointer_stringify"] = Pointer_stringify; 719 | 720 | // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns 721 | // a copy of that string as a Javascript String object. 722 | 723 | function AsciiToString(ptr) { 724 | var str = ''; 725 | while (1) { 726 | var ch = HEAP8[((ptr++)>>0)]; 727 | if (!ch) return str; 728 | str += String.fromCharCode(ch); 729 | } 730 | } 731 | Module["AsciiToString"] = AsciiToString; 732 | 733 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 734 | // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP. 735 | 736 | function stringToAscii(str, outPtr) { 737 | return writeAsciiToMemory(str, outPtr, false); 738 | } 739 | Module["stringToAscii"] = stringToAscii; 740 | 741 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns 742 | // a copy of that string as a Javascript String object. 743 | 744 | var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined; 745 | function UTF8ArrayToString(u8Array, idx) { 746 | var endPtr = idx; 747 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 748 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 749 | while (u8Array[endPtr]) ++endPtr; 750 | 751 | if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { 752 | return UTF8Decoder.decode(u8Array.subarray(idx, endPtr)); 753 | } else { 754 | var u0, u1, u2, u3, u4, u5; 755 | 756 | var str = ''; 757 | while (1) { 758 | // 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 759 | u0 = u8Array[idx++]; 760 | if (!u0) return str; 761 | if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } 762 | u1 = u8Array[idx++] & 63; 763 | if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } 764 | u2 = u8Array[idx++] & 63; 765 | if ((u0 & 0xF0) == 0xE0) { 766 | u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; 767 | } else { 768 | u3 = u8Array[idx++] & 63; 769 | if ((u0 & 0xF8) == 0xF0) { 770 | u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; 771 | } else { 772 | u4 = u8Array[idx++] & 63; 773 | if ((u0 & 0xFC) == 0xF8) { 774 | u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; 775 | } else { 776 | u5 = u8Array[idx++] & 63; 777 | u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; 778 | } 779 | } 780 | } 781 | if (u0 < 0x10000) { 782 | str += String.fromCharCode(u0); 783 | } else { 784 | var ch = u0 - 0x10000; 785 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 786 | } 787 | } 788 | } 789 | } 790 | Module["UTF8ArrayToString"] = UTF8ArrayToString; 791 | 792 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns 793 | // a copy of that string as a Javascript String object. 794 | 795 | function UTF8ToString(ptr) { 796 | return UTF8ArrayToString(HEAPU8,ptr); 797 | } 798 | Module["UTF8ToString"] = UTF8ToString; 799 | 800 | // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', 801 | // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP. 802 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 803 | // Parameters: 804 | // str: the Javascript string to copy. 805 | // outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element. 806 | // outIdx: The starting offset in the array to begin the copying. 807 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 808 | // terminator, i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else. 809 | // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator. 810 | // Returns the number of bytes written, EXCLUDING the null terminator. 811 | 812 | function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { 813 | if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. 814 | return 0; 815 | 816 | var startIdx = outIdx; 817 | var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. 818 | for (var i = 0; i < str.length; ++i) { 819 | // 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. 820 | // See http://unicode.org/faq/utf_bom.html#utf16-3 821 | // 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 822 | var u = str.charCodeAt(i); // possibly a lead surrogate 823 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 824 | if (u <= 0x7F) { 825 | if (outIdx >= endIdx) break; 826 | outU8Array[outIdx++] = u; 827 | } else if (u <= 0x7FF) { 828 | if (outIdx + 1 >= endIdx) break; 829 | outU8Array[outIdx++] = 0xC0 | (u >> 6); 830 | outU8Array[outIdx++] = 0x80 | (u & 63); 831 | } else if (u <= 0xFFFF) { 832 | if (outIdx + 2 >= endIdx) break; 833 | outU8Array[outIdx++] = 0xE0 | (u >> 12); 834 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 835 | outU8Array[outIdx++] = 0x80 | (u & 63); 836 | } else if (u <= 0x1FFFFF) { 837 | if (outIdx + 3 >= endIdx) break; 838 | outU8Array[outIdx++] = 0xF0 | (u >> 18); 839 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 840 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 841 | outU8Array[outIdx++] = 0x80 | (u & 63); 842 | } else if (u <= 0x3FFFFFF) { 843 | if (outIdx + 4 >= endIdx) break; 844 | outU8Array[outIdx++] = 0xF8 | (u >> 24); 845 | outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); 846 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 847 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 848 | outU8Array[outIdx++] = 0x80 | (u & 63); 849 | } else { 850 | if (outIdx + 5 >= endIdx) break; 851 | outU8Array[outIdx++] = 0xFC | (u >> 30); 852 | outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63); 853 | outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); 854 | outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); 855 | outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); 856 | outU8Array[outIdx++] = 0x80 | (u & 63); 857 | } 858 | } 859 | // Null-terminate the pointer to the buffer. 860 | outU8Array[outIdx] = 0; 861 | return outIdx - startIdx; 862 | } 863 | Module["stringToUTF8Array"] = stringToUTF8Array; 864 | 865 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 866 | // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP. 867 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. 868 | // Returns the number of bytes written, EXCLUDING the null terminator. 869 | 870 | function stringToUTF8(str, outPtr, maxBytesToWrite) { 871 | return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); 872 | } 873 | Module["stringToUTF8"] = stringToUTF8; 874 | 875 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. 876 | 877 | function lengthBytesUTF8(str) { 878 | var len = 0; 879 | for (var i = 0; i < str.length; ++i) { 880 | // 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. 881 | // See http://unicode.org/faq/utf_bom.html#utf16-3 882 | var u = str.charCodeAt(i); // possibly a lead surrogate 883 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 884 | if (u <= 0x7F) { 885 | ++len; 886 | } else if (u <= 0x7FF) { 887 | len += 2; 888 | } else if (u <= 0xFFFF) { 889 | len += 3; 890 | } else if (u <= 0x1FFFFF) { 891 | len += 4; 892 | } else if (u <= 0x3FFFFFF) { 893 | len += 5; 894 | } else { 895 | len += 6; 896 | } 897 | } 898 | return len; 899 | } 900 | Module["lengthBytesUTF8"] = lengthBytesUTF8; 901 | 902 | // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns 903 | // a copy of that string as a Javascript String object. 904 | 905 | var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; 906 | function UTF16ToString(ptr) { 907 | var endPtr = ptr; 908 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. 909 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. 910 | var idx = endPtr >> 1; 911 | while (HEAP16[idx]) ++idx; 912 | endPtr = idx << 1; 913 | 914 | if (endPtr - ptr > 32 && UTF16Decoder) { 915 | return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); 916 | } else { 917 | var i = 0; 918 | 919 | var str = ''; 920 | while (1) { 921 | var codeUnit = HEAP16[(((ptr)+(i*2))>>1)]; 922 | if (codeUnit == 0) return str; 923 | ++i; 924 | // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. 925 | str += String.fromCharCode(codeUnit); 926 | } 927 | } 928 | } 929 | 930 | 931 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 932 | // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP. 933 | // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write. 934 | // Parameters: 935 | // str: the Javascript string to copy. 936 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 937 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 938 | // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else. 939 | // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator. 940 | // Returns the number of bytes written, EXCLUDING the null terminator. 941 | 942 | function stringToUTF16(str, outPtr, maxBytesToWrite) { 943 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 944 | if (maxBytesToWrite === undefined) { 945 | maxBytesToWrite = 0x7FFFFFFF; 946 | } 947 | if (maxBytesToWrite < 2) return 0; 948 | maxBytesToWrite -= 2; // Null terminator. 949 | var startPtr = outPtr; 950 | var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; 951 | for (var i = 0; i < numCharsToWrite; ++i) { 952 | // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. 953 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 954 | HEAP16[((outPtr)>>1)]=codeUnit; 955 | outPtr += 2; 956 | } 957 | // Null-terminate the pointer to the HEAP. 958 | HEAP16[((outPtr)>>1)]=0; 959 | return outPtr - startPtr; 960 | } 961 | 962 | 963 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 964 | 965 | function lengthBytesUTF16(str) { 966 | return str.length*2; 967 | } 968 | 969 | 970 | function UTF32ToString(ptr) { 971 | var i = 0; 972 | 973 | var str = ''; 974 | while (1) { 975 | var utf32 = HEAP32[(((ptr)+(i*4))>>2)]; 976 | if (utf32 == 0) 977 | return str; 978 | ++i; 979 | // 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. 980 | // See http://unicode.org/faq/utf_bom.html#utf16-3 981 | if (utf32 >= 0x10000) { 982 | var ch = utf32 - 0x10000; 983 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); 984 | } else { 985 | str += String.fromCharCode(utf32); 986 | } 987 | } 988 | } 989 | 990 | 991 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', 992 | // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP. 993 | // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write. 994 | // Parameters: 995 | // str: the Javascript string to copy. 996 | // outPtr: Byte address in Emscripten HEAP where to write the string to. 997 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null 998 | // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else. 999 | // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator. 1000 | // Returns the number of bytes written, EXCLUDING the null terminator. 1001 | 1002 | function stringToUTF32(str, outPtr, maxBytesToWrite) { 1003 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. 1004 | if (maxBytesToWrite === undefined) { 1005 | maxBytesToWrite = 0x7FFFFFFF; 1006 | } 1007 | if (maxBytesToWrite < 4) return 0; 1008 | var startPtr = outPtr; 1009 | var endPtr = startPtr + maxBytesToWrite - 4; 1010 | for (var i = 0; i < str.length; ++i) { 1011 | // 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. 1012 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1013 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate 1014 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { 1015 | var trailSurrogate = str.charCodeAt(++i); 1016 | codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); 1017 | } 1018 | HEAP32[((outPtr)>>2)]=codeUnit; 1019 | outPtr += 4; 1020 | if (outPtr + 4 > endPtr) break; 1021 | } 1022 | // Null-terminate the pointer to the HEAP. 1023 | HEAP32[((outPtr)>>2)]=0; 1024 | return outPtr - startPtr; 1025 | } 1026 | 1027 | 1028 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. 1029 | 1030 | function lengthBytesUTF32(str) { 1031 | var len = 0; 1032 | for (var i = 0; i < str.length; ++i) { 1033 | // 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. 1034 | // See http://unicode.org/faq/utf_bom.html#utf16-3 1035 | var codeUnit = str.charCodeAt(i); 1036 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. 1037 | len += 4; 1038 | } 1039 | 1040 | return len; 1041 | } 1042 | 1043 | 1044 | function demangle(func) { 1045 | var __cxa_demangle_func = Module['___cxa_demangle'] || Module['__cxa_demangle']; 1046 | if (__cxa_demangle_func) { 1047 | try { 1048 | var s = 1049 | func.substr(1); 1050 | var len = lengthBytesUTF8(s)+1; 1051 | var buf = _malloc(len); 1052 | stringToUTF8(s, buf, len); 1053 | var status = _malloc(4); 1054 | var ret = __cxa_demangle_func(buf, 0, 0, status); 1055 | if (getValue(status, 'i32') === 0 && ret) { 1056 | return Pointer_stringify(ret); 1057 | } 1058 | // otherwise, libcxxabi failed 1059 | } catch(e) { 1060 | // ignore problems here 1061 | } finally { 1062 | if (buf) _free(buf); 1063 | if (status) _free(status); 1064 | if (ret) _free(ret); 1065 | } 1066 | // failure when using libcxxabi, don't demangle 1067 | return func; 1068 | } 1069 | Runtime.warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling'); 1070 | return func; 1071 | } 1072 | 1073 | function demangleAll(text) { 1074 | var regex = 1075 | /__Z[\w\d_]+/g; 1076 | return text.replace(regex, 1077 | function(x) { 1078 | var y = demangle(x); 1079 | return x === y ? x : (x + ' [' + y + ']'); 1080 | }); 1081 | } 1082 | 1083 | function jsStackTrace() { 1084 | var err = new Error(); 1085 | if (!err.stack) { 1086 | // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown, 1087 | // so try that as a special-case. 1088 | try { 1089 | throw new Error(0); 1090 | } catch(e) { 1091 | err = e; 1092 | } 1093 | if (!err.stack) { 1094 | return '(no stack trace available)'; 1095 | } 1096 | } 1097 | return err.stack.toString(); 1098 | } 1099 | 1100 | function stackTrace() { 1101 | var js = jsStackTrace(); 1102 | if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); 1103 | return demangleAll(js); 1104 | } 1105 | Module["stackTrace"] = stackTrace; 1106 | 1107 | // Memory management 1108 | 1109 | var PAGE_SIZE = 4096; 1110 | 1111 | function alignMemoryPage(x) { 1112 | if (x % 4096 > 0) { 1113 | x += (4096 - (x % 4096)); 1114 | } 1115 | return x; 1116 | } 1117 | 1118 | var HEAP; 1119 | var buffer; 1120 | var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; 1121 | 1122 | function updateGlobalBuffer(buf) { 1123 | Module['buffer'] = buffer = buf; 1124 | } 1125 | 1126 | function updateGlobalBufferViews() { 1127 | Module['HEAP8'] = HEAP8 = new Int8Array(buffer); 1128 | Module['HEAP16'] = HEAP16 = new Int16Array(buffer); 1129 | Module['HEAP32'] = HEAP32 = new Int32Array(buffer); 1130 | Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer); 1131 | Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer); 1132 | Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer); 1133 | Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer); 1134 | Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer); 1135 | } 1136 | 1137 | var STATIC_BASE, STATICTOP, staticSealed; // static area 1138 | var STACK_BASE, STACKTOP, STACK_MAX; // stack area 1139 | var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk 1140 | 1141 | STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0; 1142 | staticSealed = false; 1143 | 1144 | 1145 | 1146 | function abortOnCannotGrowMemory() { 1147 | abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which adjusts the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); 1148 | } 1149 | 1150 | 1151 | function enlargeMemory() { 1152 | abortOnCannotGrowMemory(); 1153 | } 1154 | 1155 | 1156 | var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880; 1157 | var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216; 1158 | 1159 | var WASM_PAGE_SIZE = 64 * 1024; 1160 | 1161 | var totalMemory = WASM_PAGE_SIZE; 1162 | while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { 1163 | if (totalMemory < 16*1024*1024) { 1164 | totalMemory *= 2; 1165 | } else { 1166 | totalMemory += 16*1024*1024; 1167 | } 1168 | } 1169 | if (totalMemory !== TOTAL_MEMORY) { 1170 | TOTAL_MEMORY = totalMemory; 1171 | } 1172 | 1173 | // Initialize the runtime's memory 1174 | 1175 | 1176 | 1177 | // Use a provided buffer, if there is one, or else allocate a new one 1178 | if (Module['buffer']) { 1179 | buffer = Module['buffer']; 1180 | } else { 1181 | // Use a WebAssembly memory where available 1182 | if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { 1183 | Module['wasmMemory'] = new WebAssembly.Memory({ initial: TOTAL_MEMORY / WASM_PAGE_SIZE, maximum: TOTAL_MEMORY / WASM_PAGE_SIZE }); 1184 | buffer = Module['wasmMemory'].buffer; 1185 | } else 1186 | { 1187 | buffer = new ArrayBuffer(TOTAL_MEMORY); 1188 | } 1189 | } 1190 | updateGlobalBufferViews(); 1191 | 1192 | 1193 | function getTotalMemory() { 1194 | return TOTAL_MEMORY; 1195 | } 1196 | 1197 | // Endianness check (note: assumes compiler arch was little-endian) 1198 | HEAP32[0] = 0x63736d65; /* 'emsc' */ 1199 | HEAP16[1] = 0x6373; 1200 | if (HEAPU8[2] !== 0x73 || HEAPU8[3] !== 0x63) throw 'Runtime error: expected the system to be little-endian!'; 1201 | 1202 | Module['HEAP'] = HEAP; 1203 | Module['buffer'] = buffer; 1204 | Module['HEAP8'] = HEAP8; 1205 | Module['HEAP16'] = HEAP16; 1206 | Module['HEAP32'] = HEAP32; 1207 | Module['HEAPU8'] = HEAPU8; 1208 | Module['HEAPU16'] = HEAPU16; 1209 | Module['HEAPU32'] = HEAPU32; 1210 | Module['HEAPF32'] = HEAPF32; 1211 | Module['HEAPF64'] = HEAPF64; 1212 | 1213 | function callRuntimeCallbacks(callbacks) { 1214 | while(callbacks.length > 0) { 1215 | var callback = callbacks.shift(); 1216 | if (typeof callback == 'function') { 1217 | callback(); 1218 | continue; 1219 | } 1220 | var func = callback.func; 1221 | if (typeof func === 'number') { 1222 | if (callback.arg === undefined) { 1223 | Runtime.dynCall('v', func); 1224 | } else { 1225 | Runtime.dynCall('vi', func, [callback.arg]); 1226 | } 1227 | } else { 1228 | func(callback.arg === undefined ? null : callback.arg); 1229 | } 1230 | } 1231 | } 1232 | 1233 | var __ATPRERUN__ = []; // functions called before the runtime is initialized 1234 | var __ATINIT__ = []; // functions called during startup 1235 | var __ATMAIN__ = []; // functions called when main() is to be run 1236 | var __ATEXIT__ = []; // functions called during shutdown 1237 | var __ATPOSTRUN__ = []; // functions called after the runtime has exited 1238 | 1239 | var runtimeInitialized = false; 1240 | var runtimeExited = false; 1241 | 1242 | 1243 | function preRun() { 1244 | // compatibility - merge in anything from Module['preRun'] at this time 1245 | if (Module['preRun']) { 1246 | if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; 1247 | while (Module['preRun'].length) { 1248 | addOnPreRun(Module['preRun'].shift()); 1249 | } 1250 | } 1251 | callRuntimeCallbacks(__ATPRERUN__); 1252 | } 1253 | 1254 | function ensureInitRuntime() { 1255 | if (runtimeInitialized) return; 1256 | runtimeInitialized = true; 1257 | callRuntimeCallbacks(__ATINIT__); 1258 | } 1259 | 1260 | function preMain() { 1261 | callRuntimeCallbacks(__ATMAIN__); 1262 | } 1263 | 1264 | function exitRuntime() { 1265 | callRuntimeCallbacks(__ATEXIT__); 1266 | runtimeExited = true; 1267 | } 1268 | 1269 | function postRun() { 1270 | // compatibility - merge in anything from Module['postRun'] at this time 1271 | if (Module['postRun']) { 1272 | if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; 1273 | while (Module['postRun'].length) { 1274 | addOnPostRun(Module['postRun'].shift()); 1275 | } 1276 | } 1277 | callRuntimeCallbacks(__ATPOSTRUN__); 1278 | } 1279 | 1280 | function addOnPreRun(cb) { 1281 | __ATPRERUN__.unshift(cb); 1282 | } 1283 | Module["addOnPreRun"] = addOnPreRun; 1284 | 1285 | function addOnInit(cb) { 1286 | __ATINIT__.unshift(cb); 1287 | } 1288 | Module["addOnInit"] = addOnInit; 1289 | 1290 | function addOnPreMain(cb) { 1291 | __ATMAIN__.unshift(cb); 1292 | } 1293 | Module["addOnPreMain"] = addOnPreMain; 1294 | 1295 | function addOnExit(cb) { 1296 | __ATEXIT__.unshift(cb); 1297 | } 1298 | Module["addOnExit"] = addOnExit; 1299 | 1300 | function addOnPostRun(cb) { 1301 | __ATPOSTRUN__.unshift(cb); 1302 | } 1303 | Module["addOnPostRun"] = addOnPostRun; 1304 | 1305 | // Tools 1306 | 1307 | 1308 | function intArrayFromString(stringy, dontAddNull, length /* optional */) { 1309 | var len = length > 0 ? length : lengthBytesUTF8(stringy)+1; 1310 | var u8array = new Array(len); 1311 | var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length); 1312 | if (dontAddNull) u8array.length = numBytesWritten; 1313 | return u8array; 1314 | } 1315 | Module["intArrayFromString"] = intArrayFromString; 1316 | 1317 | function intArrayToString(array) { 1318 | var ret = []; 1319 | for (var i = 0; i < array.length; i++) { 1320 | var chr = array[i]; 1321 | if (chr > 0xFF) { 1322 | chr &= 0xFF; 1323 | } 1324 | ret.push(String.fromCharCode(chr)); 1325 | } 1326 | return ret.join(''); 1327 | } 1328 | Module["intArrayToString"] = intArrayToString; 1329 | 1330 | // Deprecated: This function should not be called because it is unsafe and does not provide 1331 | // a maximum length limit of how many bytes it is allowed to write. Prefer calling the 1332 | // function stringToUTF8Array() instead, which takes in a maximum length that can be used 1333 | // to be secure from out of bounds writes. 1334 | function writeStringToMemory(string, buffer, dontAddNull) { 1335 | Runtime.warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); 1336 | 1337 | var lastChar, end; 1338 | if (dontAddNull) { 1339 | // stringToUTF8Array always appends null. If we don't want to do that, remember the 1340 | // character that existed at the location where the null will be placed, and restore 1341 | // that after the write (below). 1342 | end = buffer + lengthBytesUTF8(string); 1343 | lastChar = HEAP8[end]; 1344 | } 1345 | stringToUTF8(string, buffer, Infinity); 1346 | if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. 1347 | } 1348 | Module["writeStringToMemory"] = writeStringToMemory; 1349 | 1350 | function writeArrayToMemory(array, buffer) { 1351 | HEAP8.set(array, buffer); 1352 | } 1353 | Module["writeArrayToMemory"] = writeArrayToMemory; 1354 | 1355 | function writeAsciiToMemory(str, buffer, dontAddNull) { 1356 | for (var i = 0; i < str.length; ++i) { 1357 | HEAP8[((buffer++)>>0)]=str.charCodeAt(i); 1358 | } 1359 | // Null-terminate the pointer to the HEAP. 1360 | if (!dontAddNull) HEAP8[((buffer)>>0)]=0; 1361 | } 1362 | Module["writeAsciiToMemory"] = writeAsciiToMemory; 1363 | 1364 | function unSign(value, bits, ignore) { 1365 | if (value >= 0) { 1366 | return value; 1367 | } 1368 | 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 1369 | : Math.pow(2, bits) + value; 1370 | } 1371 | function reSign(value, bits, ignore) { 1372 | if (value <= 0) { 1373 | return value; 1374 | } 1375 | var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32 1376 | : Math.pow(2, bits-1); 1377 | 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 1378 | // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors 1379 | // TODO: In i64 mode 1, resign the two parts separately and safely 1380 | value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts 1381 | } 1382 | return value; 1383 | } 1384 | 1385 | 1386 | // check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) 1387 | if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { 1388 | var ah = a >>> 16; 1389 | var al = a & 0xffff; 1390 | var bh = b >>> 16; 1391 | var bl = b & 0xffff; 1392 | return (al*bl + ((ah*bl + al*bh) << 16))|0; 1393 | }; 1394 | Math.imul = Math['imul']; 1395 | 1396 | if (!Math['fround']) { 1397 | var froundBuffer = new Float32Array(1); 1398 | Math['fround'] = function(x) { froundBuffer[0] = x; return froundBuffer[0] }; 1399 | } 1400 | Math.fround = Math['fround']; 1401 | 1402 | if (!Math['clz32']) Math['clz32'] = function(x) { 1403 | x = x >>> 0; 1404 | for (var i = 0; i < 32; i++) { 1405 | if (x & (1 << (31 - i))) return i; 1406 | } 1407 | return 32; 1408 | }; 1409 | Math.clz32 = Math['clz32'] 1410 | 1411 | if (!Math['trunc']) Math['trunc'] = function(x) { 1412 | return x < 0 ? Math.ceil(x) : Math.floor(x); 1413 | }; 1414 | Math.trunc = Math['trunc']; 1415 | 1416 | var Math_abs = Math.abs; 1417 | var Math_cos = Math.cos; 1418 | var Math_sin = Math.sin; 1419 | var Math_tan = Math.tan; 1420 | var Math_acos = Math.acos; 1421 | var Math_asin = Math.asin; 1422 | var Math_atan = Math.atan; 1423 | var Math_atan2 = Math.atan2; 1424 | var Math_exp = Math.exp; 1425 | var Math_log = Math.log; 1426 | var Math_sqrt = Math.sqrt; 1427 | var Math_ceil = Math.ceil; 1428 | var Math_floor = Math.floor; 1429 | var Math_pow = Math.pow; 1430 | var Math_imul = Math.imul; 1431 | var Math_fround = Math.fround; 1432 | var Math_round = Math.round; 1433 | var Math_min = Math.min; 1434 | var Math_clz32 = Math.clz32; 1435 | var Math_trunc = Math.trunc; 1436 | 1437 | // A counter of dependencies for calling run(). If we need to 1438 | // do asynchronous work before running, increment this and 1439 | // decrement it. Incrementing must happen in a place like 1440 | // PRE_RUN_ADDITIONS (used by emcc to add file preloading). 1441 | // Note that you can add dependencies in preRun, even though 1442 | // it happens right before run - run will be postponed until 1443 | // the dependencies are met. 1444 | var runDependencies = 0; 1445 | var runDependencyWatcher = null; 1446 | var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled 1447 | 1448 | function getUniqueRunDependency(id) { 1449 | return id; 1450 | } 1451 | 1452 | function addRunDependency(id) { 1453 | runDependencies++; 1454 | if (Module['monitorRunDependencies']) { 1455 | Module['monitorRunDependencies'](runDependencies); 1456 | } 1457 | } 1458 | Module["addRunDependency"] = addRunDependency; 1459 | 1460 | function removeRunDependency(id) { 1461 | runDependencies--; 1462 | if (Module['monitorRunDependencies']) { 1463 | Module['monitorRunDependencies'](runDependencies); 1464 | } 1465 | if (runDependencies == 0) { 1466 | if (runDependencyWatcher !== null) { 1467 | clearInterval(runDependencyWatcher); 1468 | runDependencyWatcher = null; 1469 | } 1470 | if (dependenciesFulfilled) { 1471 | var callback = dependenciesFulfilled; 1472 | dependenciesFulfilled = null; 1473 | callback(); // can add another dependenciesFulfilled 1474 | } 1475 | } 1476 | } 1477 | Module["removeRunDependency"] = removeRunDependency; 1478 | 1479 | Module["preloadedImages"] = {}; // maps url to image data 1480 | Module["preloadedAudios"] = {}; // maps url to audio data 1481 | 1482 | 1483 | 1484 | var memoryInitializer = null; 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | function integrateWasmJS(Module) { 1491 | // wasm.js has several methods for creating the compiled code module here: 1492 | // * 'native-wasm' : use native WebAssembly support in the browser 1493 | // * 'interpret-s-expr': load s-expression code from a .wast and interpret 1494 | // * 'interpret-binary': load binary wasm and interpret 1495 | // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret 1496 | // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing) 1497 | // The method can be set at compile time (BINARYEN_METHOD), or runtime by setting Module['wasmJSMethod']. 1498 | // The method can be a comma-separated list, in which case, we will try the 1499 | // options one by one. Some of them can fail gracefully, and then we can try 1500 | // the next. 1501 | 1502 | // inputs 1503 | 1504 | var method = Module['wasmJSMethod'] || 'native-wasm'; 1505 | Module['wasmJSMethod'] = method; 1506 | 1507 | var wasmTextFile = Module['wasmTextFile'] || 'wasm_dsp_module.wast'; 1508 | var wasmBinaryFile = Module['wasmBinaryFile'] || 'wasm_dsp_module.wasm'; 1509 | var asmjsCodeFile = Module['asmjsCodeFile'] || 'wasm_dsp_module.asm.js'; 1510 | 1511 | // utilities 1512 | 1513 | var wasmPageSize = 64*1024; 1514 | 1515 | var asm2wasmImports = { // special asm2wasm imports 1516 | "f64-rem": function(x, y) { 1517 | return x % y; 1518 | }, 1519 | "f64-to-int": function(x) { 1520 | return x | 0; 1521 | }, 1522 | "i32s-div": function(x, y) { 1523 | return ((x | 0) / (y | 0)) | 0; 1524 | }, 1525 | "i32u-div": function(x, y) { 1526 | return ((x >>> 0) / (y >>> 0)) >>> 0; 1527 | }, 1528 | "i32s-rem": function(x, y) { 1529 | return ((x | 0) % (y | 0)) | 0; 1530 | }, 1531 | "i32u-rem": function(x, y) { 1532 | return ((x >>> 0) % (y >>> 0)) >>> 0; 1533 | }, 1534 | "debugger": function() { 1535 | debugger; 1536 | }, 1537 | }; 1538 | 1539 | var info = { 1540 | 'global': null, 1541 | 'env': null, 1542 | 'asm2wasm': asm2wasmImports, 1543 | 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program. 1544 | }; 1545 | 1546 | var exports = null; 1547 | 1548 | function lookupImport(mod, base) { 1549 | var lookup = info; 1550 | if (mod.indexOf('.') < 0) { 1551 | lookup = (lookup || {})[mod]; 1552 | } else { 1553 | var parts = mod.split('.'); 1554 | lookup = (lookup || {})[parts[0]]; 1555 | lookup = (lookup || {})[parts[1]]; 1556 | } 1557 | if (base) { 1558 | lookup = (lookup || {})[base]; 1559 | } 1560 | if (lookup === undefined) { 1561 | abort('bad lookupImport to (' + mod + ').' + base); 1562 | } 1563 | return lookup; 1564 | } 1565 | 1566 | function mergeMemory(newBuffer) { 1567 | // The wasm instance creates its memory. But static init code might have written to 1568 | // buffer already, including the mem init file, and we must copy it over in a proper merge. 1569 | // TODO: avoid this copy, by avoiding such static init writes 1570 | // TODO: in shorter term, just copy up to the last static init write 1571 | var oldBuffer = Module['buffer']; 1572 | if (newBuffer.byteLength < oldBuffer.byteLength) { 1573 | Module['printErr']('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here'); 1574 | } 1575 | var oldView = new Int8Array(oldBuffer); 1576 | var newView = new Int8Array(newBuffer); 1577 | 1578 | // If we have a mem init file, do not trample it 1579 | if (!memoryInitializer) { 1580 | oldView.set(newView.subarray(Module['STATIC_BASE'], Module['STATIC_BASE'] + Module['STATIC_BUMP']), Module['STATIC_BASE']); 1581 | } 1582 | 1583 | newView.set(oldView); 1584 | updateGlobalBuffer(newBuffer); 1585 | updateGlobalBufferViews(); 1586 | } 1587 | 1588 | var WasmTypes = { 1589 | none: 0, 1590 | i32: 1, 1591 | i64: 2, 1592 | f32: 3, 1593 | f64: 4 1594 | }; 1595 | 1596 | function fixImports(imports) { 1597 | if (!0) return imports; 1598 | var ret = {}; 1599 | for (var i in imports) { 1600 | var fixed = i; 1601 | if (fixed[0] == '_') fixed = fixed.substr(1); 1602 | ret[fixed] = imports[i]; 1603 | } 1604 | return ret; 1605 | } 1606 | 1607 | function getBinary() { 1608 | var binary; 1609 | if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { 1610 | binary = Module['wasmBinary']; 1611 | assert(binary, "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)"); 1612 | binary = new Uint8Array(binary); 1613 | } else { 1614 | binary = Module['readBinary'](wasmBinaryFile); 1615 | } 1616 | return binary; 1617 | } 1618 | 1619 | // do-method functions 1620 | 1621 | function doJustAsm(global, env, providedBuffer) { 1622 | // if no Module.asm, or it's the method handler helper (see below), then apply 1623 | // the asmjs 1624 | if (typeof Module['asm'] !== 'function' || Module['asm'] === methodHandler) { 1625 | if (!Module['asmPreload']) { 1626 | // you can load the .asm.js file before this, to avoid this sync xhr and eval 1627 | eval(Module['read'](asmjsCodeFile)); // set Module.asm 1628 | } else { 1629 | Module['asm'] = Module['asmPreload']; 1630 | } 1631 | } 1632 | if (typeof Module['asm'] !== 'function') { 1633 | Module['printErr']('asm evalling did not set the module properly'); 1634 | return false; 1635 | } 1636 | return Module['asm'](global, env, providedBuffer); 1637 | } 1638 | 1639 | function doNativeWasm(global, env, providedBuffer) { 1640 | if (typeof WebAssembly !== 'object') { 1641 | Module['printErr']('no native wasm support detected'); 1642 | return false; 1643 | } 1644 | // prepare memory import 1645 | if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) { 1646 | Module['printErr']('no native wasm Memory in use'); 1647 | return false; 1648 | } 1649 | env['memory'] = Module['wasmMemory']; 1650 | // Load the wasm module and create an instance of using native support in the JS engine. 1651 | info['global'] = { 1652 | 'NaN': NaN, 1653 | 'Infinity': Infinity 1654 | }; 1655 | info['global.Math'] = global.Math; 1656 | info['env'] = env; 1657 | var instance; 1658 | try { 1659 | instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), info) 1660 | } catch (e) { 1661 | Module['printErr']('failed to compile wasm module: ' + e); 1662 | if (e.toString().indexOf('imported Memory with incompatible size') >= 0) { 1663 | Module['printErr']('Memory size incompatibility issues may be due to changing TOTAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set TOTAL_MEMORY at runtime to something smaller than it was at compile time).'); 1664 | } 1665 | return false; 1666 | } 1667 | exports = instance.exports; 1668 | if (exports.memory) mergeMemory(exports.memory); 1669 | 1670 | Module["usingWasm"] = true; 1671 | 1672 | return exports; 1673 | } 1674 | 1675 | function doWasmPolyfill(global, env, providedBuffer, method) { 1676 | if (typeof WasmJS !== 'function') { 1677 | Module['printErr']('WasmJS not detected - polyfill not bundled?'); 1678 | return false; 1679 | } 1680 | 1681 | // Use wasm.js to polyfill and execute code in a wasm interpreter. 1682 | var wasmJS = WasmJS({}); 1683 | 1684 | // XXX don't be confused. Module here is in the outside program. wasmJS is the inner wasm-js.cpp. 1685 | wasmJS['outside'] = Module; // Inside wasm-js.cpp, Module['outside'] reaches the outside module. 1686 | 1687 | // Information for the instance of the module. 1688 | wasmJS['info'] = info; 1689 | 1690 | wasmJS['lookupImport'] = lookupImport; 1691 | 1692 | assert(providedBuffer === Module['buffer']); // we should not even need to pass it as a 3rd arg for wasm, but that's the asm.js way. 1693 | 1694 | info.global = global; 1695 | info.env = env; 1696 | 1697 | // polyfill interpreter expects an ArrayBuffer 1698 | assert(providedBuffer === Module['buffer']); 1699 | env['memory'] = providedBuffer; 1700 | assert(env['memory'] instanceof ArrayBuffer); 1701 | 1702 | wasmJS['providedTotalMemory'] = Module['buffer'].byteLength; 1703 | 1704 | // Prepare to generate wasm, using either asm2wasm or s-exprs 1705 | var code; 1706 | if (method === 'interpret-binary') { 1707 | code = getBinary(); 1708 | } else { 1709 | code = Module['read'](method == 'interpret-asm2wasm' ? asmjsCodeFile : wasmTextFile); 1710 | } 1711 | var temp; 1712 | if (method == 'interpret-asm2wasm') { 1713 | temp = wasmJS['_malloc'](code.length + 1); 1714 | wasmJS['writeAsciiToMemory'](code, temp); 1715 | wasmJS['_load_asm2wasm'](temp); 1716 | } else if (method === 'interpret-s-expr') { 1717 | temp = wasmJS['_malloc'](code.length + 1); 1718 | wasmJS['writeAsciiToMemory'](code, temp); 1719 | wasmJS['_load_s_expr2wasm'](temp); 1720 | } else if (method === 'interpret-binary') { 1721 | temp = wasmJS['_malloc'](code.length); 1722 | wasmJS['HEAPU8'].set(code, temp); 1723 | wasmJS['_load_binary2wasm'](temp, code.length); 1724 | } else { 1725 | throw 'what? ' + method; 1726 | } 1727 | wasmJS['_free'](temp); 1728 | 1729 | wasmJS['_instantiate'](temp); 1730 | 1731 | if (Module['newBuffer']) { 1732 | mergeMemory(Module['newBuffer']); 1733 | Module['newBuffer'] = null; 1734 | } 1735 | 1736 | exports = wasmJS['asmExports']; 1737 | 1738 | return exports; 1739 | } 1740 | 1741 | // We may have a preloaded value in Module.asm, save it 1742 | Module['asmPreload'] = Module['asm']; 1743 | 1744 | // Memory growth integration code 1745 | Module['reallocBuffer'] = function(size) { 1746 | size = Math.ceil(size / wasmPageSize) * wasmPageSize; // round up to wasm page size 1747 | var old = Module['buffer']; 1748 | var result = exports['__growWasmMemory'](size / wasmPageSize); // tiny wasm method that just does grow_memory 1749 | if (Module["usingWasm"]) { 1750 | if (result !== (-1 | 0)) { 1751 | // success in native wasm memory growth, get the buffer from the memory 1752 | return Module['buffer'] = Module['wasmMemory'].buffer; 1753 | } else { 1754 | return null; 1755 | } 1756 | } else { 1757 | // in interpreter, we replace Module.buffer if we allocate 1758 | return Module['buffer'] !== old ? Module['buffer'] : null; // if it was reallocated, it changed 1759 | } 1760 | }; 1761 | 1762 | // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate 1763 | // the wasm module at that time, and it receives imports and provides exports and so forth, the app 1764 | // doesn't need to care that it is wasm or olyfilled wasm or asm.js. 1765 | 1766 | Module['asm'] = function(global, env, providedBuffer) { 1767 | global = fixImports(global); 1768 | env = fixImports(env); 1769 | 1770 | // import table 1771 | if (!env['table']) { 1772 | var TABLE_SIZE = Module['wasmTableSize']; 1773 | if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least 1774 | var MAX_TABLE_SIZE = Module['wasmMaxTableSize']; 1775 | if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') { 1776 | if (MAX_TABLE_SIZE !== undefined) { 1777 | env['table'] = new WebAssembly.Table({ initial: TABLE_SIZE, maximum: MAX_TABLE_SIZE, element: 'anyfunc' }); 1778 | } else { 1779 | env['table'] = new WebAssembly.Table({ initial: TABLE_SIZE, element: 'anyfunc' }); 1780 | } 1781 | } else { 1782 | env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least 1783 | } 1784 | Module['wasmTable'] = env['table']; 1785 | } 1786 | 1787 | if (!env['memoryBase']) { 1788 | env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves 1789 | } 1790 | if (!env['tableBase']) { 1791 | env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change 1792 | } 1793 | 1794 | // try the methods. each should return the exports if it succeeded 1795 | 1796 | var exports; 1797 | var methods = method.split(','); 1798 | 1799 | for (var i = 0; i < methods.length; i++) { 1800 | var curr = methods[i]; 1801 | 1802 | Module['printErr']('trying binaryen method: ' + curr); 1803 | 1804 | if (curr === 'native-wasm') { 1805 | if (exports = doNativeWasm(global, env, providedBuffer)) break; 1806 | } else if (curr === 'asmjs') { 1807 | if (exports = doJustAsm(global, env, providedBuffer)) break; 1808 | } else if (curr === 'interpret-asm2wasm' || curr === 'interpret-s-expr' || curr === 'interpret-binary') { 1809 | if (exports = doWasmPolyfill(global, env, providedBuffer, curr)) break; 1810 | } else { 1811 | throw 'bad method: ' + curr; 1812 | } 1813 | } 1814 | 1815 | if (!exports) throw 'no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods'; 1816 | 1817 | Module['printErr']('binaryen method succeeded.'); 1818 | 1819 | return exports; 1820 | }; 1821 | 1822 | var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later 1823 | } 1824 | 1825 | integrateWasmJS(Module); 1826 | 1827 | // === Body === 1828 | 1829 | var ASM_CONSTS = []; 1830 | 1831 | 1832 | 1833 | 1834 | STATIC_BASE = 1024; 1835 | 1836 | STATICTOP = STATIC_BASE + 3072; 1837 | /* global initializers */ __ATINIT__.push(); 1838 | 1839 | 1840 | memoryInitializer = Module["wasmJSMethod"].indexOf("asmjs") >= 0 || Module["wasmJSMethod"].indexOf("interpret-asm2wasm") >= 0 ? "wasm_dsp_module.js.mem" : null; 1841 | 1842 | 1843 | 1844 | 1845 | var STATIC_BUMP = 3072; 1846 | Module["STATIC_BASE"] = STATIC_BASE; 1847 | Module["STATIC_BUMP"] = STATIC_BUMP; 1848 | 1849 | /* no memory initializer */ 1850 | var tempDoublePtr = STATICTOP; STATICTOP += 16; 1851 | 1852 | function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much 1853 | 1854 | HEAP8[tempDoublePtr] = HEAP8[ptr]; 1855 | 1856 | HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; 1857 | 1858 | HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; 1859 | 1860 | HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; 1861 | 1862 | } 1863 | 1864 | function copyTempDouble(ptr) { 1865 | 1866 | HEAP8[tempDoublePtr] = HEAP8[ptr]; 1867 | 1868 | HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; 1869 | 1870 | HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; 1871 | 1872 | HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; 1873 | 1874 | HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; 1875 | 1876 | HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; 1877 | 1878 | HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; 1879 | 1880 | HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; 1881 | 1882 | } 1883 | 1884 | // {{PRE_LIBRARY}} 1885 | 1886 | 1887 | 1888 | Module["_memset"] = _memset; 1889 | 1890 | function _pthread_cleanup_push(routine, arg) { 1891 | __ATEXIT__.push(function() { Runtime.dynCall('vi', routine, [arg]) }) 1892 | _pthread_cleanup_push.level = __ATEXIT__.length; 1893 | } 1894 | 1895 | function _pthread_cleanup_pop() { 1896 | assert(_pthread_cleanup_push.level == __ATEXIT__.length, 'cannot pop if something else added meanwhile!'); 1897 | __ATEXIT__.pop(); 1898 | _pthread_cleanup_push.level = __ATEXIT__.length; 1899 | } 1900 | 1901 | function _abort() { 1902 | Module['abort'](); 1903 | } 1904 | 1905 | function ___lock() {} 1906 | 1907 | function ___unlock() {} 1908 | 1909 | 1910 | var SYSCALLS={varargs:0,get:function (varargs) { 1911 | SYSCALLS.varargs += 4; 1912 | var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; 1913 | return ret; 1914 | },getStr:function () { 1915 | var ret = Pointer_stringify(SYSCALLS.get()); 1916 | return ret; 1917 | },get64:function () { 1918 | var low = SYSCALLS.get(), high = SYSCALLS.get(); 1919 | if (low >= 0) assert(high === 0); 1920 | else assert(high === -1); 1921 | return low; 1922 | },getZero:function () { 1923 | assert(SYSCALLS.get() === 0); 1924 | }};function ___syscall6(which, varargs) {SYSCALLS.varargs = varargs; 1925 | try { 1926 | // close 1927 | var stream = SYSCALLS.getStreamFromFD(); 1928 | FS.close(stream); 1929 | return 0; 1930 | } catch (e) { 1931 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1932 | return -e.errno; 1933 | } 1934 | } 1935 | 1936 | 1937 | function ___setErrNo(value) { 1938 | if (Module['___errno_location']) HEAP32[((Module['___errno_location']())>>2)]=value; 1939 | return value; 1940 | } 1941 | Module["_sbrk"] = _sbrk; 1942 | 1943 | 1944 | function _emscripten_memcpy_big(dest, src, num) { 1945 | HEAPU8.set(HEAPU8.subarray(src, src+num), dest); 1946 | return dest; 1947 | } 1948 | Module["_memcpy"] = _memcpy; 1949 | 1950 | 1951 | Module["_pthread_self"] = _pthread_self; 1952 | 1953 | function ___syscall140(which, varargs) {SYSCALLS.varargs = varargs; 1954 | try { 1955 | // llseek 1956 | var stream = SYSCALLS.getStreamFromFD(), offset_high = SYSCALLS.get(), offset_low = SYSCALLS.get(), result = SYSCALLS.get(), whence = SYSCALLS.get(); 1957 | var offset = offset_low; 1958 | assert(offset_high === 0); 1959 | FS.llseek(stream, offset, whence); 1960 | HEAP32[((result)>>2)]=stream.position; 1961 | if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state 1962 | return 0; 1963 | } catch (e) { 1964 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1965 | return -e.errno; 1966 | } 1967 | } 1968 | 1969 | function ___syscall146(which, varargs) {SYSCALLS.varargs = varargs; 1970 | try { 1971 | // writev 1972 | // hack to support printf in NO_FILESYSTEM 1973 | var stream = SYSCALLS.get(), iov = SYSCALLS.get(), iovcnt = SYSCALLS.get(); 1974 | var ret = 0; 1975 | if (!___syscall146.buffer) { 1976 | ___syscall146.buffers = [null, [], []]; // 1 => stdout, 2 => stderr 1977 | ___syscall146.printChar = function(stream, curr) { 1978 | var buffer = ___syscall146.buffers[stream]; 1979 | assert(buffer); 1980 | if (curr === 0 || curr === 10) { 1981 | (stream === 1 ? Module['print'] : Module['printErr'])(UTF8ArrayToString(buffer, 0)); 1982 | buffer.length = 0; 1983 | } else { 1984 | buffer.push(curr); 1985 | } 1986 | }; 1987 | } 1988 | for (var i = 0; i < iovcnt; i++) { 1989 | var ptr = HEAP32[(((iov)+(i*8))>>2)]; 1990 | var len = HEAP32[(((iov)+(i*8 + 4))>>2)]; 1991 | for (var j = 0; j < len; j++) { 1992 | ___syscall146.printChar(stream, HEAPU8[ptr+j]); 1993 | } 1994 | ret += len; 1995 | } 1996 | return ret; 1997 | } catch (e) { 1998 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 1999 | return -e.errno; 2000 | } 2001 | } 2002 | 2003 | function ___syscall54(which, varargs) {SYSCALLS.varargs = varargs; 2004 | try { 2005 | // ioctl 2006 | return 0; 2007 | } catch (e) { 2008 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); 2009 | return -e.errno; 2010 | } 2011 | } 2012 | /* flush anything remaining in the buffer during shutdown */ __ATEXIT__.push(function() { var fflush = Module["_fflush"]; if (fflush) fflush(0); var printChar = ___syscall146.printChar; if (!printChar) return; var buffers = ___syscall146.buffers; if (buffers[1].length) printChar(1, 10); if (buffers[2].length) printChar(2, 10); });; 2013 | DYNAMICTOP_PTR = allocate(1, "i32", ALLOC_STATIC); 2014 | 2015 | STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP); 2016 | 2017 | STACK_MAX = STACK_BASE + TOTAL_STACK; 2018 | 2019 | DYNAMIC_BASE = Runtime.alignMemory(STACK_MAX); 2020 | 2021 | HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE; 2022 | 2023 | staticSealed = true; // seal the static portion of memory 2024 | 2025 | 2026 | 2027 | Module['wasmTableSize'] = 8; 2028 | 2029 | Module['wasmMaxTableSize'] = 8; 2030 | 2031 | function invoke_ii(index,a1) { 2032 | try { 2033 | return Module["dynCall_ii"](index,a1); 2034 | } catch(e) { 2035 | if (typeof e !== 'number' && e !== 'longjmp') throw e; 2036 | asm["setThrew"](1, 0); 2037 | } 2038 | } 2039 | 2040 | function invoke_iiii(index,a1,a2,a3) { 2041 | try { 2042 | return Module["dynCall_iiii"](index,a1,a2,a3); 2043 | } catch(e) { 2044 | if (typeof e !== 'number' && e !== 'longjmp') throw e; 2045 | asm["setThrew"](1, 0); 2046 | } 2047 | } 2048 | 2049 | function invoke_vi(index,a1) { 2050 | try { 2051 | Module["dynCall_vi"](index,a1); 2052 | } catch(e) { 2053 | if (typeof e !== 'number' && e !== 'longjmp') throw e; 2054 | asm["setThrew"](1, 0); 2055 | } 2056 | } 2057 | 2058 | Module.asmGlobalArg = { "Math": Math, "Int8Array": Int8Array, "Int16Array": Int16Array, "Int32Array": Int32Array, "Uint8Array": Uint8Array, "Uint16Array": Uint16Array, "Uint32Array": Uint32Array, "Float32Array": Float32Array, "Float64Array": Float64Array, "NaN": NaN, "Infinity": Infinity }; 2059 | 2060 | Module.asmLibraryArg = { "abort": abort, "assert": assert, "enlargeMemory": enlargeMemory, "getTotalMemory": getTotalMemory, "abortOnCannotGrowMemory": abortOnCannotGrowMemory, "invoke_ii": invoke_ii, "invoke_iiii": invoke_iiii, "invoke_vi": invoke_vi, "_pthread_cleanup_pop": _pthread_cleanup_pop, "___lock": ___lock, "___syscall6": ___syscall6, "_pthread_cleanup_push": _pthread_cleanup_push, "_abort": _abort, "___unlock": ___unlock, "___setErrNo": ___setErrNo, "_emscripten_memcpy_big": _emscripten_memcpy_big, "___syscall54": ___syscall54, "___syscall140": ___syscall140, "___syscall146": ___syscall146, "DYNAMICTOP_PTR": DYNAMICTOP_PTR, "tempDoublePtr": tempDoublePtr, "ABORT": ABORT, "STACKTOP": STACKTOP, "STACK_MAX": STACK_MAX }; 2061 | // EMSCRIPTEN_START_ASM 2062 | var asm =Module["asm"]// EMSCRIPTEN_END_ASM 2063 | (Module.asmGlobalArg, Module.asmLibraryArg, buffer); 2064 | 2065 | var _malloc = Module["_malloc"] = asm["_malloc"]; 2066 | var _free = Module["_free"] = asm["_free"]; 2067 | var runPostSets = Module["runPostSets"] = asm["runPostSets"]; 2068 | var _pthread_self = Module["_pthread_self"] = asm["_pthread_self"]; 2069 | var _memset = Module["_memset"] = asm["_memset"]; 2070 | var _sbrk = Module["_sbrk"] = asm["_sbrk"]; 2071 | var _sum_osc_static = Module["_sum_osc_static"] = asm["_sum_osc_static"]; 2072 | var _memcpy = Module["_memcpy"] = asm["_memcpy"]; 2073 | var _fflush = Module["_fflush"] = asm["_fflush"]; 2074 | var ___errno_location = Module["___errno_location"] = asm["___errno_location"]; 2075 | var dynCall_ii = Module["dynCall_ii"] = asm["dynCall_ii"]; 2076 | var dynCall_iiii = Module["dynCall_iiii"] = asm["dynCall_iiii"]; 2077 | var dynCall_vi = Module["dynCall_vi"] = asm["dynCall_vi"]; 2078 | ; 2079 | 2080 | Runtime.stackAlloc = asm['stackAlloc']; 2081 | Runtime.stackSave = asm['stackSave']; 2082 | Runtime.stackRestore = asm['stackRestore']; 2083 | Runtime.establishStackSpace = asm['establishStackSpace']; 2084 | 2085 | Runtime.setTempRet0 = asm['setTempRet0']; 2086 | Runtime.getTempRet0 = asm['getTempRet0']; 2087 | 2088 | 2089 | 2090 | // === Auto-generated postamble setup entry stuff === 2091 | 2092 | 2093 | 2094 | if (memoryInitializer) { 2095 | if (typeof Module['locateFile'] === 'function') { 2096 | memoryInitializer = Module['locateFile'](memoryInitializer); 2097 | } else if (Module['memoryInitializerPrefixURL']) { 2098 | memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer; 2099 | } 2100 | if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) { 2101 | var data = Module['readBinary'](memoryInitializer); 2102 | HEAPU8.set(data, Runtime.GLOBAL_BASE); 2103 | } else { 2104 | addRunDependency('memory initializer'); 2105 | var applyMemoryInitializer = function(data) { 2106 | if (data.byteLength) data = new Uint8Array(data); 2107 | HEAPU8.set(data, Runtime.GLOBAL_BASE); 2108 | // Delete the typed array that contains the large blob of the memory initializer request response so that 2109 | // we won't keep unnecessary memory lying around. However, keep the XHR object itself alive so that e.g. 2110 | // its .status field can still be accessed later. 2111 | if (Module['memoryInitializerRequest']) delete Module['memoryInitializerRequest'].response; 2112 | removeRunDependency('memory initializer'); 2113 | } 2114 | function doBrowserLoad() { 2115 | Module['readAsync'](memoryInitializer, applyMemoryInitializer, function() { 2116 | throw 'could not load memory initializer ' + memoryInitializer; 2117 | }); 2118 | } 2119 | if (Module['memoryInitializerRequest']) { 2120 | // a network request has already been created, just use that 2121 | function useRequest() { 2122 | var request = Module['memoryInitializerRequest']; 2123 | if (request.status !== 200 && request.status !== 0) { 2124 | // If you see this warning, the issue may be that you are using locateFile or memoryInitializerPrefixURL, and defining them in JS. That 2125 | // means that the HTML file doesn't know about them, and when it tries to create the mem init request early, does it to the wrong place. 2126 | // Look in your browser's devtools network console to see what's going on. 2127 | console.warn('a problem seems to have happened with Module.memoryInitializerRequest, status: ' + request.status + ', retrying ' + memoryInitializer); 2128 | doBrowserLoad(); 2129 | return; 2130 | } 2131 | applyMemoryInitializer(request.response); 2132 | } 2133 | if (Module['memoryInitializerRequest'].response) { 2134 | setTimeout(useRequest, 0); // it's already here; but, apply it asynchronously 2135 | } else { 2136 | Module['memoryInitializerRequest'].addEventListener('load', useRequest); // wait for it 2137 | } 2138 | } else { 2139 | // fetch it from the network ourselves 2140 | doBrowserLoad(); 2141 | } 2142 | } 2143 | } 2144 | 2145 | 2146 | function ExitStatus(status) { 2147 | this.name = "ExitStatus"; 2148 | this.message = "Program terminated with exit(" + status + ")"; 2149 | this.status = status; 2150 | }; 2151 | ExitStatus.prototype = new Error(); 2152 | ExitStatus.prototype.constructor = ExitStatus; 2153 | 2154 | var initialStackTop; 2155 | var preloadStartTime = null; 2156 | var calledMain = false; 2157 | 2158 | dependenciesFulfilled = function runCaller() { 2159 | // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false) 2160 | if (!Module['calledRun']) run(); 2161 | if (!Module['calledRun']) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled 2162 | } 2163 | 2164 | Module['callMain'] = Module.callMain = function callMain(args) { 2165 | 2166 | args = args || []; 2167 | 2168 | ensureInitRuntime(); 2169 | 2170 | var argc = args.length+1; 2171 | function pad() { 2172 | for (var i = 0; i < 4-1; i++) { 2173 | argv.push(0); 2174 | } 2175 | } 2176 | var argv = [allocate(intArrayFromString(Module['thisProgram']), 'i8', ALLOC_NORMAL) ]; 2177 | pad(); 2178 | for (var i = 0; i < argc-1; i = i + 1) { 2179 | argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); 2180 | pad(); 2181 | } 2182 | argv.push(0); 2183 | argv = allocate(argv, 'i32', ALLOC_NORMAL); 2184 | 2185 | 2186 | try { 2187 | 2188 | var ret = Module['_main'](argc, argv, 0); 2189 | 2190 | 2191 | // if we're not running an evented main loop, it's time to exit 2192 | exit(ret, /* implicit = */ true); 2193 | } 2194 | catch(e) { 2195 | if (e instanceof ExitStatus) { 2196 | // exit() throws this once it's done to make sure execution 2197 | // has been stopped completely 2198 | return; 2199 | } else if (e == 'SimulateInfiniteLoop') { 2200 | // running an evented main loop, don't immediately exit 2201 | Module['noExitRuntime'] = true; 2202 | return; 2203 | } else { 2204 | if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); 2205 | throw e; 2206 | } 2207 | } finally { 2208 | calledMain = true; 2209 | } 2210 | } 2211 | 2212 | 2213 | 2214 | 2215 | function run(args) { 2216 | args = args || Module['arguments']; 2217 | 2218 | if (preloadStartTime === null) preloadStartTime = Date.now(); 2219 | 2220 | if (runDependencies > 0) { 2221 | return; 2222 | } 2223 | 2224 | 2225 | preRun(); 2226 | 2227 | if (runDependencies > 0) return; // a preRun added a dependency, run will be called later 2228 | if (Module['calledRun']) return; // run may have just been called through dependencies being fulfilled just in this very frame 2229 | 2230 | function doRun() { 2231 | if (Module['calledRun']) return; // run may have just been called while the async setStatus time below was happening 2232 | Module['calledRun'] = true; 2233 | 2234 | if (ABORT) return; 2235 | 2236 | ensureInitRuntime(); 2237 | 2238 | preMain(); 2239 | 2240 | 2241 | if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized'](); 2242 | 2243 | if (Module['_main'] && shouldRunNow) Module['callMain'](args); 2244 | 2245 | postRun(); 2246 | } 2247 | 2248 | if (Module['setStatus']) { 2249 | Module['setStatus']('Running...'); 2250 | setTimeout(function() { 2251 | setTimeout(function() { 2252 | Module['setStatus'](''); 2253 | }, 1); 2254 | doRun(); 2255 | }, 1); 2256 | } else { 2257 | doRun(); 2258 | } 2259 | } 2260 | Module['run'] = Module.run = run; 2261 | 2262 | function exit(status, implicit) { 2263 | if (implicit && Module['noExitRuntime']) { 2264 | return; 2265 | } 2266 | 2267 | if (Module['noExitRuntime']) { 2268 | } else { 2269 | 2270 | ABORT = true; 2271 | EXITSTATUS = status; 2272 | STACKTOP = initialStackTop; 2273 | 2274 | exitRuntime(); 2275 | 2276 | if (Module['onExit']) Module['onExit'](status); 2277 | } 2278 | 2279 | if (ENVIRONMENT_IS_NODE) { 2280 | process['exit'](status); 2281 | } else if (ENVIRONMENT_IS_SHELL && typeof quit === 'function') { 2282 | quit(status); 2283 | } 2284 | // if we reach here, we must throw an exception to halt the current execution 2285 | throw new ExitStatus(status); 2286 | } 2287 | Module['exit'] = Module.exit = exit; 2288 | 2289 | var abortDecorators = []; 2290 | 2291 | function abort(what) { 2292 | if (what !== undefined) { 2293 | Module.print(what); 2294 | Module.printErr(what); 2295 | what = JSON.stringify(what) 2296 | } else { 2297 | what = ''; 2298 | } 2299 | 2300 | ABORT = true; 2301 | EXITSTATUS = 1; 2302 | 2303 | var extra = '\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.'; 2304 | 2305 | var output = 'abort(' + what + ') at ' + stackTrace() + extra; 2306 | if (abortDecorators) { 2307 | abortDecorators.forEach(function(decorator) { 2308 | output = decorator(output, what); 2309 | }); 2310 | } 2311 | throw output; 2312 | } 2313 | Module['abort'] = Module.abort = abort; 2314 | 2315 | // {{PRE_RUN_ADDITIONS}} 2316 | 2317 | if (Module['preInit']) { 2318 | if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']]; 2319 | while (Module['preInit'].length > 0) { 2320 | Module['preInit'].pop()(); 2321 | } 2322 | } 2323 | 2324 | // shouldRunNow refers to calling main(), not run(). 2325 | var shouldRunNow = true; 2326 | if (Module['noInitialRun']) { 2327 | shouldRunNow = false; 2328 | } 2329 | 2330 | 2331 | run(); 2332 | 2333 | // {{POST_RUN_ADDITIONS}} 2334 | 2335 | 2336 | 2337 | 2338 | 2339 | // {{MODULE_ADDITIONS}} 2340 | 2341 | 2342 | 2343 | 2344 | return WasmDspModule; 2345 | }; 2346 | --------------------------------------------------------------------------------