"use strict"; // WebAssembly module cache // for Emscripten-compiled functions Object.defineProperty(exports, "__esModule", { value: true }); exports.setupStdin = exports.print_fn = exports.setupFS = exports.loadNative = exports.loadWASM = exports.loadWASMBinary = exports.load = exports.loadFilesystem = exports.fsMeta = exports.execMain = exports.moduleInstFn = exports.getWASMBinary = exports.getWASMMemory = exports.emglobal = void 0; const builder_1 = require("./builder"); const ENVIRONMENT_IS_WEB = typeof window === 'object'; const ENVIRONMENT_IS_WORKER = typeof importScripts === 'function'; exports.emglobal = ENVIRONMENT_IS_WORKER ? self : ENVIRONMENT_IS_WEB ? window : global; // simple CommonJS module loader // TODO: relative paths for dependencies if (!exports.emglobal['require']) { exports.emglobal['require'] = (modpath) => { if (modpath.endsWith('.js')) modpath = modpath.slice(-3); var modname = modpath.split('/').slice(-1)[0]; var hasNamespace = exports.emglobal[modname] != null; console.log('@@@ require', modname, modpath, hasNamespace); if (!hasNamespace) { exports = {}; importScripts(`${modpath}.js`); } if (exports.emglobal[modname] == null) { exports.emglobal[modname] = exports; // TODO: always put in global scope? } return exports.emglobal[modname]; // TODO }; } // TODO: leaks memory even when disabled... var _WASM_module_cache = {}; var CACHE_WASM_MODULES = true; // if false, use asm.js only // TODO: which modules need this? var wasmMemory; function getWASMMemory() { if (wasmMemory == null) { wasmMemory = new WebAssembly.Memory({ 'initial': 1024, 'maximum': 16384, // 1024MB }); } return wasmMemory; } exports.getWASMMemory = getWASMMemory; function getWASMBinary(module_id) { return wasmBlob[module_id]; } exports.getWASMBinary = getWASMBinary; function getWASMModule(module_id) { var module = _WASM_module_cache[module_id]; if (!module) { (0, builder_1.starttime)(); module = new WebAssembly.Module(wasmBlob[module_id]); if (CACHE_WASM_MODULES) { _WASM_module_cache[module_id] = module; delete wasmBlob[module_id]; } (0, builder_1.endtime)("module creation " + module_id); } return module; } // function for use with instantiateWasm function moduleInstFn(module_id) { return function (imports, ri) { var mod = getWASMModule(module_id); var inst = new WebAssembly.Instance(mod, imports); ri(inst); return inst.exports; }; } exports.moduleInstFn = moduleInstFn; function execMain(step, mod, args) { (0, builder_1.starttime)(); var run = mod.callMain || mod.run; // TODO: run? run(args); (0, builder_1.endtime)(step.tool); } exports.execMain = execMain; /// asm.js / WASM / filesystem loading exports.fsMeta = {}; var fsBlob = {}; var wasmBlob = {}; // load filesystems for CC65 and others asynchronously function loadFilesystem(name) { var xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; xhr.open("GET", builder_1.PWORKER + "fs/fs" + name + ".data", false); // synchronous request xhr.send(null); fsBlob[name] = xhr.response; xhr = new XMLHttpRequest(); xhr.responseType = 'json'; xhr.open("GET", builder_1.PWORKER + "fs/fs" + name + ".js.metadata", false); // synchronous request xhr.send(null); exports.fsMeta[name] = xhr.response; console.log("Loaded " + name + " filesystem", exports.fsMeta[name].files.length, 'files', fsBlob[name].size, 'bytes'); } exports.loadFilesystem = loadFilesystem; var loaded = {}; function load(modulename, debug) { if (!loaded[modulename]) { importScripts(builder_1.PWORKER + 'asmjs/' + modulename + (debug ? "." + debug + ".js" : ".js")); loaded[modulename] = 1; } } exports.load = load; function loadWASMBinary(modulename) { if (!loaded[modulename]) { var xhr = new XMLHttpRequest(); xhr.responseType = 'arraybuffer'; xhr.open("GET", builder_1.PWORKER + "wasm/" + modulename + ".wasm", false); // synchronous request xhr.send(null); if (xhr.response) { wasmBlob[modulename] = new Uint8Array(xhr.response); console.log("Loaded " + modulename + ".wasm (" + wasmBlob[modulename].length + " bytes)"); loaded[modulename] = 1; } else { throw Error("Could not load WASM file " + modulename + ".wasm"); } } return wasmBlob[modulename]; } exports.loadWASMBinary = loadWASMBinary; function loadWASM(modulename, debug) { if (!loaded[modulename]) { importScripts(builder_1.PWORKER + "wasm/" + modulename + (debug ? "." + debug + ".js" : ".js")); loadWASMBinary(modulename); } } exports.loadWASM = loadWASM; function loadNative(modulename) { // detect WASM if (CACHE_WASM_MODULES && typeof WebAssembly === 'object') { loadWASM(modulename); } else { load(modulename); } } exports.loadNative = loadNative; // mount the filesystem at /share function setupFS(FS, name) { var WORKERFS = FS.filesystems['WORKERFS']; if (name === '65-vector') name = '65-none'; // TODO if (name === '65-atari7800') name = '65-none'; // TODO if (name === '65-devel') name = '65-none'; // TODO if (name === '65-vcs') name = '65-atari2600'; // TODO if (name === '65-exidy') name = '65-none'; // TODO if (!exports.fsMeta[name]) throw Error("No filesystem for '" + name + "'"); FS.mkdir('/share'); FS.mount(WORKERFS, { packages: [{ metadata: exports.fsMeta[name], blob: fsBlob[name] }] }, '/share'); // fix for slow Blob operations by caching typed arrays // https://github.com/kripken/emscripten/blob/incoming/src/library_workerfs.js // https://bugs.chromium.org/p/chromium/issues/detail?id=349304#c30 var reader = WORKERFS.reader; var blobcache = {}; WORKERFS.stream_ops.read = function (stream, buffer, offset, length, position) { if (position >= stream.node.size) return 0; var contents = blobcache[stream.path]; if (!contents) { var ab = reader.readAsArrayBuffer(stream.node.contents); contents = blobcache[stream.path] = new Uint8Array(ab); } if (position + length > contents.length) length = contents.length - position; for (var i = 0; i < length; i++) { buffer[offset + i] = contents[position + i]; } return length; }; } exports.setupFS = setupFS; var print_fn = function (s) { console.log(s); //console.log(new Error().stack); }; exports.print_fn = print_fn; function setupStdin(fs, code) { var i = 0; fs.init(function () { return i < code.length ? code.charCodeAt(i++) : null; }); } exports.setupStdin = setupStdin; //# sourceMappingURL=wasmutils.js.map