1 |
|
---|
2 |
|
---|
3 | // The Module object: Our interface to the outside world. We import
|
---|
4 | // and export values on it. There are various ways Module can be used:
|
---|
5 | // 1. Not defined. We create it here
|
---|
6 | // 2. A function parameter, function(Module) { ..generated code.. }
|
---|
7 | // 3. pre-run appended it, var Module = {}; ..generated code..
|
---|
8 | // 4. External script tag defines var Module.
|
---|
9 | // We need to check if Module already exists (e.g. case 3 above).
|
---|
10 | // Substitution will be replaced with actual code on later stage of the build,
|
---|
11 | // this way Closure Compiler will not mangle it (e.g. case 4. above).
|
---|
12 | // Note that if you want to run closure, and also to use Module
|
---|
13 | // after the generated code, you will need to define var Module = {};
|
---|
14 | // before the code. Then that object will be used in the code, and you
|
---|
15 | // can continue to use Module afterwards as well.
|
---|
16 | var Module = typeof Module !== 'undefined' ? Module : {};
|
---|
17 |
|
---|
18 |
|
---|
19 |
|
---|
20 | // --pre-jses are emitted after the Module integration code, so that they can
|
---|
21 | // refer to Module (if they choose; they can also define Module)
|
---|
22 | var mrbc = function(Module) {
|
---|
23 | Module['preRun'].push(function () {
|
---|
24 | Module['FS'] = FS;
|
---|
25 | });
|
---|
26 |
|
---|
27 |
|
---|
28 |
|
---|
29 | // Sometimes an existing Module object exists with properties
|
---|
30 | // meant to overwrite the default module functionality. Here
|
---|
31 | // we collect those properties and reapply _after_ we configure
|
---|
32 | // the current environment's defaults to avoid having to be so
|
---|
33 | // defensive during initialization.
|
---|
34 | var moduleOverrides = {};
|
---|
35 | var key;
|
---|
36 | for (key in Module) {
|
---|
37 | if (Module.hasOwnProperty(key)) {
|
---|
38 | moduleOverrides[key] = Module[key];
|
---|
39 | }
|
---|
40 | }
|
---|
41 |
|
---|
42 | var arguments_ = [];
|
---|
43 | var thisProgram = './this.program';
|
---|
44 | var quit_ = function(status, toThrow) {
|
---|
45 | throw toThrow;
|
---|
46 | };
|
---|
47 |
|
---|
48 | // Determine the runtime environment we are in. You can customize this by
|
---|
49 | // setting the ENVIRONMENT setting at compile time (see settings.js).
|
---|
50 |
|
---|
51 | var ENVIRONMENT_IS_WEB = false;
|
---|
52 | var ENVIRONMENT_IS_WORKER = false;
|
---|
53 | var ENVIRONMENT_IS_NODE = false;
|
---|
54 | var ENVIRONMENT_IS_SHELL = false;
|
---|
55 | ENVIRONMENT_IS_WEB = typeof window === 'object';
|
---|
56 | ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
|
---|
57 | // N.b. Electron.js environment is simultaneously a NODE-environment, but
|
---|
58 | // also a web environment.
|
---|
59 | ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
|
---|
60 | ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
|
---|
61 |
|
---|
62 | if (Module['ENVIRONMENT']) {
|
---|
63 | throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)');
|
---|
64 | }
|
---|
65 |
|
---|
66 |
|
---|
67 |
|
---|
68 | // `/` should be present at the end if `scriptDirectory` is not empty
|
---|
69 | var scriptDirectory = '';
|
---|
70 | function locateFile(path) {
|
---|
71 | if (Module['locateFile']) {
|
---|
72 | return Module['locateFile'](path, scriptDirectory);
|
---|
73 | }
|
---|
74 | return scriptDirectory + path;
|
---|
75 | }
|
---|
76 |
|
---|
77 | // Hooks that are implemented differently in different runtime environments.
|
---|
78 | var read_,
|
---|
79 | readAsync,
|
---|
80 | readBinary,
|
---|
81 | setWindowTitle;
|
---|
82 |
|
---|
83 | var nodeFS;
|
---|
84 | var nodePath;
|
---|
85 |
|
---|
86 | if (ENVIRONMENT_IS_NODE) {
|
---|
87 | if (ENVIRONMENT_IS_WORKER) {
|
---|
88 | scriptDirectory = require('path').dirname(scriptDirectory) + '/';
|
---|
89 | } else {
|
---|
90 | scriptDirectory = __dirname + '/';
|
---|
91 | }
|
---|
92 |
|
---|
93 |
|
---|
94 |
|
---|
95 |
|
---|
96 | read_ = function shell_read(filename, binary) {
|
---|
97 | if (!nodeFS) nodeFS = require('fs');
|
---|
98 | if (!nodePath) nodePath = require('path');
|
---|
99 | filename = nodePath['normalize'](filename);
|
---|
100 | return nodeFS['readFileSync'](filename, binary ? null : 'utf8');
|
---|
101 | };
|
---|
102 |
|
---|
103 | readBinary = function readBinary(filename) {
|
---|
104 | var ret = read_(filename, true);
|
---|
105 | if (!ret.buffer) {
|
---|
106 | ret = new Uint8Array(ret);
|
---|
107 | }
|
---|
108 | assert(ret.buffer);
|
---|
109 | return ret;
|
---|
110 | };
|
---|
111 |
|
---|
112 |
|
---|
113 |
|
---|
114 |
|
---|
115 | if (process['argv'].length > 1) {
|
---|
116 | thisProgram = process['argv'][1].replace(/\\/g, '/');
|
---|
117 | }
|
---|
118 |
|
---|
119 | arguments_ = process['argv'].slice(2);
|
---|
120 |
|
---|
121 | if (typeof module !== 'undefined') {
|
---|
122 | module['exports'] = Module;
|
---|
123 | }
|
---|
124 |
|
---|
125 | process['on']('uncaughtException', function(ex) {
|
---|
126 | // suppress ExitStatus exceptions from showing an error
|
---|
127 | if (!(ex instanceof ExitStatus)) {
|
---|
128 | throw ex;
|
---|
129 | }
|
---|
130 | });
|
---|
131 |
|
---|
132 | process['on']('unhandledRejection', abort);
|
---|
133 |
|
---|
134 | quit_ = function(status) {
|
---|
135 | process['exit'](status);
|
---|
136 | };
|
---|
137 |
|
---|
138 | Module['inspect'] = function () { return '[Emscripten Module object]'; };
|
---|
139 |
|
---|
140 |
|
---|
141 |
|
---|
142 | } else
|
---|
143 | if (ENVIRONMENT_IS_SHELL) {
|
---|
144 |
|
---|
145 |
|
---|
146 | if (typeof read != 'undefined') {
|
---|
147 | read_ = function shell_read(f) {
|
---|
148 | return read(f);
|
---|
149 | };
|
---|
150 | }
|
---|
151 |
|
---|
152 | readBinary = function readBinary(f) {
|
---|
153 | var data;
|
---|
154 | if (typeof readbuffer === 'function') {
|
---|
155 | return new Uint8Array(readbuffer(f));
|
---|
156 | }
|
---|
157 | data = read(f, 'binary');
|
---|
158 | assert(typeof data === 'object');
|
---|
159 | return data;
|
---|
160 | };
|
---|
161 |
|
---|
162 | if (typeof scriptArgs != 'undefined') {
|
---|
163 | arguments_ = scriptArgs;
|
---|
164 | } else if (typeof arguments != 'undefined') {
|
---|
165 | arguments_ = arguments;
|
---|
166 | }
|
---|
167 |
|
---|
168 | if (typeof quit === 'function') {
|
---|
169 | quit_ = function(status) {
|
---|
170 | quit(status);
|
---|
171 | };
|
---|
172 | }
|
---|
173 |
|
---|
174 | if (typeof print !== 'undefined') {
|
---|
175 | // Prefer to use print/printErr where they exist, as they usually work better.
|
---|
176 | if (typeof console === 'undefined') console = /** @type{!Console} */({});
|
---|
177 | console.log = /** @type{!function(this:Console, ...*): undefined} */ (print);
|
---|
178 | console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr !== 'undefined' ? printErr : print);
|
---|
179 | }
|
---|
180 |
|
---|
181 |
|
---|
182 | } else
|
---|
183 |
|
---|
184 | // Note that this includes Node.js workers when relevant (pthreads is enabled).
|
---|
185 | // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
|
---|
186 | // ENVIRONMENT_IS_NODE.
|
---|
187 | if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
|
---|
188 | if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled
|
---|
189 | scriptDirectory = self.location.href;
|
---|
190 | } else if (document.currentScript) { // web
|
---|
191 | scriptDirectory = document.currentScript.src;
|
---|
192 | }
|
---|
193 | // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
|
---|
194 | // otherwise, slice off the final part of the url to find the script directory.
|
---|
195 | // if scriptDirectory does not contain a slash, lastIndexOf will return -1,
|
---|
196 | // and scriptDirectory will correctly be replaced with an empty string.
|
---|
197 | if (scriptDirectory.indexOf('blob:') !== 0) {
|
---|
198 | scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1);
|
---|
199 | } else {
|
---|
200 | scriptDirectory = '';
|
---|
201 | }
|
---|
202 |
|
---|
203 |
|
---|
204 | // Differentiate the Web Worker from the Node Worker case, as reading must
|
---|
205 | // be done differently.
|
---|
206 | {
|
---|
207 |
|
---|
208 |
|
---|
209 |
|
---|
210 |
|
---|
211 | read_ = function shell_read(url) {
|
---|
212 | var xhr = new XMLHttpRequest();
|
---|
213 | xhr.open('GET', url, false);
|
---|
214 | xhr.send(null);
|
---|
215 | return xhr.responseText;
|
---|
216 | };
|
---|
217 |
|
---|
218 | if (ENVIRONMENT_IS_WORKER) {
|
---|
219 | readBinary = function readBinary(url) {
|
---|
220 | var xhr = new XMLHttpRequest();
|
---|
221 | xhr.open('GET', url, false);
|
---|
222 | xhr.responseType = 'arraybuffer';
|
---|
223 | xhr.send(null);
|
---|
224 | return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));
|
---|
225 | };
|
---|
226 | }
|
---|
227 |
|
---|
228 | readAsync = function readAsync(url, onload, onerror) {
|
---|
229 | var xhr = new XMLHttpRequest();
|
---|
230 | xhr.open('GET', url, true);
|
---|
231 | xhr.responseType = 'arraybuffer';
|
---|
232 | xhr.onload = function xhr_onload() {
|
---|
233 | if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
|
---|
234 | onload(xhr.response);
|
---|
235 | return;
|
---|
236 | }
|
---|
237 | onerror();
|
---|
238 | };
|
---|
239 | xhr.onerror = onerror;
|
---|
240 | xhr.send(null);
|
---|
241 | };
|
---|
242 |
|
---|
243 |
|
---|
244 |
|
---|
245 |
|
---|
246 | }
|
---|
247 |
|
---|
248 | setWindowTitle = function(title) { document.title = title };
|
---|
249 | } else
|
---|
250 | {
|
---|
251 | throw new Error('environment detection error');
|
---|
252 | }
|
---|
253 |
|
---|
254 |
|
---|
255 | // Set up the out() and err() hooks, which are how we can print to stdout or
|
---|
256 | // stderr, respectively.
|
---|
257 | var out = Module['print'] || console.log.bind(console);
|
---|
258 | var err = Module['printErr'] || console.warn.bind(console);
|
---|
259 |
|
---|
260 | // Merge back in the overrides
|
---|
261 | for (key in moduleOverrides) {
|
---|
262 | if (moduleOverrides.hasOwnProperty(key)) {
|
---|
263 | Module[key] = moduleOverrides[key];
|
---|
264 | }
|
---|
265 | }
|
---|
266 | // Free the object hierarchy contained in the overrides, this lets the GC
|
---|
267 | // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
|
---|
268 | moduleOverrides = null;
|
---|
269 |
|
---|
270 | // Emit code to handle expected values on the Module object. This applies Module.x
|
---|
271 | // to the proper local x. This has two benefits: first, we only emit it if it is
|
---|
272 | // expected to arrive, and second, by using a local everywhere else that can be
|
---|
273 | // minified.
|
---|
274 | if (Module['arguments']) arguments_ = Module['arguments'];if (!Object.getOwnPropertyDescriptor(Module, 'arguments')) Object.defineProperty(Module, 'arguments', { configurable: true, get: function() { abort('Module.arguments has been replaced with plain arguments_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
275 | if (Module['thisProgram']) thisProgram = Module['thisProgram'];if (!Object.getOwnPropertyDescriptor(Module, 'thisProgram')) Object.defineProperty(Module, 'thisProgram', { configurable: true, get: function() { abort('Module.thisProgram has been replaced with plain thisProgram (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
276 | if (Module['quit']) quit_ = Module['quit'];if (!Object.getOwnPropertyDescriptor(Module, 'quit')) Object.defineProperty(Module, 'quit', { configurable: true, get: function() { abort('Module.quit has been replaced with plain quit_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
277 |
|
---|
278 | // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
|
---|
279 | // Assertions on removed incoming Module JS APIs.
|
---|
280 | assert(typeof Module['memoryInitializerPrefixURL'] === 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
|
---|
281 | assert(typeof Module['pthreadMainPrefixURL'] === 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
|
---|
282 | assert(typeof Module['cdInitializerPrefixURL'] === 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
|
---|
283 | assert(typeof Module['filePackagePrefixURL'] === 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
|
---|
284 | assert(typeof Module['read'] === 'undefined', 'Module.read option was removed (modify read_ in JS)');
|
---|
285 | assert(typeof Module['readAsync'] === 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
|
---|
286 | assert(typeof Module['readBinary'] === 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
|
---|
287 | assert(typeof Module['setWindowTitle'] === 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)');
|
---|
288 | assert(typeof Module['TOTAL_MEMORY'] === 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
|
---|
289 | if (!Object.getOwnPropertyDescriptor(Module, 'read')) Object.defineProperty(Module, 'read', { configurable: true, get: function() { abort('Module.read has been replaced with plain read_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
290 | if (!Object.getOwnPropertyDescriptor(Module, 'readAsync')) Object.defineProperty(Module, 'readAsync', { configurable: true, get: function() { abort('Module.readAsync has been replaced with plain readAsync (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
291 | if (!Object.getOwnPropertyDescriptor(Module, 'readBinary')) Object.defineProperty(Module, 'readBinary', { configurable: true, get: function() { abort('Module.readBinary has been replaced with plain readBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
292 | if (!Object.getOwnPropertyDescriptor(Module, 'setWindowTitle')) Object.defineProperty(Module, 'setWindowTitle', { configurable: true, get: function() { abort('Module.setWindowTitle has been replaced with plain setWindowTitle (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
293 | var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js';
|
---|
294 | var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js';
|
---|
295 | var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js';
|
---|
296 | var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
|
---|
297 |
|
---|
298 |
|
---|
299 |
|
---|
300 |
|
---|
301 |
|
---|
302 |
|
---|
303 | // {{PREAMBLE_ADDITIONS}}
|
---|
304 |
|
---|
305 | var STACK_ALIGN = 16;
|
---|
306 |
|
---|
307 | function dynamicAlloc(size) {
|
---|
308 | assert(DYNAMICTOP_PTR);
|
---|
309 | var ret = HEAP32[DYNAMICTOP_PTR>>2];
|
---|
310 | var end = (ret + size + 15) & -16;
|
---|
311 | assert(end <= HEAP8.length, 'failure to dynamicAlloc - memory growth etc. is not supported there, call malloc/sbrk directly');
|
---|
312 | HEAP32[DYNAMICTOP_PTR>>2] = end;
|
---|
313 | return ret;
|
---|
314 | }
|
---|
315 |
|
---|
316 | function alignMemory(size, factor) {
|
---|
317 | if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default
|
---|
318 | return Math.ceil(size / factor) * factor;
|
---|
319 | }
|
---|
320 |
|
---|
321 | function getNativeTypeSize(type) {
|
---|
322 | switch (type) {
|
---|
323 | case 'i1': case 'i8': return 1;
|
---|
324 | case 'i16': return 2;
|
---|
325 | case 'i32': return 4;
|
---|
326 | case 'i64': return 8;
|
---|
327 | case 'float': return 4;
|
---|
328 | case 'double': return 8;
|
---|
329 | default: {
|
---|
330 | if (type[type.length-1] === '*') {
|
---|
331 | return 4; // A pointer
|
---|
332 | } else if (type[0] === 'i') {
|
---|
333 | var bits = Number(type.substr(1));
|
---|
334 | assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type);
|
---|
335 | return bits / 8;
|
---|
336 | } else {
|
---|
337 | return 0;
|
---|
338 | }
|
---|
339 | }
|
---|
340 | }
|
---|
341 | }
|
---|
342 |
|
---|
343 | function warnOnce(text) {
|
---|
344 | if (!warnOnce.shown) warnOnce.shown = {};
|
---|
345 | if (!warnOnce.shown[text]) {
|
---|
346 | warnOnce.shown[text] = 1;
|
---|
347 | err(text);
|
---|
348 | }
|
---|
349 | }
|
---|
350 |
|
---|
351 |
|
---|
352 |
|
---|
353 |
|
---|
354 |
|
---|
355 |
|
---|
356 |
|
---|
357 |
|
---|
358 | // Wraps a JS function as a wasm function with a given signature.
|
---|
359 | function convertJsFunctionToWasm(func, sig) {
|
---|
360 |
|
---|
361 | // If the type reflection proposal is available, use the new
|
---|
362 | // "WebAssembly.Function" constructor.
|
---|
363 | // Otherwise, construct a minimal wasm module importing the JS function and
|
---|
364 | // re-exporting it.
|
---|
365 | if (typeof WebAssembly.Function === "function") {
|
---|
366 | var typeNames = {
|
---|
367 | 'i': 'i32',
|
---|
368 | 'j': 'i64',
|
---|
369 | 'f': 'f32',
|
---|
370 | 'd': 'f64'
|
---|
371 | };
|
---|
372 | var type = {
|
---|
373 | parameters: [],
|
---|
374 | results: sig[0] == 'v' ? [] : [typeNames[sig[0]]]
|
---|
375 | };
|
---|
376 | for (var i = 1; i < sig.length; ++i) {
|
---|
377 | type.parameters.push(typeNames[sig[i]]);
|
---|
378 | }
|
---|
379 | return new WebAssembly.Function(type, func);
|
---|
380 | }
|
---|
381 |
|
---|
382 | // The module is static, with the exception of the type section, which is
|
---|
383 | // generated based on the signature passed in.
|
---|
384 | var typeSection = [
|
---|
385 | 0x01, // id: section,
|
---|
386 | 0x00, // length: 0 (placeholder)
|
---|
387 | 0x01, // count: 1
|
---|
388 | 0x60, // form: func
|
---|
389 | ];
|
---|
390 | var sigRet = sig.slice(0, 1);
|
---|
391 | var sigParam = sig.slice(1);
|
---|
392 | var typeCodes = {
|
---|
393 | 'i': 0x7f, // i32
|
---|
394 | 'j': 0x7e, // i64
|
---|
395 | 'f': 0x7d, // f32
|
---|
396 | 'd': 0x7c, // f64
|
---|
397 | };
|
---|
398 |
|
---|
399 | // Parameters, length + signatures
|
---|
400 | typeSection.push(sigParam.length);
|
---|
401 | for (var i = 0; i < sigParam.length; ++i) {
|
---|
402 | typeSection.push(typeCodes[sigParam[i]]);
|
---|
403 | }
|
---|
404 |
|
---|
405 | // Return values, length + signatures
|
---|
406 | // With no multi-return in MVP, either 0 (void) or 1 (anything else)
|
---|
407 | if (sigRet == 'v') {
|
---|
408 | typeSection.push(0x00);
|
---|
409 | } else {
|
---|
410 | typeSection = typeSection.concat([0x01, typeCodes[sigRet]]);
|
---|
411 | }
|
---|
412 |
|
---|
413 | // Write the overall length of the type section back into the section header
|
---|
414 | // (excepting the 2 bytes for the section id and length)
|
---|
415 | typeSection[1] = typeSection.length - 2;
|
---|
416 |
|
---|
417 | // Rest of the module is static
|
---|
418 | var bytes = new Uint8Array([
|
---|
419 | 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
|
---|
420 | 0x01, 0x00, 0x00, 0x00, // version: 1
|
---|
421 | ].concat(typeSection, [
|
---|
422 | 0x02, 0x07, // import section
|
---|
423 | // (import "e" "f" (func 0 (type 0)))
|
---|
424 | 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
|
---|
425 | 0x07, 0x05, // export section
|
---|
426 | // (export "f" (func 0 (type 0)))
|
---|
427 | 0x01, 0x01, 0x66, 0x00, 0x00,
|
---|
428 | ]));
|
---|
429 |
|
---|
430 | // We can compile this wasm module synchronously because it is very small.
|
---|
431 | // This accepts an import (at "e.f"), that it reroutes to an export (at "f")
|
---|
432 | var module = new WebAssembly.Module(bytes);
|
---|
433 | var instance = new WebAssembly.Instance(module, {
|
---|
434 | 'e': {
|
---|
435 | 'f': func
|
---|
436 | }
|
---|
437 | });
|
---|
438 | var wrappedFunc = instance.exports['f'];
|
---|
439 | return wrappedFunc;
|
---|
440 | }
|
---|
441 |
|
---|
442 | var freeTableIndexes = [];
|
---|
443 |
|
---|
444 | // Weak map of functions in the table to their indexes, created on first use.
|
---|
445 | var functionsInTableMap;
|
---|
446 |
|
---|
447 | // Add a wasm function to the table.
|
---|
448 | function addFunctionWasm(func, sig) {
|
---|
449 | var table = wasmTable;
|
---|
450 |
|
---|
451 | // Check if the function is already in the table, to ensure each function
|
---|
452 | // gets a unique index. First, create the map if this is the first use.
|
---|
453 | if (!functionsInTableMap) {
|
---|
454 | functionsInTableMap = new WeakMap();
|
---|
455 | for (var i = 0; i < table.length; i++) {
|
---|
456 | var item = table.get(i);
|
---|
457 | // Ignore null values.
|
---|
458 | if (item) {
|
---|
459 | functionsInTableMap.set(item, i);
|
---|
460 | }
|
---|
461 | }
|
---|
462 | }
|
---|
463 | if (functionsInTableMap.has(func)) {
|
---|
464 | return functionsInTableMap.get(func);
|
---|
465 | }
|
---|
466 |
|
---|
467 | // It's not in the table, add it now.
|
---|
468 |
|
---|
469 |
|
---|
470 | var ret;
|
---|
471 | // Reuse a free index if there is one, otherwise grow.
|
---|
472 | if (freeTableIndexes.length) {
|
---|
473 | ret = freeTableIndexes.pop();
|
---|
474 | } else {
|
---|
475 | ret = table.length;
|
---|
476 | // Grow the table
|
---|
477 | try {
|
---|
478 | table.grow(1);
|
---|
479 | } catch (err) {
|
---|
480 | if (!(err instanceof RangeError)) {
|
---|
481 | throw err;
|
---|
482 | }
|
---|
483 | throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.';
|
---|
484 | }
|
---|
485 | }
|
---|
486 |
|
---|
487 | // Set the new value.
|
---|
488 | try {
|
---|
489 | // Attempting to call this with JS function will cause of table.set() to fail
|
---|
490 | table.set(ret, func);
|
---|
491 | } catch (err) {
|
---|
492 | if (!(err instanceof TypeError)) {
|
---|
493 | throw err;
|
---|
494 | }
|
---|
495 | assert(typeof sig !== 'undefined', 'Missing signature argument to addFunction');
|
---|
496 | var wrapped = convertJsFunctionToWasm(func, sig);
|
---|
497 | table.set(ret, wrapped);
|
---|
498 | }
|
---|
499 |
|
---|
500 | functionsInTableMap.set(func, ret);
|
---|
501 |
|
---|
502 | return ret;
|
---|
503 | }
|
---|
504 |
|
---|
505 | function removeFunctionWasm(index) {
|
---|
506 | functionsInTableMap.delete(wasmTable.get(index));
|
---|
507 | freeTableIndexes.push(index);
|
---|
508 | }
|
---|
509 |
|
---|
510 | // 'sig' parameter is required for the llvm backend but only when func is not
|
---|
511 | // already a WebAssembly function.
|
---|
512 | function addFunction(func, sig) {
|
---|
513 | assert(typeof func !== 'undefined');
|
---|
514 |
|
---|
515 | return addFunctionWasm(func, sig);
|
---|
516 | }
|
---|
517 |
|
---|
518 | function removeFunction(index) {
|
---|
519 | removeFunctionWasm(index);
|
---|
520 | }
|
---|
521 |
|
---|
522 |
|
---|
523 |
|
---|
524 | var funcWrappers = {};
|
---|
525 |
|
---|
526 | function getFuncWrapper(func, sig) {
|
---|
527 | if (!func) return; // on null pointer, return undefined
|
---|
528 | assert(sig);
|
---|
529 | if (!funcWrappers[sig]) {
|
---|
530 | funcWrappers[sig] = {};
|
---|
531 | }
|
---|
532 | var sigCache = funcWrappers[sig];
|
---|
533 | if (!sigCache[func]) {
|
---|
534 | // optimize away arguments usage in common cases
|
---|
535 | if (sig.length === 1) {
|
---|
536 | sigCache[func] = function dynCall_wrapper() {
|
---|
537 | return dynCall(sig, func);
|
---|
538 | };
|
---|
539 | } else if (sig.length === 2) {
|
---|
540 | sigCache[func] = function dynCall_wrapper(arg) {
|
---|
541 | return dynCall(sig, func, [arg]);
|
---|
542 | };
|
---|
543 | } else {
|
---|
544 | // general case
|
---|
545 | sigCache[func] = function dynCall_wrapper() {
|
---|
546 | return dynCall(sig, func, Array.prototype.slice.call(arguments));
|
---|
547 | };
|
---|
548 | }
|
---|
549 | }
|
---|
550 | return sigCache[func];
|
---|
551 | }
|
---|
552 |
|
---|
553 |
|
---|
554 |
|
---|
555 |
|
---|
556 |
|
---|
557 |
|
---|
558 |
|
---|
559 | function makeBigInt(low, high, unsigned) {
|
---|
560 | return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0));
|
---|
561 | }
|
---|
562 |
|
---|
563 | /** @param {Array=} args */
|
---|
564 | function dynCall(sig, ptr, args) {
|
---|
565 | if (args && args.length) {
|
---|
566 | // j (64-bit integer) must be passed in as two numbers [low 32, high 32].
|
---|
567 | assert(args.length === sig.substring(1).replace(/j/g, '--').length);
|
---|
568 | assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
|
---|
569 | return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
|
---|
570 | } else {
|
---|
571 | assert(sig.length == 1);
|
---|
572 | assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
|
---|
573 | return Module['dynCall_' + sig].call(null, ptr);
|
---|
574 | }
|
---|
575 | }
|
---|
576 |
|
---|
577 | var tempRet0 = 0;
|
---|
578 |
|
---|
579 | var setTempRet0 = function(value) {
|
---|
580 | tempRet0 = value;
|
---|
581 | };
|
---|
582 |
|
---|
583 | var getTempRet0 = function() {
|
---|
584 | return tempRet0;
|
---|
585 | };
|
---|
586 |
|
---|
587 | function getCompilerSetting(name) {
|
---|
588 | throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for getCompilerSetting or emscripten_get_compiler_setting to work';
|
---|
589 | }
|
---|
590 |
|
---|
591 | // The address globals begin at. Very low in memory, for code size and optimization opportunities.
|
---|
592 | // Above 0 is static memory, starting with globals.
|
---|
593 | // Then the stack.
|
---|
594 | // Then 'dynamic' memory for sbrk.
|
---|
595 | var GLOBAL_BASE = 1024;
|
---|
596 |
|
---|
597 |
|
---|
598 |
|
---|
599 |
|
---|
600 |
|
---|
601 | // === Preamble library stuff ===
|
---|
602 |
|
---|
603 | // Documentation for the public APIs defined in this file must be updated in:
|
---|
604 | // site/source/docs/api_reference/preamble.js.rst
|
---|
605 | // A prebuilt local version of the documentation is available at:
|
---|
606 | // site/build/text/docs/api_reference/preamble.js.txt
|
---|
607 | // You can also build docs locally as HTML or other formats in site/
|
---|
608 | // An online HTML version (which may be of a different version of Emscripten)
|
---|
609 | // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
|
---|
610 |
|
---|
611 |
|
---|
612 | var wasmBinary;if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];if (!Object.getOwnPropertyDescriptor(Module, 'wasmBinary')) Object.defineProperty(Module, 'wasmBinary', { configurable: true, get: function() { abort('Module.wasmBinary has been replaced with plain wasmBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
613 | var noExitRuntime;if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];if (!Object.getOwnPropertyDescriptor(Module, 'noExitRuntime')) Object.defineProperty(Module, 'noExitRuntime', { configurable: true, get: function() { abort('Module.noExitRuntime has been replaced with plain noExitRuntime (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
614 |
|
---|
615 |
|
---|
616 | if (typeof WebAssembly !== 'object') {
|
---|
617 | abort('no native wasm support detected');
|
---|
618 | }
|
---|
619 |
|
---|
620 |
|
---|
621 |
|
---|
622 |
|
---|
623 | // In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking.
|
---|
624 | // In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties)
|
---|
625 |
|
---|
626 | /** @param {number} ptr
|
---|
627 | @param {number} value
|
---|
628 | @param {string} type
|
---|
629 | @param {number|boolean=} noSafe */
|
---|
630 | function setValue(ptr, value, type, noSafe) {
|
---|
631 | type = type || 'i8';
|
---|
632 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
|
---|
633 | switch(type) {
|
---|
634 | case 'i1': HEAP8[((ptr)>>0)]=value; break;
|
---|
635 | case 'i8': HEAP8[((ptr)>>0)]=value; break;
|
---|
636 | case 'i16': HEAP16[((ptr)>>1)]=value; break;
|
---|
637 | case 'i32': HEAP32[((ptr)>>2)]=value; break;
|
---|
638 | 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;
|
---|
639 | case 'float': HEAPF32[((ptr)>>2)]=value; break;
|
---|
640 | case 'double': HEAPF64[((ptr)>>3)]=value; break;
|
---|
641 | default: abort('invalid type for setValue: ' + type);
|
---|
642 | }
|
---|
643 | }
|
---|
644 |
|
---|
645 | /** @param {number} ptr
|
---|
646 | @param {string} type
|
---|
647 | @param {number|boolean=} noSafe */
|
---|
648 | function getValue(ptr, type, noSafe) {
|
---|
649 | type = type || 'i8';
|
---|
650 | if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
|
---|
651 | switch(type) {
|
---|
652 | case 'i1': return HEAP8[((ptr)>>0)];
|
---|
653 | case 'i8': return HEAP8[((ptr)>>0)];
|
---|
654 | case 'i16': return HEAP16[((ptr)>>1)];
|
---|
655 | case 'i32': return HEAP32[((ptr)>>2)];
|
---|
656 | case 'i64': return HEAP32[((ptr)>>2)];
|
---|
657 | case 'float': return HEAPF32[((ptr)>>2)];
|
---|
658 | case 'double': return HEAPF64[((ptr)>>3)];
|
---|
659 | default: abort('invalid type for getValue: ' + type);
|
---|
660 | }
|
---|
661 | return null;
|
---|
662 | }
|
---|
663 |
|
---|
664 |
|
---|
665 |
|
---|
666 |
|
---|
667 |
|
---|
668 |
|
---|
669 | // Wasm globals
|
---|
670 |
|
---|
671 | var wasmMemory;
|
---|
672 |
|
---|
673 | // In fastcomp asm.js, we don't need a wasm Table at all.
|
---|
674 | // In the wasm backend, we polyfill the WebAssembly object,
|
---|
675 | // so this creates a (non-native-wasm) table for us.
|
---|
676 | var wasmTable = new WebAssembly.Table({
|
---|
677 | 'initial': 336,
|
---|
678 | 'maximum': 336 + 0,
|
---|
679 | 'element': 'anyfunc'
|
---|
680 | });
|
---|
681 |
|
---|
682 |
|
---|
683 | //========================================
|
---|
684 | // Runtime essentials
|
---|
685 | //========================================
|
---|
686 |
|
---|
687 | // whether we are quitting the application. no code should run after this.
|
---|
688 | // set in exit() and abort()
|
---|
689 | var ABORT = false;
|
---|
690 |
|
---|
691 | // set by exit() and abort(). Passed to 'onExit' handler.
|
---|
692 | // NOTE: This is also used as the process return code code in shell environments
|
---|
693 | // but only when noExitRuntime is false.
|
---|
694 | var EXITSTATUS = 0;
|
---|
695 |
|
---|
696 | /** @type {function(*, string=)} */
|
---|
697 | function assert(condition, text) {
|
---|
698 | if (!condition) {
|
---|
699 | abort('Assertion failed: ' + text);
|
---|
700 | }
|
---|
701 | }
|
---|
702 |
|
---|
703 | // Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
|
---|
704 | function getCFunc(ident) {
|
---|
705 | var func = Module['_' + ident]; // closure exported function
|
---|
706 | assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
|
---|
707 | return func;
|
---|
708 | }
|
---|
709 |
|
---|
710 | // C calling interface.
|
---|
711 | /** @param {string|null=} returnType
|
---|
712 | @param {Array=} argTypes
|
---|
713 | @param {Arguments|Array=} args
|
---|
714 | @param {Object=} opts */
|
---|
715 | function ccall(ident, returnType, argTypes, args, opts) {
|
---|
716 | // For fast lookup of conversion functions
|
---|
717 | var toC = {
|
---|
718 | 'string': function(str) {
|
---|
719 | var ret = 0;
|
---|
720 | if (str !== null && str !== undefined && str !== 0) { // null string
|
---|
721 | // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
|
---|
722 | var len = (str.length << 2) + 1;
|
---|
723 | ret = stackAlloc(len);
|
---|
724 | stringToUTF8(str, ret, len);
|
---|
725 | }
|
---|
726 | return ret;
|
---|
727 | },
|
---|
728 | 'array': function(arr) {
|
---|
729 | var ret = stackAlloc(arr.length);
|
---|
730 | writeArrayToMemory(arr, ret);
|
---|
731 | return ret;
|
---|
732 | }
|
---|
733 | };
|
---|
734 |
|
---|
735 | function convertReturnValue(ret) {
|
---|
736 | if (returnType === 'string') return UTF8ToString(ret);
|
---|
737 | if (returnType === 'boolean') return Boolean(ret);
|
---|
738 | return ret;
|
---|
739 | }
|
---|
740 |
|
---|
741 | var func = getCFunc(ident);
|
---|
742 | var cArgs = [];
|
---|
743 | var stack = 0;
|
---|
744 | assert(returnType !== 'array', 'Return type should not be "array".');
|
---|
745 | if (args) {
|
---|
746 | for (var i = 0; i < args.length; i++) {
|
---|
747 | var converter = toC[argTypes[i]];
|
---|
748 | if (converter) {
|
---|
749 | if (stack === 0) stack = stackSave();
|
---|
750 | cArgs[i] = converter(args[i]);
|
---|
751 | } else {
|
---|
752 | cArgs[i] = args[i];
|
---|
753 | }
|
---|
754 | }
|
---|
755 | }
|
---|
756 | var ret = func.apply(null, cArgs);
|
---|
757 |
|
---|
758 | ret = convertReturnValue(ret);
|
---|
759 | if (stack !== 0) stackRestore(stack);
|
---|
760 | return ret;
|
---|
761 | }
|
---|
762 |
|
---|
763 | /** @param {string=} returnType
|
---|
764 | @param {Array=} argTypes
|
---|
765 | @param {Object=} opts */
|
---|
766 | function cwrap(ident, returnType, argTypes, opts) {
|
---|
767 | return function() {
|
---|
768 | return ccall(ident, returnType, argTypes, arguments, opts);
|
---|
769 | }
|
---|
770 | }
|
---|
771 |
|
---|
772 | var ALLOC_NORMAL = 0; // Tries to use _malloc()
|
---|
773 | var ALLOC_STACK = 1; // Lives for the duration of the current function call
|
---|
774 | var ALLOC_DYNAMIC = 2; // Cannot be freed except through sbrk
|
---|
775 | var ALLOC_NONE = 3; // Do not allocate
|
---|
776 |
|
---|
777 | // allocate(): This is for internal use. You can use it yourself as well, but the interface
|
---|
778 | // is a little tricky (see docs right below). The reason is that it is optimized
|
---|
779 | // for multiple syntaxes to save space in generated code. So you should
|
---|
780 | // normally not use allocate(), and instead allocate memory using _malloc(),
|
---|
781 | // initialize it with setValue(), and so forth.
|
---|
782 | // @slab: An array of data, or a number. If a number, then the size of the block to allocate,
|
---|
783 | // in *bytes* (note that this is sometimes confusing: the next parameter does not
|
---|
784 | // affect this!)
|
---|
785 | // @types: Either an array of types, one for each byte (or 0 if no type at that position),
|
---|
786 | // or a single type which is used for the entire block. This only matters if there
|
---|
787 | // is initial data - if @slab is a number, then this does not matter at all and is
|
---|
788 | // ignored.
|
---|
789 | // @allocator: How to allocate memory, see ALLOC_*
|
---|
790 | /** @type {function((TypedArray|Array<number>|number), string, number, number=)} */
|
---|
791 | function allocate(slab, types, allocator, ptr) {
|
---|
792 | var zeroinit, size;
|
---|
793 | if (typeof slab === 'number') {
|
---|
794 | zeroinit = true;
|
---|
795 | size = slab;
|
---|
796 | } else {
|
---|
797 | zeroinit = false;
|
---|
798 | size = slab.length;
|
---|
799 | }
|
---|
800 |
|
---|
801 | var singleType = typeof types === 'string' ? types : null;
|
---|
802 |
|
---|
803 | var ret;
|
---|
804 | if (allocator == ALLOC_NONE) {
|
---|
805 | ret = ptr;
|
---|
806 | } else {
|
---|
807 | ret = [_malloc,
|
---|
808 | stackAlloc,
|
---|
809 | dynamicAlloc][allocator](Math.max(size, singleType ? 1 : types.length));
|
---|
810 | }
|
---|
811 |
|
---|
812 | if (zeroinit) {
|
---|
813 | var stop;
|
---|
814 | ptr = ret;
|
---|
815 | assert((ret & 3) == 0);
|
---|
816 | stop = ret + (size & ~3);
|
---|
817 | for (; ptr < stop; ptr += 4) {
|
---|
818 | HEAP32[((ptr)>>2)]=0;
|
---|
819 | }
|
---|
820 | stop = ret + size;
|
---|
821 | while (ptr < stop) {
|
---|
822 | HEAP8[((ptr++)>>0)]=0;
|
---|
823 | }
|
---|
824 | return ret;
|
---|
825 | }
|
---|
826 |
|
---|
827 | if (singleType === 'i8') {
|
---|
828 | if (slab.subarray || slab.slice) {
|
---|
829 | HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret);
|
---|
830 | } else {
|
---|
831 | HEAPU8.set(new Uint8Array(slab), ret);
|
---|
832 | }
|
---|
833 | return ret;
|
---|
834 | }
|
---|
835 |
|
---|
836 | var i = 0, type, typeSize, previousType;
|
---|
837 | while (i < size) {
|
---|
838 | var curr = slab[i];
|
---|
839 |
|
---|
840 | type = singleType || types[i];
|
---|
841 | if (type === 0) {
|
---|
842 | i++;
|
---|
843 | continue;
|
---|
844 | }
|
---|
845 | assert(type, 'Must know what type to store in allocate!');
|
---|
846 |
|
---|
847 | if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
|
---|
848 |
|
---|
849 | setValue(ret+i, curr, type);
|
---|
850 |
|
---|
851 | // no need to look up size unless type changes, so cache it
|
---|
852 | if (previousType !== type) {
|
---|
853 | typeSize = getNativeTypeSize(type);
|
---|
854 | previousType = type;
|
---|
855 | }
|
---|
856 | i += typeSize;
|
---|
857 | }
|
---|
858 |
|
---|
859 | return ret;
|
---|
860 | }
|
---|
861 |
|
---|
862 | // Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready
|
---|
863 | function getMemory(size) {
|
---|
864 | if (!runtimeInitialized) return dynamicAlloc(size);
|
---|
865 | return _malloc(size);
|
---|
866 | }
|
---|
867 |
|
---|
868 |
|
---|
869 |
|
---|
870 |
|
---|
871 | // runtime_strings.js: Strings related runtime functions that are part of both MINIMAL_RUNTIME and regular runtime.
|
---|
872 |
|
---|
873 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
|
---|
874 | // a copy of that string as a Javascript String object.
|
---|
875 |
|
---|
876 | var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined;
|
---|
877 |
|
---|
878 | /**
|
---|
879 | * @param {number} idx
|
---|
880 | * @param {number=} maxBytesToRead
|
---|
881 | * @return {string}
|
---|
882 | */
|
---|
883 | function UTF8ArrayToString(heap, idx, maxBytesToRead) {
|
---|
884 | var endIdx = idx + maxBytesToRead;
|
---|
885 | var endPtr = idx;
|
---|
886 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
|
---|
887 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
|
---|
888 | // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity)
|
---|
889 | while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
|
---|
890 |
|
---|
891 | if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
|
---|
892 | return UTF8Decoder.decode(heap.subarray(idx, endPtr));
|
---|
893 | } else {
|
---|
894 | var str = '';
|
---|
895 | // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that
|
---|
896 | while (idx < endPtr) {
|
---|
897 | // For UTF8 byte structure, see:
|
---|
898 | // http://en.wikipedia.org/wiki/UTF-8#Description
|
---|
899 | // https://www.ietf.org/rfc/rfc2279.txt
|
---|
900 | // https://tools.ietf.org/html/rfc3629
|
---|
901 | var u0 = heap[idx++];
|
---|
902 | if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
|
---|
903 | var u1 = heap[idx++] & 63;
|
---|
904 | if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
|
---|
905 | var u2 = heap[idx++] & 63;
|
---|
906 | if ((u0 & 0xF0) == 0xE0) {
|
---|
907 | u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
|
---|
908 | } else {
|
---|
909 | if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!');
|
---|
910 | u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
|
---|
911 | }
|
---|
912 |
|
---|
913 | if (u0 < 0x10000) {
|
---|
914 | str += String.fromCharCode(u0);
|
---|
915 | } else {
|
---|
916 | var ch = u0 - 0x10000;
|
---|
917 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
|
---|
918 | }
|
---|
919 | }
|
---|
920 | }
|
---|
921 | return str;
|
---|
922 | }
|
---|
923 |
|
---|
924 | // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a
|
---|
925 | // copy of that string as a Javascript String object.
|
---|
926 | // maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit
|
---|
927 | // this parameter to scan the string until the first \0 byte. If maxBytesToRead is
|
---|
928 | // passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the
|
---|
929 | // middle, then the string will cut short at that byte index (i.e. maxBytesToRead will
|
---|
930 | // not produce a string of exact length [ptr, ptr+maxBytesToRead[)
|
---|
931 | // N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may
|
---|
932 | // throw JS JIT optimizations off, so it is worth to consider consistently using one
|
---|
933 | // style or the other.
|
---|
934 | /**
|
---|
935 | * @param {number} ptr
|
---|
936 | * @param {number=} maxBytesToRead
|
---|
937 | * @return {string}
|
---|
938 | */
|
---|
939 | function UTF8ToString(ptr, maxBytesToRead) {
|
---|
940 | return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
|
---|
941 | }
|
---|
942 |
|
---|
943 | // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
|
---|
944 | // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP.
|
---|
945 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
|
---|
946 | // Parameters:
|
---|
947 | // str: the Javascript string to copy.
|
---|
948 | // heap: the array to copy to. Each index in this array is assumed to be one 8-byte element.
|
---|
949 | // outIdx: The starting offset in the array to begin the copying.
|
---|
950 | // maxBytesToWrite: The maximum number of bytes this function can write to the array.
|
---|
951 | // This count should include the null terminator,
|
---|
952 | // i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else.
|
---|
953 | // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator.
|
---|
954 | // Returns the number of bytes written, EXCLUDING the null terminator.
|
---|
955 |
|
---|
956 | function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
|
---|
957 | if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
|
---|
958 | return 0;
|
---|
959 |
|
---|
960 | var startIdx = outIdx;
|
---|
961 | var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
|
---|
962 | for (var i = 0; i < str.length; ++i) {
|
---|
963 | // 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.
|
---|
964 | // See http://unicode.org/faq/utf_bom.html#utf16-3
|
---|
965 | // 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
|
---|
966 | var u = str.charCodeAt(i); // possibly a lead surrogate
|
---|
967 | if (u >= 0xD800 && u <= 0xDFFF) {
|
---|
968 | var u1 = str.charCodeAt(++i);
|
---|
969 | u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
|
---|
970 | }
|
---|
971 | if (u <= 0x7F) {
|
---|
972 | if (outIdx >= endIdx) break;
|
---|
973 | heap[outIdx++] = u;
|
---|
974 | } else if (u <= 0x7FF) {
|
---|
975 | if (outIdx + 1 >= endIdx) break;
|
---|
976 | heap[outIdx++] = 0xC0 | (u >> 6);
|
---|
977 | heap[outIdx++] = 0x80 | (u & 63);
|
---|
978 | } else if (u <= 0xFFFF) {
|
---|
979 | if (outIdx + 2 >= endIdx) break;
|
---|
980 | heap[outIdx++] = 0xE0 | (u >> 12);
|
---|
981 | heap[outIdx++] = 0x80 | ((u >> 6) & 63);
|
---|
982 | heap[outIdx++] = 0x80 | (u & 63);
|
---|
983 | } else {
|
---|
984 | if (outIdx + 3 >= endIdx) break;
|
---|
985 | if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).');
|
---|
986 | heap[outIdx++] = 0xF0 | (u >> 18);
|
---|
987 | heap[outIdx++] = 0x80 | ((u >> 12) & 63);
|
---|
988 | heap[outIdx++] = 0x80 | ((u >> 6) & 63);
|
---|
989 | heap[outIdx++] = 0x80 | (u & 63);
|
---|
990 | }
|
---|
991 | }
|
---|
992 | // Null-terminate the pointer to the buffer.
|
---|
993 | heap[outIdx] = 0;
|
---|
994 | return outIdx - startIdx;
|
---|
995 | }
|
---|
996 |
|
---|
997 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
|
---|
998 | // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP.
|
---|
999 | // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
|
---|
1000 | // Returns the number of bytes written, EXCLUDING the null terminator.
|
---|
1001 |
|
---|
1002 | function stringToUTF8(str, outPtr, maxBytesToWrite) {
|
---|
1003 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
|
---|
1004 | return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
|
---|
1005 | }
|
---|
1006 |
|
---|
1007 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
|
---|
1008 | function lengthBytesUTF8(str) {
|
---|
1009 | var len = 0;
|
---|
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! So decode UTF16->UTF32->UTF8.
|
---|
1012 | // See http://unicode.org/faq/utf_bom.html#utf16-3
|
---|
1013 | var u = str.charCodeAt(i); // possibly a lead surrogate
|
---|
1014 | if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
|
---|
1015 | if (u <= 0x7F) ++len;
|
---|
1016 | else if (u <= 0x7FF) len += 2;
|
---|
1017 | else if (u <= 0xFFFF) len += 3;
|
---|
1018 | else len += 4;
|
---|
1019 | }
|
---|
1020 | return len;
|
---|
1021 | }
|
---|
1022 |
|
---|
1023 |
|
---|
1024 |
|
---|
1025 |
|
---|
1026 |
|
---|
1027 | // runtime_strings_extra.js: Strings related runtime functions that are available only in regular runtime.
|
---|
1028 |
|
---|
1029 | // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
|
---|
1030 | // a copy of that string as a Javascript String object.
|
---|
1031 |
|
---|
1032 | function AsciiToString(ptr) {
|
---|
1033 | var str = '';
|
---|
1034 | while (1) {
|
---|
1035 | var ch = HEAPU8[((ptr++)>>0)];
|
---|
1036 | if (!ch) return str;
|
---|
1037 | str += String.fromCharCode(ch);
|
---|
1038 | }
|
---|
1039 | }
|
---|
1040 |
|
---|
1041 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
|
---|
1042 | // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
|
---|
1043 |
|
---|
1044 | function stringToAscii(str, outPtr) {
|
---|
1045 | return writeAsciiToMemory(str, outPtr, false);
|
---|
1046 | }
|
---|
1047 |
|
---|
1048 | // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
|
---|
1049 | // a copy of that string as a Javascript String object.
|
---|
1050 |
|
---|
1051 | var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined;
|
---|
1052 |
|
---|
1053 | function UTF16ToString(ptr, maxBytesToRead) {
|
---|
1054 | assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!');
|
---|
1055 | var endPtr = ptr;
|
---|
1056 | // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
|
---|
1057 | // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
|
---|
1058 | var idx = endPtr >> 1;
|
---|
1059 | var maxIdx = idx + maxBytesToRead / 2;
|
---|
1060 | // If maxBytesToRead is not passed explicitly, it will be undefined, and this
|
---|
1061 | // will always evaluate to true. This saves on code size.
|
---|
1062 | while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
|
---|
1063 | endPtr = idx << 1;
|
---|
1064 |
|
---|
1065 | if (endPtr - ptr > 32 && UTF16Decoder) {
|
---|
1066 | return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
|
---|
1067 | } else {
|
---|
1068 | var i = 0;
|
---|
1069 |
|
---|
1070 | var str = '';
|
---|
1071 | while (1) {
|
---|
1072 | var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
|
---|
1073 | if (codeUnit == 0 || i == maxBytesToRead / 2) return str;
|
---|
1074 | ++i;
|
---|
1075 | // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
|
---|
1076 | str += String.fromCharCode(codeUnit);
|
---|
1077 | }
|
---|
1078 | }
|
---|
1079 | }
|
---|
1080 |
|
---|
1081 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
|
---|
1082 | // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP.
|
---|
1083 | // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write.
|
---|
1084 | // Parameters:
|
---|
1085 | // str: the Javascript string to copy.
|
---|
1086 | // outPtr: Byte address in Emscripten HEAP where to write the string to.
|
---|
1087 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
|
---|
1088 | // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else.
|
---|
1089 | // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator.
|
---|
1090 | // Returns the number of bytes written, EXCLUDING the null terminator.
|
---|
1091 |
|
---|
1092 | function stringToUTF16(str, outPtr, maxBytesToWrite) {
|
---|
1093 | assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!');
|
---|
1094 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
|
---|
1095 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
|
---|
1096 | if (maxBytesToWrite === undefined) {
|
---|
1097 | maxBytesToWrite = 0x7FFFFFFF;
|
---|
1098 | }
|
---|
1099 | if (maxBytesToWrite < 2) return 0;
|
---|
1100 | maxBytesToWrite -= 2; // Null terminator.
|
---|
1101 | var startPtr = outPtr;
|
---|
1102 | var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length;
|
---|
1103 | for (var i = 0; i < numCharsToWrite; ++i) {
|
---|
1104 | // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
|
---|
1105 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
|
---|
1106 | HEAP16[((outPtr)>>1)]=codeUnit;
|
---|
1107 | outPtr += 2;
|
---|
1108 | }
|
---|
1109 | // Null-terminate the pointer to the HEAP.
|
---|
1110 | HEAP16[((outPtr)>>1)]=0;
|
---|
1111 | return outPtr - startPtr;
|
---|
1112 | }
|
---|
1113 |
|
---|
1114 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
|
---|
1115 |
|
---|
1116 | function lengthBytesUTF16(str) {
|
---|
1117 | return str.length*2;
|
---|
1118 | }
|
---|
1119 |
|
---|
1120 | function UTF32ToString(ptr, maxBytesToRead) {
|
---|
1121 | assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!');
|
---|
1122 | var i = 0;
|
---|
1123 |
|
---|
1124 | var str = '';
|
---|
1125 | // If maxBytesToRead is not passed explicitly, it will be undefined, and this
|
---|
1126 | // will always evaluate to true. This saves on code size.
|
---|
1127 | while (!(i >= maxBytesToRead / 4)) {
|
---|
1128 | var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
|
---|
1129 | if (utf32 == 0) break;
|
---|
1130 | ++i;
|
---|
1131 | // 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.
|
---|
1132 | // See http://unicode.org/faq/utf_bom.html#utf16-3
|
---|
1133 | if (utf32 >= 0x10000) {
|
---|
1134 | var ch = utf32 - 0x10000;
|
---|
1135 | str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
|
---|
1136 | } else {
|
---|
1137 | str += String.fromCharCode(utf32);
|
---|
1138 | }
|
---|
1139 | }
|
---|
1140 | return str;
|
---|
1141 | }
|
---|
1142 |
|
---|
1143 | // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
|
---|
1144 | // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP.
|
---|
1145 | // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write.
|
---|
1146 | // Parameters:
|
---|
1147 | // str: the Javascript string to copy.
|
---|
1148 | // outPtr: Byte address in Emscripten HEAP where to write the string to.
|
---|
1149 | // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
|
---|
1150 | // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else.
|
---|
1151 | // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator.
|
---|
1152 | // Returns the number of bytes written, EXCLUDING the null terminator.
|
---|
1153 |
|
---|
1154 | function stringToUTF32(str, outPtr, maxBytesToWrite) {
|
---|
1155 | assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!');
|
---|
1156 | assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
|
---|
1157 | // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
|
---|
1158 | if (maxBytesToWrite === undefined) {
|
---|
1159 | maxBytesToWrite = 0x7FFFFFFF;
|
---|
1160 | }
|
---|
1161 | if (maxBytesToWrite < 4) return 0;
|
---|
1162 | var startPtr = outPtr;
|
---|
1163 | var endPtr = startPtr + maxBytesToWrite - 4;
|
---|
1164 | for (var i = 0; i < str.length; ++i) {
|
---|
1165 | // 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.
|
---|
1166 | // See http://unicode.org/faq/utf_bom.html#utf16-3
|
---|
1167 | var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
|
---|
1168 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
|
---|
1169 | var trailSurrogate = str.charCodeAt(++i);
|
---|
1170 | codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
|
---|
1171 | }
|
---|
1172 | HEAP32[((outPtr)>>2)]=codeUnit;
|
---|
1173 | outPtr += 4;
|
---|
1174 | if (outPtr + 4 > endPtr) break;
|
---|
1175 | }
|
---|
1176 | // Null-terminate the pointer to the HEAP.
|
---|
1177 | HEAP32[((outPtr)>>2)]=0;
|
---|
1178 | return outPtr - startPtr;
|
---|
1179 | }
|
---|
1180 |
|
---|
1181 | // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
|
---|
1182 |
|
---|
1183 | function lengthBytesUTF32(str) {
|
---|
1184 | var len = 0;
|
---|
1185 | for (var i = 0; i < str.length; ++i) {
|
---|
1186 | // 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.
|
---|
1187 | // See http://unicode.org/faq/utf_bom.html#utf16-3
|
---|
1188 | var codeUnit = str.charCodeAt(i);
|
---|
1189 | if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
|
---|
1190 | len += 4;
|
---|
1191 | }
|
---|
1192 |
|
---|
1193 | return len;
|
---|
1194 | }
|
---|
1195 |
|
---|
1196 | // Allocate heap space for a JS string, and write it there.
|
---|
1197 | // It is the responsibility of the caller to free() that memory.
|
---|
1198 | function allocateUTF8(str) {
|
---|
1199 | var size = lengthBytesUTF8(str) + 1;
|
---|
1200 | var ret = _malloc(size);
|
---|
1201 | if (ret) stringToUTF8Array(str, HEAP8, ret, size);
|
---|
1202 | return ret;
|
---|
1203 | }
|
---|
1204 |
|
---|
1205 | // Allocate stack space for a JS string, and write it there.
|
---|
1206 | function allocateUTF8OnStack(str) {
|
---|
1207 | var size = lengthBytesUTF8(str) + 1;
|
---|
1208 | var ret = stackAlloc(size);
|
---|
1209 | stringToUTF8Array(str, HEAP8, ret, size);
|
---|
1210 | return ret;
|
---|
1211 | }
|
---|
1212 |
|
---|
1213 | // Deprecated: This function should not be called because it is unsafe and does not provide
|
---|
1214 | // a maximum length limit of how many bytes it is allowed to write. Prefer calling the
|
---|
1215 | // function stringToUTF8Array() instead, which takes in a maximum length that can be used
|
---|
1216 | // to be secure from out of bounds writes.
|
---|
1217 | /** @deprecated
|
---|
1218 | @param {boolean=} dontAddNull */
|
---|
1219 | function writeStringToMemory(string, buffer, dontAddNull) {
|
---|
1220 | warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
|
---|
1221 |
|
---|
1222 | var /** @type {number} */ lastChar, /** @type {number} */ end;
|
---|
1223 | if (dontAddNull) {
|
---|
1224 | // stringToUTF8Array always appends null. If we don't want to do that, remember the
|
---|
1225 | // character that existed at the location where the null will be placed, and restore
|
---|
1226 | // that after the write (below).
|
---|
1227 | end = buffer + lengthBytesUTF8(string);
|
---|
1228 | lastChar = HEAP8[end];
|
---|
1229 | }
|
---|
1230 | stringToUTF8(string, buffer, Infinity);
|
---|
1231 | if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
|
---|
1232 | }
|
---|
1233 |
|
---|
1234 | function writeArrayToMemory(array, buffer) {
|
---|
1235 | assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')
|
---|
1236 | HEAP8.set(array, buffer);
|
---|
1237 | }
|
---|
1238 |
|
---|
1239 | /** @param {boolean=} dontAddNull */
|
---|
1240 | function writeAsciiToMemory(str, buffer, dontAddNull) {
|
---|
1241 | for (var i = 0; i < str.length; ++i) {
|
---|
1242 | assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff);
|
---|
1243 | HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
|
---|
1244 | }
|
---|
1245 | // Null-terminate the pointer to the HEAP.
|
---|
1246 | if (!dontAddNull) HEAP8[((buffer)>>0)]=0;
|
---|
1247 | }
|
---|
1248 |
|
---|
1249 |
|
---|
1250 |
|
---|
1251 | // Memory management
|
---|
1252 |
|
---|
1253 | var PAGE_SIZE = 16384;
|
---|
1254 | var WASM_PAGE_SIZE = 65536;
|
---|
1255 | var ASMJS_PAGE_SIZE = 16777216;
|
---|
1256 |
|
---|
1257 | function alignUp(x, multiple) {
|
---|
1258 | if (x % multiple > 0) {
|
---|
1259 | x += multiple - (x % multiple);
|
---|
1260 | }
|
---|
1261 | return x;
|
---|
1262 | }
|
---|
1263 |
|
---|
1264 | var HEAP,
|
---|
1265 | /** @type {ArrayBuffer} */
|
---|
1266 | buffer,
|
---|
1267 | /** @type {Int8Array} */
|
---|
1268 | HEAP8,
|
---|
1269 | /** @type {Uint8Array} */
|
---|
1270 | HEAPU8,
|
---|
1271 | /** @type {Int16Array} */
|
---|
1272 | HEAP16,
|
---|
1273 | /** @type {Uint16Array} */
|
---|
1274 | HEAPU16,
|
---|
1275 | /** @type {Int32Array} */
|
---|
1276 | HEAP32,
|
---|
1277 | /** @type {Uint32Array} */
|
---|
1278 | HEAPU32,
|
---|
1279 | /** @type {Float32Array} */
|
---|
1280 | HEAPF32,
|
---|
1281 | /** @type {Float64Array} */
|
---|
1282 | HEAPF64;
|
---|
1283 |
|
---|
1284 | function updateGlobalBufferAndViews(buf) {
|
---|
1285 | buffer = buf;
|
---|
1286 | Module['HEAP8'] = HEAP8 = new Int8Array(buf);
|
---|
1287 | Module['HEAP16'] = HEAP16 = new Int16Array(buf);
|
---|
1288 | Module['HEAP32'] = HEAP32 = new Int32Array(buf);
|
---|
1289 | Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf);
|
---|
1290 | Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf);
|
---|
1291 | Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf);
|
---|
1292 | Module['HEAPF32'] = HEAPF32 = new Float32Array(buf);
|
---|
1293 | Module['HEAPF64'] = HEAPF64 = new Float64Array(buf);
|
---|
1294 | }
|
---|
1295 |
|
---|
1296 | var STATIC_BASE = 1024,
|
---|
1297 | STACK_BASE = 5322752,
|
---|
1298 | STACKTOP = STACK_BASE,
|
---|
1299 | STACK_MAX = 79872,
|
---|
1300 | DYNAMIC_BASE = 5322752,
|
---|
1301 | DYNAMICTOP_PTR = 79712;
|
---|
1302 |
|
---|
1303 | assert(STACK_BASE % 16 === 0, 'stack must start aligned');
|
---|
1304 | assert(DYNAMIC_BASE % 16 === 0, 'heap must start aligned');
|
---|
1305 |
|
---|
1306 |
|
---|
1307 | var TOTAL_STACK = 5242880;
|
---|
1308 | if (Module['TOTAL_STACK']) assert(TOTAL_STACK === Module['TOTAL_STACK'], 'the stack size can no longer be determined at runtime')
|
---|
1309 |
|
---|
1310 | var INITIAL_INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;if (!Object.getOwnPropertyDescriptor(Module, 'INITIAL_MEMORY')) Object.defineProperty(Module, 'INITIAL_MEMORY', { configurable: true, get: function() { abort('Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
|
---|
1311 |
|
---|
1312 | assert(INITIAL_INITIAL_MEMORY >= TOTAL_STACK, 'INITIAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_INITIAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')');
|
---|
1313 |
|
---|
1314 | // check for full engine support (use string 'subarray' to avoid closure compiler confusion)
|
---|
1315 | assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined,
|
---|
1316 | 'JS engine does not provide full typed array support');
|
---|
1317 |
|
---|
1318 |
|
---|
1319 |
|
---|
1320 |
|
---|
1321 |
|
---|
1322 |
|
---|
1323 |
|
---|
1324 |
|
---|
1325 | // In non-standalone/normal mode, we create the memory here.
|
---|
1326 |
|
---|
1327 |
|
---|
1328 |
|
---|
1329 | // Create the main memory. (Note: this isn't used in STANDALONE_WASM mode since the wasm
|
---|
1330 | // memory is created in the wasm, not in JS.)
|
---|
1331 |
|
---|
1332 | if (Module['wasmMemory']) {
|
---|
1333 | wasmMemory = Module['wasmMemory'];
|
---|
1334 | } else
|
---|
1335 | {
|
---|
1336 | wasmMemory = new WebAssembly.Memory({
|
---|
1337 | 'initial': INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
|
---|
1338 | ,
|
---|
1339 | 'maximum': INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
|
---|
1340 | });
|
---|
1341 | }
|
---|
1342 |
|
---|
1343 |
|
---|
1344 | if (wasmMemory) {
|
---|
1345 | buffer = wasmMemory.buffer;
|
---|
1346 | }
|
---|
1347 |
|
---|
1348 | // If the user provides an incorrect length, just use that length instead rather than providing the user to
|
---|
1349 | // specifically provide the memory length with Module['INITIAL_MEMORY'].
|
---|
1350 | INITIAL_INITIAL_MEMORY = buffer.byteLength;
|
---|
1351 | assert(INITIAL_INITIAL_MEMORY % WASM_PAGE_SIZE === 0);
|
---|
1352 | updateGlobalBufferAndViews(buffer);
|
---|
1353 |
|
---|
1354 | HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE;
|
---|
1355 |
|
---|
1356 |
|
---|
1357 |
|
---|
1358 |
|
---|
1359 |
|
---|
1360 |
|
---|
1361 | // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
|
---|
1362 | function writeStackCookie() {
|
---|
1363 | assert((STACK_MAX & 3) == 0);
|
---|
1364 | // The stack grows downwards
|
---|
1365 | HEAPU32[(STACK_MAX >> 2)+1] = 0x2135467;
|
---|
1366 | HEAPU32[(STACK_MAX >> 2)+2] = 0x89BACDFE;
|
---|
1367 | // Also test the global address 0 for integrity.
|
---|
1368 | // We don't do this with ASan because ASan does its own checks for this.
|
---|
1369 | HEAP32[0] = 0x63736d65; /* 'emsc' */
|
---|
1370 | }
|
---|
1371 |
|
---|
1372 | function checkStackCookie() {
|
---|
1373 | var cookie1 = HEAPU32[(STACK_MAX >> 2)+1];
|
---|
1374 | var cookie2 = HEAPU32[(STACK_MAX >> 2)+2];
|
---|
1375 | if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) {
|
---|
1376 | abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x' + cookie2.toString(16) + ' ' + cookie1.toString(16));
|
---|
1377 | }
|
---|
1378 | // Also test the global address 0 for integrity.
|
---|
1379 | // We don't do this with ASan because ASan does its own checks for this.
|
---|
1380 | if (HEAP32[0] !== 0x63736d65 /* 'emsc' */) abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
|
---|
1381 | }
|
---|
1382 |
|
---|
1383 |
|
---|
1384 |
|
---|
1385 |
|
---|
1386 |
|
---|
1387 | // Endianness check (note: assumes compiler arch was little-endian)
|
---|
1388 | (function() {
|
---|
1389 | var h16 = new Int16Array(1);
|
---|
1390 | var h8 = new Int8Array(h16.buffer);
|
---|
1391 | h16[0] = 0x6373;
|
---|
1392 | if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian!';
|
---|
1393 | })();
|
---|
1394 |
|
---|
1395 | function abortFnPtrError(ptr, sig) {
|
---|
1396 | abort("Invalid function pointer " + ptr + " called with signature '" + sig + "'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this). Build with ASSERTIONS=2 for more info.");
|
---|
1397 | }
|
---|
1398 |
|
---|
1399 |
|
---|
1400 |
|
---|
1401 | function callRuntimeCallbacks(callbacks) {
|
---|
1402 | while(callbacks.length > 0) {
|
---|
1403 | var callback = callbacks.shift();
|
---|
1404 | if (typeof callback == 'function') {
|
---|
1405 | callback(Module); // Pass the module as the first argument.
|
---|
1406 | continue;
|
---|
1407 | }
|
---|
1408 | var func = callback.func;
|
---|
1409 | if (typeof func === 'number') {
|
---|
1410 | if (callback.arg === undefined) {
|
---|
1411 | Module['dynCall_v'](func);
|
---|
1412 | } else {
|
---|
1413 | Module['dynCall_vi'](func, callback.arg);
|
---|
1414 | }
|
---|
1415 | } else {
|
---|
1416 | func(callback.arg === undefined ? null : callback.arg);
|
---|
1417 | }
|
---|
1418 | }
|
---|
1419 | }
|
---|
1420 |
|
---|
1421 | var __ATPRERUN__ = []; // functions called before the runtime is initialized
|
---|
1422 | var __ATINIT__ = []; // functions called during startup
|
---|
1423 | var __ATMAIN__ = []; // functions called when main() is to be run
|
---|
1424 | var __ATEXIT__ = []; // functions called during shutdown
|
---|
1425 | var __ATPOSTRUN__ = []; // functions called after the main() is called
|
---|
1426 |
|
---|
1427 | var runtimeInitialized = false;
|
---|
1428 | var runtimeExited = false;
|
---|
1429 |
|
---|
1430 |
|
---|
1431 | function preRun() {
|
---|
1432 |
|
---|
1433 | if (Module['preRun']) {
|
---|
1434 | if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
|
---|
1435 | while (Module['preRun'].length) {
|
---|
1436 | addOnPreRun(Module['preRun'].shift());
|
---|
1437 | }
|
---|
1438 | }
|
---|
1439 |
|
---|
1440 | callRuntimeCallbacks(__ATPRERUN__);
|
---|
1441 | }
|
---|
1442 |
|
---|
1443 | function initRuntime() {
|
---|
1444 | checkStackCookie();
|
---|
1445 | assert(!runtimeInitialized);
|
---|
1446 | runtimeInitialized = true;
|
---|
1447 | if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
|
---|
1448 | TTY.init();
|
---|
1449 | callRuntimeCallbacks(__ATINIT__);
|
---|
1450 | }
|
---|
1451 |
|
---|
1452 | function preMain() {
|
---|
1453 | checkStackCookie();
|
---|
1454 | FS.ignorePermissions = false;
|
---|
1455 | callRuntimeCallbacks(__ATMAIN__);
|
---|
1456 | }
|
---|
1457 |
|
---|
1458 | function exitRuntime() {
|
---|
1459 | checkStackCookie();
|
---|
1460 | runtimeExited = true;
|
---|
1461 | }
|
---|
1462 |
|
---|
1463 | function postRun() {
|
---|
1464 | checkStackCookie();
|
---|
1465 |
|
---|
1466 | if (Module['postRun']) {
|
---|
1467 | if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
|
---|
1468 | while (Module['postRun'].length) {
|
---|
1469 | addOnPostRun(Module['postRun'].shift());
|
---|
1470 | }
|
---|
1471 | }
|
---|
1472 |
|
---|
1473 | callRuntimeCallbacks(__ATPOSTRUN__);
|
---|
1474 | }
|
---|
1475 |
|
---|
1476 | function addOnPreRun(cb) {
|
---|
1477 | __ATPRERUN__.unshift(cb);
|
---|
1478 | }
|
---|
1479 |
|
---|
1480 | function addOnInit(cb) {
|
---|
1481 | __ATINIT__.unshift(cb);
|
---|
1482 | }
|
---|
1483 |
|
---|
1484 | function addOnPreMain(cb) {
|
---|
1485 | __ATMAIN__.unshift(cb);
|
---|
1486 | }
|
---|
1487 |
|
---|
1488 | function addOnExit(cb) {
|
---|
1489 | }
|
---|
1490 |
|
---|
1491 | function addOnPostRun(cb) {
|
---|
1492 | __ATPOSTRUN__.unshift(cb);
|
---|
1493 | }
|
---|
1494 |
|
---|
1495 | /** @param {number|boolean=} ignore */
|
---|
1496 | function unSign(value, bits, ignore) {
|
---|
1497 | if (value >= 0) {
|
---|
1498 | return value;
|
---|
1499 | }
|
---|
1500 | 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
|
---|
1501 | : Math.pow(2, bits) + value;
|
---|
1502 | }
|
---|
1503 | /** @param {number|boolean=} ignore */
|
---|
1504 | function reSign(value, bits, ignore) {
|
---|
1505 | if (value <= 0) {
|
---|
1506 | return value;
|
---|
1507 | }
|
---|
1508 | var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
|
---|
1509 | : Math.pow(2, bits-1);
|
---|
1510 | 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
|
---|
1511 | // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
|
---|
1512 | // TODO: In i64 mode 1, resign the two parts separately and safely
|
---|
1513 | value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
|
---|
1514 | }
|
---|
1515 | return value;
|
---|
1516 | }
|
---|
1517 |
|
---|
1518 |
|
---|
1519 |
|
---|
1520 |
|
---|
1521 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
|
---|
1522 |
|
---|
1523 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
|
---|
1524 |
|
---|
1525 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
|
---|
1526 |
|
---|
1527 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
|
---|
1528 |
|
---|
1529 | assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
|
---|
1530 | assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
|
---|
1531 | assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
|
---|
1532 | assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
|
---|
1533 |
|
---|
1534 | var Math_abs = Math.abs;
|
---|
1535 | var Math_cos = Math.cos;
|
---|
1536 | var Math_sin = Math.sin;
|
---|
1537 | var Math_tan = Math.tan;
|
---|
1538 | var Math_acos = Math.acos;
|
---|
1539 | var Math_asin = Math.asin;
|
---|
1540 | var Math_atan = Math.atan;
|
---|
1541 | var Math_atan2 = Math.atan2;
|
---|
1542 | var Math_exp = Math.exp;
|
---|
1543 | var Math_log = Math.log;
|
---|
1544 | var Math_sqrt = Math.sqrt;
|
---|
1545 | var Math_ceil = Math.ceil;
|
---|
1546 | var Math_floor = Math.floor;
|
---|
1547 | var Math_pow = Math.pow;
|
---|
1548 | var Math_imul = Math.imul;
|
---|
1549 | var Math_fround = Math.fround;
|
---|
1550 | var Math_round = Math.round;
|
---|
1551 | var Math_min = Math.min;
|
---|
1552 | var Math_max = Math.max;
|
---|
1553 | var Math_clz32 = Math.clz32;
|
---|
1554 | var Math_trunc = Math.trunc;
|
---|
1555 |
|
---|
1556 |
|
---|
1557 |
|
---|
1558 | // A counter of dependencies for calling run(). If we need to
|
---|
1559 | // do asynchronous work before running, increment this and
|
---|
1560 | // decrement it. Incrementing must happen in a place like
|
---|
1561 | // Module.preRun (used by emcc to add file preloading).
|
---|
1562 | // Note that you can add dependencies in preRun, even though
|
---|
1563 | // it happens right before run - run will be postponed until
|
---|
1564 | // the dependencies are met.
|
---|
1565 | var runDependencies = 0;
|
---|
1566 | var runDependencyWatcher = null;
|
---|
1567 | var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
|
---|
1568 | var runDependencyTracking = {};
|
---|
1569 |
|
---|
1570 | function getUniqueRunDependency(id) {
|
---|
1571 | var orig = id;
|
---|
1572 | while (1) {
|
---|
1573 | if (!runDependencyTracking[id]) return id;
|
---|
1574 | id = orig + Math.random();
|
---|
1575 | }
|
---|
1576 | }
|
---|
1577 |
|
---|
1578 | function addRunDependency(id) {
|
---|
1579 | runDependencies++;
|
---|
1580 |
|
---|
1581 | if (Module['monitorRunDependencies']) {
|
---|
1582 | Module['monitorRunDependencies'](runDependencies);
|
---|
1583 | }
|
---|
1584 |
|
---|
1585 | if (id) {
|
---|
1586 | assert(!runDependencyTracking[id]);
|
---|
1587 | runDependencyTracking[id] = 1;
|
---|
1588 | if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
|
---|
1589 | // Check for missing dependencies every few seconds
|
---|
1590 | runDependencyWatcher = setInterval(function() {
|
---|
1591 | if (ABORT) {
|
---|
1592 | clearInterval(runDependencyWatcher);
|
---|
1593 | runDependencyWatcher = null;
|
---|
1594 | return;
|
---|
1595 | }
|
---|
1596 | var shown = false;
|
---|
1597 | for (var dep in runDependencyTracking) {
|
---|
1598 | if (!shown) {
|
---|
1599 | shown = true;
|
---|
1600 | err('still waiting on run dependencies:');
|
---|
1601 | }
|
---|
1602 | err('dependency: ' + dep);
|
---|
1603 | }
|
---|
1604 | if (shown) {
|
---|
1605 | err('(end of list)');
|
---|
1606 | }
|
---|
1607 | }, 10000);
|
---|
1608 | }
|
---|
1609 | } else {
|
---|
1610 | err('warning: run dependency added without ID');
|
---|
1611 | }
|
---|
1612 | }
|
---|
1613 |
|
---|
1614 | function removeRunDependency(id) {
|
---|
1615 | runDependencies--;
|
---|
1616 |
|
---|
1617 | if (Module['monitorRunDependencies']) {
|
---|
1618 | Module['monitorRunDependencies'](runDependencies);
|
---|
1619 | }
|
---|
1620 |
|
---|
1621 | if (id) {
|
---|
1622 | assert(runDependencyTracking[id]);
|
---|
1623 | delete runDependencyTracking[id];
|
---|
1624 | } else {
|
---|
1625 | err('warning: run dependency removed without ID');
|
---|
1626 | }
|
---|
1627 | if (runDependencies == 0) {
|
---|
1628 | if (runDependencyWatcher !== null) {
|
---|
1629 | clearInterval(runDependencyWatcher);
|
---|
1630 | runDependencyWatcher = null;
|
---|
1631 | }
|
---|
1632 | if (dependenciesFulfilled) {
|
---|
1633 | var callback = dependenciesFulfilled;
|
---|
1634 | dependenciesFulfilled = null;
|
---|
1635 | callback(); // can add another dependenciesFulfilled
|
---|
1636 | }
|
---|
1637 | }
|
---|
1638 | }
|
---|
1639 |
|
---|
1640 | Module["preloadedImages"] = {}; // maps url to image data
|
---|
1641 | Module["preloadedAudios"] = {}; // maps url to audio data
|
---|
1642 |
|
---|
1643 | /** @param {string|number=} what */
|
---|
1644 | function abort(what) {
|
---|
1645 | if (Module['onAbort']) {
|
---|
1646 | Module['onAbort'](what);
|
---|
1647 | }
|
---|
1648 |
|
---|
1649 | what += '';
|
---|
1650 | out(what);
|
---|
1651 | err(what);
|
---|
1652 |
|
---|
1653 | ABORT = true;
|
---|
1654 | EXITSTATUS = 1;
|
---|
1655 |
|
---|
1656 | var output = 'abort(' + what + ') at ' + stackTrace();
|
---|
1657 | what = output;
|
---|
1658 |
|
---|
1659 | // Throw a wasm runtime error, because a JS error might be seen as a foreign
|
---|
1660 | // exception, which means we'd run destructors on it. We need the error to
|
---|
1661 | // simply make the program stop.
|
---|
1662 | throw new WebAssembly.RuntimeError(what);
|
---|
1663 | }
|
---|
1664 |
|
---|
1665 |
|
---|
1666 | var memoryInitializer = null;
|
---|
1667 |
|
---|
1668 |
|
---|
1669 |
|
---|
1670 |
|
---|
1671 |
|
---|
1672 |
|
---|
1673 |
|
---|
1674 |
|
---|
1675 |
|
---|
1676 |
|
---|
1677 |
|
---|
1678 |
|
---|
1679 | function hasPrefix(str, prefix) {
|
---|
1680 | return String.prototype.startsWith ?
|
---|
1681 | str.startsWith(prefix) :
|
---|
1682 | str.indexOf(prefix) === 0;
|
---|
1683 | }
|
---|
1684 |
|
---|
1685 | // Prefix of data URIs emitted by SINGLE_FILE and related options.
|
---|
1686 | var dataURIPrefix = 'data:application/octet-stream;base64,';
|
---|
1687 |
|
---|
1688 | // Indicates whether filename is a base64 data URI.
|
---|
1689 | function isDataURI(filename) {
|
---|
1690 | return hasPrefix(filename, dataURIPrefix);
|
---|
1691 | }
|
---|
1692 |
|
---|
1693 | var fileURIPrefix = "file://";
|
---|
1694 |
|
---|
1695 | // Indicates whether filename is delivered via file protocol (as opposed to http/https)
|
---|
1696 | function isFileURI(filename) {
|
---|
1697 | return hasPrefix(filename, fileURIPrefix);
|
---|
1698 | }
|
---|
1699 |
|
---|
1700 |
|
---|
1701 |
|
---|
1702 | function createExportWrapper(name, fixedasm) {
|
---|
1703 | return function() {
|
---|
1704 | var displayName = name;
|
---|
1705 | var asm = fixedasm;
|
---|
1706 | if (!fixedasm) {
|
---|
1707 | asm = Module['asm'];
|
---|
1708 | }
|
---|
1709 | assert(runtimeInitialized, 'native function `' + displayName + '` called before runtime initialization');
|
---|
1710 | assert(!runtimeExited, 'native function `' + displayName + '` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
|
---|
1711 | if (!asm[name]) {
|
---|
1712 | assert(asm[name], 'exported native function `' + displayName + '` not found');
|
---|
1713 | }
|
---|
1714 | return asm[name].apply(null, arguments);
|
---|
1715 | };
|
---|
1716 | }
|
---|
1717 |
|
---|
1718 | var wasmBinaryFile = 'mrbc.wasm';
|
---|
1719 | if (!isDataURI(wasmBinaryFile)) {
|
---|
1720 | wasmBinaryFile = locateFile(wasmBinaryFile);
|
---|
1721 | }
|
---|
1722 |
|
---|
1723 | function getBinary() {
|
---|
1724 | try {
|
---|
1725 | if (wasmBinary) {
|
---|
1726 | return new Uint8Array(wasmBinary);
|
---|
1727 | }
|
---|
1728 |
|
---|
1729 | if (readBinary) {
|
---|
1730 | return readBinary(wasmBinaryFile);
|
---|
1731 | } else {
|
---|
1732 | throw "both async and sync fetching of the wasm failed";
|
---|
1733 | }
|
---|
1734 | }
|
---|
1735 | catch (err) {
|
---|
1736 | abort(err);
|
---|
1737 | }
|
---|
1738 | }
|
---|
1739 |
|
---|
1740 | function getBinaryPromise() {
|
---|
1741 | // If we don't have the binary yet, and have the Fetch api, use that;
|
---|
1742 | // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
|
---|
1743 | if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function'
|
---|
1744 | // Let's not use fetch to get objects over file:// as it's most likely Cordova which doesn't support fetch for file://
|
---|
1745 | && !isFileURI(wasmBinaryFile)
|
---|
1746 | ) {
|
---|
1747 | return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
|
---|
1748 | if (!response['ok']) {
|
---|
1749 | throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
|
---|
1750 | }
|
---|
1751 | return response['arrayBuffer']();
|
---|
1752 | }).catch(function () {
|
---|
1753 | return getBinary();
|
---|
1754 | });
|
---|
1755 | }
|
---|
1756 | // Otherwise, getBinary should be able to get it synchronously
|
---|
1757 | return new Promise(function(resolve, reject) {
|
---|
1758 | resolve(getBinary());
|
---|
1759 | });
|
---|
1760 | }
|
---|
1761 |
|
---|
1762 |
|
---|
1763 |
|
---|
1764 | // Create the wasm instance.
|
---|
1765 | // Receives the wasm imports, returns the exports.
|
---|
1766 | function createWasm() {
|
---|
1767 | // prepare imports
|
---|
1768 | var info = {
|
---|
1769 | 'env': asmLibraryArg,
|
---|
1770 | 'wasi_snapshot_preview1': asmLibraryArg
|
---|
1771 | };
|
---|
1772 | // Load the wasm module and create an instance of using native support in the JS engine.
|
---|
1773 | // handle a generated wasm instance, receiving its exports and
|
---|
1774 | // performing other necessary setup
|
---|
1775 | /** @param {WebAssembly.Module=} module*/
|
---|
1776 | function receiveInstance(instance, module) {
|
---|
1777 | var exports = instance.exports;
|
---|
1778 | Module['asm'] = exports;
|
---|
1779 | removeRunDependency('wasm-instantiate');
|
---|
1780 | }
|
---|
1781 | // we can't run yet (except in a pthread, where we have a custom sync instantiator)
|
---|
1782 | addRunDependency('wasm-instantiate');
|
---|
1783 |
|
---|
1784 |
|
---|
1785 | // Async compilation can be confusing when an error on the page overwrites Module
|
---|
1786 | // (for example, if the order of elements is wrong, and the one defining Module is
|
---|
1787 | // later), so we save Module and check it later.
|
---|
1788 | var trueModule = Module;
|
---|
1789 | function receiveInstantiatedSource(output) {
|
---|
1790 | // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.
|
---|
1791 | // receiveInstance() will swap in the exports (to Module.asm) so they can be called
|
---|
1792 | assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
|
---|
1793 | trueModule = null;
|
---|
1794 | // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
|
---|
1795 | // When the regression is fixed, can restore the above USE_PTHREADS-enabled path.
|
---|
1796 | receiveInstance(output['instance']);
|
---|
1797 | }
|
---|
1798 |
|
---|
1799 |
|
---|
1800 | function instantiateArrayBuffer(receiver) {
|
---|
1801 | return getBinaryPromise().then(function(binary) {
|
---|
1802 | return WebAssembly.instantiate(binary, info);
|
---|
1803 | }).then(receiver, function(reason) {
|
---|
1804 | err('failed to asynchronously prepare wasm: ' + reason);
|
---|
1805 |
|
---|
1806 |
|
---|
1807 | abort(reason);
|
---|
1808 | });
|
---|
1809 | }
|
---|
1810 |
|
---|
1811 | // Prefer streaming instantiation if available.
|
---|
1812 | function instantiateAsync() {
|
---|
1813 | if (!wasmBinary &&
|
---|
1814 | typeof WebAssembly.instantiateStreaming === 'function' &&
|
---|
1815 | !isDataURI(wasmBinaryFile) &&
|
---|
1816 | // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
|
---|
1817 | !isFileURI(wasmBinaryFile) &&
|
---|
1818 | typeof fetch === 'function') {
|
---|
1819 | fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) {
|
---|
1820 | var result = WebAssembly.instantiateStreaming(response, info);
|
---|
1821 | return result.then(receiveInstantiatedSource, function(reason) {
|
---|
1822 | // We expect the most common failure cause to be a bad MIME type for the binary,
|
---|
1823 | // in which case falling back to ArrayBuffer instantiation should work.
|
---|
1824 | err('wasm streaming compile failed: ' + reason);
|
---|
1825 | err('falling back to ArrayBuffer instantiation');
|
---|
1826 | return instantiateArrayBuffer(receiveInstantiatedSource);
|
---|
1827 | });
|
---|
1828 | });
|
---|
1829 | } else {
|
---|
1830 | return instantiateArrayBuffer(receiveInstantiatedSource);
|
---|
1831 | }
|
---|
1832 | }
|
---|
1833 | // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
|
---|
1834 | // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
|
---|
1835 | // to any other async startup actions they are performing.
|
---|
1836 | if (Module['instantiateWasm']) {
|
---|
1837 | try {
|
---|
1838 | var exports = Module['instantiateWasm'](info, receiveInstance);
|
---|
1839 | return exports;
|
---|
1840 | } catch(e) {
|
---|
1841 | err('Module.instantiateWasm callback failed with error: ' + e);
|
---|
1842 | return false;
|
---|
1843 | }
|
---|
1844 | }
|
---|
1845 |
|
---|
1846 | instantiateAsync();
|
---|
1847 | return {}; // no exports yet; we'll fill them in later
|
---|
1848 | }
|
---|
1849 |
|
---|
1850 |
|
---|
1851 | // Globals used by JS i64 conversions
|
---|
1852 | var tempDouble;
|
---|
1853 | var tempI64;
|
---|
1854 |
|
---|
1855 | // === Body ===
|
---|
1856 |
|
---|
1857 | var ASM_CONSTS = {
|
---|
1858 |
|
---|
1859 | };
|
---|
1860 |
|
---|
1861 |
|
---|
1862 |
|
---|
1863 |
|
---|
1864 | // STATICTOP = STATIC_BASE + 78848;
|
---|
1865 | /* global initializers */ __ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
|
---|
1866 |
|
---|
1867 |
|
---|
1868 |
|
---|
1869 |
|
---|
1870 | /* no memory initializer */
|
---|
1871 | // {{PRE_LIBRARY}}
|
---|
1872 |
|
---|
1873 |
|
---|
1874 |
|
---|
1875 |
|
---|
1876 | function _emscripten_set_main_loop_timing(mode, value) {
|
---|
1877 | Browser.mainLoop.timingMode = mode;
|
---|
1878 | Browser.mainLoop.timingValue = value;
|
---|
1879 |
|
---|
1880 | if (!Browser.mainLoop.func) {
|
---|
1881 | console.error('emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.');
|
---|
1882 | return 1; // Return non-zero on failure, can't set timing mode when there is no main loop.
|
---|
1883 | }
|
---|
1884 |
|
---|
1885 | if (mode == 0 /*EM_TIMING_SETTIMEOUT*/) {
|
---|
1886 | Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() {
|
---|
1887 | var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now())|0;
|
---|
1888 | setTimeout(Browser.mainLoop.runner, timeUntilNextTick); // doing this each time means that on exception, we stop
|
---|
1889 | };
|
---|
1890 | Browser.mainLoop.method = 'timeout';
|
---|
1891 | } else if (mode == 1 /*EM_TIMING_RAF*/) {
|
---|
1892 | Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() {
|
---|
1893 | Browser.requestAnimationFrame(Browser.mainLoop.runner);
|
---|
1894 | };
|
---|
1895 | Browser.mainLoop.method = 'rAF';
|
---|
1896 | } else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) {
|
---|
1897 | if (typeof setImmediate === 'undefined') {
|
---|
1898 | // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed)
|
---|
1899 | var setImmediates = [];
|
---|
1900 | var emscriptenMainLoopMessageId = 'setimmediate';
|
---|
1901 | var Browser_setImmediate_messageHandler = function(event) {
|
---|
1902 | // When called in current thread or Worker, the main loop ID is structured slightly different to accommodate for --proxy-to-worker runtime listening to Worker events,
|
---|
1903 | // so check for both cases.
|
---|
1904 | if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) {
|
---|
1905 | event.stopPropagation();
|
---|
1906 | setImmediates.shift()();
|
---|
1907 | }
|
---|
1908 | }
|
---|
1909 | addEventListener("message", Browser_setImmediate_messageHandler, true);
|
---|
1910 | setImmediate = /** @type{function(function(): ?, ...?): number} */(function Browser_emulated_setImmediate(func) {
|
---|
1911 | setImmediates.push(func);
|
---|
1912 | if (ENVIRONMENT_IS_WORKER) {
|
---|
1913 | if (Module['setImmediates'] === undefined) Module['setImmediates'] = [];
|
---|
1914 | Module['setImmediates'].push(func);
|
---|
1915 | postMessage({target: emscriptenMainLoopMessageId}); // In --proxy-to-worker, route the message via proxyClient.js
|
---|
1916 | } else postMessage(emscriptenMainLoopMessageId, "*"); // On the main thread, can just send the message to itself.
|
---|
1917 | })
|
---|
1918 | }
|
---|
1919 | Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() {
|
---|
1920 | setImmediate(Browser.mainLoop.runner);
|
---|
1921 | };
|
---|
1922 | Browser.mainLoop.method = 'immediate';
|
---|
1923 | }
|
---|
1924 | return 0;
|
---|
1925 | }
|
---|
1926 |
|
---|
1927 | var _emscripten_get_now;if (ENVIRONMENT_IS_NODE) {
|
---|
1928 | _emscripten_get_now = function() {
|
---|
1929 | var t = process['hrtime']();
|
---|
1930 | return t[0] * 1e3 + t[1] / 1e6;
|
---|
1931 | };
|
---|
1932 | } else if (typeof dateNow !== 'undefined') {
|
---|
1933 | _emscripten_get_now = dateNow;
|
---|
1934 | } else _emscripten_get_now = function() { return performance.now(); }
|
---|
1935 | ;/** @param {number|boolean=} noSetTiming */
|
---|
1936 | function _emscripten_set_main_loop(func, fps, simulateInfiniteLoop, arg, noSetTiming) {
|
---|
1937 | noExitRuntime = true;
|
---|
1938 |
|
---|
1939 | assert(!Browser.mainLoop.func, 'emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.');
|
---|
1940 |
|
---|
1941 | Browser.mainLoop.func = func;
|
---|
1942 | Browser.mainLoop.arg = arg;
|
---|
1943 |
|
---|
1944 | var browserIterationFunc;
|
---|
1945 | if (typeof arg !== 'undefined') {
|
---|
1946 | browserIterationFunc = function() {
|
---|
1947 | Module['dynCall_vi'](func, arg);
|
---|
1948 | };
|
---|
1949 | } else {
|
---|
1950 | browserIterationFunc = function() {
|
---|
1951 | Module['dynCall_v'](func);
|
---|
1952 | };
|
---|
1953 | }
|
---|
1954 |
|
---|
1955 | var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop;
|
---|
1956 |
|
---|
1957 | Browser.mainLoop.runner = function Browser_mainLoop_runner() {
|
---|
1958 | if (ABORT) return;
|
---|
1959 | if (Browser.mainLoop.queue.length > 0) {
|
---|
1960 | var start = Date.now();
|
---|
1961 | var blocker = Browser.mainLoop.queue.shift();
|
---|
1962 | blocker.func(blocker.arg);
|
---|
1963 | if (Browser.mainLoop.remainingBlockers) {
|
---|
1964 | var remaining = Browser.mainLoop.remainingBlockers;
|
---|
1965 | var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining);
|
---|
1966 | if (blocker.counted) {
|
---|
1967 | Browser.mainLoop.remainingBlockers = next;
|
---|
1968 | } else {
|
---|
1969 | // not counted, but move the progress along a tiny bit
|
---|
1970 | next = next + 0.5; // do not steal all the next one's progress
|
---|
1971 | Browser.mainLoop.remainingBlockers = (8*remaining + next)/9;
|
---|
1972 | }
|
---|
1973 | }
|
---|
1974 | console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers);
|
---|
1975 | Browser.mainLoop.updateStatus();
|
---|
1976 |
|
---|
1977 | // catches pause/resume main loop from blocker execution
|
---|
1978 | if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
|
---|
1979 |
|
---|
1980 | setTimeout(Browser.mainLoop.runner, 0);
|
---|
1981 | return;
|
---|
1982 | }
|
---|
1983 |
|
---|
1984 | // catch pauses from non-main loop sources
|
---|
1985 | if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
|
---|
1986 |
|
---|
1987 | // Implement very basic swap interval control
|
---|
1988 | Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0;
|
---|
1989 | if (Browser.mainLoop.timingMode == 1/*EM_TIMING_RAF*/ && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) {
|
---|
1990 | // Not the scheduled time to render this frame - skip.
|
---|
1991 | Browser.mainLoop.scheduler();
|
---|
1992 | return;
|
---|
1993 | } else if (Browser.mainLoop.timingMode == 0/*EM_TIMING_SETTIMEOUT*/) {
|
---|
1994 | Browser.mainLoop.tickStartTime = _emscripten_get_now();
|
---|
1995 | }
|
---|
1996 |
|
---|
1997 | // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize
|
---|
1998 | // VBO double-buffering and reduce GPU stalls.
|
---|
1999 |
|
---|
2000 |
|
---|
2001 |
|
---|
2002 | if (Browser.mainLoop.method === 'timeout' && Module.ctx) {
|
---|
2003 | warnOnce('Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!');
|
---|
2004 | Browser.mainLoop.method = ''; // just warn once per call to set main loop
|
---|
2005 | }
|
---|
2006 |
|
---|
2007 | Browser.mainLoop.runIter(browserIterationFunc);
|
---|
2008 |
|
---|
2009 | checkStackCookie();
|
---|
2010 |
|
---|
2011 | // catch pauses from the main loop itself
|
---|
2012 | if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
|
---|
2013 |
|
---|
2014 | // Queue new audio data. This is important to be right after the main loop invocation, so that we will immediately be able
|
---|
2015 | // to queue the newest produced audio samples.
|
---|
2016 | // TODO: Consider adding pre- and post- rAF callbacks so that GL.newRenderingFrameStarted() and SDL.audio.queueNewAudioData()
|
---|
2017 | // do not need to be hardcoded into this function, but can be more generic.
|
---|
2018 | if (typeof SDL === 'object' && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
|
---|
2019 |
|
---|
2020 | Browser.mainLoop.scheduler();
|
---|
2021 | }
|
---|
2022 |
|
---|
2023 | if (!noSetTiming) {
|
---|
2024 | if (fps && fps > 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 1000.0 / fps);
|
---|
2025 | else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, 1); // Do rAF by rendering each frame (no decimating)
|
---|
2026 |
|
---|
2027 | Browser.mainLoop.scheduler();
|
---|
2028 | }
|
---|
2029 |
|
---|
2030 | if (simulateInfiniteLoop) {
|
---|
2031 | throw 'unwind';
|
---|
2032 | }
|
---|
2033 | }var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function() {
|
---|
2034 | Browser.mainLoop.scheduler = null;
|
---|
2035 | Browser.mainLoop.currentlyRunningMainloop++; // Incrementing this signals the previous main loop that it's now become old, and it must return.
|
---|
2036 | },resume:function() {
|
---|
2037 | Browser.mainLoop.currentlyRunningMainloop++;
|
---|
2038 | var timingMode = Browser.mainLoop.timingMode;
|
---|
2039 | var timingValue = Browser.mainLoop.timingValue;
|
---|
2040 | var func = Browser.mainLoop.func;
|
---|
2041 | Browser.mainLoop.func = null;
|
---|
2042 | _emscripten_set_main_loop(func, 0, false, Browser.mainLoop.arg, true /* do not set timing and call scheduler, we will do it on the next lines */);
|
---|
2043 | _emscripten_set_main_loop_timing(timingMode, timingValue);
|
---|
2044 | Browser.mainLoop.scheduler();
|
---|
2045 | },updateStatus:function() {
|
---|
2046 | if (Module['setStatus']) {
|
---|
2047 | var message = Module['statusMessage'] || 'Please wait...';
|
---|
2048 | var remaining = Browser.mainLoop.remainingBlockers;
|
---|
2049 | var expected = Browser.mainLoop.expectedBlockers;
|
---|
2050 | if (remaining) {
|
---|
2051 | if (remaining < expected) {
|
---|
2052 | Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')');
|
---|
2053 | } else {
|
---|
2054 | Module['setStatus'](message);
|
---|
2055 | }
|
---|
2056 | } else {
|
---|
2057 | Module['setStatus']('');
|
---|
2058 | }
|
---|
2059 | }
|
---|
2060 | },runIter:function(func) {
|
---|
2061 | if (ABORT) return;
|
---|
2062 | if (Module['preMainLoop']) {
|
---|
2063 | var preRet = Module['preMainLoop']();
|
---|
2064 | if (preRet === false) {
|
---|
2065 | return; // |return false| skips a frame
|
---|
2066 | }
|
---|
2067 | }
|
---|
2068 | try {
|
---|
2069 | func();
|
---|
2070 | } catch (e) {
|
---|
2071 | if (e instanceof ExitStatus) {
|
---|
2072 | return;
|
---|
2073 | } else {
|
---|
2074 | if (e && typeof e === 'object' && e.stack) err('exception thrown: ' + [e, e.stack]);
|
---|
2075 | throw e;
|
---|
2076 | }
|
---|
2077 | }
|
---|
2078 | if (Module['postMainLoop']) Module['postMainLoop']();
|
---|
2079 | }},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function() {
|
---|
2080 | if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers
|
---|
2081 |
|
---|
2082 | if (Browser.initted) return;
|
---|
2083 | Browser.initted = true;
|
---|
2084 |
|
---|
2085 | try {
|
---|
2086 | new Blob();
|
---|
2087 | Browser.hasBlobConstructor = true;
|
---|
2088 | } catch(e) {
|
---|
2089 | Browser.hasBlobConstructor = false;
|
---|
2090 | console.log("warning: no blob constructor, cannot create blobs with mimetypes");
|
---|
2091 | }
|
---|
2092 | Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null));
|
---|
2093 | Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined;
|
---|
2094 | if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') {
|
---|
2095 | console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");
|
---|
2096 | Module.noImageDecoding = true;
|
---|
2097 | }
|
---|
2098 |
|
---|
2099 | // Support for plugins that can process preloaded files. You can add more of these to
|
---|
2100 | // your app by creating and appending to Module.preloadPlugins.
|
---|
2101 | //
|
---|
2102 | // Each plugin is asked if it can handle a file based on the file's name. If it can,
|
---|
2103 | // it is given the file's raw data. When it is done, it calls a callback with the file's
|
---|
2104 | // (possibly modified) data. For example, a plugin might decompress a file, or it
|
---|
2105 | // might create some side data structure for use later (like an Image element, etc.).
|
---|
2106 |
|
---|
2107 | var imagePlugin = {};
|
---|
2108 | imagePlugin['canHandle'] = function imagePlugin_canHandle(name) {
|
---|
2109 | return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
|
---|
2110 | };
|
---|
2111 | imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) {
|
---|
2112 | var b = null;
|
---|
2113 | if (Browser.hasBlobConstructor) {
|
---|
2114 | try {
|
---|
2115 | b = new Blob([byteArray], { type: Browser.getMimetype(name) });
|
---|
2116 | if (b.size !== byteArray.length) { // Safari bug #118630
|
---|
2117 | // Safari's Blob can only take an ArrayBuffer
|
---|
2118 | b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) });
|
---|
2119 | }
|
---|
2120 | } catch(e) {
|
---|
2121 | warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
|
---|
2122 | }
|
---|
2123 | }
|
---|
2124 | if (!b) {
|
---|
2125 | var bb = new Browser.BlobBuilder();
|
---|
2126 | bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range
|
---|
2127 | b = bb.getBlob();
|
---|
2128 | }
|
---|
2129 | var url = Browser.URLObject.createObjectURL(b);
|
---|
2130 | assert(typeof url == 'string', 'createObjectURL must return a url as a string');
|
---|
2131 | var img = new Image();
|
---|
2132 | img.onload = function img_onload() {
|
---|
2133 | assert(img.complete, 'Image ' + name + ' could not be decoded');
|
---|
2134 | var canvas = document.createElement('canvas');
|
---|
2135 | canvas.width = img.width;
|
---|
2136 | canvas.height = img.height;
|
---|
2137 | var ctx = canvas.getContext('2d');
|
---|
2138 | ctx.drawImage(img, 0, 0);
|
---|
2139 | Module["preloadedImages"][name] = canvas;
|
---|
2140 | Browser.URLObject.revokeObjectURL(url);
|
---|
2141 | if (onload) onload(byteArray);
|
---|
2142 | };
|
---|
2143 | img.onerror = function img_onerror(event) {
|
---|
2144 | console.log('Image ' + url + ' could not be decoded');
|
---|
2145 | if (onerror) onerror();
|
---|
2146 | };
|
---|
2147 | img.src = url;
|
---|
2148 | };
|
---|
2149 | Module['preloadPlugins'].push(imagePlugin);
|
---|
2150 |
|
---|
2151 | var audioPlugin = {};
|
---|
2152 | audioPlugin['canHandle'] = function audioPlugin_canHandle(name) {
|
---|
2153 | return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 };
|
---|
2154 | };
|
---|
2155 | audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) {
|
---|
2156 | var done = false;
|
---|
2157 | function finish(audio) {
|
---|
2158 | if (done) return;
|
---|
2159 | done = true;
|
---|
2160 | Module["preloadedAudios"][name] = audio;
|
---|
2161 | if (onload) onload(byteArray);
|
---|
2162 | }
|
---|
2163 | function fail() {
|
---|
2164 | if (done) return;
|
---|
2165 | done = true;
|
---|
2166 | Module["preloadedAudios"][name] = new Audio(); // empty shim
|
---|
2167 | if (onerror) onerror();
|
---|
2168 | }
|
---|
2169 | if (Browser.hasBlobConstructor) {
|
---|
2170 | try {
|
---|
2171 | var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
|
---|
2172 | } catch(e) {
|
---|
2173 | return fail();
|
---|
2174 | }
|
---|
2175 | var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this!
|
---|
2176 | assert(typeof url == 'string', 'createObjectURL must return a url as a string');
|
---|
2177 | var audio = new Audio();
|
---|
2178 | audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926
|
---|
2179 | audio.onerror = function audio_onerror(event) {
|
---|
2180 | if (done) return;
|
---|
2181 | console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach');
|
---|
2182 | function encode64(data) {
|
---|
2183 | var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
---|
2184 | var PAD = '=';
|
---|
2185 | var ret = '';
|
---|
2186 | var leftchar = 0;
|
---|
2187 | var leftbits = 0;
|
---|
2188 | for (var i = 0; i < data.length; i++) {
|
---|
2189 | leftchar = (leftchar << 8) | data[i];
|
---|
2190 | leftbits += 8;
|
---|
2191 | while (leftbits >= 6) {
|
---|
2192 | var curr = (leftchar >> (leftbits-6)) & 0x3f;
|
---|
2193 | leftbits -= 6;
|
---|
2194 | ret += BASE[curr];
|
---|
2195 | }
|
---|
2196 | }
|
---|
2197 | if (leftbits == 2) {
|
---|
2198 | ret += BASE[(leftchar&3) << 4];
|
---|
2199 | ret += PAD + PAD;
|
---|
2200 | } else if (leftbits == 4) {
|
---|
2201 | ret += BASE[(leftchar&0xf) << 2];
|
---|
2202 | ret += PAD;
|
---|
2203 | }
|
---|
2204 | return ret;
|
---|
2205 | }
|
---|
2206 | audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray);
|
---|
2207 | finish(audio); // we don't wait for confirmation this worked - but it's worth trying
|
---|
2208 | };
|
---|
2209 | audio.src = url;
|
---|
2210 | // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
|
---|
2211 | Browser.safeSetTimeout(function() {
|
---|
2212 | finish(audio); // try to use it even though it is not necessarily ready to play
|
---|
2213 | }, 10000);
|
---|
2214 | } else {
|
---|
2215 | return fail();
|
---|
2216 | }
|
---|
2217 | };
|
---|
2218 | Module['preloadPlugins'].push(audioPlugin);
|
---|
2219 |
|
---|
2220 |
|
---|
2221 | // Canvas event setup
|
---|
2222 |
|
---|
2223 | function pointerLockChange() {
|
---|
2224 | Browser.pointerLock = document['pointerLockElement'] === Module['canvas'] ||
|
---|
2225 | document['mozPointerLockElement'] === Module['canvas'] ||
|
---|
2226 | document['webkitPointerLockElement'] === Module['canvas'] ||
|
---|
2227 | document['msPointerLockElement'] === Module['canvas'];
|
---|
2228 | }
|
---|
2229 | var canvas = Module['canvas'];
|
---|
2230 | if (canvas) {
|
---|
2231 | // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
|
---|
2232 | // Module['forcedAspectRatio'] = 4 / 3;
|
---|
2233 |
|
---|
2234 | canvas.requestPointerLock = canvas['requestPointerLock'] ||
|
---|
2235 | canvas['mozRequestPointerLock'] ||
|
---|
2236 | canvas['webkitRequestPointerLock'] ||
|
---|
2237 | canvas['msRequestPointerLock'] ||
|
---|
2238 | function(){};
|
---|
2239 | canvas.exitPointerLock = document['exitPointerLock'] ||
|
---|
2240 | document['mozExitPointerLock'] ||
|
---|
2241 | document['webkitExitPointerLock'] ||
|
---|
2242 | document['msExitPointerLock'] ||
|
---|
2243 | function(){}; // no-op if function does not exist
|
---|
2244 | canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
|
---|
2245 |
|
---|
2246 | document.addEventListener('pointerlockchange', pointerLockChange, false);
|
---|
2247 | document.addEventListener('mozpointerlockchange', pointerLockChange, false);
|
---|
2248 | document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
|
---|
2249 | document.addEventListener('mspointerlockchange', pointerLockChange, false);
|
---|
2250 |
|
---|
2251 | if (Module['elementPointerLock']) {
|
---|
2252 | canvas.addEventListener("click", function(ev) {
|
---|
2253 | if (!Browser.pointerLock && Module['canvas'].requestPointerLock) {
|
---|
2254 | Module['canvas'].requestPointerLock();
|
---|
2255 | ev.preventDefault();
|
---|
2256 | }
|
---|
2257 | }, false);
|
---|
2258 | }
|
---|
2259 | }
|
---|
2260 | },createContext:function(canvas, useWebGL, setInModule, webGLContextAttributes) {
|
---|
2261 | if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
|
---|
2262 |
|
---|
2263 | var ctx;
|
---|
2264 | var contextHandle;
|
---|
2265 | if (useWebGL) {
|
---|
2266 | // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
|
---|
2267 | var contextAttributes = {
|
---|
2268 | antialias: false,
|
---|
2269 | alpha: false,
|
---|
2270 | majorVersion: 1,
|
---|
2271 | };
|
---|
2272 |
|
---|
2273 | if (webGLContextAttributes) {
|
---|
2274 | for (var attribute in webGLContextAttributes) {
|
---|
2275 | contextAttributes[attribute] = webGLContextAttributes[attribute];
|
---|
2276 | }
|
---|
2277 | }
|
---|
2278 |
|
---|
2279 | // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not
|
---|
2280 | // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function
|
---|
2281 | // Browser.createContext() should not even be emitted.
|
---|
2282 | if (typeof GL !== 'undefined') {
|
---|
2283 | contextHandle = GL.createContext(canvas, contextAttributes);
|
---|
2284 | if (contextHandle) {
|
---|
2285 | ctx = GL.getContext(contextHandle).GLctx;
|
---|
2286 | }
|
---|
2287 | }
|
---|
2288 | } else {
|
---|
2289 | ctx = canvas.getContext('2d');
|
---|
2290 | }
|
---|
2291 |
|
---|
2292 | if (!ctx) return null;
|
---|
2293 |
|
---|
2294 | if (setInModule) {
|
---|
2295 | if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
|
---|
2296 |
|
---|
2297 | Module.ctx = ctx;
|
---|
2298 | if (useWebGL) GL.makeContextCurrent(contextHandle);
|
---|
2299 | Module.useWebGL = useWebGL;
|
---|
2300 | Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
|
---|
2301 | Browser.init();
|
---|
2302 | }
|
---|
2303 | return ctx;
|
---|
2304 | },destroyContext:function(canvas, useWebGL, setInModule) {},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer, resizeCanvas) {
|
---|
2305 | Browser.lockPointer = lockPointer;
|
---|
2306 | Browser.resizeCanvas = resizeCanvas;
|
---|
2307 | if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true;
|
---|
2308 | if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false;
|
---|
2309 |
|
---|
2310 | var canvas = Module['canvas'];
|
---|
2311 | function fullscreenChange() {
|
---|
2312 | Browser.isFullscreen = false;
|
---|
2313 | var canvasContainer = canvas.parentNode;
|
---|
2314 | if ((document['fullscreenElement'] || document['mozFullScreenElement'] ||
|
---|
2315 | document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
|
---|
2316 | document['webkitCurrentFullScreenElement']) === canvasContainer) {
|
---|
2317 | canvas.exitFullscreen = Browser.exitFullscreen;
|
---|
2318 | if (Browser.lockPointer) canvas.requestPointerLock();
|
---|
2319 | Browser.isFullscreen = true;
|
---|
2320 | if (Browser.resizeCanvas) {
|
---|
2321 | Browser.setFullscreenCanvasSize();
|
---|
2322 | } else {
|
---|
2323 | Browser.updateCanvasDimensions(canvas);
|
---|
2324 | }
|
---|
2325 | } else {
|
---|
2326 | // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
|
---|
2327 | canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
|
---|
2328 | canvasContainer.parentNode.removeChild(canvasContainer);
|
---|
2329 |
|
---|
2330 | if (Browser.resizeCanvas) {
|
---|
2331 | Browser.setWindowedCanvasSize();
|
---|
2332 | } else {
|
---|
2333 | Browser.updateCanvasDimensions(canvas);
|
---|
2334 | }
|
---|
2335 | }
|
---|
2336 | if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen);
|
---|
2337 | if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen);
|
---|
2338 | }
|
---|
2339 |
|
---|
2340 | if (!Browser.fullscreenHandlersInstalled) {
|
---|
2341 | Browser.fullscreenHandlersInstalled = true;
|
---|
2342 | document.addEventListener('fullscreenchange', fullscreenChange, false);
|
---|
2343 | document.addEventListener('mozfullscreenchange', fullscreenChange, false);
|
---|
2344 | document.addEventListener('webkitfullscreenchange', fullscreenChange, false);
|
---|
2345 | document.addEventListener('MSFullscreenChange', fullscreenChange, false);
|
---|
2346 | }
|
---|
2347 |
|
---|
2348 | // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root
|
---|
2349 | var canvasContainer = document.createElement("div");
|
---|
2350 | canvas.parentNode.insertBefore(canvasContainer, canvas);
|
---|
2351 | canvasContainer.appendChild(canvas);
|
---|
2352 |
|
---|
2353 | // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
|
---|
2354 | canvasContainer.requestFullscreen = canvasContainer['requestFullscreen'] ||
|
---|
2355 | canvasContainer['mozRequestFullScreen'] ||
|
---|
2356 | canvasContainer['msRequestFullscreen'] ||
|
---|
2357 | (canvasContainer['webkitRequestFullscreen'] ? function() { canvasContainer['webkitRequestFullscreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null) ||
|
---|
2358 | (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
|
---|
2359 |
|
---|
2360 | canvasContainer.requestFullscreen();
|
---|
2361 | },requestFullScreen:function() {
|
---|
2362 | abort('Module.requestFullScreen has been replaced by Module.requestFullscreen (without a capital S)');
|
---|
2363 | },exitFullscreen:function() {
|
---|
2364 | // This is workaround for chrome. Trying to exit from fullscreen
|
---|
2365 | // not in fullscreen state will cause "TypeError: Document not active"
|
---|
2366 | // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236
|
---|
2367 | if (!Browser.isFullscreen) {
|
---|
2368 | return false;
|
---|
2369 | }
|
---|
2370 |
|
---|
2371 | var CFS = document['exitFullscreen'] ||
|
---|
2372 | document['cancelFullScreen'] ||
|
---|
2373 | document['mozCancelFullScreen'] ||
|
---|
2374 | document['msExitFullscreen'] ||
|
---|
2375 | document['webkitCancelFullScreen'] ||
|
---|
2376 | (function() {});
|
---|
2377 | CFS.apply(document, []);
|
---|
2378 | return true;
|
---|
2379 | },nextRAF:0,fakeRequestAnimationFrame:function(func) {
|
---|
2380 | // try to keep 60fps between calls to here
|
---|
2381 | var now = Date.now();
|
---|
2382 | if (Browser.nextRAF === 0) {
|
---|
2383 | Browser.nextRAF = now + 1000/60;
|
---|
2384 | } else {
|
---|
2385 | while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
|
---|
2386 | Browser.nextRAF += 1000/60;
|
---|
2387 | }
|
---|
2388 | }
|
---|
2389 | var delay = Math.max(Browser.nextRAF - now, 0);
|
---|
2390 | setTimeout(func, delay);
|
---|
2391 | },requestAnimationFrame:function(func) {
|
---|
2392 | if (typeof requestAnimationFrame === 'function') {
|
---|
2393 | requestAnimationFrame(func);
|
---|
2394 | return;
|
---|
2395 | }
|
---|
2396 | var RAF = Browser.fakeRequestAnimationFrame;
|
---|
2397 | RAF(func);
|
---|
2398 | },safeCallback:function(func) {
|
---|
2399 | return function() {
|
---|
2400 | if (!ABORT) return func.apply(null, arguments);
|
---|
2401 | };
|
---|
2402 | },allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function() {
|
---|
2403 | Browser.allowAsyncCallbacks = false;
|
---|
2404 | },resumeAsyncCallbacks:function() { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now
|
---|
2405 | Browser.allowAsyncCallbacks = true;
|
---|
2406 | if (Browser.queuedAsyncCallbacks.length > 0) {
|
---|
2407 | var callbacks = Browser.queuedAsyncCallbacks;
|
---|
2408 | Browser.queuedAsyncCallbacks = [];
|
---|
2409 | callbacks.forEach(function(func) {
|
---|
2410 | func();
|
---|
2411 | });
|
---|
2412 | }
|
---|
2413 | },safeRequestAnimationFrame:function(func) {
|
---|
2414 | return Browser.requestAnimationFrame(function() {
|
---|
2415 | if (ABORT) return;
|
---|
2416 | if (Browser.allowAsyncCallbacks) {
|
---|
2417 | func();
|
---|
2418 | } else {
|
---|
2419 | Browser.queuedAsyncCallbacks.push(func);
|
---|
2420 | }
|
---|
2421 | });
|
---|
2422 | },safeSetTimeout:function(func, timeout) {
|
---|
2423 | noExitRuntime = true;
|
---|
2424 | return setTimeout(function() {
|
---|
2425 | if (ABORT) return;
|
---|
2426 | if (Browser.allowAsyncCallbacks) {
|
---|
2427 | func();
|
---|
2428 | } else {
|
---|
2429 | Browser.queuedAsyncCallbacks.push(func);
|
---|
2430 | }
|
---|
2431 | }, timeout);
|
---|
2432 | },safeSetInterval:function(func, timeout) {
|
---|
2433 | noExitRuntime = true;
|
---|
2434 | return setInterval(function() {
|
---|
2435 | if (ABORT) return;
|
---|
2436 | if (Browser.allowAsyncCallbacks) {
|
---|
2437 | func();
|
---|
2438 | } // drop it on the floor otherwise, next interval will kick in
|
---|
2439 | }, timeout);
|
---|
2440 | },getMimetype:function(name) {
|
---|
2441 | return {
|
---|
2442 | 'jpg': 'image/jpeg',
|
---|
2443 | 'jpeg': 'image/jpeg',
|
---|
2444 | 'png': 'image/png',
|
---|
2445 | 'bmp': 'image/bmp',
|
---|
2446 | 'ogg': 'audio/ogg',
|
---|
2447 | 'wav': 'audio/wav',
|
---|
2448 | 'mp3': 'audio/mpeg'
|
---|
2449 | }[name.substr(name.lastIndexOf('.')+1)];
|
---|
2450 | },getUserMedia:function(func) {
|
---|
2451 | if(!window.getUserMedia) {
|
---|
2452 | window.getUserMedia = navigator['getUserMedia'] ||
|
---|
2453 | navigator['mozGetUserMedia'];
|
---|
2454 | }
|
---|
2455 | window.getUserMedia(func);
|
---|
2456 | },getMovementX:function(event) {
|
---|
2457 | return event['movementX'] ||
|
---|
2458 | event['mozMovementX'] ||
|
---|
2459 | event['webkitMovementX'] ||
|
---|
2460 | 0;
|
---|
2461 | },getMovementY:function(event) {
|
---|
2462 | return event['movementY'] ||
|
---|
2463 | event['mozMovementY'] ||
|
---|
2464 | event['webkitMovementY'] ||
|
---|
2465 | 0;
|
---|
2466 | },getMouseWheelDelta:function(event) {
|
---|
2467 | var delta = 0;
|
---|
2468 | switch (event.type) {
|
---|
2469 | case 'DOMMouseScroll':
|
---|
2470 | // 3 lines make up a step
|
---|
2471 | delta = event.detail / 3;
|
---|
2472 | break;
|
---|
2473 | case 'mousewheel':
|
---|
2474 | // 120 units make up a step
|
---|
2475 | delta = event.wheelDelta / 120;
|
---|
2476 | break;
|
---|
2477 | case 'wheel':
|
---|
2478 | delta = event.deltaY
|
---|
2479 | switch(event.deltaMode) {
|
---|
2480 | case 0:
|
---|
2481 | // DOM_DELTA_PIXEL: 100 pixels make up a step
|
---|
2482 | delta /= 100;
|
---|
2483 | break;
|
---|
2484 | case 1:
|
---|
2485 | // DOM_DELTA_LINE: 3 lines make up a step
|
---|
2486 | delta /= 3;
|
---|
2487 | break;
|
---|
2488 | case 2:
|
---|
2489 | // DOM_DELTA_PAGE: A page makes up 80 steps
|
---|
2490 | delta *= 80;
|
---|
2491 | break;
|
---|
2492 | default:
|
---|
2493 | throw 'unrecognized mouse wheel delta mode: ' + event.deltaMode;
|
---|
2494 | }
|
---|
2495 | break;
|
---|
2496 | default:
|
---|
2497 | throw 'unrecognized mouse wheel event: ' + event.type;
|
---|
2498 | }
|
---|
2499 | return delta;
|
---|
2500 | },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event) { // event should be mousemove, mousedown or mouseup
|
---|
2501 | if (Browser.pointerLock) {
|
---|
2502 | // When the pointer is locked, calculate the coordinates
|
---|
2503 | // based on the movement of the mouse.
|
---|
2504 | // Workaround for Firefox bug 764498
|
---|
2505 | if (event.type != 'mousemove' &&
|
---|
2506 | ('mozMovementX' in event)) {
|
---|
2507 | Browser.mouseMovementX = Browser.mouseMovementY = 0;
|
---|
2508 | } else {
|
---|
2509 | Browser.mouseMovementX = Browser.getMovementX(event);
|
---|
2510 | Browser.mouseMovementY = Browser.getMovementY(event);
|
---|
2511 | }
|
---|
2512 |
|
---|
2513 | // check if SDL is available
|
---|
2514 | if (typeof SDL != "undefined") {
|
---|
2515 | Browser.mouseX = SDL.mouseX + Browser.mouseMovementX;
|
---|
2516 | Browser.mouseY = SDL.mouseY + Browser.mouseMovementY;
|
---|
2517 | } else {
|
---|
2518 | // just add the mouse delta to the current absolut mouse position
|
---|
2519 | // FIXME: ideally this should be clamped against the canvas size and zero
|
---|
2520 | Browser.mouseX += Browser.mouseMovementX;
|
---|
2521 | Browser.mouseY += Browser.mouseMovementY;
|
---|
2522 | }
|
---|
2523 | } else {
|
---|
2524 | // Otherwise, calculate the movement based on the changes
|
---|
2525 | // in the coordinates.
|
---|
2526 | var rect = Module["canvas"].getBoundingClientRect();
|
---|
2527 | var cw = Module["canvas"].width;
|
---|
2528 | var ch = Module["canvas"].height;
|
---|
2529 |
|
---|
2530 | // Neither .scrollX or .pageXOffset are defined in a spec, but
|
---|
2531 | // we prefer .scrollX because it is currently in a spec draft.
|
---|
2532 | // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
|
---|
2533 | var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset);
|
---|
2534 | var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset);
|
---|
2535 | // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset
|
---|
2536 | // and we have no viable fallback.
|
---|
2537 | assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.');
|
---|
2538 |
|
---|
2539 | if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') {
|
---|
2540 | var touch = event.touch;
|
---|
2541 | if (touch === undefined) {
|
---|
2542 | return; // the "touch" property is only defined in SDL
|
---|
2543 |
|
---|
2544 | }
|
---|
2545 | var adjustedX = touch.pageX - (scrollX + rect.left);
|
---|
2546 | var adjustedY = touch.pageY - (scrollY + rect.top);
|
---|
2547 |
|
---|
2548 | adjustedX = adjustedX * (cw / rect.width);
|
---|
2549 | adjustedY = adjustedY * (ch / rect.height);
|
---|
2550 |
|
---|
2551 | var coords = { x: adjustedX, y: adjustedY };
|
---|
2552 |
|
---|
2553 | if (event.type === 'touchstart') {
|
---|
2554 | Browser.lastTouches[touch.identifier] = coords;
|
---|
2555 | Browser.touches[touch.identifier] = coords;
|
---|
2556 | } else if (event.type === 'touchend' || event.type === 'touchmove') {
|
---|
2557 | var last = Browser.touches[touch.identifier];
|
---|
2558 | if (!last) last = coords;
|
---|
2559 | Browser.lastTouches[touch.identifier] = last;
|
---|
2560 | Browser.touches[touch.identifier] = coords;
|
---|
2561 | }
|
---|
2562 | return;
|
---|
2563 | }
|
---|
2564 |
|
---|
2565 | var x = event.pageX - (scrollX + rect.left);
|
---|
2566 | var y = event.pageY - (scrollY + rect.top);
|
---|
2567 |
|
---|
2568 | // the canvas might be CSS-scaled compared to its backbuffer;
|
---|
2569 | // SDL-using content will want mouse coordinates in terms
|
---|
2570 | // of backbuffer units.
|
---|
2571 | x = x * (cw / rect.width);
|
---|
2572 | y = y * (ch / rect.height);
|
---|
2573 |
|
---|
2574 | Browser.mouseMovementX = x - Browser.mouseX;
|
---|
2575 | Browser.mouseMovementY = y - Browser.mouseY;
|
---|
2576 | Browser.mouseX = x;
|
---|
2577 | Browser.mouseY = y;
|
---|
2578 | }
|
---|
2579 | },asyncLoad:function(url, onload, onerror, noRunDep) {
|
---|
2580 | var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : '';
|
---|
2581 | readAsync(url, function(arrayBuffer) {
|
---|
2582 | assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
|
---|
2583 | onload(new Uint8Array(arrayBuffer));
|
---|
2584 | if (dep) removeRunDependency(dep);
|
---|
2585 | }, function(event) {
|
---|
2586 | if (onerror) {
|
---|
2587 | onerror();
|
---|
2588 | } else {
|
---|
2589 | throw 'Loading data file "' + url + '" failed.';
|
---|
2590 | }
|
---|
2591 | });
|
---|
2592 | if (dep) addRunDependency(dep);
|
---|
2593 | },resizeListeners:[],updateResizeListeners:function() {
|
---|
2594 | var canvas = Module['canvas'];
|
---|
2595 | Browser.resizeListeners.forEach(function(listener) {
|
---|
2596 | listener(canvas.width, canvas.height);
|
---|
2597 | });
|
---|
2598 | },setCanvasSize:function(width, height, noUpdates) {
|
---|
2599 | var canvas = Module['canvas'];
|
---|
2600 | Browser.updateCanvasDimensions(canvas, width, height);
|
---|
2601 | if (!noUpdates) Browser.updateResizeListeners();
|
---|
2602 | },windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function() {
|
---|
2603 | // check if SDL is available
|
---|
2604 | if (typeof SDL != "undefined") {
|
---|
2605 | var flags = HEAPU32[((SDL.screen)>>2)];
|
---|
2606 | flags = flags | 0x00800000; // set SDL_FULLSCREEN flag
|
---|
2607 | HEAP32[((SDL.screen)>>2)]=flags
|
---|
2608 | }
|
---|
2609 | Browser.updateCanvasDimensions(Module['canvas']);
|
---|
2610 | Browser.updateResizeListeners();
|
---|
2611 | },setWindowedCanvasSize:function() {
|
---|
2612 | // check if SDL is available
|
---|
2613 | if (typeof SDL != "undefined") {
|
---|
2614 | var flags = HEAPU32[((SDL.screen)>>2)];
|
---|
2615 | flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag
|
---|
2616 | HEAP32[((SDL.screen)>>2)]=flags
|
---|
2617 | }
|
---|
2618 | Browser.updateCanvasDimensions(Module['canvas']);
|
---|
2619 | Browser.updateResizeListeners();
|
---|
2620 | },updateCanvasDimensions:function(canvas, wNative, hNative) {
|
---|
2621 | if (wNative && hNative) {
|
---|
2622 | canvas.widthNative = wNative;
|
---|
2623 | canvas.heightNative = hNative;
|
---|
2624 | } else {
|
---|
2625 | wNative = canvas.widthNative;
|
---|
2626 | hNative = canvas.heightNative;
|
---|
2627 | }
|
---|
2628 | var w = wNative;
|
---|
2629 | var h = hNative;
|
---|
2630 | if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) {
|
---|
2631 | if (w/h < Module['forcedAspectRatio']) {
|
---|
2632 | w = Math.round(h * Module['forcedAspectRatio']);
|
---|
2633 | } else {
|
---|
2634 | h = Math.round(w / Module['forcedAspectRatio']);
|
---|
2635 | }
|
---|
2636 | }
|
---|
2637 | if (((document['fullscreenElement'] || document['mozFullScreenElement'] ||
|
---|
2638 | document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
|
---|
2639 | document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) {
|
---|
2640 | var factor = Math.min(screen.width / w, screen.height / h);
|
---|
2641 | w = Math.round(w * factor);
|
---|
2642 | h = Math.round(h * factor);
|
---|
2643 | }
|
---|
2644 | if (Browser.resizeCanvas) {
|
---|
2645 | if (canvas.width != w) canvas.width = w;
|
---|
2646 | if (canvas.height != h) canvas.height = h;
|
---|
2647 | if (typeof canvas.style != 'undefined') {
|
---|
2648 | canvas.style.removeProperty( "width");
|
---|
2649 | canvas.style.removeProperty("height");
|
---|
2650 | }
|
---|
2651 | } else {
|
---|
2652 | if (canvas.width != wNative) canvas.width = wNative;
|
---|
2653 | if (canvas.height != hNative) canvas.height = hNative;
|
---|
2654 | if (typeof canvas.style != 'undefined') {
|
---|
2655 | if (w != wNative || h != hNative) {
|
---|
2656 | canvas.style.setProperty( "width", w + "px", "important");
|
---|
2657 | canvas.style.setProperty("height", h + "px", "important");
|
---|
2658 | } else {
|
---|
2659 | canvas.style.removeProperty( "width");
|
---|
2660 | canvas.style.removeProperty("height");
|
---|
2661 | }
|
---|
2662 | }
|
---|
2663 | }
|
---|
2664 | },wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function() {
|
---|
2665 | var handle = Browser.nextWgetRequestHandle;
|
---|
2666 | Browser.nextWgetRequestHandle++;
|
---|
2667 | return handle;
|
---|
2668 | }};
|
---|
2669 |
|
---|
2670 | function abortStackOverflow(allocSize) {
|
---|
2671 | abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (STACK_MAX - stackSave() + allocSize) + ' bytes available!');
|
---|
2672 | }
|
---|
2673 |
|
---|
2674 | function demangle(func) {
|
---|
2675 | warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling');
|
---|
2676 | return func;
|
---|
2677 | }
|
---|
2678 |
|
---|
2679 | function demangleAll(text) {
|
---|
2680 | var regex =
|
---|
2681 | /\b_Z[\w\d_]+/g;
|
---|
2682 | return text.replace(regex,
|
---|
2683 | function(x) {
|
---|
2684 | var y = demangle(x);
|
---|
2685 | return x === y ? x : (y + ' [' + x + ']');
|
---|
2686 | });
|
---|
2687 | }
|
---|
2688 |
|
---|
2689 | function jsStackTrace() {
|
---|
2690 | var err = new Error();
|
---|
2691 | if (!err.stack) {
|
---|
2692 | // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
|
---|
2693 | // so try that as a special-case.
|
---|
2694 | try {
|
---|
2695 | throw new Error();
|
---|
2696 | } catch(e) {
|
---|
2697 | err = e;
|
---|
2698 | }
|
---|
2699 | if (!err.stack) {
|
---|
2700 | return '(no stack trace available)';
|
---|
2701 | }
|
---|
2702 | }
|
---|
2703 | return err.stack.toString();
|
---|
2704 | }
|
---|
2705 |
|
---|
2706 | function stackTrace() {
|
---|
2707 | var js = jsStackTrace();
|
---|
2708 | if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
|
---|
2709 | return demangleAll(js);
|
---|
2710 | }
|
---|
2711 |
|
---|
2712 | function ___handle_stack_overflow() {
|
---|
2713 | abort('stack overflow')
|
---|
2714 | }
|
---|
2715 |
|
---|
2716 |
|
---|
2717 | function setErrNo(value) {
|
---|
2718 | HEAP32[((___errno_location())>>2)]=value;
|
---|
2719 | return value;
|
---|
2720 | }
|
---|
2721 |
|
---|
2722 |
|
---|
2723 | var PATH={splitPath:function(filename) {
|
---|
2724 | var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
|
---|
2725 | return splitPathRe.exec(filename).slice(1);
|
---|
2726 | },normalizeArray:function(parts, allowAboveRoot) {
|
---|
2727 | // if the path tries to go above the root, `up` ends up > 0
|
---|
2728 | var up = 0;
|
---|
2729 | for (var i = parts.length - 1; i >= 0; i--) {
|
---|
2730 | var last = parts[i];
|
---|
2731 | if (last === '.') {
|
---|
2732 | parts.splice(i, 1);
|
---|
2733 | } else if (last === '..') {
|
---|
2734 | parts.splice(i, 1);
|
---|
2735 | up++;
|
---|
2736 | } else if (up) {
|
---|
2737 | parts.splice(i, 1);
|
---|
2738 | up--;
|
---|
2739 | }
|
---|
2740 | }
|
---|
2741 | // if the path is allowed to go above the root, restore leading ..s
|
---|
2742 | if (allowAboveRoot) {
|
---|
2743 | for (; up; up--) {
|
---|
2744 | parts.unshift('..');
|
---|
2745 | }
|
---|
2746 | }
|
---|
2747 | return parts;
|
---|
2748 | },normalize:function(path) {
|
---|
2749 | var isAbsolute = path.charAt(0) === '/',
|
---|
2750 | trailingSlash = path.substr(-1) === '/';
|
---|
2751 | // Normalize the path
|
---|
2752 | path = PATH.normalizeArray(path.split('/').filter(function(p) {
|
---|
2753 | return !!p;
|
---|
2754 | }), !isAbsolute).join('/');
|
---|
2755 | if (!path && !isAbsolute) {
|
---|
2756 | path = '.';
|
---|
2757 | }
|
---|
2758 | if (path && trailingSlash) {
|
---|
2759 | path += '/';
|
---|
2760 | }
|
---|
2761 | return (isAbsolute ? '/' : '') + path;
|
---|
2762 | },dirname:function(path) {
|
---|
2763 | var result = PATH.splitPath(path),
|
---|
2764 | root = result[0],
|
---|
2765 | dir = result[1];
|
---|
2766 | if (!root && !dir) {
|
---|
2767 | // No dirname whatsoever
|
---|
2768 | return '.';
|
---|
2769 | }
|
---|
2770 | if (dir) {
|
---|
2771 | // It has a dirname, strip trailing slash
|
---|
2772 | dir = dir.substr(0, dir.length - 1);
|
---|
2773 | }
|
---|
2774 | return root + dir;
|
---|
2775 | },basename:function(path) {
|
---|
2776 | // EMSCRIPTEN return '/'' for '/', not an empty string
|
---|
2777 | if (path === '/') return '/';
|
---|
2778 | var lastSlash = path.lastIndexOf('/');
|
---|
2779 | if (lastSlash === -1) return path;
|
---|
2780 | return path.substr(lastSlash+1);
|
---|
2781 | },extname:function(path) {
|
---|
2782 | return PATH.splitPath(path)[3];
|
---|
2783 | },join:function() {
|
---|
2784 | var paths = Array.prototype.slice.call(arguments, 0);
|
---|
2785 | return PATH.normalize(paths.join('/'));
|
---|
2786 | },join2:function(l, r) {
|
---|
2787 | return PATH.normalize(l + '/' + r);
|
---|
2788 | }};
|
---|
2789 |
|
---|
2790 |
|
---|
2791 | var PATH_FS={resolve:function() {
|
---|
2792 | var resolvedPath = '',
|
---|
2793 | resolvedAbsolute = false;
|
---|
2794 | for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
---|
2795 | var path = (i >= 0) ? arguments[i] : FS.cwd();
|
---|
2796 | // Skip empty and invalid entries
|
---|
2797 | if (typeof path !== 'string') {
|
---|
2798 | throw new TypeError('Arguments to path.resolve must be strings');
|
---|
2799 | } else if (!path) {
|
---|
2800 | return ''; // an invalid portion invalidates the whole thing
|
---|
2801 | }
|
---|
2802 | resolvedPath = path + '/' + resolvedPath;
|
---|
2803 | resolvedAbsolute = path.charAt(0) === '/';
|
---|
2804 | }
|
---|
2805 | // At this point the path should be resolved to a full absolute path, but
|
---|
2806 | // handle relative paths to be safe (might happen when process.cwd() fails)
|
---|
2807 | resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) {
|
---|
2808 | return !!p;
|
---|
2809 | }), !resolvedAbsolute).join('/');
|
---|
2810 | return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
|
---|
2811 | },relative:function(from, to) {
|
---|
2812 | from = PATH_FS.resolve(from).substr(1);
|
---|
2813 | to = PATH_FS.resolve(to).substr(1);
|
---|
2814 | function trim(arr) {
|
---|
2815 | var start = 0;
|
---|
2816 | for (; start < arr.length; start++) {
|
---|
2817 | if (arr[start] !== '') break;
|
---|
2818 | }
|
---|
2819 | var end = arr.length - 1;
|
---|
2820 | for (; end >= 0; end--) {
|
---|
2821 | if (arr[end] !== '') break;
|
---|
2822 | }
|
---|
2823 | if (start > end) return [];
|
---|
2824 | return arr.slice(start, end - start + 1);
|
---|
2825 | }
|
---|
2826 | var fromParts = trim(from.split('/'));
|
---|
2827 | var toParts = trim(to.split('/'));
|
---|
2828 | var length = Math.min(fromParts.length, toParts.length);
|
---|
2829 | var samePartsLength = length;
|
---|
2830 | for (var i = 0; i < length; i++) {
|
---|
2831 | if (fromParts[i] !== toParts[i]) {
|
---|
2832 | samePartsLength = i;
|
---|
2833 | break;
|
---|
2834 | }
|
---|
2835 | }
|
---|
2836 | var outputParts = [];
|
---|
2837 | for (var i = samePartsLength; i < fromParts.length; i++) {
|
---|
2838 | outputParts.push('..');
|
---|
2839 | }
|
---|
2840 | outputParts = outputParts.concat(toParts.slice(samePartsLength));
|
---|
2841 | return outputParts.join('/');
|
---|
2842 | }};
|
---|
2843 |
|
---|
2844 | var TTY={ttys:[],init:function () {
|
---|
2845 | // https://github.com/emscripten-core/emscripten/pull/1555
|
---|
2846 | // if (ENVIRONMENT_IS_NODE) {
|
---|
2847 | // // currently, FS.init does not distinguish if process.stdin is a file or TTY
|
---|
2848 | // // device, it always assumes it's a TTY device. because of this, we're forcing
|
---|
2849 | // // process.stdin to UTF8 encoding to at least make stdin reading compatible
|
---|
2850 | // // with text files until FS.init can be refactored.
|
---|
2851 | // process['stdin']['setEncoding']('utf8');
|
---|
2852 | // }
|
---|
2853 | },shutdown:function() {
|
---|
2854 | // https://github.com/emscripten-core/emscripten/pull/1555
|
---|
2855 | // if (ENVIRONMENT_IS_NODE) {
|
---|
2856 | // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
|
---|
2857 | // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation
|
---|
2858 | // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
|
---|
2859 | // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
|
---|
2860 | // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
|
---|
2861 | // process['stdin']['pause']();
|
---|
2862 | // }
|
---|
2863 | },register:function(dev, ops) {
|
---|
2864 | TTY.ttys[dev] = { input: [], output: [], ops: ops };
|
---|
2865 | FS.registerDevice(dev, TTY.stream_ops);
|
---|
2866 | },stream_ops:{open:function(stream) {
|
---|
2867 | var tty = TTY.ttys[stream.node.rdev];
|
---|
2868 | if (!tty) {
|
---|
2869 | throw new FS.ErrnoError(43);
|
---|
2870 | }
|
---|
2871 | stream.tty = tty;
|
---|
2872 | stream.seekable = false;
|
---|
2873 | },close:function(stream) {
|
---|
2874 | // flush any pending line data
|
---|
2875 | stream.tty.ops.flush(stream.tty);
|
---|
2876 | },flush:function(stream) {
|
---|
2877 | stream.tty.ops.flush(stream.tty);
|
---|
2878 | },read:function(stream, buffer, offset, length, pos /* ignored */) {
|
---|
2879 | if (!stream.tty || !stream.tty.ops.get_char) {
|
---|
2880 | throw new FS.ErrnoError(60);
|
---|
2881 | }
|
---|
2882 | var bytesRead = 0;
|
---|
2883 | for (var i = 0; i < length; i++) {
|
---|
2884 | var result;
|
---|
2885 | try {
|
---|
2886 | result = stream.tty.ops.get_char(stream.tty);
|
---|
2887 | } catch (e) {
|
---|
2888 | throw new FS.ErrnoError(29);
|
---|
2889 | }
|
---|
2890 | if (result === undefined && bytesRead === 0) {
|
---|
2891 | throw new FS.ErrnoError(6);
|
---|
2892 | }
|
---|
2893 | if (result === null || result === undefined) break;
|
---|
2894 | bytesRead++;
|
---|
2895 | buffer[offset+i] = result;
|
---|
2896 | }
|
---|
2897 | if (bytesRead) {
|
---|
2898 | stream.node.timestamp = Date.now();
|
---|
2899 | }
|
---|
2900 | return bytesRead;
|
---|
2901 | },write:function(stream, buffer, offset, length, pos) {
|
---|
2902 | if (!stream.tty || !stream.tty.ops.put_char) {
|
---|
2903 | throw new FS.ErrnoError(60);
|
---|
2904 | }
|
---|
2905 | try {
|
---|
2906 | for (var i = 0; i < length; i++) {
|
---|
2907 | stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
|
---|
2908 | }
|
---|
2909 | } catch (e) {
|
---|
2910 | throw new FS.ErrnoError(29);
|
---|
2911 | }
|
---|
2912 | if (length) {
|
---|
2913 | stream.node.timestamp = Date.now();
|
---|
2914 | }
|
---|
2915 | return i;
|
---|
2916 | }},default_tty_ops:{get_char:function(tty) {
|
---|
2917 | if (!tty.input.length) {
|
---|
2918 | var result = null;
|
---|
2919 | if (ENVIRONMENT_IS_NODE) {
|
---|
2920 | // we will read data by chunks of BUFSIZE
|
---|
2921 | var BUFSIZE = 256;
|
---|
2922 | var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE);
|
---|
2923 | var bytesRead = 0;
|
---|
2924 |
|
---|
2925 | try {
|
---|
2926 | bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
|
---|
2927 | } catch(e) {
|
---|
2928 | // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
|
---|
2929 | // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
|
---|
2930 | if (e.toString().indexOf('EOF') != -1) bytesRead = 0;
|
---|
2931 | else throw e;
|
---|
2932 | }
|
---|
2933 |
|
---|
2934 | if (bytesRead > 0) {
|
---|
2935 | result = buf.slice(0, bytesRead).toString('utf-8');
|
---|
2936 | } else {
|
---|
2937 | result = null;
|
---|
2938 | }
|
---|
2939 | } else
|
---|
2940 | if (typeof window != 'undefined' &&
|
---|
2941 | typeof window.prompt == 'function') {
|
---|
2942 | // Browser.
|
---|
2943 | result = window.prompt('Input: '); // returns null on cancel
|
---|
2944 | if (result !== null) {
|
---|
2945 | result += '\n';
|
---|
2946 | }
|
---|
2947 | } else if (typeof readline == 'function') {
|
---|
2948 | // Command line.
|
---|
2949 | result = readline();
|
---|
2950 | if (result !== null) {
|
---|
2951 | result += '\n';
|
---|
2952 | }
|
---|
2953 | }
|
---|
2954 | if (!result) {
|
---|
2955 | return null;
|
---|
2956 | }
|
---|
2957 | tty.input = intArrayFromString(result, true);
|
---|
2958 | }
|
---|
2959 | return tty.input.shift();
|
---|
2960 | },put_char:function(tty, val) {
|
---|
2961 | if (val === null || val === 10) {
|
---|
2962 | out(UTF8ArrayToString(tty.output, 0));
|
---|
2963 | tty.output = [];
|
---|
2964 | } else {
|
---|
2965 | if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle.
|
---|
2966 | }
|
---|
2967 | },flush:function(tty) {
|
---|
2968 | if (tty.output && tty.output.length > 0) {
|
---|
2969 | out(UTF8ArrayToString(tty.output, 0));
|
---|
2970 | tty.output = [];
|
---|
2971 | }
|
---|
2972 | }},default_tty1_ops:{put_char:function(tty, val) {
|
---|
2973 | if (val === null || val === 10) {
|
---|
2974 | err(UTF8ArrayToString(tty.output, 0));
|
---|
2975 | tty.output = [];
|
---|
2976 | } else {
|
---|
2977 | if (val != 0) tty.output.push(val);
|
---|
2978 | }
|
---|
2979 | },flush:function(tty) {
|
---|
2980 | if (tty.output && tty.output.length > 0) {
|
---|
2981 | err(UTF8ArrayToString(tty.output, 0));
|
---|
2982 | tty.output = [];
|
---|
2983 | }
|
---|
2984 | }}};
|
---|
2985 |
|
---|
2986 | var MEMFS={ops_table:null,mount:function(mount) {
|
---|
2987 | return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
|
---|
2988 | },createNode:function(parent, name, mode, dev) {
|
---|
2989 | if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
|
---|
2990 | // no supported
|
---|
2991 | throw new FS.ErrnoError(63);
|
---|
2992 | }
|
---|
2993 | if (!MEMFS.ops_table) {
|
---|
2994 | MEMFS.ops_table = {
|
---|
2995 | dir: {
|
---|
2996 | node: {
|
---|
2997 | getattr: MEMFS.node_ops.getattr,
|
---|
2998 | setattr: MEMFS.node_ops.setattr,
|
---|
2999 | lookup: MEMFS.node_ops.lookup,
|
---|
3000 | mknod: MEMFS.node_ops.mknod,
|
---|
3001 | rename: MEMFS.node_ops.rename,
|
---|
3002 | unlink: MEMFS.node_ops.unlink,
|
---|
3003 | rmdir: MEMFS.node_ops.rmdir,
|
---|
3004 | readdir: MEMFS.node_ops.readdir,
|
---|
3005 | symlink: MEMFS.node_ops.symlink
|
---|
3006 | },
|
---|
3007 | stream: {
|
---|
3008 | llseek: MEMFS.stream_ops.llseek
|
---|
3009 | }
|
---|
3010 | },
|
---|
3011 | file: {
|
---|
3012 | node: {
|
---|
3013 | getattr: MEMFS.node_ops.getattr,
|
---|
3014 | setattr: MEMFS.node_ops.setattr
|
---|
3015 | },
|
---|
3016 | stream: {
|
---|
3017 | llseek: MEMFS.stream_ops.llseek,
|
---|
3018 | read: MEMFS.stream_ops.read,
|
---|
3019 | write: MEMFS.stream_ops.write,
|
---|
3020 | allocate: MEMFS.stream_ops.allocate,
|
---|
3021 | mmap: MEMFS.stream_ops.mmap,
|
---|
3022 | msync: MEMFS.stream_ops.msync
|
---|
3023 | }
|
---|
3024 | },
|
---|
3025 | link: {
|
---|
3026 | node: {
|
---|
3027 | getattr: MEMFS.node_ops.getattr,
|
---|
3028 | setattr: MEMFS.node_ops.setattr,
|
---|
3029 | readlink: MEMFS.node_ops.readlink
|
---|
3030 | },
|
---|
3031 | stream: {}
|
---|
3032 | },
|
---|
3033 | chrdev: {
|
---|
3034 | node: {
|
---|
3035 | getattr: MEMFS.node_ops.getattr,
|
---|
3036 | setattr: MEMFS.node_ops.setattr
|
---|
3037 | },
|
---|
3038 | stream: FS.chrdev_stream_ops
|
---|
3039 | }
|
---|
3040 | };
|
---|
3041 | }
|
---|
3042 | var node = FS.createNode(parent, name, mode, dev);
|
---|
3043 | if (FS.isDir(node.mode)) {
|
---|
3044 | node.node_ops = MEMFS.ops_table.dir.node;
|
---|
3045 | node.stream_ops = MEMFS.ops_table.dir.stream;
|
---|
3046 | node.contents = {};
|
---|
3047 | } else if (FS.isFile(node.mode)) {
|
---|
3048 | node.node_ops = MEMFS.ops_table.file.node;
|
---|
3049 | node.stream_ops = MEMFS.ops_table.file.stream;
|
---|
3050 | node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
|
---|
3051 | // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
|
---|
3052 | // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
|
---|
3053 | // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
|
---|
3054 | node.contents = null;
|
---|
3055 | } else if (FS.isLink(node.mode)) {
|
---|
3056 | node.node_ops = MEMFS.ops_table.link.node;
|
---|
3057 | node.stream_ops = MEMFS.ops_table.link.stream;
|
---|
3058 | } else if (FS.isChrdev(node.mode)) {
|
---|
3059 | node.node_ops = MEMFS.ops_table.chrdev.node;
|
---|
3060 | node.stream_ops = MEMFS.ops_table.chrdev.stream;
|
---|
3061 | }
|
---|
3062 | node.timestamp = Date.now();
|
---|
3063 | // add the new node to the parent
|
---|
3064 | if (parent) {
|
---|
3065 | parent.contents[name] = node;
|
---|
3066 | }
|
---|
3067 | return node;
|
---|
3068 | },getFileDataAsRegularArray:function(node) {
|
---|
3069 | if (node.contents && node.contents.subarray) {
|
---|
3070 | var arr = [];
|
---|
3071 | for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i]);
|
---|
3072 | return arr; // Returns a copy of the original data.
|
---|
3073 | }
|
---|
3074 | return node.contents; // No-op, the file contents are already in a JS array. Return as-is.
|
---|
3075 | },getFileDataAsTypedArray:function(node) {
|
---|
3076 | if (!node.contents) return new Uint8Array(0);
|
---|
3077 | if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
|
---|
3078 | return new Uint8Array(node.contents);
|
---|
3079 | },expandFileStorage:function(node, newCapacity) {
|
---|
3080 | var prevCapacity = node.contents ? node.contents.length : 0;
|
---|
3081 | if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
|
---|
3082 | // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
|
---|
3083 | // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
|
---|
3084 | // avoid overshooting the allocation cap by a very large margin.
|
---|
3085 | var CAPACITY_DOUBLING_MAX = 1024 * 1024;
|
---|
3086 | newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
|
---|
3087 | if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
|
---|
3088 | var oldContents = node.contents;
|
---|
3089 | node.contents = new Uint8Array(newCapacity); // Allocate new storage.
|
---|
3090 | if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
|
---|
3091 | return;
|
---|
3092 | },resizeFileStorage:function(node, newSize) {
|
---|
3093 | if (node.usedBytes == newSize) return;
|
---|
3094 | if (newSize == 0) {
|
---|
3095 | node.contents = null; // Fully decommit when requesting a resize to zero.
|
---|
3096 | node.usedBytes = 0;
|
---|
3097 | return;
|
---|
3098 | }
|
---|
3099 | if (!node.contents || node.contents.subarray) { // Resize a typed array if that is being used as the backing store.
|
---|
3100 | var oldContents = node.contents;
|
---|
3101 | node.contents = new Uint8Array(newSize); // Allocate new storage.
|
---|
3102 | if (oldContents) {
|
---|
3103 | node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
|
---|
3104 | }
|
---|
3105 | node.usedBytes = newSize;
|
---|
3106 | return;
|
---|
3107 | }
|
---|
3108 | // Backing with a JS array.
|
---|
3109 | if (!node.contents) node.contents = [];
|
---|
3110 | if (node.contents.length > newSize) node.contents.length = newSize;
|
---|
3111 | else while (node.contents.length < newSize) node.contents.push(0);
|
---|
3112 | node.usedBytes = newSize;
|
---|
3113 | },node_ops:{getattr:function(node) {
|
---|
3114 | var attr = {};
|
---|
3115 | // device numbers reuse inode numbers.
|
---|
3116 | attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
|
---|
3117 | attr.ino = node.id;
|
---|
3118 | attr.mode = node.mode;
|
---|
3119 | attr.nlink = 1;
|
---|
3120 | attr.uid = 0;
|
---|
3121 | attr.gid = 0;
|
---|
3122 | attr.rdev = node.rdev;
|
---|
3123 | if (FS.isDir(node.mode)) {
|
---|
3124 | attr.size = 4096;
|
---|
3125 | } else if (FS.isFile(node.mode)) {
|
---|
3126 | attr.size = node.usedBytes;
|
---|
3127 | } else if (FS.isLink(node.mode)) {
|
---|
3128 | attr.size = node.link.length;
|
---|
3129 | } else {
|
---|
3130 | attr.size = 0;
|
---|
3131 | }
|
---|
3132 | attr.atime = new Date(node.timestamp);
|
---|
3133 | attr.mtime = new Date(node.timestamp);
|
---|
3134 | attr.ctime = new Date(node.timestamp);
|
---|
3135 | // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
|
---|
3136 | // but this is not required by the standard.
|
---|
3137 | attr.blksize = 4096;
|
---|
3138 | attr.blocks = Math.ceil(attr.size / attr.blksize);
|
---|
3139 | return attr;
|
---|
3140 | },setattr:function(node, attr) {
|
---|
3141 | if (attr.mode !== undefined) {
|
---|
3142 | node.mode = attr.mode;
|
---|
3143 | }
|
---|
3144 | if (attr.timestamp !== undefined) {
|
---|
3145 | node.timestamp = attr.timestamp;
|
---|
3146 | }
|
---|
3147 | if (attr.size !== undefined) {
|
---|
3148 | MEMFS.resizeFileStorage(node, attr.size);
|
---|
3149 | }
|
---|
3150 | },lookup:function(parent, name) {
|
---|
3151 | throw FS.genericErrors[44];
|
---|
3152 | },mknod:function(parent, name, mode, dev) {
|
---|
3153 | return MEMFS.createNode(parent, name, mode, dev);
|
---|
3154 | },rename:function(old_node, new_dir, new_name) {
|
---|
3155 | // if we're overwriting a directory at new_name, make sure it's empty.
|
---|
3156 | if (FS.isDir(old_node.mode)) {
|
---|
3157 | var new_node;
|
---|
3158 | try {
|
---|
3159 | new_node = FS.lookupNode(new_dir, new_name);
|
---|
3160 | } catch (e) {
|
---|
3161 | }
|
---|
3162 | if (new_node) {
|
---|
3163 | for (var i in new_node.contents) {
|
---|
3164 | throw new FS.ErrnoError(55);
|
---|
3165 | }
|
---|
3166 | }
|
---|
3167 | }
|
---|
3168 | // do the internal rewiring
|
---|
3169 | delete old_node.parent.contents[old_node.name];
|
---|
3170 | old_node.name = new_name;
|
---|
3171 | new_dir.contents[new_name] = old_node;
|
---|
3172 | old_node.parent = new_dir;
|
---|
3173 | },unlink:function(parent, name) {
|
---|
3174 | delete parent.contents[name];
|
---|
3175 | },rmdir:function(parent, name) {
|
---|
3176 | var node = FS.lookupNode(parent, name);
|
---|
3177 | for (var i in node.contents) {
|
---|
3178 | throw new FS.ErrnoError(55);
|
---|
3179 | }
|
---|
3180 | delete parent.contents[name];
|
---|
3181 | },readdir:function(node) {
|
---|
3182 | var entries = ['.', '..'];
|
---|
3183 | for (var key in node.contents) {
|
---|
3184 | if (!node.contents.hasOwnProperty(key)) {
|
---|
3185 | continue;
|
---|
3186 | }
|
---|
3187 | entries.push(key);
|
---|
3188 | }
|
---|
3189 | return entries;
|
---|
3190 | },symlink:function(parent, newname, oldpath) {
|
---|
3191 | var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
|
---|
3192 | node.link = oldpath;
|
---|
3193 | return node;
|
---|
3194 | },readlink:function(node) {
|
---|
3195 | if (!FS.isLink(node.mode)) {
|
---|
3196 | throw new FS.ErrnoError(28);
|
---|
3197 | }
|
---|
3198 | return node.link;
|
---|
3199 | }},stream_ops:{read:function(stream, buffer, offset, length, position) {
|
---|
3200 | var contents = stream.node.contents;
|
---|
3201 | if (position >= stream.node.usedBytes) return 0;
|
---|
3202 | var size = Math.min(stream.node.usedBytes - position, length);
|
---|
3203 | assert(size >= 0);
|
---|
3204 | if (size > 8 && contents.subarray) { // non-trivial, and typed array
|
---|
3205 | buffer.set(contents.subarray(position, position + size), offset);
|
---|
3206 | } else {
|
---|
3207 | for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
|
---|
3208 | }
|
---|
3209 | return size;
|
---|
3210 | },write:function(stream, buffer, offset, length, position, canOwn) {
|
---|
3211 | // The data buffer should be a typed array view
|
---|
3212 | assert(!(buffer instanceof ArrayBuffer));
|
---|
3213 |
|
---|
3214 | if (!length) return 0;
|
---|
3215 | var node = stream.node;
|
---|
3216 | node.timestamp = Date.now();
|
---|
3217 |
|
---|
3218 | if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
|
---|
3219 | if (canOwn) {
|
---|
3220 | assert(position === 0, 'canOwn must imply no weird position inside the file');
|
---|
3221 | node.contents = buffer.subarray(offset, offset + length);
|
---|
3222 | node.usedBytes = length;
|
---|
3223 | return length;
|
---|
3224 | } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
|
---|
3225 | node.contents = buffer.slice(offset, offset + length);
|
---|
3226 | node.usedBytes = length;
|
---|
3227 | return length;
|
---|
3228 | } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
|
---|
3229 | node.contents.set(buffer.subarray(offset, offset + length), position);
|
---|
3230 | return length;
|
---|
3231 | }
|
---|
3232 | }
|
---|
3233 |
|
---|
3234 | // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
|
---|
3235 | MEMFS.expandFileStorage(node, position+length);
|
---|
3236 | if (node.contents.subarray && buffer.subarray) node.contents.set(buffer.subarray(offset, offset + length), position); // Use typed array write if available.
|
---|
3237 | else {
|
---|
3238 | for (var i = 0; i < length; i++) {
|
---|
3239 | node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
|
---|
3240 | }
|
---|
3241 | }
|
---|
3242 | node.usedBytes = Math.max(node.usedBytes, position + length);
|
---|
3243 | return length;
|
---|
3244 | },llseek:function(stream, offset, whence) {
|
---|
3245 | var position = offset;
|
---|
3246 | if (whence === 1) {
|
---|
3247 | position += stream.position;
|
---|
3248 | } else if (whence === 2) {
|
---|
3249 | if (FS.isFile(stream.node.mode)) {
|
---|
3250 | position += stream.node.usedBytes;
|
---|
3251 | }
|
---|
3252 | }
|
---|
3253 | if (position < 0) {
|
---|
3254 | throw new FS.ErrnoError(28);
|
---|
3255 | }
|
---|
3256 | return position;
|
---|
3257 | },allocate:function(stream, offset, length) {
|
---|
3258 | MEMFS.expandFileStorage(stream.node, offset + length);
|
---|
3259 | stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
|
---|
3260 | },mmap:function(stream, address, length, position, prot, flags) {
|
---|
3261 | // We don't currently support location hints for the address of the mapping
|
---|
3262 | assert(address === 0);
|
---|
3263 |
|
---|
3264 | if (!FS.isFile(stream.node.mode)) {
|
---|
3265 | throw new FS.ErrnoError(43);
|
---|
3266 | }
|
---|
3267 | var ptr;
|
---|
3268 | var allocated;
|
---|
3269 | var contents = stream.node.contents;
|
---|
3270 | // Only make a new copy when MAP_PRIVATE is specified.
|
---|
3271 | if (!(flags & 2) && contents.buffer === buffer) {
|
---|
3272 | // We can't emulate MAP_SHARED when the file is not backed by the buffer
|
---|
3273 | // we're mapping to (e.g. the HEAP buffer).
|
---|
3274 | allocated = false;
|
---|
3275 | ptr = contents.byteOffset;
|
---|
3276 | } else {
|
---|
3277 | // Try to avoid unnecessary slices.
|
---|
3278 | if (position > 0 || position + length < contents.length) {
|
---|
3279 | if (contents.subarray) {
|
---|
3280 | contents = contents.subarray(position, position + length);
|
---|
3281 | } else {
|
---|
3282 | contents = Array.prototype.slice.call(contents, position, position + length);
|
---|
3283 | }
|
---|
3284 | }
|
---|
3285 | allocated = true;
|
---|
3286 | ptr = _malloc(length);
|
---|
3287 | if (!ptr) {
|
---|
3288 | throw new FS.ErrnoError(48);
|
---|
3289 | }
|
---|
3290 | HEAP8.set(contents, ptr);
|
---|
3291 | }
|
---|
3292 | return { ptr: ptr, allocated: allocated };
|
---|
3293 | },msync:function(stream, buffer, offset, length, mmapFlags) {
|
---|
3294 | if (!FS.isFile(stream.node.mode)) {
|
---|
3295 | throw new FS.ErrnoError(43);
|
---|
3296 | }
|
---|
3297 | if (mmapFlags & 2) {
|
---|
3298 | // MAP_PRIVATE calls need not to be synced back to underlying fs
|
---|
3299 | return 0;
|
---|
3300 | }
|
---|
3301 |
|
---|
3302 | var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
|
---|
3303 | // should we check if bytesWritten and length are the same?
|
---|
3304 | return 0;
|
---|
3305 | }}};
|
---|
3306 |
|
---|
3307 | var ERRNO_MESSAGES={0:"Success",1:"Arg list too long",2:"Permission denied",3:"Address already in use",4:"Address not available",5:"Address family not supported by protocol family",6:"No more processes",7:"Socket already connected",8:"Bad file number",9:"Trying to read unreadable message",10:"Mount device busy",11:"Operation canceled",12:"No children",13:"Connection aborted",14:"Connection refused",15:"Connection reset by peer",16:"File locking deadlock error",17:"Destination address required",18:"Math arg out of domain of func",19:"Quota exceeded",20:"File exists",21:"Bad address",22:"File too large",23:"Host is unreachable",24:"Identifier removed",25:"Illegal byte sequence",26:"Connection already in progress",27:"Interrupted system call",28:"Invalid argument",29:"I/O error",30:"Socket is already connected",31:"Is a directory",32:"Too many symbolic links",33:"Too many open files",34:"Too many links",35:"Message too long",36:"Multihop attempted",37:"File or path name too long",38:"Network interface is not configured",39:"Connection reset by network",40:"Network is unreachable",41:"Too many open files in system",42:"No buffer space available",43:"No such device",44:"No such file or directory",45:"Exec format error",46:"No record locks available",47:"The link has been severed",48:"Not enough core",49:"No message of desired type",50:"Protocol not available",51:"No space left on device",52:"Function not implemented",53:"Socket is not connected",54:"Not a directory",55:"Directory not empty",56:"State not recoverable",57:"Socket operation on non-socket",59:"Not a typewriter",60:"No such device or address",61:"Value too large for defined data type",62:"Previous owner died",63:"Not super-user",64:"Broken pipe",65:"Protocol error",66:"Unknown protocol",67:"Protocol wrong type for socket",68:"Math result not representable",69:"Read only file system",70:"Illegal seek",71:"No such process",72:"Stale file handle",73:"Connection timed out",74:"Text file busy",75:"Cross-device link",100:"Device not a stream",101:"Bad font file fmt",102:"Invalid slot",103:"Invalid request code",104:"No anode",105:"Block device required",106:"Channel number out of range",107:"Level 3 halted",108:"Level 3 reset",109:"Link number out of range",110:"Protocol driver not attached",111:"No CSI structure available",112:"Level 2 halted",113:"Invalid exchange",114:"Invalid request descriptor",115:"Exchange full",116:"No data (for no delay io)",117:"Timer expired",118:"Out of streams resources",119:"Machine is not on the network",120:"Package not installed",121:"The object is remote",122:"Advertise error",123:"Srmount error",124:"Communication error on send",125:"Cross mount point (not really error)",126:"Given log. name not unique",127:"f.d. invalid for this operation",128:"Remote address changed",129:"Can access a needed shared lib",130:"Accessing a corrupted shared lib",131:".lib section in a.out corrupted",132:"Attempting to link in too many libs",133:"Attempting to exec a shared library",135:"Streams pipe error",136:"Too many users",137:"Socket type not supported",138:"Not supported",139:"Protocol family not supported",140:"Can't send after socket shutdown",141:"Too many references",142:"Host is down",148:"No medium (in tape drive)",156:"Level 2 not synchronized"};
|
---|
3308 |
|
---|
3309 | var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(e) {
|
---|
3310 | if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
|
---|
3311 | return setErrNo(e.errno);
|
---|
3312 | },lookupPath:function(path, opts) {
|
---|
3313 | path = PATH_FS.resolve(FS.cwd(), path);
|
---|
3314 | opts = opts || {};
|
---|
3315 |
|
---|
3316 | if (!path) return { path: '', node: null };
|
---|
3317 |
|
---|
3318 | var defaults = {
|
---|
3319 | follow_mount: true,
|
---|
3320 | recurse_count: 0
|
---|
3321 | };
|
---|
3322 | for (var key in defaults) {
|
---|
3323 | if (opts[key] === undefined) {
|
---|
3324 | opts[key] = defaults[key];
|
---|
3325 | }
|
---|
3326 | }
|
---|
3327 |
|
---|
3328 | if (opts.recurse_count > 8) { // max recursive lookup of 8
|
---|
3329 | throw new FS.ErrnoError(32);
|
---|
3330 | }
|
---|
3331 |
|
---|
3332 | // split the path
|
---|
3333 | var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
|
---|
3334 | return !!p;
|
---|
3335 | }), false);
|
---|
3336 |
|
---|
3337 | // start at the root
|
---|
3338 | var current = FS.root;
|
---|
3339 | var current_path = '/';
|
---|
3340 |
|
---|
3341 | for (var i = 0; i < parts.length; i++) {
|
---|
3342 | var islast = (i === parts.length-1);
|
---|
3343 | if (islast && opts.parent) {
|
---|
3344 | // stop resolving
|
---|
3345 | break;
|
---|
3346 | }
|
---|
3347 |
|
---|
3348 | current = FS.lookupNode(current, parts[i]);
|
---|
3349 | current_path = PATH.join2(current_path, parts[i]);
|
---|
3350 |
|
---|
3351 | // jump to the mount's root node if this is a mountpoint
|
---|
3352 | if (FS.isMountpoint(current)) {
|
---|
3353 | if (!islast || (islast && opts.follow_mount)) {
|
---|
3354 | current = current.mounted.root;
|
---|
3355 | }
|
---|
3356 | }
|
---|
3357 |
|
---|
3358 | // by default, lookupPath will not follow a symlink if it is the final path component.
|
---|
3359 | // setting opts.follow = true will override this behavior.
|
---|
3360 | if (!islast || opts.follow) {
|
---|
3361 | var count = 0;
|
---|
3362 | while (FS.isLink(current.mode)) {
|
---|
3363 | var link = FS.readlink(current_path);
|
---|
3364 | current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
|
---|
3365 |
|
---|
3366 | var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
|
---|
3367 | current = lookup.node;
|
---|
3368 |
|
---|
3369 | if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
|
---|
3370 | throw new FS.ErrnoError(32);
|
---|
3371 | }
|
---|
3372 | }
|
---|
3373 | }
|
---|
3374 | }
|
---|
3375 |
|
---|
3376 | return { path: current_path, node: current };
|
---|
3377 | },getPath:function(node) {
|
---|
3378 | var path;
|
---|
3379 | while (true) {
|
---|
3380 | if (FS.isRoot(node)) {
|
---|
3381 | var mount = node.mount.mountpoint;
|
---|
3382 | if (!path) return mount;
|
---|
3383 | return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
|
---|
3384 | }
|
---|
3385 | path = path ? node.name + '/' + path : node.name;
|
---|
3386 | node = node.parent;
|
---|
3387 | }
|
---|
3388 | },hashName:function(parentid, name) {
|
---|
3389 | var hash = 0;
|
---|
3390 |
|
---|
3391 |
|
---|
3392 | for (var i = 0; i < name.length; i++) {
|
---|
3393 | hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
|
---|
3394 | }
|
---|
3395 | return ((parentid + hash) >>> 0) % FS.nameTable.length;
|
---|
3396 | },hashAddNode:function(node) {
|
---|
3397 | var hash = FS.hashName(node.parent.id, node.name);
|
---|
3398 | node.name_next = FS.nameTable[hash];
|
---|
3399 | FS.nameTable[hash] = node;
|
---|
3400 | },hashRemoveNode:function(node) {
|
---|
3401 | var hash = FS.hashName(node.parent.id, node.name);
|
---|
3402 | if (FS.nameTable[hash] === node) {
|
---|
3403 | FS.nameTable[hash] = node.name_next;
|
---|
3404 | } else {
|
---|
3405 | var current = FS.nameTable[hash];
|
---|
3406 | while (current) {
|
---|
3407 | if (current.name_next === node) {
|
---|
3408 | current.name_next = node.name_next;
|
---|
3409 | break;
|
---|
3410 | }
|
---|
3411 | current = current.name_next;
|
---|
3412 | }
|
---|
3413 | }
|
---|
3414 | },lookupNode:function(parent, name) {
|
---|
3415 | var errCode = FS.mayLookup(parent);
|
---|
3416 | if (errCode) {
|
---|
3417 | throw new FS.ErrnoError(errCode, parent);
|
---|
3418 | }
|
---|
3419 | var hash = FS.hashName(parent.id, name);
|
---|
3420 | for (var node = FS.nameTable[hash]; node; node = node.name_next) {
|
---|
3421 | var nodeName = node.name;
|
---|
3422 | if (node.parent.id === parent.id && nodeName === name) {
|
---|
3423 | return node;
|
---|
3424 | }
|
---|
3425 | }
|
---|
3426 | // if we failed to find it in the cache, call into the VFS
|
---|
3427 | return FS.lookup(parent, name);
|
---|
3428 | },createNode:function(parent, name, mode, rdev) {
|
---|
3429 | var node = new FS.FSNode(parent, name, mode, rdev);
|
---|
3430 |
|
---|
3431 | FS.hashAddNode(node);
|
---|
3432 |
|
---|
3433 | return node;
|
---|
3434 | },destroyNode:function(node) {
|
---|
3435 | FS.hashRemoveNode(node);
|
---|
3436 | },isRoot:function(node) {
|
---|
3437 | return node === node.parent;
|
---|
3438 | },isMountpoint:function(node) {
|
---|
3439 | return !!node.mounted;
|
---|
3440 | },isFile:function(mode) {
|
---|
3441 | return (mode & 61440) === 32768;
|
---|
3442 | },isDir:function(mode) {
|
---|
3443 | return (mode & 61440) === 16384;
|
---|
3444 | },isLink:function(mode) {
|
---|
3445 | return (mode & 61440) === 40960;
|
---|
3446 | },isChrdev:function(mode) {
|
---|
3447 | return (mode & 61440) === 8192;
|
---|
3448 | },isBlkdev:function(mode) {
|
---|
3449 | return (mode & 61440) === 24576;
|
---|
3450 | },isFIFO:function(mode) {
|
---|
3451 | return (mode & 61440) === 4096;
|
---|
3452 | },isSocket:function(mode) {
|
---|
3453 | return (mode & 49152) === 49152;
|
---|
3454 | },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str) {
|
---|
3455 | var flags = FS.flagModes[str];
|
---|
3456 | if (typeof flags === 'undefined') {
|
---|
3457 | throw new Error('Unknown file open mode: ' + str);
|
---|
3458 | }
|
---|
3459 | return flags;
|
---|
3460 | },flagsToPermissionString:function(flag) {
|
---|
3461 | var perms = ['r', 'w', 'rw'][flag & 3];
|
---|
3462 | if ((flag & 512)) {
|
---|
3463 | perms += 'w';
|
---|
3464 | }
|
---|
3465 | return perms;
|
---|
3466 | },nodePermissions:function(node, perms) {
|
---|
3467 | if (FS.ignorePermissions) {
|
---|
3468 | return 0;
|
---|
3469 | }
|
---|
3470 | // return 0 if any user, group or owner bits are set.
|
---|
3471 | if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
|
---|
3472 | return 2;
|
---|
3473 | } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
|
---|
3474 | return 2;
|
---|
3475 | } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
|
---|
3476 | return 2;
|
---|
3477 | }
|
---|
3478 | return 0;
|
---|
3479 | },mayLookup:function(dir) {
|
---|
3480 | var errCode = FS.nodePermissions(dir, 'x');
|
---|
3481 | if (errCode) return errCode;
|
---|
3482 | if (!dir.node_ops.lookup) return 2;
|
---|
3483 | return 0;
|
---|
3484 | },mayCreate:function(dir, name) {
|
---|
3485 | try {
|
---|
3486 | var node = FS.lookupNode(dir, name);
|
---|
3487 | return 20;
|
---|
3488 | } catch (e) {
|
---|
3489 | }
|
---|
3490 | return FS.nodePermissions(dir, 'wx');
|
---|
3491 | },mayDelete:function(dir, name, isdir) {
|
---|
3492 | var node;
|
---|
3493 | try {
|
---|
3494 | node = FS.lookupNode(dir, name);
|
---|
3495 | } catch (e) {
|
---|
3496 | return e.errno;
|
---|
3497 | }
|
---|
3498 | var errCode = FS.nodePermissions(dir, 'wx');
|
---|
3499 | if (errCode) {
|
---|
3500 | return errCode;
|
---|
3501 | }
|
---|
3502 | if (isdir) {
|
---|
3503 | if (!FS.isDir(node.mode)) {
|
---|
3504 | return 54;
|
---|
3505 | }
|
---|
3506 | if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
|
---|
3507 | return 10;
|
---|
3508 | }
|
---|
3509 | } else {
|
---|
3510 | if (FS.isDir(node.mode)) {
|
---|
3511 | return 31;
|
---|
3512 | }
|
---|
3513 | }
|
---|
3514 | return 0;
|
---|
3515 | },mayOpen:function(node, flags) {
|
---|
3516 | if (!node) {
|
---|
3517 | return 44;
|
---|
3518 | }
|
---|
3519 | if (FS.isLink(node.mode)) {
|
---|
3520 | return 32;
|
---|
3521 | } else if (FS.isDir(node.mode)) {
|
---|
3522 | if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write
|
---|
3523 | (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only)
|
---|
3524 | return 31;
|
---|
3525 | }
|
---|
3526 | }
|
---|
3527 | return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
|
---|
3528 | },MAX_OPEN_FDS:4096,nextfd:function(fd_start, fd_end) {
|
---|
3529 | fd_start = fd_start || 0;
|
---|
3530 | fd_end = fd_end || FS.MAX_OPEN_FDS;
|
---|
3531 | for (var fd = fd_start; fd <= fd_end; fd++) {
|
---|
3532 | if (!FS.streams[fd]) {
|
---|
3533 | return fd;
|
---|
3534 | }
|
---|
3535 | }
|
---|
3536 | throw new FS.ErrnoError(33);
|
---|
3537 | },getStream:function(fd) {
|
---|
3538 | return FS.streams[fd];
|
---|
3539 | },createStream:function(stream, fd_start, fd_end) {
|
---|
3540 | if (!FS.FSStream) {
|
---|
3541 | FS.FSStream = /** @constructor */ function(){};
|
---|
3542 | FS.FSStream.prototype = {
|
---|
3543 | object: {
|
---|
3544 | get: function() { return this.node; },
|
---|
3545 | set: function(val) { this.node = val; }
|
---|
3546 | },
|
---|
3547 | isRead: {
|
---|
3548 | get: function() { return (this.flags & 2097155) !== 1; }
|
---|
3549 | },
|
---|
3550 | isWrite: {
|
---|
3551 | get: function() { return (this.flags & 2097155) !== 0; }
|
---|
3552 | },
|
---|
3553 | isAppend: {
|
---|
3554 | get: function() { return (this.flags & 1024); }
|
---|
3555 | }
|
---|
3556 | };
|
---|
3557 | }
|
---|
3558 | // clone it, so we can return an instance of FSStream
|
---|
3559 | var newStream = new FS.FSStream();
|
---|
3560 | for (var p in stream) {
|
---|
3561 | newStream[p] = stream[p];
|
---|
3562 | }
|
---|
3563 | stream = newStream;
|
---|
3564 | var fd = FS.nextfd(fd_start, fd_end);
|
---|
3565 | stream.fd = fd;
|
---|
3566 | FS.streams[fd] = stream;
|
---|
3567 | return stream;
|
---|
3568 | },closeStream:function(fd) {
|
---|
3569 | FS.streams[fd] = null;
|
---|
3570 | },chrdev_stream_ops:{open:function(stream) {
|
---|
3571 | var device = FS.getDevice(stream.node.rdev);
|
---|
3572 | // override node's stream ops with the device's
|
---|
3573 | stream.stream_ops = device.stream_ops;
|
---|
3574 | // forward the open call
|
---|
3575 | if (stream.stream_ops.open) {
|
---|
3576 | stream.stream_ops.open(stream);
|
---|
3577 | }
|
---|
3578 | },llseek:function() {
|
---|
3579 | throw new FS.ErrnoError(70);
|
---|
3580 | }},major:function(dev) {
|
---|
3581 | return ((dev) >> 8);
|
---|
3582 | },minor:function(dev) {
|
---|
3583 | return ((dev) & 0xff);
|
---|
3584 | },makedev:function(ma, mi) {
|
---|
3585 | return ((ma) << 8 | (mi));
|
---|
3586 | },registerDevice:function(dev, ops) {
|
---|
3587 | FS.devices[dev] = { stream_ops: ops };
|
---|
3588 | },getDevice:function(dev) {
|
---|
3589 | return FS.devices[dev];
|
---|
3590 | },getMounts:function(mount) {
|
---|
3591 | var mounts = [];
|
---|
3592 | var check = [mount];
|
---|
3593 |
|
---|
3594 | while (check.length) {
|
---|
3595 | var m = check.pop();
|
---|
3596 |
|
---|
3597 | mounts.push(m);
|
---|
3598 |
|
---|
3599 | check.push.apply(check, m.mounts);
|
---|
3600 | }
|
---|
3601 |
|
---|
3602 | return mounts;
|
---|
3603 | },syncfs:function(populate, callback) {
|
---|
3604 | if (typeof(populate) === 'function') {
|
---|
3605 | callback = populate;
|
---|
3606 | populate = false;
|
---|
3607 | }
|
---|
3608 |
|
---|
3609 | FS.syncFSRequests++;
|
---|
3610 |
|
---|
3611 | if (FS.syncFSRequests > 1) {
|
---|
3612 | err('warning: ' + FS.syncFSRequests + ' FS.syncfs operations in flight at once, probably just doing extra work');
|
---|
3613 | }
|
---|
3614 |
|
---|
3615 | var mounts = FS.getMounts(FS.root.mount);
|
---|
3616 | var completed = 0;
|
---|
3617 |
|
---|
3618 | function doCallback(errCode) {
|
---|
3619 | assert(FS.syncFSRequests > 0);
|
---|
3620 | FS.syncFSRequests--;
|
---|
3621 | return callback(errCode);
|
---|
3622 | }
|
---|
3623 |
|
---|
3624 | function done(errCode) {
|
---|
3625 | if (errCode) {
|
---|
3626 | if (!done.errored) {
|
---|
3627 | done.errored = true;
|
---|
3628 | return doCallback(errCode);
|
---|
3629 | }
|
---|
3630 | return;
|
---|
3631 | }
|
---|
3632 | if (++completed >= mounts.length) {
|
---|
3633 | doCallback(null);
|
---|
3634 | }
|
---|
3635 | };
|
---|
3636 |
|
---|
3637 | // sync all mounts
|
---|
3638 | mounts.forEach(function (mount) {
|
---|
3639 | if (!mount.type.syncfs) {
|
---|
3640 | return done(null);
|
---|
3641 | }
|
---|
3642 | mount.type.syncfs(mount, populate, done);
|
---|
3643 | });
|
---|
3644 | },mount:function(type, opts, mountpoint) {
|
---|
3645 | if (typeof type === 'string') {
|
---|
3646 | // The filesystem was not included, and instead we have an error
|
---|
3647 | // message stored in the variable.
|
---|
3648 | throw type;
|
---|
3649 | }
|
---|
3650 | var root = mountpoint === '/';
|
---|
3651 | var pseudo = !mountpoint;
|
---|
3652 | var node;
|
---|
3653 |
|
---|
3654 | if (root && FS.root) {
|
---|
3655 | throw new FS.ErrnoError(10);
|
---|
3656 | } else if (!root && !pseudo) {
|
---|
3657 | var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
|
---|
3658 |
|
---|
3659 | mountpoint = lookup.path; // use the absolute path
|
---|
3660 | node = lookup.node;
|
---|
3661 |
|
---|
3662 | if (FS.isMountpoint(node)) {
|
---|
3663 | throw new FS.ErrnoError(10);
|
---|
3664 | }
|
---|
3665 |
|
---|
3666 | if (!FS.isDir(node.mode)) {
|
---|
3667 | throw new FS.ErrnoError(54);
|
---|
3668 | }
|
---|
3669 | }
|
---|
3670 |
|
---|
3671 | var mount = {
|
---|
3672 | type: type,
|
---|
3673 | opts: opts,
|
---|
3674 | mountpoint: mountpoint,
|
---|
3675 | mounts: []
|
---|
3676 | };
|
---|
3677 |
|
---|
3678 | // create a root node for the fs
|
---|
3679 | var mountRoot = type.mount(mount);
|
---|
3680 | mountRoot.mount = mount;
|
---|
3681 | mount.root = mountRoot;
|
---|
3682 |
|
---|
3683 | if (root) {
|
---|
3684 | FS.root = mountRoot;
|
---|
3685 | } else if (node) {
|
---|
3686 | // set as a mountpoint
|
---|
3687 | node.mounted = mount;
|
---|
3688 |
|
---|
3689 | // add the new mount to the current mount's children
|
---|
3690 | if (node.mount) {
|
---|
3691 | node.mount.mounts.push(mount);
|
---|
3692 | }
|
---|
3693 | }
|
---|
3694 |
|
---|
3695 | return mountRoot;
|
---|
3696 | },unmount:function (mountpoint) {
|
---|
3697 | var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
|
---|
3698 |
|
---|
3699 | if (!FS.isMountpoint(lookup.node)) {
|
---|
3700 | throw new FS.ErrnoError(28);
|
---|
3701 | }
|
---|
3702 |
|
---|
3703 | // destroy the nodes for this mount, and all its child mounts
|
---|
3704 | var node = lookup.node;
|
---|
3705 | var mount = node.mounted;
|
---|
3706 | var mounts = FS.getMounts(mount);
|
---|
3707 |
|
---|
3708 | Object.keys(FS.nameTable).forEach(function (hash) {
|
---|
3709 | var current = FS.nameTable[hash];
|
---|
3710 |
|
---|
3711 | while (current) {
|
---|
3712 | var next = current.name_next;
|
---|
3713 |
|
---|
3714 | if (mounts.indexOf(current.mount) !== -1) {
|
---|
3715 | FS.destroyNode(current);
|
---|
3716 | }
|
---|
3717 |
|
---|
3718 | current = next;
|
---|
3719 | }
|
---|
3720 | });
|
---|
3721 |
|
---|
3722 | // no longer a mountpoint
|
---|
3723 | node.mounted = null;
|
---|
3724 |
|
---|
3725 | // remove this mount from the child mounts
|
---|
3726 | var idx = node.mount.mounts.indexOf(mount);
|
---|
3727 | assert(idx !== -1);
|
---|
3728 | node.mount.mounts.splice(idx, 1);
|
---|
3729 | },lookup:function(parent, name) {
|
---|
3730 | return parent.node_ops.lookup(parent, name);
|
---|
3731 | },mknod:function(path, mode, dev) {
|
---|
3732 | var lookup = FS.lookupPath(path, { parent: true });
|
---|
3733 | var parent = lookup.node;
|
---|
3734 | var name = PATH.basename(path);
|
---|
3735 | if (!name || name === '.' || name === '..') {
|
---|
3736 | throw new FS.ErrnoError(28);
|
---|
3737 | }
|
---|
3738 | var errCode = FS.mayCreate(parent, name);
|
---|
3739 | if (errCode) {
|
---|
3740 | throw new FS.ErrnoError(errCode);
|
---|
3741 | }
|
---|
3742 | if (!parent.node_ops.mknod) {
|
---|
3743 | throw new FS.ErrnoError(63);
|
---|
3744 | }
|
---|
3745 | return parent.node_ops.mknod(parent, name, mode, dev);
|
---|
3746 | },create:function(path, mode) {
|
---|
3747 | mode = mode !== undefined ? mode : 438 /* 0666 */;
|
---|
3748 | mode &= 4095;
|
---|
3749 | mode |= 32768;
|
---|
3750 | return FS.mknod(path, mode, 0);
|
---|
3751 | },mkdir:function(path, mode) {
|
---|
3752 | mode = mode !== undefined ? mode : 511 /* 0777 */;
|
---|
3753 | mode &= 511 | 512;
|
---|
3754 | mode |= 16384;
|
---|
3755 | return FS.mknod(path, mode, 0);
|
---|
3756 | },mkdirTree:function(path, mode) {
|
---|
3757 | var dirs = path.split('/');
|
---|
3758 | var d = '';
|
---|
3759 | for (var i = 0; i < dirs.length; ++i) {
|
---|
3760 | if (!dirs[i]) continue;
|
---|
3761 | d += '/' + dirs[i];
|
---|
3762 | try {
|
---|
3763 | FS.mkdir(d, mode);
|
---|
3764 | } catch(e) {
|
---|
3765 | if (e.errno != 20) throw e;
|
---|
3766 | }
|
---|
3767 | }
|
---|
3768 | },mkdev:function(path, mode, dev) {
|
---|
3769 | if (typeof(dev) === 'undefined') {
|
---|
3770 | dev = mode;
|
---|
3771 | mode = 438 /* 0666 */;
|
---|
3772 | }
|
---|
3773 | mode |= 8192;
|
---|
3774 | return FS.mknod(path, mode, dev);
|
---|
3775 | },symlink:function(oldpath, newpath) {
|
---|
3776 | if (!PATH_FS.resolve(oldpath)) {
|
---|
3777 | throw new FS.ErrnoError(44);
|
---|
3778 | }
|
---|
3779 | var lookup = FS.lookupPath(newpath, { parent: true });
|
---|
3780 | var parent = lookup.node;
|
---|
3781 | if (!parent) {
|
---|
3782 | throw new FS.ErrnoError(44);
|
---|
3783 | }
|
---|
3784 | var newname = PATH.basename(newpath);
|
---|
3785 | var errCode = FS.mayCreate(parent, newname);
|
---|
3786 | if (errCode) {
|
---|
3787 | throw new FS.ErrnoError(errCode);
|
---|
3788 | }
|
---|
3789 | if (!parent.node_ops.symlink) {
|
---|
3790 | throw new FS.ErrnoError(63);
|
---|
3791 | }
|
---|
3792 | return parent.node_ops.symlink(parent, newname, oldpath);
|
---|
3793 | },rename:function(old_path, new_path) {
|
---|
3794 | var old_dirname = PATH.dirname(old_path);
|
---|
3795 | var new_dirname = PATH.dirname(new_path);
|
---|
3796 | var old_name = PATH.basename(old_path);
|
---|
3797 | var new_name = PATH.basename(new_path);
|
---|
3798 | // parents must exist
|
---|
3799 | var lookup, old_dir, new_dir;
|
---|
3800 | try {
|
---|
3801 | lookup = FS.lookupPath(old_path, { parent: true });
|
---|
3802 | old_dir = lookup.node;
|
---|
3803 | lookup = FS.lookupPath(new_path, { parent: true });
|
---|
3804 | new_dir = lookup.node;
|
---|
3805 | } catch (e) {
|
---|
3806 | throw new FS.ErrnoError(10);
|
---|
3807 | }
|
---|
3808 | if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
|
---|
3809 | // need to be part of the same mount
|
---|
3810 | if (old_dir.mount !== new_dir.mount) {
|
---|
3811 | throw new FS.ErrnoError(75);
|
---|
3812 | }
|
---|
3813 | // source must exist
|
---|
3814 | var old_node = FS.lookupNode(old_dir, old_name);
|
---|
3815 | // old path should not be an ancestor of the new path
|
---|
3816 | var relative = PATH_FS.relative(old_path, new_dirname);
|
---|
3817 | if (relative.charAt(0) !== '.') {
|
---|
3818 | throw new FS.ErrnoError(28);
|
---|
3819 | }
|
---|
3820 | // new path should not be an ancestor of the old path
|
---|
3821 | relative = PATH_FS.relative(new_path, old_dirname);
|
---|
3822 | if (relative.charAt(0) !== '.') {
|
---|
3823 | throw new FS.ErrnoError(55);
|
---|
3824 | }
|
---|
3825 | // see if the new path already exists
|
---|
3826 | var new_node;
|
---|
3827 | try {
|
---|
3828 | new_node = FS.lookupNode(new_dir, new_name);
|
---|
3829 | } catch (e) {
|
---|
3830 | // not fatal
|
---|
3831 | }
|
---|
3832 | // early out if nothing needs to change
|
---|
3833 | if (old_node === new_node) {
|
---|
3834 | return;
|
---|
3835 | }
|
---|
3836 | // we'll need to delete the old entry
|
---|
3837 | var isdir = FS.isDir(old_node.mode);
|
---|
3838 | var errCode = FS.mayDelete(old_dir, old_name, isdir);
|
---|
3839 | if (errCode) {
|
---|
3840 | throw new FS.ErrnoError(errCode);
|
---|
3841 | }
|
---|
3842 | // need delete permissions if we'll be overwriting.
|
---|
3843 | // need create permissions if new doesn't already exist.
|
---|
3844 | errCode = new_node ?
|
---|
3845 | FS.mayDelete(new_dir, new_name, isdir) :
|
---|
3846 | FS.mayCreate(new_dir, new_name);
|
---|
3847 | if (errCode) {
|
---|
3848 | throw new FS.ErrnoError(errCode);
|
---|
3849 | }
|
---|
3850 | if (!old_dir.node_ops.rename) {
|
---|
3851 | throw new FS.ErrnoError(63);
|
---|
3852 | }
|
---|
3853 | if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
|
---|
3854 | throw new FS.ErrnoError(10);
|
---|
3855 | }
|
---|
3856 | // if we are going to change the parent, check write permissions
|
---|
3857 | if (new_dir !== old_dir) {
|
---|
3858 | errCode = FS.nodePermissions(old_dir, 'w');
|
---|
3859 | if (errCode) {
|
---|
3860 | throw new FS.ErrnoError(errCode);
|
---|
3861 | }
|
---|
3862 | }
|
---|
3863 | try {
|
---|
3864 | if (FS.trackingDelegate['willMovePath']) {
|
---|
3865 | FS.trackingDelegate['willMovePath'](old_path, new_path);
|
---|
3866 | }
|
---|
3867 | } catch(e) {
|
---|
3868 | err("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
|
---|
3869 | }
|
---|
3870 | // remove the node from the lookup hash
|
---|
3871 | FS.hashRemoveNode(old_node);
|
---|
3872 | // do the underlying fs rename
|
---|
3873 | try {
|
---|
3874 | old_dir.node_ops.rename(old_node, new_dir, new_name);
|
---|
3875 | } catch (e) {
|
---|
3876 | throw e;
|
---|
3877 | } finally {
|
---|
3878 | // add the node back to the hash (in case node_ops.rename
|
---|
3879 | // changed its name)
|
---|
3880 | FS.hashAddNode(old_node);
|
---|
3881 | }
|
---|
3882 | try {
|
---|
3883 | if (FS.trackingDelegate['onMovePath']) FS.trackingDelegate['onMovePath'](old_path, new_path);
|
---|
3884 | } catch(e) {
|
---|
3885 | err("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
|
---|
3886 | }
|
---|
3887 | },rmdir:function(path) {
|
---|
3888 | var lookup = FS.lookupPath(path, { parent: true });
|
---|
3889 | var parent = lookup.node;
|
---|
3890 | var name = PATH.basename(path);
|
---|
3891 | var node = FS.lookupNode(parent, name);
|
---|
3892 | var errCode = FS.mayDelete(parent, name, true);
|
---|
3893 | if (errCode) {
|
---|
3894 | throw new FS.ErrnoError(errCode);
|
---|
3895 | }
|
---|
3896 | if (!parent.node_ops.rmdir) {
|
---|
3897 | throw new FS.ErrnoError(63);
|
---|
3898 | }
|
---|
3899 | if (FS.isMountpoint(node)) {
|
---|
3900 | throw new FS.ErrnoError(10);
|
---|
3901 | }
|
---|
3902 | try {
|
---|
3903 | if (FS.trackingDelegate['willDeletePath']) {
|
---|
3904 | FS.trackingDelegate['willDeletePath'](path);
|
---|
3905 | }
|
---|
3906 | } catch(e) {
|
---|
3907 | err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
|
---|
3908 | }
|
---|
3909 | parent.node_ops.rmdir(parent, name);
|
---|
3910 | FS.destroyNode(node);
|
---|
3911 | try {
|
---|
3912 | if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
|
---|
3913 | } catch(e) {
|
---|
3914 | err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
|
---|
3915 | }
|
---|
3916 | },readdir:function(path) {
|
---|
3917 | var lookup = FS.lookupPath(path, { follow: true });
|
---|
3918 | var node = lookup.node;
|
---|
3919 | if (!node.node_ops.readdir) {
|
---|
3920 | throw new FS.ErrnoError(54);
|
---|
3921 | }
|
---|
3922 | return node.node_ops.readdir(node);
|
---|
3923 | },unlink:function(path) {
|
---|
3924 | var lookup = FS.lookupPath(path, { parent: true });
|
---|
3925 | var parent = lookup.node;
|
---|
3926 | var name = PATH.basename(path);
|
---|
3927 | var node = FS.lookupNode(parent, name);
|
---|
3928 | var errCode = FS.mayDelete(parent, name, false);
|
---|
3929 | if (errCode) {
|
---|
3930 | // According to POSIX, we should map EISDIR to EPERM, but
|
---|
3931 | // we instead do what Linux does (and we must, as we use
|
---|
3932 | // the musl linux libc).
|
---|
3933 | throw new FS.ErrnoError(errCode);
|
---|
3934 | }
|
---|
3935 | if (!parent.node_ops.unlink) {
|
---|
3936 | throw new FS.ErrnoError(63);
|
---|
3937 | }
|
---|
3938 | if (FS.isMountpoint(node)) {
|
---|
3939 | throw new FS.ErrnoError(10);
|
---|
3940 | }
|
---|
3941 | try {
|
---|
3942 | if (FS.trackingDelegate['willDeletePath']) {
|
---|
3943 | FS.trackingDelegate['willDeletePath'](path);
|
---|
3944 | }
|
---|
3945 | } catch(e) {
|
---|
3946 | err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
|
---|
3947 | }
|
---|
3948 | parent.node_ops.unlink(parent, name);
|
---|
3949 | FS.destroyNode(node);
|
---|
3950 | try {
|
---|
3951 | if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
|
---|
3952 | } catch(e) {
|
---|
3953 | err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
|
---|
3954 | }
|
---|
3955 | },readlink:function(path) {
|
---|
3956 | var lookup = FS.lookupPath(path);
|
---|
3957 | var link = lookup.node;
|
---|
3958 | if (!link) {
|
---|
3959 | throw new FS.ErrnoError(44);
|
---|
3960 | }
|
---|
3961 | if (!link.node_ops.readlink) {
|
---|
3962 | throw new FS.ErrnoError(28);
|
---|
3963 | }
|
---|
3964 | return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
|
---|
3965 | },stat:function(path, dontFollow) {
|
---|
3966 | var lookup = FS.lookupPath(path, { follow: !dontFollow });
|
---|
3967 | var node = lookup.node;
|
---|
3968 | if (!node) {
|
---|
3969 | throw new FS.ErrnoError(44);
|
---|
3970 | }
|
---|
3971 | if (!node.node_ops.getattr) {
|
---|
3972 | throw new FS.ErrnoError(63);
|
---|
3973 | }
|
---|
3974 | return node.node_ops.getattr(node);
|
---|
3975 | },lstat:function(path) {
|
---|
3976 | return FS.stat(path, true);
|
---|
3977 | },chmod:function(path, mode, dontFollow) {
|
---|
3978 | var node;
|
---|
3979 | if (typeof path === 'string') {
|
---|
3980 | var lookup = FS.lookupPath(path, { follow: !dontFollow });
|
---|
3981 | node = lookup.node;
|
---|
3982 | } else {
|
---|
3983 | node = path;
|
---|
3984 | }
|
---|
3985 | if (!node.node_ops.setattr) {
|
---|
3986 | throw new FS.ErrnoError(63);
|
---|
3987 | }
|
---|
3988 | node.node_ops.setattr(node, {
|
---|
3989 | mode: (mode & 4095) | (node.mode & ~4095),
|
---|
3990 | timestamp: Date.now()
|
---|
3991 | });
|
---|
3992 | },lchmod:function(path, mode) {
|
---|
3993 | FS.chmod(path, mode, true);
|
---|
3994 | },fchmod:function(fd, mode) {
|
---|
3995 | var stream = FS.getStream(fd);
|
---|
3996 | if (!stream) {
|
---|
3997 | throw new FS.ErrnoError(8);
|
---|
3998 | }
|
---|
3999 | FS.chmod(stream.node, mode);
|
---|
4000 | },chown:function(path, uid, gid, dontFollow) {
|
---|
4001 | var node;
|
---|
4002 | if (typeof path === 'string') {
|
---|
4003 | var lookup = FS.lookupPath(path, { follow: !dontFollow });
|
---|
4004 | node = lookup.node;
|
---|
4005 | } else {
|
---|
4006 | node = path;
|
---|
4007 | }
|
---|
4008 | if (!node.node_ops.setattr) {
|
---|
4009 | throw new FS.ErrnoError(63);
|
---|
4010 | }
|
---|
4011 | node.node_ops.setattr(node, {
|
---|
4012 | timestamp: Date.now()
|
---|
4013 | // we ignore the uid / gid for now
|
---|
4014 | });
|
---|
4015 | },lchown:function(path, uid, gid) {
|
---|
4016 | FS.chown(path, uid, gid, true);
|
---|
4017 | },fchown:function(fd, uid, gid) {
|
---|
4018 | var stream = FS.getStream(fd);
|
---|
4019 | if (!stream) {
|
---|
4020 | throw new FS.ErrnoError(8);
|
---|
4021 | }
|
---|
4022 | FS.chown(stream.node, uid, gid);
|
---|
4023 | },truncate:function(path, len) {
|
---|
4024 | if (len < 0) {
|
---|
4025 | throw new FS.ErrnoError(28);
|
---|
4026 | }
|
---|
4027 | var node;
|
---|
4028 | if (typeof path === 'string') {
|
---|
4029 | var lookup = FS.lookupPath(path, { follow: true });
|
---|
4030 | node = lookup.node;
|
---|
4031 | } else {
|
---|
4032 | node = path;
|
---|
4033 | }
|
---|
4034 | if (!node.node_ops.setattr) {
|
---|
4035 | throw new FS.ErrnoError(63);
|
---|
4036 | }
|
---|
4037 | if (FS.isDir(node.mode)) {
|
---|
4038 | throw new FS.ErrnoError(31);
|
---|
4039 | }
|
---|
4040 | if (!FS.isFile(node.mode)) {
|
---|
4041 | throw new FS.ErrnoError(28);
|
---|
4042 | }
|
---|
4043 | var errCode = FS.nodePermissions(node, 'w');
|
---|
4044 | if (errCode) {
|
---|
4045 | throw new FS.ErrnoError(errCode);
|
---|
4046 | }
|
---|
4047 | node.node_ops.setattr(node, {
|
---|
4048 | size: len,
|
---|
4049 | timestamp: Date.now()
|
---|
4050 | });
|
---|
4051 | },ftruncate:function(fd, len) {
|
---|
4052 | var stream = FS.getStream(fd);
|
---|
4053 | if (!stream) {
|
---|
4054 | throw new FS.ErrnoError(8);
|
---|
4055 | }
|
---|
4056 | if ((stream.flags & 2097155) === 0) {
|
---|
4057 | throw new FS.ErrnoError(28);
|
---|
4058 | }
|
---|
4059 | FS.truncate(stream.node, len);
|
---|
4060 | },utime:function(path, atime, mtime) {
|
---|
4061 | var lookup = FS.lookupPath(path, { follow: true });
|
---|
4062 | var node = lookup.node;
|
---|
4063 | node.node_ops.setattr(node, {
|
---|
4064 | timestamp: Math.max(atime, mtime)
|
---|
4065 | });
|
---|
4066 | },open:function(path, flags, mode, fd_start, fd_end) {
|
---|
4067 | if (path === "") {
|
---|
4068 | throw new FS.ErrnoError(44);
|
---|
4069 | }
|
---|
4070 | flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
|
---|
4071 | mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode;
|
---|
4072 | if ((flags & 64)) {
|
---|
4073 | mode = (mode & 4095) | 32768;
|
---|
4074 | } else {
|
---|
4075 | mode = 0;
|
---|
4076 | }
|
---|
4077 | var node;
|
---|
4078 | if (typeof path === 'object') {
|
---|
4079 | node = path;
|
---|
4080 | } else {
|
---|
4081 | path = PATH.normalize(path);
|
---|
4082 | try {
|
---|
4083 | var lookup = FS.lookupPath(path, {
|
---|
4084 | follow: !(flags & 131072)
|
---|
4085 | });
|
---|
4086 | node = lookup.node;
|
---|
4087 | } catch (e) {
|
---|
4088 | // ignore
|
---|
4089 | }
|
---|
4090 | }
|
---|
4091 | // perhaps we need to create the node
|
---|
4092 | var created = false;
|
---|
4093 | if ((flags & 64)) {
|
---|
4094 | if (node) {
|
---|
4095 | // if O_CREAT and O_EXCL are set, error out if the node already exists
|
---|
4096 | if ((flags & 128)) {
|
---|
4097 | throw new FS.ErrnoError(20);
|
---|
4098 | }
|
---|
4099 | } else {
|
---|
4100 | // node doesn't exist, try to create it
|
---|
4101 | node = FS.mknod(path, mode, 0);
|
---|
4102 | created = true;
|
---|
4103 | }
|
---|
4104 | }
|
---|
4105 | if (!node) {
|
---|
4106 | throw new FS.ErrnoError(44);
|
---|
4107 | }
|
---|
4108 | // can't truncate a device
|
---|
4109 | if (FS.isChrdev(node.mode)) {
|
---|
4110 | flags &= ~512;
|
---|
4111 | }
|
---|
4112 | // if asked only for a directory, then this must be one
|
---|
4113 | if ((flags & 65536) && !FS.isDir(node.mode)) {
|
---|
4114 | throw new FS.ErrnoError(54);
|
---|
4115 | }
|
---|
4116 | // check permissions, if this is not a file we just created now (it is ok to
|
---|
4117 | // create and write to a file with read-only permissions; it is read-only
|
---|
4118 | // for later use)
|
---|
4119 | if (!created) {
|
---|
4120 | var errCode = FS.mayOpen(node, flags);
|
---|
4121 | if (errCode) {
|
---|
4122 | throw new FS.ErrnoError(errCode);
|
---|
4123 | }
|
---|
4124 | }
|
---|
4125 | // do truncation if necessary
|
---|
4126 | if ((flags & 512)) {
|
---|
4127 | FS.truncate(node, 0);
|
---|
4128 | }
|
---|
4129 | // we've already handled these, don't pass down to the underlying vfs
|
---|
4130 | flags &= ~(128 | 512 | 131072);
|
---|
4131 |
|
---|
4132 | // register the stream with the filesystem
|
---|
4133 | var stream = FS.createStream({
|
---|
4134 | node: node,
|
---|
4135 | path: FS.getPath(node), // we want the absolute path to the node
|
---|
4136 | flags: flags,
|
---|
4137 | seekable: true,
|
---|
4138 | position: 0,
|
---|
4139 | stream_ops: node.stream_ops,
|
---|
4140 | // used by the file family libc calls (fopen, fwrite, ferror, etc.)
|
---|
4141 | ungotten: [],
|
---|
4142 | error: false
|
---|
4143 | }, fd_start, fd_end);
|
---|
4144 | // call the new stream's open function
|
---|
4145 | if (stream.stream_ops.open) {
|
---|
4146 | stream.stream_ops.open(stream);
|
---|
4147 | }
|
---|
4148 | if (Module['logReadFiles'] && !(flags & 1)) {
|
---|
4149 | if (!FS.readFiles) FS.readFiles = {};
|
---|
4150 | if (!(path in FS.readFiles)) {
|
---|
4151 | FS.readFiles[path] = 1;
|
---|
4152 | err("FS.trackingDelegate error on read file: " + path);
|
---|
4153 | }
|
---|
4154 | }
|
---|
4155 | try {
|
---|
4156 | if (FS.trackingDelegate['onOpenFile']) {
|
---|
4157 | var trackingFlags = 0;
|
---|
4158 | if ((flags & 2097155) !== 1) {
|
---|
4159 | trackingFlags |= FS.tracking.openFlags.READ;
|
---|
4160 | }
|
---|
4161 | if ((flags & 2097155) !== 0) {
|
---|
4162 | trackingFlags |= FS.tracking.openFlags.WRITE;
|
---|
4163 | }
|
---|
4164 | FS.trackingDelegate['onOpenFile'](path, trackingFlags);
|
---|
4165 | }
|
---|
4166 | } catch(e) {
|
---|
4167 | err("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: " + e.message);
|
---|
4168 | }
|
---|
4169 | return stream;
|
---|
4170 | },close:function(stream) {
|
---|
4171 | if (FS.isClosed(stream)) {
|
---|
4172 | throw new FS.ErrnoError(8);
|
---|
4173 | }
|
---|
4174 | if (stream.getdents) stream.getdents = null; // free readdir state
|
---|
4175 | try {
|
---|
4176 | if (stream.stream_ops.close) {
|
---|
4177 | stream.stream_ops.close(stream);
|
---|
4178 | }
|
---|
4179 | } catch (e) {
|
---|
4180 | throw e;
|
---|
4181 | } finally {
|
---|
4182 | FS.closeStream(stream.fd);
|
---|
4183 | }
|
---|
4184 | stream.fd = null;
|
---|
4185 | },isClosed:function(stream) {
|
---|
4186 | return stream.fd === null;
|
---|
4187 | },llseek:function(stream, offset, whence) {
|
---|
4188 | if (FS.isClosed(stream)) {
|
---|
4189 | throw new FS.ErrnoError(8);
|
---|
4190 | }
|
---|
4191 | if (!stream.seekable || !stream.stream_ops.llseek) {
|
---|
4192 | throw new FS.ErrnoError(70);
|
---|
4193 | }
|
---|
4194 | if (whence != 0 && whence != 1 && whence != 2) {
|
---|
4195 | throw new FS.ErrnoError(28);
|
---|
4196 | }
|
---|
4197 | stream.position = stream.stream_ops.llseek(stream, offset, whence);
|
---|
4198 | stream.ungotten = [];
|
---|
4199 | return stream.position;
|
---|
4200 | },read:function(stream, buffer, offset, length, position) {
|
---|
4201 | if (length < 0 || position < 0) {
|
---|
4202 | throw new FS.ErrnoError(28);
|
---|
4203 | }
|
---|
4204 | if (FS.isClosed(stream)) {
|
---|
4205 | throw new FS.ErrnoError(8);
|
---|
4206 | }
|
---|
4207 | if ((stream.flags & 2097155) === 1) {
|
---|
4208 | throw new FS.ErrnoError(8);
|
---|
4209 | }
|
---|
4210 | if (FS.isDir(stream.node.mode)) {
|
---|
4211 | throw new FS.ErrnoError(31);
|
---|
4212 | }
|
---|
4213 | if (!stream.stream_ops.read) {
|
---|
4214 | throw new FS.ErrnoError(28);
|
---|
4215 | }
|
---|
4216 | var seeking = typeof position !== 'undefined';
|
---|
4217 | if (!seeking) {
|
---|
4218 | position = stream.position;
|
---|
4219 | } else if (!stream.seekable) {
|
---|
4220 | throw new FS.ErrnoError(70);
|
---|
4221 | }
|
---|
4222 | var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
|
---|
4223 | if (!seeking) stream.position += bytesRead;
|
---|
4224 | return bytesRead;
|
---|
4225 | },write:function(stream, buffer, offset, length, position, canOwn) {
|
---|
4226 | if (length < 0 || position < 0) {
|
---|
4227 | throw new FS.ErrnoError(28);
|
---|
4228 | }
|
---|
4229 | if (FS.isClosed(stream)) {
|
---|
4230 | throw new FS.ErrnoError(8);
|
---|
4231 | }
|
---|
4232 | if ((stream.flags & 2097155) === 0) {
|
---|
4233 | throw new FS.ErrnoError(8);
|
---|
4234 | }
|
---|
4235 | if (FS.isDir(stream.node.mode)) {
|
---|
4236 | throw new FS.ErrnoError(31);
|
---|
4237 | }
|
---|
4238 | if (!stream.stream_ops.write) {
|
---|
4239 | throw new FS.ErrnoError(28);
|
---|
4240 | }
|
---|
4241 | if (stream.seekable && stream.flags & 1024) {
|
---|
4242 | // seek to the end before writing in append mode
|
---|
4243 | FS.llseek(stream, 0, 2);
|
---|
4244 | }
|
---|
4245 | var seeking = typeof position !== 'undefined';
|
---|
4246 | if (!seeking) {
|
---|
4247 | position = stream.position;
|
---|
4248 | } else if (!stream.seekable) {
|
---|
4249 | throw new FS.ErrnoError(70);
|
---|
4250 | }
|
---|
4251 | var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
|
---|
4252 | if (!seeking) stream.position += bytesWritten;
|
---|
4253 | try {
|
---|
4254 | if (stream.path && FS.trackingDelegate['onWriteToFile']) FS.trackingDelegate['onWriteToFile'](stream.path);
|
---|
4255 | } catch(e) {
|
---|
4256 | err("FS.trackingDelegate['onWriteToFile']('"+stream.path+"') threw an exception: " + e.message);
|
---|
4257 | }
|
---|
4258 | return bytesWritten;
|
---|
4259 | },allocate:function(stream, offset, length) {
|
---|
4260 | if (FS.isClosed(stream)) {
|
---|
4261 | throw new FS.ErrnoError(8);
|
---|
4262 | }
|
---|
4263 | if (offset < 0 || length <= 0) {
|
---|
4264 | throw new FS.ErrnoError(28);
|
---|
4265 | }
|
---|
4266 | if ((stream.flags & 2097155) === 0) {
|
---|
4267 | throw new FS.ErrnoError(8);
|
---|
4268 | }
|
---|
4269 | if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
|
---|
4270 | throw new FS.ErrnoError(43);
|
---|
4271 | }
|
---|
4272 | if (!stream.stream_ops.allocate) {
|
---|
4273 | throw new FS.ErrnoError(138);
|
---|
4274 | }
|
---|
4275 | stream.stream_ops.allocate(stream, offset, length);
|
---|
4276 | },mmap:function(stream, address, length, position, prot, flags) {
|
---|
4277 | // User requests writing to file (prot & PROT_WRITE != 0).
|
---|
4278 | // Checking if we have permissions to write to the file unless
|
---|
4279 | // MAP_PRIVATE flag is set. According to POSIX spec it is possible
|
---|
4280 | // to write to file opened in read-only mode with MAP_PRIVATE flag,
|
---|
4281 | // as all modifications will be visible only in the memory of
|
---|
4282 | // the current process.
|
---|
4283 | if ((prot & 2) !== 0
|
---|
4284 | && (flags & 2) === 0
|
---|
4285 | && (stream.flags & 2097155) !== 2) {
|
---|
4286 | throw new FS.ErrnoError(2);
|
---|
4287 | }
|
---|
4288 | if ((stream.flags & 2097155) === 1) {
|
---|
4289 | throw new FS.ErrnoError(2);
|
---|
4290 | }
|
---|
4291 | if (!stream.stream_ops.mmap) {
|
---|
4292 | throw new FS.ErrnoError(43);
|
---|
4293 | }
|
---|
4294 | return stream.stream_ops.mmap(stream, address, length, position, prot, flags);
|
---|
4295 | },msync:function(stream, buffer, offset, length, mmapFlags) {
|
---|
4296 | if (!stream || !stream.stream_ops.msync) {
|
---|
4297 | return 0;
|
---|
4298 | }
|
---|
4299 | return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
|
---|
4300 | },munmap:function(stream) {
|
---|
4301 | return 0;
|
---|
4302 | },ioctl:function(stream, cmd, arg) {
|
---|
4303 | if (!stream.stream_ops.ioctl) {
|
---|
4304 | throw new FS.ErrnoError(59);
|
---|
4305 | }
|
---|
4306 | return stream.stream_ops.ioctl(stream, cmd, arg);
|
---|
4307 | },readFile:function(path, opts) {
|
---|
4308 | opts = opts || {};
|
---|
4309 | opts.flags = opts.flags || 'r';
|
---|
4310 | opts.encoding = opts.encoding || 'binary';
|
---|
4311 | if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
|
---|
4312 | throw new Error('Invalid encoding type "' + opts.encoding + '"');
|
---|
4313 | }
|
---|
4314 | var ret;
|
---|
4315 | var stream = FS.open(path, opts.flags);
|
---|
4316 | var stat = FS.stat(path);
|
---|
4317 | var length = stat.size;
|
---|
4318 | var buf = new Uint8Array(length);
|
---|
4319 | FS.read(stream, buf, 0, length, 0);
|
---|
4320 | if (opts.encoding === 'utf8') {
|
---|
4321 | ret = UTF8ArrayToString(buf, 0);
|
---|
4322 | } else if (opts.encoding === 'binary') {
|
---|
4323 | ret = buf;
|
---|
4324 | }
|
---|
4325 | FS.close(stream);
|
---|
4326 | return ret;
|
---|
4327 | },writeFile:function(path, data, opts) {
|
---|
4328 | opts = opts || {};
|
---|
4329 | opts.flags = opts.flags || 'w';
|
---|
4330 | var stream = FS.open(path, opts.flags, opts.mode);
|
---|
4331 | if (typeof data === 'string') {
|
---|
4332 | var buf = new Uint8Array(lengthBytesUTF8(data)+1);
|
---|
4333 | var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
|
---|
4334 | FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
|
---|
4335 | } else if (ArrayBuffer.isView(data)) {
|
---|
4336 | FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
|
---|
4337 | } else {
|
---|
4338 | throw new Error('Unsupported data type');
|
---|
4339 | }
|
---|
4340 | FS.close(stream);
|
---|
4341 | },cwd:function() {
|
---|
4342 | return FS.currentPath;
|
---|
4343 | },chdir:function(path) {
|
---|
4344 | var lookup = FS.lookupPath(path, { follow: true });
|
---|
4345 | if (lookup.node === null) {
|
---|
4346 | throw new FS.ErrnoError(44);
|
---|
4347 | }
|
---|
4348 | if (!FS.isDir(lookup.node.mode)) {
|
---|
4349 | throw new FS.ErrnoError(54);
|
---|
4350 | }
|
---|
4351 | var errCode = FS.nodePermissions(lookup.node, 'x');
|
---|
4352 | if (errCode) {
|
---|
4353 | throw new FS.ErrnoError(errCode);
|
---|
4354 | }
|
---|
4355 | FS.currentPath = lookup.path;
|
---|
4356 | },createDefaultDirectories:function() {
|
---|
4357 | FS.mkdir('/tmp');
|
---|
4358 | FS.mkdir('/home');
|
---|
4359 | FS.mkdir('/home/web_user');
|
---|
4360 | },createDefaultDevices:function() {
|
---|
4361 | // create /dev
|
---|
4362 | FS.mkdir('/dev');
|
---|
4363 | // setup /dev/null
|
---|
4364 | FS.registerDevice(FS.makedev(1, 3), {
|
---|
4365 | read: function() { return 0; },
|
---|
4366 | write: function(stream, buffer, offset, length, pos) { return length; }
|
---|
4367 | });
|
---|
4368 | FS.mkdev('/dev/null', FS.makedev(1, 3));
|
---|
4369 | // setup /dev/tty and /dev/tty1
|
---|
4370 | // stderr needs to print output using Module['printErr']
|
---|
4371 | // so we register a second tty just for it.
|
---|
4372 | TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
|
---|
4373 | TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
|
---|
4374 | FS.mkdev('/dev/tty', FS.makedev(5, 0));
|
---|
4375 | FS.mkdev('/dev/tty1', FS.makedev(6, 0));
|
---|
4376 | // setup /dev/[u]random
|
---|
4377 | var random_device;
|
---|
4378 | if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') {
|
---|
4379 | // for modern web browsers
|
---|
4380 | var randomBuffer = new Uint8Array(1);
|
---|
4381 | random_device = function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; };
|
---|
4382 | } else
|
---|
4383 | if (ENVIRONMENT_IS_NODE) {
|
---|
4384 | // for nodejs with or without crypto support included
|
---|
4385 | try {
|
---|
4386 | var crypto_module = require('crypto');
|
---|
4387 | // nodejs has crypto support
|
---|
4388 | random_device = function() { return crypto_module['randomBytes'](1)[0]; };
|
---|
4389 | } catch (e) {
|
---|
4390 | // nodejs doesn't have crypto support
|
---|
4391 | }
|
---|
4392 | } else
|
---|
4393 | {}
|
---|
4394 | if (!random_device) {
|
---|
4395 | // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096
|
---|
4396 | random_device = function() { abort("no cryptographic support found for random_device. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };"); };
|
---|
4397 | }
|
---|
4398 | FS.createDevice('/dev', 'random', random_device);
|
---|
4399 | FS.createDevice('/dev', 'urandom', random_device);
|
---|
4400 | // we're not going to emulate the actual shm device,
|
---|
4401 | // just create the tmp dirs that reside in it commonly
|
---|
4402 | FS.mkdir('/dev/shm');
|
---|
4403 | FS.mkdir('/dev/shm/tmp');
|
---|
4404 | },createSpecialDirectories:function() {
|
---|
4405 | // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the name of the stream for fd 6 (see test_unistd_ttyname)
|
---|
4406 | FS.mkdir('/proc');
|
---|
4407 | FS.mkdir('/proc/self');
|
---|
4408 | FS.mkdir('/proc/self/fd');
|
---|
4409 | FS.mount({
|
---|
4410 | mount: function() {
|
---|
4411 | var node = FS.createNode('/proc/self', 'fd', 16384 | 511 /* 0777 */, 73);
|
---|
4412 | node.node_ops = {
|
---|
4413 | lookup: function(parent, name) {
|
---|
4414 | var fd = +name;
|
---|
4415 | var stream = FS.getStream(fd);
|
---|
4416 | if (!stream) throw new FS.ErrnoError(8);
|
---|
4417 | var ret = {
|
---|
4418 | parent: null,
|
---|
4419 | mount: { mountpoint: 'fake' },
|
---|
4420 | node_ops: { readlink: function() { return stream.path } }
|
---|
4421 | };
|
---|
4422 | ret.parent = ret; // make it look like a simple root node
|
---|
4423 | return ret;
|
---|
4424 | }
|
---|
4425 | };
|
---|
4426 | return node;
|
---|
4427 | }
|
---|
4428 | }, {}, '/proc/self/fd');
|
---|
4429 | },createStandardStreams:function() {
|
---|
4430 | // TODO deprecate the old functionality of a single
|
---|
4431 | // input / output callback and that utilizes FS.createDevice
|
---|
4432 | // and instead require a unique set of stream ops
|
---|
4433 |
|
---|
4434 | // by default, we symlink the standard streams to the
|
---|
4435 | // default tty devices. however, if the standard streams
|
---|
4436 | // have been overwritten we create a unique device for
|
---|
4437 | // them instead.
|
---|
4438 | if (Module['stdin']) {
|
---|
4439 | FS.createDevice('/dev', 'stdin', Module['stdin']);
|
---|
4440 | } else {
|
---|
4441 | FS.symlink('/dev/tty', '/dev/stdin');
|
---|
4442 | }
|
---|
4443 | if (Module['stdout']) {
|
---|
4444 | FS.createDevice('/dev', 'stdout', null, Module['stdout']);
|
---|
4445 | } else {
|
---|
4446 | FS.symlink('/dev/tty', '/dev/stdout');
|
---|
4447 | }
|
---|
4448 | if (Module['stderr']) {
|
---|
4449 | FS.createDevice('/dev', 'stderr', null, Module['stderr']);
|
---|
4450 | } else {
|
---|
4451 | FS.symlink('/dev/tty1', '/dev/stderr');
|
---|
4452 | }
|
---|
4453 |
|
---|
4454 | // open default streams for the stdin, stdout and stderr devices
|
---|
4455 | var stdin = FS.open('/dev/stdin', 'r');
|
---|
4456 | var stdout = FS.open('/dev/stdout', 'w');
|
---|
4457 | var stderr = FS.open('/dev/stderr', 'w');
|
---|
4458 | assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')');
|
---|
4459 | assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')');
|
---|
4460 | assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')');
|
---|
4461 | },ensureErrnoError:function() {
|
---|
4462 | if (FS.ErrnoError) return;
|
---|
4463 | FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) {
|
---|
4464 | this.node = node;
|
---|
4465 | this.setErrno = /** @this{Object} */ function(errno) {
|
---|
4466 | this.errno = errno;
|
---|
4467 | for (var key in ERRNO_CODES) {
|
---|
4468 | if (ERRNO_CODES[key] === errno) {
|
---|
4469 | this.code = key;
|
---|
4470 | break;
|
---|
4471 | }
|
---|
4472 | }
|
---|
4473 | };
|
---|
4474 | this.setErrno(errno);
|
---|
4475 | this.message = ERRNO_MESSAGES[errno];
|
---|
4476 |
|
---|
4477 | // Try to get a maximally helpful stack trace. On Node.js, getting Error.stack
|
---|
4478 | // now ensures it shows what we want.
|
---|
4479 | if (this.stack) {
|
---|
4480 | // Define the stack property for Node.js 4, which otherwise errors on the next line.
|
---|
4481 | Object.defineProperty(this, "stack", { value: (new Error).stack, writable: true });
|
---|
4482 | this.stack = demangleAll(this.stack);
|
---|
4483 | }
|
---|
4484 | };
|
---|
4485 | FS.ErrnoError.prototype = new Error();
|
---|
4486 | FS.ErrnoError.prototype.constructor = FS.ErrnoError;
|
---|
4487 | // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info)
|
---|
4488 | [44].forEach(function(code) {
|
---|
4489 | FS.genericErrors[code] = new FS.ErrnoError(code);
|
---|
4490 | FS.genericErrors[code].stack = '<generic error, no stack>';
|
---|
4491 | });
|
---|
4492 | },staticInit:function() {
|
---|
4493 | FS.ensureErrnoError();
|
---|
4494 |
|
---|
4495 | FS.nameTable = new Array(4096);
|
---|
4496 |
|
---|
4497 | FS.mount(MEMFS, {}, '/');
|
---|
4498 |
|
---|
4499 | FS.createDefaultDirectories();
|
---|
4500 | FS.createDefaultDevices();
|
---|
4501 | FS.createSpecialDirectories();
|
---|
4502 |
|
---|
4503 | FS.filesystems = {
|
---|
4504 | 'MEMFS': MEMFS,
|
---|
4505 | };
|
---|
4506 | },init:function(input, output, error) {
|
---|
4507 | assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
|
---|
4508 | FS.init.initialized = true;
|
---|
4509 |
|
---|
4510 | FS.ensureErrnoError();
|
---|
4511 |
|
---|
4512 | // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
|
---|
4513 | Module['stdin'] = input || Module['stdin'];
|
---|
4514 | Module['stdout'] = output || Module['stdout'];
|
---|
4515 | Module['stderr'] = error || Module['stderr'];
|
---|
4516 |
|
---|
4517 | FS.createStandardStreams();
|
---|
4518 | },quit:function() {
|
---|
4519 | FS.init.initialized = false;
|
---|
4520 | // force-flush all streams, so we get musl std streams printed out
|
---|
4521 | var fflush = Module['_fflush'];
|
---|
4522 | if (fflush) fflush(0);
|
---|
4523 | // close all of our streams
|
---|
4524 | for (var i = 0; i < FS.streams.length; i++) {
|
---|
4525 | var stream = FS.streams[i];
|
---|
4526 | if (!stream) {
|
---|
4527 | continue;
|
---|
4528 | }
|
---|
4529 | FS.close(stream);
|
---|
4530 | }
|
---|
4531 | },getMode:function(canRead, canWrite) {
|
---|
4532 | var mode = 0;
|
---|
4533 | if (canRead) mode |= 292 | 73;
|
---|
4534 | if (canWrite) mode |= 146;
|
---|
4535 | return mode;
|
---|
4536 | },joinPath:function(parts, forceRelative) {
|
---|
4537 | var path = PATH.join.apply(null, parts);
|
---|
4538 | if (forceRelative && path[0] == '/') path = path.substr(1);
|
---|
4539 | return path;
|
---|
4540 | },absolutePath:function(relative, base) {
|
---|
4541 | return PATH_FS.resolve(base, relative);
|
---|
4542 | },standardizePath:function(path) {
|
---|
4543 | return PATH.normalize(path);
|
---|
4544 | },findObject:function(path, dontResolveLastLink) {
|
---|
4545 | var ret = FS.analyzePath(path, dontResolveLastLink);
|
---|
4546 | if (ret.exists) {
|
---|
4547 | return ret.object;
|
---|
4548 | } else {
|
---|
4549 | setErrNo(ret.error);
|
---|
4550 | return null;
|
---|
4551 | }
|
---|
4552 | },analyzePath:function(path, dontResolveLastLink) {
|
---|
4553 | // operate from within the context of the symlink's target
|
---|
4554 | try {
|
---|
4555 | var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
|
---|
4556 | path = lookup.path;
|
---|
4557 | } catch (e) {
|
---|
4558 | }
|
---|
4559 | var ret = {
|
---|
4560 | isRoot: false, exists: false, error: 0, name: null, path: null, object: null,
|
---|
4561 | parentExists: false, parentPath: null, parentObject: null
|
---|
4562 | };
|
---|
4563 | try {
|
---|
4564 | var lookup = FS.lookupPath(path, { parent: true });
|
---|
4565 | ret.parentExists = true;
|
---|
4566 | ret.parentPath = lookup.path;
|
---|
4567 | ret.parentObject = lookup.node;
|
---|
4568 | ret.name = PATH.basename(path);
|
---|
4569 | lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
|
---|
4570 | ret.exists = true;
|
---|
4571 | ret.path = lookup.path;
|
---|
4572 | ret.object = lookup.node;
|
---|
4573 | ret.name = lookup.node.name;
|
---|
4574 | ret.isRoot = lookup.path === '/';
|
---|
4575 | } catch (e) {
|
---|
4576 | ret.error = e.errno;
|
---|
4577 | };
|
---|
4578 | return ret;
|
---|
4579 | },createFolder:function(parent, name, canRead, canWrite) {
|
---|
4580 | var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
|
---|
4581 | var mode = FS.getMode(canRead, canWrite);
|
---|
4582 | return FS.mkdir(path, mode);
|
---|
4583 | },createPath:function(parent, path, canRead, canWrite) {
|
---|
4584 | parent = typeof parent === 'string' ? parent : FS.getPath(parent);
|
---|
4585 | var parts = path.split('/').reverse();
|
---|
4586 | while (parts.length) {
|
---|
4587 | var part = parts.pop();
|
---|
4588 | if (!part) continue;
|
---|
4589 | var current = PATH.join2(parent, part);
|
---|
4590 | try {
|
---|
4591 | FS.mkdir(current);
|
---|
4592 | } catch (e) {
|
---|
4593 | // ignore EEXIST
|
---|
4594 | }
|
---|
4595 | parent = current;
|
---|
4596 | }
|
---|
4597 | return current;
|
---|
4598 | },createFile:function(parent, name, properties, canRead, canWrite) {
|
---|
4599 | var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
|
---|
4600 | var mode = FS.getMode(canRead, canWrite);
|
---|
4601 | return FS.create(path, mode);
|
---|
4602 | },createDataFile:function(parent, name, data, canRead, canWrite, canOwn) {
|
---|
4603 | var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
|
---|
4604 | var mode = FS.getMode(canRead, canWrite);
|
---|
4605 | var node = FS.create(path, mode);
|
---|
4606 | if (data) {
|
---|
4607 | if (typeof data === 'string') {
|
---|
4608 | var arr = new Array(data.length);
|
---|
4609 | for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
|
---|
4610 | data = arr;
|
---|
4611 | }
|
---|
4612 | // make sure we can write to the file
|
---|
4613 | FS.chmod(node, mode | 146);
|
---|
4614 | var stream = FS.open(node, 'w');
|
---|
4615 | FS.write(stream, data, 0, data.length, 0, canOwn);
|
---|
4616 | FS.close(stream);
|
---|
4617 | FS.chmod(node, mode);
|
---|
4618 | }
|
---|
4619 | return node;
|
---|
4620 | },createDevice:function(parent, name, input, output) {
|
---|
4621 | var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
|
---|
4622 | var mode = FS.getMode(!!input, !!output);
|
---|
4623 | if (!FS.createDevice.major) FS.createDevice.major = 64;
|
---|
4624 | var dev = FS.makedev(FS.createDevice.major++, 0);
|
---|
4625 | // Create a fake device that a set of stream ops to emulate
|
---|
4626 | // the old behavior.
|
---|
4627 | FS.registerDevice(dev, {
|
---|
4628 | open: function(stream) {
|
---|
4629 | stream.seekable = false;
|
---|
4630 | },
|
---|
4631 | close: function(stream) {
|
---|
4632 | // flush any pending line data
|
---|
4633 | if (output && output.buffer && output.buffer.length) {
|
---|
4634 | output(10);
|
---|
4635 | }
|
---|
4636 | },
|
---|
4637 | read: function(stream, buffer, offset, length, pos /* ignored */) {
|
---|
4638 | var bytesRead = 0;
|
---|
4639 | for (var i = 0; i < length; i++) {
|
---|
4640 | var result;
|
---|
4641 | try {
|
---|
4642 | result = input();
|
---|
4643 | } catch (e) {
|
---|
4644 | throw new FS.ErrnoError(29);
|
---|
4645 | }
|
---|
4646 | if (result === undefined && bytesRead === 0) {
|
---|
4647 | throw new FS.ErrnoError(6);
|
---|
4648 | }
|
---|
4649 | if (result === null || result === undefined) break;
|
---|
4650 | bytesRead++;
|
---|
4651 | buffer[offset+i] = result;
|
---|
4652 | }
|
---|
4653 | if (bytesRead) {
|
---|
4654 | stream.node.timestamp = Date.now();
|
---|
4655 | }
|
---|
4656 | return bytesRead;
|
---|
4657 | },
|
---|
4658 | write: function(stream, buffer, offset, length, pos) {
|
---|
4659 | for (var i = 0; i < length; i++) {
|
---|
4660 | try {
|
---|
4661 | output(buffer[offset+i]);
|
---|
4662 | } catch (e) {
|
---|
4663 | throw new FS.ErrnoError(29);
|
---|
4664 | }
|
---|
4665 | }
|
---|
4666 | if (length) {
|
---|
4667 | stream.node.timestamp = Date.now();
|
---|
4668 | }
|
---|
4669 | return i;
|
---|
4670 | }
|
---|
4671 | });
|
---|
4672 | return FS.mkdev(path, mode, dev);
|
---|
4673 | },createLink:function(parent, name, target, canRead, canWrite) {
|
---|
4674 | var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
|
---|
4675 | return FS.symlink(target, path);
|
---|
4676 | },forceLoadFile:function(obj) {
|
---|
4677 | if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
|
---|
4678 | var success = true;
|
---|
4679 | if (typeof XMLHttpRequest !== 'undefined') {
|
---|
4680 | throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
|
---|
4681 | } else if (read_) {
|
---|
4682 | // Command-line.
|
---|
4683 | try {
|
---|
4684 | // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
|
---|
4685 | // read() will try to parse UTF8.
|
---|
4686 | obj.contents = intArrayFromString(read_(obj.url), true);
|
---|
4687 | obj.usedBytes = obj.contents.length;
|
---|
4688 | } catch (e) {
|
---|
4689 | success = false;
|
---|
4690 | }
|
---|
4691 | } else {
|
---|
4692 | throw new Error('Cannot load without read() or XMLHttpRequest.');
|
---|
4693 | }
|
---|
4694 | if (!success) setErrNo(29);
|
---|
4695 | return success;
|
---|
4696 | },createLazyFile:function(parent, name, url, canRead, canWrite) {
|
---|
4697 | // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
|
---|
4698 | /** @constructor */
|
---|
4699 | function LazyUint8Array() {
|
---|
4700 | this.lengthKnown = false;
|
---|
4701 | this.chunks = []; // Loaded chunks. Index is the chunk number
|
---|
4702 | }
|
---|
4703 | LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) {
|
---|
4704 | if (idx > this.length-1 || idx < 0) {
|
---|
4705 | return undefined;
|
---|
4706 | }
|
---|
4707 | var chunkOffset = idx % this.chunkSize;
|
---|
4708 | var chunkNum = (idx / this.chunkSize)|0;
|
---|
4709 | return this.getter(chunkNum)[chunkOffset];
|
---|
4710 | };
|
---|
4711 | LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
|
---|
4712 | this.getter = getter;
|
---|
4713 | };
|
---|
4714 | LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
|
---|
4715 | // Find length
|
---|
4716 | var xhr = new XMLHttpRequest();
|
---|
4717 | xhr.open('HEAD', url, false);
|
---|
4718 | xhr.send(null);
|
---|
4719 | if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
|
---|
4720 | var datalength = Number(xhr.getResponseHeader("Content-length"));
|
---|
4721 | var header;
|
---|
4722 | var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
|
---|
4723 | var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
|
---|
4724 |
|
---|
4725 | var chunkSize = 1024*1024; // Chunk size in bytes
|
---|
4726 |
|
---|
4727 | if (!hasByteServing) chunkSize = datalength;
|
---|
4728 |
|
---|
4729 | // Function to get a range from the remote URL.
|
---|
4730 | var doXHR = (function(from, to) {
|
---|
4731 | if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
|
---|
4732 | if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
|
---|
4733 |
|
---|
4734 | // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
|
---|
4735 | var xhr = new XMLHttpRequest();
|
---|
4736 | xhr.open('GET', url, false);
|
---|
4737 | if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
|
---|
4738 |
|
---|
4739 | // Some hints to the browser that we want binary data.
|
---|
4740 | if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
|
---|
4741 | if (xhr.overrideMimeType) {
|
---|
4742 | xhr.overrideMimeType('text/plain; charset=x-user-defined');
|
---|
4743 | }
|
---|
4744 |
|
---|
4745 | xhr.send(null);
|
---|
4746 | if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
|
---|
4747 | if (xhr.response !== undefined) {
|
---|
4748 | return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
|
---|
4749 | } else {
|
---|
4750 | return intArrayFromString(xhr.responseText || '', true);
|
---|
4751 | }
|
---|
4752 | });
|
---|
4753 | var lazyArray = this;
|
---|
4754 | lazyArray.setDataGetter(function(chunkNum) {
|
---|
4755 | var start = chunkNum * chunkSize;
|
---|
4756 | var end = (chunkNum+1) * chunkSize - 1; // including this byte
|
---|
4757 | end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
|
---|
4758 | if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
|
---|
4759 | lazyArray.chunks[chunkNum] = doXHR(start, end);
|
---|
4760 | }
|
---|
4761 | if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
|
---|
4762 | return lazyArray.chunks[chunkNum];
|
---|
4763 | });
|
---|
4764 |
|
---|
4765 | if (usesGzip || !datalength) {
|
---|
4766 | // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
|
---|
4767 | chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
|
---|
4768 | datalength = this.getter(0).length;
|
---|
4769 | chunkSize = datalength;
|
---|
4770 | out("LazyFiles on gzip forces download of the whole file when length is accessed");
|
---|
4771 | }
|
---|
4772 |
|
---|
4773 | this._length = datalength;
|
---|
4774 | this._chunkSize = chunkSize;
|
---|
4775 | this.lengthKnown = true;
|
---|
4776 | };
|
---|
4777 | if (typeof XMLHttpRequest !== 'undefined') {
|
---|
4778 | if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
|
---|
4779 | var lazyArray = new LazyUint8Array();
|
---|
4780 | Object.defineProperties(lazyArray, {
|
---|
4781 | length: {
|
---|
4782 | get: /** @this{Object} */ function() {
|
---|
4783 | if(!this.lengthKnown) {
|
---|
4784 | this.cacheLength();
|
---|
4785 | }
|
---|
4786 | return this._length;
|
---|
4787 | }
|
---|
4788 | },
|
---|
4789 | chunkSize: {
|
---|
4790 | get: /** @this{Object} */ function() {
|
---|
4791 | if(!this.lengthKnown) {
|
---|
4792 | this.cacheLength();
|
---|
4793 | }
|
---|
4794 | return this._chunkSize;
|
---|
4795 | }
|
---|
4796 | }
|
---|
4797 | });
|
---|
4798 |
|
---|
4799 | var properties = { isDevice: false, contents: lazyArray };
|
---|
4800 | } else {
|
---|
4801 | var properties = { isDevice: false, url: url };
|
---|
4802 | }
|
---|
4803 |
|
---|
4804 | var node = FS.createFile(parent, name, properties, canRead, canWrite);
|
---|
4805 | // This is a total hack, but I want to get this lazy file code out of the
|
---|
4806 | // core of MEMFS. If we want to keep this lazy file concept I feel it should
|
---|
4807 | // be its own thin LAZYFS proxying calls to MEMFS.
|
---|
4808 | if (properties.contents) {
|
---|
4809 | node.contents = properties.contents;
|
---|
4810 | } else if (properties.url) {
|
---|
4811 | node.contents = null;
|
---|
4812 | node.url = properties.url;
|
---|
4813 | }
|
---|
4814 | // Add a function that defers querying the file size until it is asked the first time.
|
---|
4815 | Object.defineProperties(node, {
|
---|
4816 | usedBytes: {
|
---|
4817 | get: /** @this {FSNode} */ function() { return this.contents.length; }
|
---|
4818 | }
|
---|
4819 | });
|
---|
4820 | // override each stream op with one that tries to force load the lazy file first
|
---|
4821 | var stream_ops = {};
|
---|
4822 | var keys = Object.keys(node.stream_ops);
|
---|
4823 | keys.forEach(function(key) {
|
---|
4824 | var fn = node.stream_ops[key];
|
---|
4825 | stream_ops[key] = function forceLoadLazyFile() {
|
---|
4826 | if (!FS.forceLoadFile(node)) {
|
---|
4827 | throw new FS.ErrnoError(29);
|
---|
4828 | }
|
---|
4829 | return fn.apply(null, arguments);
|
---|
4830 | };
|
---|
4831 | });
|
---|
4832 | // use a custom read function
|
---|
4833 | stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
|
---|
4834 | if (!FS.forceLoadFile(node)) {
|
---|
4835 | throw new FS.ErrnoError(29);
|
---|
4836 | }
|
---|
4837 | var contents = stream.node.contents;
|
---|
4838 | if (position >= contents.length)
|
---|
4839 | return 0;
|
---|
4840 | var size = Math.min(contents.length - position, length);
|
---|
4841 | assert(size >= 0);
|
---|
4842 | if (contents.slice) { // normal array
|
---|
4843 | for (var i = 0; i < size; i++) {
|
---|
4844 | buffer[offset + i] = contents[position + i];
|
---|
4845 | }
|
---|
4846 | } else {
|
---|
4847 | for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
|
---|
4848 | buffer[offset + i] = contents.get(position + i);
|
---|
4849 | }
|
---|
4850 | }
|
---|
4851 | return size;
|
---|
4852 | };
|
---|
4853 | node.stream_ops = stream_ops;
|
---|
4854 | return node;
|
---|
4855 | },createPreloadedFile:function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
|
---|
4856 | Browser.init(); // XXX perhaps this method should move onto Browser?
|
---|
4857 | // TODO we should allow people to just pass in a complete filename instead
|
---|
4858 | // of parent and name being that we just join them anyways
|
---|
4859 | var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
|
---|
4860 | var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname
|
---|
4861 | function processData(byteArray) {
|
---|
4862 | function finish(byteArray) {
|
---|
4863 | if (preFinish) preFinish();
|
---|
4864 | if (!dontCreateFile) {
|
---|
4865 | FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
|
---|
4866 | }
|
---|
4867 | if (onload) onload();
|
---|
4868 | removeRunDependency(dep);
|
---|
4869 | }
|
---|
4870 | var handled = false;
|
---|
4871 | Module['preloadPlugins'].forEach(function(plugin) {
|
---|
4872 | if (handled) return;
|
---|
4873 | if (plugin['canHandle'](fullname)) {
|
---|
4874 | plugin['handle'](byteArray, fullname, finish, function() {
|
---|
4875 | if (onerror) onerror();
|
---|
4876 | removeRunDependency(dep);
|
---|
4877 | });
|
---|
4878 | handled = true;
|
---|
4879 | }
|
---|
4880 | });
|
---|
4881 | if (!handled) finish(byteArray);
|
---|
4882 | }
|
---|
4883 | addRunDependency(dep);
|
---|
4884 | if (typeof url == 'string') {
|
---|
4885 | Browser.asyncLoad(url, function(byteArray) {
|
---|
4886 | processData(byteArray);
|
---|
4887 | }, onerror);
|
---|
4888 | } else {
|
---|
4889 | processData(url);
|
---|
4890 | }
|
---|
4891 | },indexedDB:function() {
|
---|
4892 | return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
---|
4893 | },DB_NAME:function() {
|
---|
4894 | return 'EM_FS_' + window.location.pathname;
|
---|
4895 | },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(paths, onload, onerror) {
|
---|
4896 | onload = onload || function(){};
|
---|
4897 | onerror = onerror || function(){};
|
---|
4898 | var indexedDB = FS.indexedDB();
|
---|
4899 | try {
|
---|
4900 | var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
|
---|
4901 | } catch (e) {
|
---|
4902 | return onerror(e);
|
---|
4903 | }
|
---|
4904 | openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
|
---|
4905 | out('creating db');
|
---|
4906 | var db = openRequest.result;
|
---|
4907 | db.createObjectStore(FS.DB_STORE_NAME);
|
---|
4908 | };
|
---|
4909 | openRequest.onsuccess = function openRequest_onsuccess() {
|
---|
4910 | var db = openRequest.result;
|
---|
4911 | var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
|
---|
4912 | var files = transaction.objectStore(FS.DB_STORE_NAME);
|
---|
4913 | var ok = 0, fail = 0, total = paths.length;
|
---|
4914 | function finish() {
|
---|
4915 | if (fail == 0) onload(); else onerror();
|
---|
4916 | }
|
---|
4917 | paths.forEach(function(path) {
|
---|
4918 | var putRequest = files.put(FS.analyzePath(path).object.contents, path);
|
---|
4919 | putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() };
|
---|
4920 | putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() };
|
---|
4921 | });
|
---|
4922 | transaction.onerror = onerror;
|
---|
4923 | };
|
---|
4924 | openRequest.onerror = onerror;
|
---|
4925 | },loadFilesFromDB:function(paths, onload, onerror) {
|
---|
4926 | onload = onload || function(){};
|
---|
4927 | onerror = onerror || function(){};
|
---|
4928 | var indexedDB = FS.indexedDB();
|
---|
4929 | try {
|
---|
4930 | var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
|
---|
4931 | } catch (e) {
|
---|
4932 | return onerror(e);
|
---|
4933 | }
|
---|
4934 | openRequest.onupgradeneeded = onerror; // no database to load from
|
---|
4935 | openRequest.onsuccess = function openRequest_onsuccess() {
|
---|
4936 | var db = openRequest.result;
|
---|
4937 | try {
|
---|
4938 | var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
|
---|
4939 | } catch(e) {
|
---|
4940 | onerror(e);
|
---|
4941 | return;
|
---|
4942 | }
|
---|
4943 | var files = transaction.objectStore(FS.DB_STORE_NAME);
|
---|
4944 | var ok = 0, fail = 0, total = paths.length;
|
---|
4945 | function finish() {
|
---|
4946 | if (fail == 0) onload(); else onerror();
|
---|
4947 | }
|
---|
4948 | paths.forEach(function(path) {
|
---|
4949 | var getRequest = files.get(path);
|
---|
4950 | getRequest.onsuccess = function getRequest_onsuccess() {
|
---|
4951 | if (FS.analyzePath(path).exists) {
|
---|
4952 | FS.unlink(path);
|
---|
4953 | }
|
---|
4954 | FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
|
---|
4955 | ok++;
|
---|
4956 | if (ok + fail == total) finish();
|
---|
4957 | };
|
---|
4958 | getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() };
|
---|
4959 | });
|
---|
4960 | transaction.onerror = onerror;
|
---|
4961 | };
|
---|
4962 | openRequest.onerror = onerror;
|
---|
4963 | }};var SYSCALLS={mappings:{},DEFAULT_POLLMASK:5,umask:511,calculateAt:function(dirfd, path) {
|
---|
4964 | if (path[0] !== '/') {
|
---|
4965 | // relative path
|
---|
4966 | var dir;
|
---|
4967 | if (dirfd === -100) {
|
---|
4968 | dir = FS.cwd();
|
---|
4969 | } else {
|
---|
4970 | var dirstream = FS.getStream(dirfd);
|
---|
4971 | if (!dirstream) throw new FS.ErrnoError(8);
|
---|
4972 | dir = dirstream.path;
|
---|
4973 | }
|
---|
4974 | path = PATH.join2(dir, path);
|
---|
4975 | }
|
---|
4976 | return path;
|
---|
4977 | },doStat:function(func, path, buf) {
|
---|
4978 | try {
|
---|
4979 | var stat = func(path);
|
---|
4980 | } catch (e) {
|
---|
4981 | if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
|
---|
4982 | // an error occurred while trying to look up the path; we should just report ENOTDIR
|
---|
4983 | return -54;
|
---|
4984 | }
|
---|
4985 | throw e;
|
---|
4986 | }
|
---|
4987 | HEAP32[((buf)>>2)]=stat.dev;
|
---|
4988 | HEAP32[(((buf)+(4))>>2)]=0;
|
---|
4989 | HEAP32[(((buf)+(8))>>2)]=stat.ino;
|
---|
4990 | HEAP32[(((buf)+(12))>>2)]=stat.mode;
|
---|
4991 | HEAP32[(((buf)+(16))>>2)]=stat.nlink;
|
---|
4992 | HEAP32[(((buf)+(20))>>2)]=stat.uid;
|
---|
4993 | HEAP32[(((buf)+(24))>>2)]=stat.gid;
|
---|
4994 | HEAP32[(((buf)+(28))>>2)]=stat.rdev;
|
---|
4995 | HEAP32[(((buf)+(32))>>2)]=0;
|
---|
4996 | (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(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[(((buf)+(40))>>2)]=tempI64[0],HEAP32[(((buf)+(44))>>2)]=tempI64[1]);
|
---|
4997 | HEAP32[(((buf)+(48))>>2)]=4096;
|
---|
4998 | HEAP32[(((buf)+(52))>>2)]=stat.blocks;
|
---|
4999 | HEAP32[(((buf)+(56))>>2)]=(stat.atime.getTime() / 1000)|0;
|
---|
5000 | HEAP32[(((buf)+(60))>>2)]=0;
|
---|
5001 | HEAP32[(((buf)+(64))>>2)]=(stat.mtime.getTime() / 1000)|0;
|
---|
5002 | HEAP32[(((buf)+(68))>>2)]=0;
|
---|
5003 | HEAP32[(((buf)+(72))>>2)]=(stat.ctime.getTime() / 1000)|0;
|
---|
5004 | HEAP32[(((buf)+(76))>>2)]=0;
|
---|
5005 | (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(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[(((buf)+(80))>>2)]=tempI64[0],HEAP32[(((buf)+(84))>>2)]=tempI64[1]);
|
---|
5006 | return 0;
|
---|
5007 | },doMsync:function(addr, stream, len, flags, offset) {
|
---|
5008 | var buffer = HEAPU8.slice(addr, addr + len);
|
---|
5009 | FS.msync(stream, buffer, offset, len, flags);
|
---|
5010 | },doMkdir:function(path, mode) {
|
---|
5011 | // remove a trailing slash, if one - /a/b/ has basename of '', but
|
---|
5012 | // we want to create b in the context of this function
|
---|
5013 | path = PATH.normalize(path);
|
---|
5014 | if (path[path.length-1] === '/') path = path.substr(0, path.length-1);
|
---|
5015 | FS.mkdir(path, mode, 0);
|
---|
5016 | return 0;
|
---|
5017 | },doMknod:function(path, mode, dev) {
|
---|
5018 | // we don't want this in the JS API as it uses mknod to create all nodes.
|
---|
5019 | switch (mode & 61440) {
|
---|
5020 | case 32768:
|
---|
5021 | case 8192:
|
---|
5022 | case 24576:
|
---|
5023 | case 4096:
|
---|
5024 | case 49152:
|
---|
5025 | break;
|
---|
5026 | default: return -28;
|
---|
5027 | }
|
---|
5028 | FS.mknod(path, mode, dev);
|
---|
5029 | return 0;
|
---|
5030 | },doReadlink:function(path, buf, bufsize) {
|
---|
5031 | if (bufsize <= 0) return -28;
|
---|
5032 | var ret = FS.readlink(path);
|
---|
5033 |
|
---|
5034 | var len = Math.min(bufsize, lengthBytesUTF8(ret));
|
---|
5035 | var endChar = HEAP8[buf+len];
|
---|
5036 | stringToUTF8(ret, buf, bufsize+1);
|
---|
5037 | // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
|
---|
5038 | // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
|
---|
5039 | HEAP8[buf+len] = endChar;
|
---|
5040 |
|
---|
5041 | return len;
|
---|
5042 | },doAccess:function(path, amode) {
|
---|
5043 | if (amode & ~7) {
|
---|
5044 | // need a valid mode
|
---|
5045 | return -28;
|
---|
5046 | }
|
---|
5047 | var node;
|
---|
5048 | var lookup = FS.lookupPath(path, { follow: true });
|
---|
5049 | node = lookup.node;
|
---|
5050 | if (!node) {
|
---|
5051 | return -44;
|
---|
5052 | }
|
---|
5053 | var perms = '';
|
---|
5054 | if (amode & 4) perms += 'r';
|
---|
5055 | if (amode & 2) perms += 'w';
|
---|
5056 | if (amode & 1) perms += 'x';
|
---|
5057 | if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) {
|
---|
5058 | return -2;
|
---|
5059 | }
|
---|
5060 | return 0;
|
---|
5061 | },doDup:function(path, flags, suggestFD) {
|
---|
5062 | var suggest = FS.getStream(suggestFD);
|
---|
5063 | if (suggest) FS.close(suggest);
|
---|
5064 | return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
|
---|
5065 | },doReadv:function(stream, iov, iovcnt, offset) {
|
---|
5066 | var ret = 0;
|
---|
5067 | for (var i = 0; i < iovcnt; i++) {
|
---|
5068 | var ptr = HEAP32[(((iov)+(i*8))>>2)];
|
---|
5069 | var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
|
---|
5070 | var curr = FS.read(stream, HEAP8,ptr, len, offset);
|
---|
5071 | if (curr < 0) return -1;
|
---|
5072 | ret += curr;
|
---|
5073 | if (curr < len) break; // nothing more to read
|
---|
5074 | }
|
---|
5075 | return ret;
|
---|
5076 | },doWritev:function(stream, iov, iovcnt, offset) {
|
---|
5077 | var ret = 0;
|
---|
5078 | for (var i = 0; i < iovcnt; i++) {
|
---|
5079 | var ptr = HEAP32[(((iov)+(i*8))>>2)];
|
---|
5080 | var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
|
---|
5081 | var curr = FS.write(stream, HEAP8,ptr, len, offset);
|
---|
5082 | if (curr < 0) return -1;
|
---|
5083 | ret += curr;
|
---|
5084 | }
|
---|
5085 | return ret;
|
---|
5086 | },varargs:undefined,get:function() {
|
---|
5087 | assert(SYSCALLS.varargs != undefined);
|
---|
5088 | SYSCALLS.varargs += 4;
|
---|
5089 | var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
|
---|
5090 | return ret;
|
---|
5091 | },getStr:function(ptr) {
|
---|
5092 | var ret = UTF8ToString(ptr);
|
---|
5093 | return ret;
|
---|
5094 | },getStreamFromFD:function(fd) {
|
---|
5095 | var stream = FS.getStream(fd);
|
---|
5096 | if (!stream) throw new FS.ErrnoError(8);
|
---|
5097 | return stream;
|
---|
5098 | },get64:function(low, high) {
|
---|
5099 | if (low >= 0) assert(high === 0);
|
---|
5100 | else assert(high === -1);
|
---|
5101 | return low;
|
---|
5102 | }};function ___sys_fcntl64(fd, cmd, varargs) {SYSCALLS.varargs = varargs;
|
---|
5103 | try {
|
---|
5104 |
|
---|
5105 | var stream = SYSCALLS.getStreamFromFD(fd);
|
---|
5106 | switch (cmd) {
|
---|
5107 | case 0: {
|
---|
5108 | var arg = SYSCALLS.get();
|
---|
5109 | if (arg < 0) {
|
---|
5110 | return -28;
|
---|
5111 | }
|
---|
5112 | var newStream;
|
---|
5113 | newStream = FS.open(stream.path, stream.flags, 0, arg);
|
---|
5114 | return newStream.fd;
|
---|
5115 | }
|
---|
5116 | case 1:
|
---|
5117 | case 2:
|
---|
5118 | return 0; // FD_CLOEXEC makes no sense for a single process.
|
---|
5119 | case 3:
|
---|
5120 | return stream.flags;
|
---|
5121 | case 4: {
|
---|
5122 | var arg = SYSCALLS.get();
|
---|
5123 | stream.flags |= arg;
|
---|
5124 | return 0;
|
---|
5125 | }
|
---|
5126 | case 12:
|
---|
5127 | /* case 12: Currently in musl F_GETLK64 has same value as F_GETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ {
|
---|
5128 |
|
---|
5129 | var arg = SYSCALLS.get();
|
---|
5130 | var offset = 0;
|
---|
5131 | // We're always unlocked.
|
---|
5132 | HEAP16[(((arg)+(offset))>>1)]=2;
|
---|
5133 | return 0;
|
---|
5134 | }
|
---|
5135 | case 13:
|
---|
5136 | case 14:
|
---|
5137 | /* case 13: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
|
---|
5138 | /* case 14: Currently in musl F_SETLKW64 has same value as F_SETLKW, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
|
---|
5139 |
|
---|
5140 |
|
---|
5141 | return 0; // Pretend that the locking is successful.
|
---|
5142 | case 16:
|
---|
5143 | case 8:
|
---|
5144 | return -28; // These are for sockets. We don't have them fully implemented yet.
|
---|
5145 | case 9:
|
---|
5146 | // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fnctl() returns that, and we set errno ourselves.
|
---|
5147 | setErrNo(28);
|
---|
5148 | return -1;
|
---|
5149 | default: {
|
---|
5150 | return -28;
|
---|
5151 | }
|
---|
5152 | }
|
---|
5153 | } catch (e) {
|
---|
5154 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5155 | return -e.errno;
|
---|
5156 | }
|
---|
5157 | }
|
---|
5158 |
|
---|
5159 | function ___sys_ioctl(fd, op, varargs) {SYSCALLS.varargs = varargs;
|
---|
5160 | try {
|
---|
5161 |
|
---|
5162 | var stream = SYSCALLS.getStreamFromFD(fd);
|
---|
5163 | switch (op) {
|
---|
5164 | case 21509:
|
---|
5165 | case 21505: {
|
---|
5166 | if (!stream.tty) return -59;
|
---|
5167 | return 0;
|
---|
5168 | }
|
---|
5169 | case 21510:
|
---|
5170 | case 21511:
|
---|
5171 | case 21512:
|
---|
5172 | case 21506:
|
---|
5173 | case 21507:
|
---|
5174 | case 21508: {
|
---|
5175 | if (!stream.tty) return -59;
|
---|
5176 | return 0; // no-op, not actually adjusting terminal settings
|
---|
5177 | }
|
---|
5178 | case 21519: {
|
---|
5179 | if (!stream.tty) return -59;
|
---|
5180 | var argp = SYSCALLS.get();
|
---|
5181 | HEAP32[((argp)>>2)]=0;
|
---|
5182 | return 0;
|
---|
5183 | }
|
---|
5184 | case 21520: {
|
---|
5185 | if (!stream.tty) return -59;
|
---|
5186 | return -28; // not supported
|
---|
5187 | }
|
---|
5188 | case 21531: {
|
---|
5189 | var argp = SYSCALLS.get();
|
---|
5190 | return FS.ioctl(stream, op, argp);
|
---|
5191 | }
|
---|
5192 | case 21523: {
|
---|
5193 | // TODO: in theory we should write to the winsize struct that gets
|
---|
5194 | // passed in, but for now musl doesn't read anything on it
|
---|
5195 | if (!stream.tty) return -59;
|
---|
5196 | return 0;
|
---|
5197 | }
|
---|
5198 | case 21524: {
|
---|
5199 | // TODO: technically, this ioctl call should change the window size.
|
---|
5200 | // but, since emscripten doesn't have any concept of a terminal window
|
---|
5201 | // yet, we'll just silently throw it away as we do TIOCGWINSZ
|
---|
5202 | if (!stream.tty) return -59;
|
---|
5203 | return 0;
|
---|
5204 | }
|
---|
5205 | default: abort('bad ioctl syscall ' + op);
|
---|
5206 | }
|
---|
5207 | } catch (e) {
|
---|
5208 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5209 | return -e.errno;
|
---|
5210 | }
|
---|
5211 | }
|
---|
5212 |
|
---|
5213 | function ___sys_open(path, flags, varargs) {SYSCALLS.varargs = varargs;
|
---|
5214 | try {
|
---|
5215 |
|
---|
5216 | var pathname = SYSCALLS.getStr(path);
|
---|
5217 | var mode = SYSCALLS.get();
|
---|
5218 | var stream = FS.open(pathname, flags, mode);
|
---|
5219 | return stream.fd;
|
---|
5220 | } catch (e) {
|
---|
5221 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5222 | return -e.errno;
|
---|
5223 | }
|
---|
5224 | }
|
---|
5225 |
|
---|
5226 | function _abort() {
|
---|
5227 | abort();
|
---|
5228 | }
|
---|
5229 |
|
---|
5230 | function _emscripten_get_sbrk_ptr() {
|
---|
5231 | return 79712;
|
---|
5232 | }
|
---|
5233 |
|
---|
5234 |
|
---|
5235 | function _longjmp(env, value) {
|
---|
5236 | _setThrew(env, value || 1);
|
---|
5237 | throw 'longjmp';
|
---|
5238 | }function _emscripten_longjmp(env, value) {
|
---|
5239 | _longjmp(env, value);
|
---|
5240 | }
|
---|
5241 |
|
---|
5242 | function _emscripten_memcpy_big(dest, src, num) {
|
---|
5243 | HEAPU8.copyWithin(dest, src, src + num);
|
---|
5244 | }
|
---|
5245 |
|
---|
5246 |
|
---|
5247 | function _emscripten_get_heap_size() {
|
---|
5248 | return HEAPU8.length;
|
---|
5249 | }
|
---|
5250 |
|
---|
5251 | function abortOnCannotGrowMemory(requestedSize) {
|
---|
5252 | abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
|
---|
5253 | }function _emscripten_resize_heap(requestedSize) {
|
---|
5254 | requestedSize = requestedSize >>> 0;
|
---|
5255 | abortOnCannotGrowMemory(requestedSize);
|
---|
5256 | }
|
---|
5257 |
|
---|
5258 | function _exit(status) {
|
---|
5259 | // void _exit(int status);
|
---|
5260 | // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
|
---|
5261 | exit(status);
|
---|
5262 | }
|
---|
5263 |
|
---|
5264 | function _fd_close(fd) {try {
|
---|
5265 |
|
---|
5266 | var stream = SYSCALLS.getStreamFromFD(fd);
|
---|
5267 | FS.close(stream);
|
---|
5268 | return 0;
|
---|
5269 | } catch (e) {
|
---|
5270 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5271 | return e.errno;
|
---|
5272 | }
|
---|
5273 | }
|
---|
5274 |
|
---|
5275 | function _fd_read(fd, iov, iovcnt, pnum) {try {
|
---|
5276 |
|
---|
5277 | var stream = SYSCALLS.getStreamFromFD(fd);
|
---|
5278 | var num = SYSCALLS.doReadv(stream, iov, iovcnt);
|
---|
5279 | HEAP32[((pnum)>>2)]=num
|
---|
5280 | return 0;
|
---|
5281 | } catch (e) {
|
---|
5282 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5283 | return e.errno;
|
---|
5284 | }
|
---|
5285 | }
|
---|
5286 |
|
---|
5287 | function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {try {
|
---|
5288 |
|
---|
5289 |
|
---|
5290 | var stream = SYSCALLS.getStreamFromFD(fd);
|
---|
5291 | var HIGH_OFFSET = 0x100000000; // 2^32
|
---|
5292 | // use an unsigned operator on low and shift high by 32-bits
|
---|
5293 | var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0);
|
---|
5294 |
|
---|
5295 | var DOUBLE_LIMIT = 0x20000000000000; // 2^53
|
---|
5296 | // we also check for equality since DOUBLE_LIMIT + 1 == DOUBLE_LIMIT
|
---|
5297 | if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) {
|
---|
5298 | return -61;
|
---|
5299 | }
|
---|
5300 |
|
---|
5301 | FS.llseek(stream, offset, whence);
|
---|
5302 | (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(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[((newOffset)>>2)]=tempI64[0],HEAP32[(((newOffset)+(4))>>2)]=tempI64[1]);
|
---|
5303 | if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
|
---|
5304 | return 0;
|
---|
5305 | } catch (e) {
|
---|
5306 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5307 | return e.errno;
|
---|
5308 | }
|
---|
5309 | }
|
---|
5310 |
|
---|
5311 | function _fd_write(fd, iov, iovcnt, pnum) {try {
|
---|
5312 |
|
---|
5313 | var stream = SYSCALLS.getStreamFromFD(fd);
|
---|
5314 | var num = SYSCALLS.doWritev(stream, iov, iovcnt);
|
---|
5315 | HEAP32[((pnum)>>2)]=num
|
---|
5316 | return 0;
|
---|
5317 | } catch (e) {
|
---|
5318 | if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
|
---|
5319 | return e.errno;
|
---|
5320 | }
|
---|
5321 | }
|
---|
5322 |
|
---|
5323 | function _getTempRet0() {
|
---|
5324 | return (getTempRet0() | 0);
|
---|
5325 | }
|
---|
5326 |
|
---|
5327 |
|
---|
5328 | function _round(d) {
|
---|
5329 | d = +d;
|
---|
5330 | return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5);
|
---|
5331 | }
|
---|
5332 |
|
---|
5333 | function _setTempRet0($i) {
|
---|
5334 | setTempRet0(($i) | 0);
|
---|
5335 | }
|
---|
5336 |
|
---|
5337 | Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) { Browser.requestFullscreen(lockPointer, resizeCanvas) };
|
---|
5338 | Module["requestFullScreen"] = function Module_requestFullScreen() { Browser.requestFullScreen() };
|
---|
5339 | Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) };
|
---|
5340 | Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };
|
---|
5341 | Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() };
|
---|
5342 | Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() };
|
---|
5343 | Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() }
|
---|
5344 | Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) };
|
---|
5345 | var FSNode = /** @constructor */ function(parent, name, mode, rdev) {
|
---|
5346 | if (!parent) {
|
---|
5347 | parent = this; // root node sets parent to itself
|
---|
5348 | }
|
---|
5349 | this.parent = parent;
|
---|
5350 | this.mount = parent.mount;
|
---|
5351 | this.mounted = null;
|
---|
5352 | this.id = FS.nextInode++;
|
---|
5353 | this.name = name;
|
---|
5354 | this.mode = mode;
|
---|
5355 | this.node_ops = {};
|
---|
5356 | this.stream_ops = {};
|
---|
5357 | this.rdev = rdev;
|
---|
5358 | };
|
---|
5359 | var readMode = 292/*292*/ | 73/*73*/;
|
---|
5360 | var writeMode = 146/*146*/;
|
---|
5361 | Object.defineProperties(FSNode.prototype, {
|
---|
5362 | read: {
|
---|
5363 | get: /** @this{FSNode} */function() {
|
---|
5364 | return (this.mode & readMode) === readMode;
|
---|
5365 | },
|
---|
5366 | set: /** @this{FSNode} */function(val) {
|
---|
5367 | val ? this.mode |= readMode : this.mode &= ~readMode;
|
---|
5368 | }
|
---|
5369 | },
|
---|
5370 | write: {
|
---|
5371 | get: /** @this{FSNode} */function() {
|
---|
5372 | return (this.mode & writeMode) === writeMode;
|
---|
5373 | },
|
---|
5374 | set: /** @this{FSNode} */function(val) {
|
---|
5375 | val ? this.mode |= writeMode : this.mode &= ~writeMode;
|
---|
5376 | }
|
---|
5377 | },
|
---|
5378 | isFolder: {
|
---|
5379 | get: /** @this{FSNode} */function() {
|
---|
5380 | return FS.isDir(this.mode);
|
---|
5381 | }
|
---|
5382 | },
|
---|
5383 | isDevice: {
|
---|
5384 | get: /** @this{FSNode} */function() {
|
---|
5385 | return FS.isChrdev(this.mode);
|
---|
5386 | }
|
---|
5387 | }
|
---|
5388 | });
|
---|
5389 | FS.FSNode = FSNode;
|
---|
5390 | FS.staticInit();Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice;Module["FS_unlink"] = FS.unlink;;
|
---|
5391 | var ASSERTIONS = true;
|
---|
5392 |
|
---|
5393 |
|
---|
5394 |
|
---|
5395 | /** @type {function(string, boolean=, number=)} */
|
---|
5396 | function intArrayFromString(stringy, dontAddNull, length) {
|
---|
5397 | var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
|
---|
5398 | var u8array = new Array(len);
|
---|
5399 | var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
|
---|
5400 | if (dontAddNull) u8array.length = numBytesWritten;
|
---|
5401 | return u8array;
|
---|
5402 | }
|
---|
5403 |
|
---|
5404 | function intArrayToString(array) {
|
---|
5405 | var ret = [];
|
---|
5406 | for (var i = 0; i < array.length; i++) {
|
---|
5407 | var chr = array[i];
|
---|
5408 | if (chr > 0xFF) {
|
---|
5409 | if (ASSERTIONS) {
|
---|
5410 | assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
|
---|
5411 | }
|
---|
5412 | chr &= 0xFF;
|
---|
5413 | }
|
---|
5414 | ret.push(String.fromCharCode(chr));
|
---|
5415 | }
|
---|
5416 | return ret.join('');
|
---|
5417 | }
|
---|
5418 |
|
---|
5419 |
|
---|
5420 | // ASM_LIBRARY EXTERN PRIMITIVES: Math_floor,Math_ceil
|
---|
5421 |
|
---|
5422 | var asmGlobalArg = {};
|
---|
5423 | var asmLibraryArg = { "__handle_stack_overflow": ___handle_stack_overflow, "__sys_fcntl64": ___sys_fcntl64, "__sys_ioctl": ___sys_ioctl, "__sys_open": ___sys_open, "abort": _abort, "emscripten_get_sbrk_ptr": _emscripten_get_sbrk_ptr, "emscripten_longjmp": _emscripten_longjmp, "emscripten_memcpy_big": _emscripten_memcpy_big, "emscripten_resize_heap": _emscripten_resize_heap, "exit": _exit, "fd_close": _fd_close, "fd_read": _fd_read, "fd_seek": _fd_seek, "fd_write": _fd_write, "getTempRet0": _getTempRet0, "invoke_ii": invoke_ii, "invoke_iii": invoke_iii, "invoke_iiii": invoke_iiii, "invoke_iiiii": invoke_iiiii, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_viii": invoke_viii, "invoke_viiii": invoke_viiii, "invoke_viiiii": invoke_viiiii, "invoke_viiiiii": invoke_viiiiii, "invoke_viiiiiii": invoke_viiiiiii, "memory": wasmMemory, "round": _round, "setTempRet0": _setTempRet0, "table": wasmTable };
|
---|
5424 | var asm = createWasm();
|
---|
5425 | /** @type {function(...*):?} */
|
---|
5426 | var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__wasm_call_ctors");
|
---|
5427 |
|
---|
5428 | /** @type {function(...*):?} */
|
---|
5429 | var _main = Module["_main"] = createExportWrapper("main");
|
---|
5430 |
|
---|
5431 | /** @type {function(...*):?} */
|
---|
5432 | var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location");
|
---|
5433 |
|
---|
5434 | /** @type {function(...*):?} */
|
---|
5435 | var _malloc = Module["_malloc"] = createExportWrapper("malloc");
|
---|
5436 |
|
---|
5437 | /** @type {function(...*):?} */
|
---|
5438 | var _testSetjmp = Module["_testSetjmp"] = createExportWrapper("testSetjmp");
|
---|
5439 |
|
---|
5440 | /** @type {function(...*):?} */
|
---|
5441 | var _saveSetjmp = Module["_saveSetjmp"] = createExportWrapper("saveSetjmp");
|
---|
5442 |
|
---|
5443 | /** @type {function(...*):?} */
|
---|
5444 | var _free = Module["_free"] = createExportWrapper("free");
|
---|
5445 |
|
---|
5446 | /** @type {function(...*):?} */
|
---|
5447 | var _realloc = Module["_realloc"] = createExportWrapper("realloc");
|
---|
5448 |
|
---|
5449 | /** @type {function(...*):?} */
|
---|
5450 | var _fflush = Module["_fflush"] = createExportWrapper("fflush");
|
---|
5451 |
|
---|
5452 | /** @type {function(...*):?} */
|
---|
5453 | var _setThrew = Module["_setThrew"] = createExportWrapper("setThrew");
|
---|
5454 |
|
---|
5455 | /** @type {function(...*):?} */
|
---|
5456 | var stackSave = Module["stackSave"] = createExportWrapper("stackSave");
|
---|
5457 |
|
---|
5458 | /** @type {function(...*):?} */
|
---|
5459 | var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore");
|
---|
5460 |
|
---|
5461 | /** @type {function(...*):?} */
|
---|
5462 | var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc");
|
---|
5463 |
|
---|
5464 | /** @type {function(...*):?} */
|
---|
5465 | var dynCall_vi = Module["dynCall_vi"] = createExportWrapper("dynCall_vi");
|
---|
5466 |
|
---|
5467 | /** @type {function(...*):?} */
|
---|
5468 | var dynCall_vii = Module["dynCall_vii"] = createExportWrapper("dynCall_vii");
|
---|
5469 |
|
---|
5470 | /** @type {function(...*):?} */
|
---|
5471 | var dynCall_viii = Module["dynCall_viii"] = createExportWrapper("dynCall_viii");
|
---|
5472 |
|
---|
5473 | /** @type {function(...*):?} */
|
---|
5474 | var dynCall_viiii = Module["dynCall_viiii"] = createExportWrapper("dynCall_viiii");
|
---|
5475 |
|
---|
5476 | /** @type {function(...*):?} */
|
---|
5477 | var dynCall_viiiii = Module["dynCall_viiiii"] = createExportWrapper("dynCall_viiiii");
|
---|
5478 |
|
---|
5479 | /** @type {function(...*):?} */
|
---|
5480 | var dynCall_viiiiii = Module["dynCall_viiiiii"] = createExportWrapper("dynCall_viiiiii");
|
---|
5481 |
|
---|
5482 | /** @type {function(...*):?} */
|
---|
5483 | var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = createExportWrapper("dynCall_viiiiiii");
|
---|
5484 |
|
---|
5485 | /** @type {function(...*):?} */
|
---|
5486 | var dynCall_ii = Module["dynCall_ii"] = createExportWrapper("dynCall_ii");
|
---|
5487 |
|
---|
5488 | /** @type {function(...*):?} */
|
---|
5489 | var dynCall_iii = Module["dynCall_iii"] = createExportWrapper("dynCall_iii");
|
---|
5490 |
|
---|
5491 | /** @type {function(...*):?} */
|
---|
5492 | var dynCall_iiii = Module["dynCall_iiii"] = createExportWrapper("dynCall_iiii");
|
---|
5493 |
|
---|
5494 | /** @type {function(...*):?} */
|
---|
5495 | var dynCall_iiiii = Module["dynCall_iiiii"] = createExportWrapper("dynCall_iiiii");
|
---|
5496 |
|
---|
5497 | /** @type {function(...*):?} */
|
---|
5498 | var ___set_stack_limit = Module["___set_stack_limit"] = createExportWrapper("__set_stack_limit");
|
---|
5499 |
|
---|
5500 | /** @type {function(...*):?} */
|
---|
5501 | var __growWasmMemory = Module["__growWasmMemory"] = createExportWrapper("__growWasmMemory");
|
---|
5502 |
|
---|
5503 | /** @type {function(...*):?} */
|
---|
5504 | var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji");
|
---|
5505 |
|
---|
5506 | /** @type {function(...*):?} */
|
---|
5507 | var dynCall_iidiiii = Module["dynCall_iidiiii"] = createExportWrapper("dynCall_iidiiii");
|
---|
5508 |
|
---|
5509 |
|
---|
5510 | function invoke_vi(index,a1) {
|
---|
5511 | var sp = stackSave();
|
---|
5512 | try {
|
---|
5513 | dynCall_vi(index,a1);
|
---|
5514 | } catch(e) {
|
---|
5515 | stackRestore(sp);
|
---|
5516 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5517 | _setThrew(1, 0);
|
---|
5518 | }
|
---|
5519 | }
|
---|
5520 |
|
---|
5521 | function invoke_vii(index,a1,a2) {
|
---|
5522 | var sp = stackSave();
|
---|
5523 | try {
|
---|
5524 | dynCall_vii(index,a1,a2);
|
---|
5525 | } catch(e) {
|
---|
5526 | stackRestore(sp);
|
---|
5527 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5528 | _setThrew(1, 0);
|
---|
5529 | }
|
---|
5530 | }
|
---|
5531 |
|
---|
5532 | function invoke_iiii(index,a1,a2,a3) {
|
---|
5533 | var sp = stackSave();
|
---|
5534 | try {
|
---|
5535 | return dynCall_iiii(index,a1,a2,a3);
|
---|
5536 | } catch(e) {
|
---|
5537 | stackRestore(sp);
|
---|
5538 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5539 | _setThrew(1, 0);
|
---|
5540 | }
|
---|
5541 | }
|
---|
5542 |
|
---|
5543 | function invoke_iii(index,a1,a2) {
|
---|
5544 | var sp = stackSave();
|
---|
5545 | try {
|
---|
5546 | return dynCall_iii(index,a1,a2);
|
---|
5547 | } catch(e) {
|
---|
5548 | stackRestore(sp);
|
---|
5549 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5550 | _setThrew(1, 0);
|
---|
5551 | }
|
---|
5552 | }
|
---|
5553 |
|
---|
5554 | function invoke_viiii(index,a1,a2,a3,a4) {
|
---|
5555 | var sp = stackSave();
|
---|
5556 | try {
|
---|
5557 | dynCall_viiii(index,a1,a2,a3,a4);
|
---|
5558 | } catch(e) {
|
---|
5559 | stackRestore(sp);
|
---|
5560 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5561 | _setThrew(1, 0);
|
---|
5562 | }
|
---|
5563 | }
|
---|
5564 |
|
---|
5565 | function invoke_viiiii(index,a1,a2,a3,a4,a5) {
|
---|
5566 | var sp = stackSave();
|
---|
5567 | try {
|
---|
5568 | dynCall_viiiii(index,a1,a2,a3,a4,a5);
|
---|
5569 | } catch(e) {
|
---|
5570 | stackRestore(sp);
|
---|
5571 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5572 | _setThrew(1, 0);
|
---|
5573 | }
|
---|
5574 | }
|
---|
5575 |
|
---|
5576 | function invoke_viii(index,a1,a2,a3) {
|
---|
5577 | var sp = stackSave();
|
---|
5578 | try {
|
---|
5579 | dynCall_viii(index,a1,a2,a3);
|
---|
5580 | } catch(e) {
|
---|
5581 | stackRestore(sp);
|
---|
5582 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5583 | _setThrew(1, 0);
|
---|
5584 | }
|
---|
5585 | }
|
---|
5586 |
|
---|
5587 | function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
|
---|
5588 | var sp = stackSave();
|
---|
5589 | try {
|
---|
5590 | dynCall_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7);
|
---|
5591 | } catch(e) {
|
---|
5592 | stackRestore(sp);
|
---|
5593 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5594 | _setThrew(1, 0);
|
---|
5595 | }
|
---|
5596 | }
|
---|
5597 |
|
---|
5598 | function invoke_iiiii(index,a1,a2,a3,a4) {
|
---|
5599 | var sp = stackSave();
|
---|
5600 | try {
|
---|
5601 | return dynCall_iiiii(index,a1,a2,a3,a4);
|
---|
5602 | } catch(e) {
|
---|
5603 | stackRestore(sp);
|
---|
5604 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5605 | _setThrew(1, 0);
|
---|
5606 | }
|
---|
5607 | }
|
---|
5608 |
|
---|
5609 | function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
|
---|
5610 | var sp = stackSave();
|
---|
5611 | try {
|
---|
5612 | dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6);
|
---|
5613 | } catch(e) {
|
---|
5614 | stackRestore(sp);
|
---|
5615 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5616 | _setThrew(1, 0);
|
---|
5617 | }
|
---|
5618 | }
|
---|
5619 |
|
---|
5620 | function invoke_ii(index,a1) {
|
---|
5621 | var sp = stackSave();
|
---|
5622 | try {
|
---|
5623 | return dynCall_ii(index,a1);
|
---|
5624 | } catch(e) {
|
---|
5625 | stackRestore(sp);
|
---|
5626 | if (e !== e+0 && e !== 'longjmp') throw e;
|
---|
5627 | _setThrew(1, 0);
|
---|
5628 | }
|
---|
5629 | }
|
---|
5630 |
|
---|
5631 |
|
---|
5632 |
|
---|
5633 |
|
---|
5634 | // === Auto-generated postamble setup entry stuff ===
|
---|
5635 |
|
---|
5636 |
|
---|
5637 | if (!Object.getOwnPropertyDescriptor(Module, "intArrayFromString")) Module["intArrayFromString"] = function() { abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5638 | if (!Object.getOwnPropertyDescriptor(Module, "intArrayToString")) Module["intArrayToString"] = function() { abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5639 | if (!Object.getOwnPropertyDescriptor(Module, "ccall")) Module["ccall"] = function() { abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5640 | if (!Object.getOwnPropertyDescriptor(Module, "cwrap")) Module["cwrap"] = function() { abort("'cwrap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5641 | if (!Object.getOwnPropertyDescriptor(Module, "setValue")) Module["setValue"] = function() { abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5642 | if (!Object.getOwnPropertyDescriptor(Module, "getValue")) Module["getValue"] = function() { abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5643 | if (!Object.getOwnPropertyDescriptor(Module, "allocate")) Module["allocate"] = function() { abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5644 | Module["getMemory"] = getMemory;
|
---|
5645 | if (!Object.getOwnPropertyDescriptor(Module, "UTF8ArrayToString")) Module["UTF8ArrayToString"] = function() { abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5646 | if (!Object.getOwnPropertyDescriptor(Module, "UTF8ToString")) Module["UTF8ToString"] = function() { abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5647 | if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF8Array")) Module["stringToUTF8Array"] = function() { abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5648 | if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF8")) Module["stringToUTF8"] = function() { abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5649 | if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF8")) Module["lengthBytesUTF8"] = function() { abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5650 | if (!Object.getOwnPropertyDescriptor(Module, "stackTrace")) Module["stackTrace"] = function() { abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5651 | if (!Object.getOwnPropertyDescriptor(Module, "addOnPreRun")) Module["addOnPreRun"] = function() { abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5652 | if (!Object.getOwnPropertyDescriptor(Module, "addOnInit")) Module["addOnInit"] = function() { abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5653 | if (!Object.getOwnPropertyDescriptor(Module, "addOnPreMain")) Module["addOnPreMain"] = function() { abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5654 | if (!Object.getOwnPropertyDescriptor(Module, "addOnExit")) Module["addOnExit"] = function() { abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5655 | if (!Object.getOwnPropertyDescriptor(Module, "addOnPostRun")) Module["addOnPostRun"] = function() { abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5656 | if (!Object.getOwnPropertyDescriptor(Module, "writeStringToMemory")) Module["writeStringToMemory"] = function() { abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5657 | if (!Object.getOwnPropertyDescriptor(Module, "writeArrayToMemory")) Module["writeArrayToMemory"] = function() { abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5658 | if (!Object.getOwnPropertyDescriptor(Module, "writeAsciiToMemory")) Module["writeAsciiToMemory"] = function() { abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5659 | Module["addRunDependency"] = addRunDependency;
|
---|
5660 | Module["removeRunDependency"] = removeRunDependency;
|
---|
5661 | Module["FS_createFolder"] = FS.createFolder;
|
---|
5662 | Module["FS_createPath"] = FS.createPath;
|
---|
5663 | Module["FS_createDataFile"] = FS.createDataFile;
|
---|
5664 | Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
|
---|
5665 | Module["FS_createLazyFile"] = FS.createLazyFile;
|
---|
5666 | Module["FS_createLink"] = FS.createLink;
|
---|
5667 | Module["FS_createDevice"] = FS.createDevice;
|
---|
5668 | Module["FS_unlink"] = FS.unlink;
|
---|
5669 | if (!Object.getOwnPropertyDescriptor(Module, "dynamicAlloc")) Module["dynamicAlloc"] = function() { abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5670 | if (!Object.getOwnPropertyDescriptor(Module, "loadDynamicLibrary")) Module["loadDynamicLibrary"] = function() { abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5671 | if (!Object.getOwnPropertyDescriptor(Module, "loadWebAssemblyModule")) Module["loadWebAssemblyModule"] = function() { abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5672 | if (!Object.getOwnPropertyDescriptor(Module, "getLEB")) Module["getLEB"] = function() { abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5673 | if (!Object.getOwnPropertyDescriptor(Module, "getFunctionTables")) Module["getFunctionTables"] = function() { abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5674 | if (!Object.getOwnPropertyDescriptor(Module, "alignFunctionTables")) Module["alignFunctionTables"] = function() { abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5675 | if (!Object.getOwnPropertyDescriptor(Module, "registerFunctions")) Module["registerFunctions"] = function() { abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5676 | if (!Object.getOwnPropertyDescriptor(Module, "addFunction")) Module["addFunction"] = function() { abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5677 | if (!Object.getOwnPropertyDescriptor(Module, "removeFunction")) Module["removeFunction"] = function() { abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5678 | if (!Object.getOwnPropertyDescriptor(Module, "getFuncWrapper")) Module["getFuncWrapper"] = function() { abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5679 | if (!Object.getOwnPropertyDescriptor(Module, "prettyPrint")) Module["prettyPrint"] = function() { abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5680 | if (!Object.getOwnPropertyDescriptor(Module, "makeBigInt")) Module["makeBigInt"] = function() { abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5681 | if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5682 | if (!Object.getOwnPropertyDescriptor(Module, "getCompilerSetting")) Module["getCompilerSetting"] = function() { abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5683 | if (!Object.getOwnPropertyDescriptor(Module, "print")) Module["print"] = function() { abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5684 | if (!Object.getOwnPropertyDescriptor(Module, "printErr")) Module["printErr"] = function() { abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5685 | if (!Object.getOwnPropertyDescriptor(Module, "getTempRet0")) Module["getTempRet0"] = function() { abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5686 | if (!Object.getOwnPropertyDescriptor(Module, "setTempRet0")) Module["setTempRet0"] = function() { abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5687 | if (!Object.getOwnPropertyDescriptor(Module, "callMain")) Module["callMain"] = function() { abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5688 | if (!Object.getOwnPropertyDescriptor(Module, "abort")) Module["abort"] = function() { abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5689 | if (!Object.getOwnPropertyDescriptor(Module, "stringToNewUTF8")) Module["stringToNewUTF8"] = function() { abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5690 | if (!Object.getOwnPropertyDescriptor(Module, "abortOnCannotGrowMemory")) Module["abortOnCannotGrowMemory"] = function() { abort("'abortOnCannotGrowMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5691 | if (!Object.getOwnPropertyDescriptor(Module, "emscripten_realloc_buffer")) Module["emscripten_realloc_buffer"] = function() { abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5692 | if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function() { abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5693 | if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() { abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5694 | if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() { abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5695 | if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() { abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5696 | if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() { abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5697 | if (!Object.getOwnPropertyDescriptor(Module, "GAI_ERRNO_MESSAGES")) Module["GAI_ERRNO_MESSAGES"] = function() { abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5698 | if (!Object.getOwnPropertyDescriptor(Module, "Protocols")) Module["Protocols"] = function() { abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5699 | if (!Object.getOwnPropertyDescriptor(Module, "Sockets")) Module["Sockets"] = function() { abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5700 | if (!Object.getOwnPropertyDescriptor(Module, "UNWIND_CACHE")) Module["UNWIND_CACHE"] = function() { abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5701 | if (!Object.getOwnPropertyDescriptor(Module, "readAsmConstArgs")) Module["readAsmConstArgs"] = function() { abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5702 | if (!Object.getOwnPropertyDescriptor(Module, "jstoi_q")) Module["jstoi_q"] = function() { abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5703 | if (!Object.getOwnPropertyDescriptor(Module, "jstoi_s")) Module["jstoi_s"] = function() { abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5704 | if (!Object.getOwnPropertyDescriptor(Module, "listenOnce")) Module["listenOnce"] = function() { abort("'listenOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5705 | if (!Object.getOwnPropertyDescriptor(Module, "autoResumeAudioContext")) Module["autoResumeAudioContext"] = function() { abort("'autoResumeAudioContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5706 | if (!Object.getOwnPropertyDescriptor(Module, "abortStackOverflow")) Module["abortStackOverflow"] = function() { abort("'abortStackOverflow' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5707 | if (!Object.getOwnPropertyDescriptor(Module, "reallyNegative")) Module["reallyNegative"] = function() { abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5708 | if (!Object.getOwnPropertyDescriptor(Module, "formatString")) Module["formatString"] = function() { abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5709 | if (!Object.getOwnPropertyDescriptor(Module, "PATH")) Module["PATH"] = function() { abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5710 | if (!Object.getOwnPropertyDescriptor(Module, "PATH_FS")) Module["PATH_FS"] = function() { abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5711 | if (!Object.getOwnPropertyDescriptor(Module, "SYSCALLS")) Module["SYSCALLS"] = function() { abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5712 | if (!Object.getOwnPropertyDescriptor(Module, "syscallMmap2")) Module["syscallMmap2"] = function() { abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5713 | if (!Object.getOwnPropertyDescriptor(Module, "syscallMunmap")) Module["syscallMunmap"] = function() { abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5714 | if (!Object.getOwnPropertyDescriptor(Module, "JSEvents")) Module["JSEvents"] = function() { abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5715 | if (!Object.getOwnPropertyDescriptor(Module, "specialHTMLTargets")) Module["specialHTMLTargets"] = function() { abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5716 | if (!Object.getOwnPropertyDescriptor(Module, "demangle")) Module["demangle"] = function() { abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5717 | if (!Object.getOwnPropertyDescriptor(Module, "demangleAll")) Module["demangleAll"] = function() { abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5718 | if (!Object.getOwnPropertyDescriptor(Module, "jsStackTrace")) Module["jsStackTrace"] = function() { abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5719 | if (!Object.getOwnPropertyDescriptor(Module, "stackTrace")) Module["stackTrace"] = function() { abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5720 | if (!Object.getOwnPropertyDescriptor(Module, "getEnvStrings")) Module["getEnvStrings"] = function() { abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5721 | if (!Object.getOwnPropertyDescriptor(Module, "checkWasiClock")) Module["checkWasiClock"] = function() { abort("'checkWasiClock' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5722 | if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64")) Module["writeI53ToI64"] = function() { abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5723 | if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64Clamped")) Module["writeI53ToI64Clamped"] = function() { abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5724 | if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64Signaling")) Module["writeI53ToI64Signaling"] = function() { abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5725 | if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToU64Clamped")) Module["writeI53ToU64Clamped"] = function() { abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5726 | if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToU64Signaling")) Module["writeI53ToU64Signaling"] = function() { abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5727 | if (!Object.getOwnPropertyDescriptor(Module, "readI53FromI64")) Module["readI53FromI64"] = function() { abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5728 | if (!Object.getOwnPropertyDescriptor(Module, "readI53FromU64")) Module["readI53FromU64"] = function() { abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5729 | if (!Object.getOwnPropertyDescriptor(Module, "convertI32PairToI53")) Module["convertI32PairToI53"] = function() { abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5730 | if (!Object.getOwnPropertyDescriptor(Module, "convertU32PairToI53")) Module["convertU32PairToI53"] = function() { abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5731 | if (!Object.getOwnPropertyDescriptor(Module, "Browser")) Module["Browser"] = function() { abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5732 | if (!Object.getOwnPropertyDescriptor(Module, "FS")) Module["FS"] = function() { abort("'FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5733 | if (!Object.getOwnPropertyDescriptor(Module, "MEMFS")) Module["MEMFS"] = function() { abort("'MEMFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5734 | if (!Object.getOwnPropertyDescriptor(Module, "TTY")) Module["TTY"] = function() { abort("'TTY' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5735 | if (!Object.getOwnPropertyDescriptor(Module, "PIPEFS")) Module["PIPEFS"] = function() { abort("'PIPEFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5736 | if (!Object.getOwnPropertyDescriptor(Module, "SOCKFS")) Module["SOCKFS"] = function() { abort("'SOCKFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5737 | if (!Object.getOwnPropertyDescriptor(Module, "GL")) Module["GL"] = function() { abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5738 | if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGet")) Module["emscriptenWebGLGet"] = function() { abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5739 | if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetTexPixelData")) Module["emscriptenWebGLGetTexPixelData"] = function() { abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5740 | if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetUniform")) Module["emscriptenWebGLGetUniform"] = function() { abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5741 | if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetVertexAttrib")) Module["emscriptenWebGLGetVertexAttrib"] = function() { abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5742 | if (!Object.getOwnPropertyDescriptor(Module, "writeGLArray")) Module["writeGLArray"] = function() { abort("'writeGLArray' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5743 | if (!Object.getOwnPropertyDescriptor(Module, "AL")) Module["AL"] = function() { abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5744 | if (!Object.getOwnPropertyDescriptor(Module, "SDL_unicode")) Module["SDL_unicode"] = function() { abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5745 | if (!Object.getOwnPropertyDescriptor(Module, "SDL_ttfContext")) Module["SDL_ttfContext"] = function() { abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5746 | if (!Object.getOwnPropertyDescriptor(Module, "SDL_audio")) Module["SDL_audio"] = function() { abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5747 | if (!Object.getOwnPropertyDescriptor(Module, "SDL")) Module["SDL"] = function() { abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5748 | if (!Object.getOwnPropertyDescriptor(Module, "SDL_gfx")) Module["SDL_gfx"] = function() { abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5749 | if (!Object.getOwnPropertyDescriptor(Module, "GLUT")) Module["GLUT"] = function() { abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5750 | if (!Object.getOwnPropertyDescriptor(Module, "EGL")) Module["EGL"] = function() { abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5751 | if (!Object.getOwnPropertyDescriptor(Module, "GLFW_Window")) Module["GLFW_Window"] = function() { abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5752 | if (!Object.getOwnPropertyDescriptor(Module, "GLFW")) Module["GLFW"] = function() { abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5753 | if (!Object.getOwnPropertyDescriptor(Module, "GLEW")) Module["GLEW"] = function() { abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5754 | if (!Object.getOwnPropertyDescriptor(Module, "IDBStore")) Module["IDBStore"] = function() { abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5755 | if (!Object.getOwnPropertyDescriptor(Module, "runAndAbortIfError")) Module["runAndAbortIfError"] = function() { abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5756 | if (!Object.getOwnPropertyDescriptor(Module, "warnOnce")) Module["warnOnce"] = function() { abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5757 | if (!Object.getOwnPropertyDescriptor(Module, "stackSave")) Module["stackSave"] = function() { abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5758 | if (!Object.getOwnPropertyDescriptor(Module, "stackRestore")) Module["stackRestore"] = function() { abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5759 | if (!Object.getOwnPropertyDescriptor(Module, "stackAlloc")) Module["stackAlloc"] = function() { abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5760 | if (!Object.getOwnPropertyDescriptor(Module, "AsciiToString")) Module["AsciiToString"] = function() { abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5761 | if (!Object.getOwnPropertyDescriptor(Module, "stringToAscii")) Module["stringToAscii"] = function() { abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5762 | if (!Object.getOwnPropertyDescriptor(Module, "UTF16ToString")) Module["UTF16ToString"] = function() { abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5763 | if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF16")) Module["stringToUTF16"] = function() { abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5764 | if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF16")) Module["lengthBytesUTF16"] = function() { abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5765 | if (!Object.getOwnPropertyDescriptor(Module, "UTF32ToString")) Module["UTF32ToString"] = function() { abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5766 | if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF32")) Module["stringToUTF32"] = function() { abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5767 | if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF32")) Module["lengthBytesUTF32"] = function() { abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5768 | if (!Object.getOwnPropertyDescriptor(Module, "allocateUTF8")) Module["allocateUTF8"] = function() { abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5769 | if (!Object.getOwnPropertyDescriptor(Module, "allocateUTF8OnStack")) Module["allocateUTF8OnStack"] = function() { abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
|
---|
5770 | Module["writeStackCookie"] = writeStackCookie;
|
---|
5771 | Module["checkStackCookie"] = checkStackCookie;if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_NORMAL")) Object.defineProperty(Module, "ALLOC_NORMAL", { configurable: true, get: function() { abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
|
---|
5772 | if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_STACK")) Object.defineProperty(Module, "ALLOC_STACK", { configurable: true, get: function() { abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
|
---|
5773 | if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_DYNAMIC")) Object.defineProperty(Module, "ALLOC_DYNAMIC", { configurable: true, get: function() { abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
|
---|
5774 | if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_NONE")) Object.defineProperty(Module, "ALLOC_NONE", { configurable: true, get: function() { abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
|
---|
5775 |
|
---|
5776 |
|
---|
5777 |
|
---|
5778 | var calledRun;
|
---|
5779 |
|
---|
5780 | /**
|
---|
5781 | * @constructor
|
---|
5782 | * @this {ExitStatus}
|
---|
5783 | */
|
---|
5784 | function ExitStatus(status) {
|
---|
5785 | this.name = "ExitStatus";
|
---|
5786 | this.message = "Program terminated with exit(" + status + ")";
|
---|
5787 | this.status = status;
|
---|
5788 | }
|
---|
5789 |
|
---|
5790 | var calledMain = false;
|
---|
5791 |
|
---|
5792 |
|
---|
5793 | dependenciesFulfilled = function runCaller() {
|
---|
5794 | // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
|
---|
5795 | if (!calledRun) run();
|
---|
5796 | if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
|
---|
5797 | };
|
---|
5798 |
|
---|
5799 | function callMain(args) {
|
---|
5800 | assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
|
---|
5801 | assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called');
|
---|
5802 |
|
---|
5803 | var entryFunction = Module['_main'];
|
---|
5804 |
|
---|
5805 |
|
---|
5806 | args = args || [];
|
---|
5807 |
|
---|
5808 | var argc = args.length+1;
|
---|
5809 | var argv = stackAlloc((argc + 1) * 4);
|
---|
5810 | HEAP32[argv >> 2] = allocateUTF8OnStack(thisProgram);
|
---|
5811 | for (var i = 1; i < argc; i++) {
|
---|
5812 | HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]);
|
---|
5813 | }
|
---|
5814 | HEAP32[(argv >> 2) + argc] = 0;
|
---|
5815 |
|
---|
5816 | try {
|
---|
5817 |
|
---|
5818 | Module['___set_stack_limit'](STACK_MAX);
|
---|
5819 |
|
---|
5820 | var ret = entryFunction(argc, argv);
|
---|
5821 |
|
---|
5822 |
|
---|
5823 | // In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as execution is asynchronously handed
|
---|
5824 | // off to a pthread.
|
---|
5825 | // if we're not running an evented main loop, it's time to exit
|
---|
5826 | exit(ret, /* implicit = */ true);
|
---|
5827 | }
|
---|
5828 | catch(e) {
|
---|
5829 | if (e instanceof ExitStatus) {
|
---|
5830 | // exit() throws this once it's done to make sure execution
|
---|
5831 | // has been stopped completely
|
---|
5832 | return;
|
---|
5833 | } else if (e == 'unwind') {
|
---|
5834 | // running an evented main loop, don't immediately exit
|
---|
5835 | noExitRuntime = true;
|
---|
5836 | return;
|
---|
5837 | } else {
|
---|
5838 | var toLog = e;
|
---|
5839 | if (e && typeof e === 'object' && e.stack) {
|
---|
5840 | toLog = [e, e.stack];
|
---|
5841 | }
|
---|
5842 | err('exception thrown: ' + toLog);
|
---|
5843 | quit_(1, e);
|
---|
5844 | }
|
---|
5845 | } finally {
|
---|
5846 | calledMain = true;
|
---|
5847 | }
|
---|
5848 | }
|
---|
5849 |
|
---|
5850 |
|
---|
5851 |
|
---|
5852 |
|
---|
5853 | /** @type {function(Array=)} */
|
---|
5854 | function run(args) {
|
---|
5855 | args = args || arguments_;
|
---|
5856 |
|
---|
5857 | if (runDependencies > 0) {
|
---|
5858 | return;
|
---|
5859 | }
|
---|
5860 |
|
---|
5861 | writeStackCookie();
|
---|
5862 |
|
---|
5863 | preRun();
|
---|
5864 |
|
---|
5865 | if (runDependencies > 0) return; // a preRun added a dependency, run will be called later
|
---|
5866 |
|
---|
5867 | function doRun() {
|
---|
5868 | // run may have just been called through dependencies being fulfilled just in this very frame,
|
---|
5869 | // or while the async setStatus time below was happening
|
---|
5870 | if (calledRun) return;
|
---|
5871 | calledRun = true;
|
---|
5872 | Module['calledRun'] = true;
|
---|
5873 |
|
---|
5874 | if (ABORT) return;
|
---|
5875 |
|
---|
5876 | initRuntime();
|
---|
5877 |
|
---|
5878 | preMain();
|
---|
5879 |
|
---|
5880 | if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
|
---|
5881 |
|
---|
5882 | if (shouldRunNow) callMain(args);
|
---|
5883 |
|
---|
5884 | postRun();
|
---|
5885 | }
|
---|
5886 |
|
---|
5887 | if (Module['setStatus']) {
|
---|
5888 | Module['setStatus']('Running...');
|
---|
5889 | setTimeout(function() {
|
---|
5890 | setTimeout(function() {
|
---|
5891 | Module['setStatus']('');
|
---|
5892 | }, 1);
|
---|
5893 | doRun();
|
---|
5894 | }, 1);
|
---|
5895 | } else
|
---|
5896 | {
|
---|
5897 | doRun();
|
---|
5898 | }
|
---|
5899 | checkStackCookie();
|
---|
5900 | }
|
---|
5901 | Module['run'] = run;
|
---|
5902 |
|
---|
5903 | function checkUnflushedContent() {
|
---|
5904 | // Compiler settings do not allow exiting the runtime, so flushing
|
---|
5905 | // the streams is not possible. but in ASSERTIONS mode we check
|
---|
5906 | // if there was something to flush, and if so tell the user they
|
---|
5907 | // should request that the runtime be exitable.
|
---|
5908 | // Normally we would not even include flush() at all, but in ASSERTIONS
|
---|
5909 | // builds we do so just for this check, and here we see if there is any
|
---|
5910 | // content to flush, that is, we check if there would have been
|
---|
5911 | // something a non-ASSERTIONS build would have not seen.
|
---|
5912 | // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0
|
---|
5913 | // mode (which has its own special function for this; otherwise, all
|
---|
5914 | // the code is inside libc)
|
---|
5915 | var print = out;
|
---|
5916 | var printErr = err;
|
---|
5917 | var has = false;
|
---|
5918 | out = err = function(x) {
|
---|
5919 | has = true;
|
---|
5920 | }
|
---|
5921 | try { // it doesn't matter if it fails
|
---|
5922 | var flush = Module['_fflush'];
|
---|
5923 | if (flush) flush(0);
|
---|
5924 | // also flush in the JS FS layer
|
---|
5925 | ['stdout', 'stderr'].forEach(function(name) {
|
---|
5926 | var info = FS.analyzePath('/dev/' + name);
|
---|
5927 | if (!info) return;
|
---|
5928 | var stream = info.object;
|
---|
5929 | var rdev = stream.rdev;
|
---|
5930 | var tty = TTY.ttys[rdev];
|
---|
5931 | if (tty && tty.output && tty.output.length) {
|
---|
5932 | has = true;
|
---|
5933 | }
|
---|
5934 | });
|
---|
5935 | } catch(e) {}
|
---|
5936 | out = print;
|
---|
5937 | err = printErr;
|
---|
5938 | if (has) {
|
---|
5939 | warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline when you printf etc.');
|
---|
5940 | }
|
---|
5941 | }
|
---|
5942 |
|
---|
5943 | /** @param {boolean|number=} implicit */
|
---|
5944 | function exit(status, implicit) {
|
---|
5945 | checkUnflushedContent();
|
---|
5946 |
|
---|
5947 | // if this is just main exit-ing implicitly, and the status is 0, then we
|
---|
5948 | // don't need to do anything here and can just leave. if the status is
|
---|
5949 | // non-zero, though, then we need to report it.
|
---|
5950 | // (we may have warned about this earlier, if a situation justifies doing so)
|
---|
5951 | if (implicit && noExitRuntime && status === 0) {
|
---|
5952 | return;
|
---|
5953 | }
|
---|
5954 |
|
---|
5955 | if (noExitRuntime) {
|
---|
5956 | // if exit() was called, we may warn the user if the runtime isn't actually being shut down
|
---|
5957 | if (!implicit) {
|
---|
5958 | var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
|
---|
5959 | err(msg);
|
---|
5960 | }
|
---|
5961 | } else {
|
---|
5962 |
|
---|
5963 | ABORT = true;
|
---|
5964 | EXITSTATUS = status;
|
---|
5965 |
|
---|
5966 | exitRuntime();
|
---|
5967 |
|
---|
5968 | if (Module['onExit']) Module['onExit'](status);
|
---|
5969 | }
|
---|
5970 |
|
---|
5971 | quit_(status, new ExitStatus(status));
|
---|
5972 | }
|
---|
5973 |
|
---|
5974 | if (Module['preInit']) {
|
---|
5975 | if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
|
---|
5976 | while (Module['preInit'].length > 0) {
|
---|
5977 | Module['preInit'].pop()();
|
---|
5978 | }
|
---|
5979 | }
|
---|
5980 |
|
---|
5981 | // shouldRunNow refers to calling main(), not run().
|
---|
5982 | var shouldRunNow = true;
|
---|
5983 |
|
---|
5984 | if (Module['noInitialRun']) shouldRunNow = false;
|
---|
5985 |
|
---|
5986 |
|
---|
5987 | noExitRuntime = true;
|
---|
5988 |
|
---|
5989 | run();
|
---|
5990 |
|
---|
5991 |
|
---|
5992 |
|
---|
5993 |
|
---|
5994 |
|
---|
5995 |
|
---|
5996 | // {{MODULE_ADDITIONS}}
|
---|
5997 |
|
---|
5998 |
|
---|
5999 |
|
---|
6000 | };
|
---|
6001 |
|
---|