From 673a17fa11c5b59c58de886f12bf5d86b0728644 Mon Sep 17 00:00:00 2001 From: Pablo Escobar Date: Sat, 7 Nov 2020 16:15:18 +0100 Subject: [PATCH] Platform: allow to reuse existing Emscripten Module properties. By wrapping the module creation in a function that includes properties from the original module as well as allowing to override the default properties from the outside. This also means it's possible to create differently named modules for multiple applications on the page. --- src/Magnum/Platform/EmscriptenApplication.js | 149 +++++++++------- .../WindowlessEmscriptenApplication.js | 159 ++++++++++-------- 2 files changed, 177 insertions(+), 131 deletions(-) diff --git a/src/Magnum/Platform/EmscriptenApplication.js b/src/Magnum/Platform/EmscriptenApplication.js index 4e77f9b0a..48ce2f79d 100644 --- a/src/Magnum/Platform/EmscriptenApplication.js +++ b/src/Magnum/Platform/EmscriptenApplication.js @@ -25,70 +25,93 @@ "use strict"; /* it summons the Cthulhu in a proper way, they say */ -var Module = { - preRun: [], - postRun: [], - - arguments: [], - - printErr: function(message) { - console.error(Array.prototype.slice.call(arguments).join(' ')); - }, - - print: function(message) { - console.log(Array.prototype.slice.call(arguments).join(' ')); - }, - - onAbort: function() { - Module.canvas.style.opacity = 0.333; - Module.canvas.style.zIndex = -1; - Module.setStatus("Oops :("); - Module.setStatusDescription("The app crashed. Refresh the page or check the browser console for details."); - }, - - canvas: document.getElementById('canvas'), - status: document.getElementById('status'), - statusDescription: document.getElementById('status-description'), - - setStatus: function(message) { - /* Emscripten calls setStatus("") after a timeout even if the app - aborts. That would erase the crash message, so don't allow that */ - if(Module.status && Module.status.innerHTML != "Oops :(") - Module.status.innerHTML = message; - }, - - setStatusDescription: function(message) { - if(Module.statusDescription) - Module.statusDescription.innerHTML = message; - }, - - totalDependencies: 0, - - monitorRunDependencies: function(left) { - this.totalDependencies = Math.max(this.totalDependencies, left); - - if(left) { - Module.setStatus('Downloading...'); - Module.setStatusDescription((this.totalDependencies - left) + ' / ' + this.totalDependencies); - } else { - Module.setStatus('Download complete'); - Module.setStatusDescription(''); +function createMagnumModule(init) { + /* Take the Emscripten-supplied Module object as a base */ + const module = Object.assign({}, Module); + + /* Update it with our things */ + Object.assign(module, { + preRun: [], + postRun: [], + + arguments: [], + + printErr: function(_message) { + console.error(Array.prototype.slice.call(arguments).join(' ')); + }, + + print: function(_message) { + console.log(Array.prototype.slice.call(arguments).join(' ')); + }, + + onAbort: function() { + module.canvas.style.opacity = 0.333; + module.canvas.style.zIndex = -1; + module.setStatus("Oops :("); + module.setStatusDescription("The app crashed. Refresh the page or check the browser console for details."); + }, + + canvas: document.getElementById('canvas'), + status: document.getElementById('status'), + statusDescription: document.getElementById('status-description'), + + setStatus: function(message) { + /* Emscripten calls setStatus("") after a timeout even if the app + aborts. That would erase the crash message, so don't allow that */ + if(module.status && module.status.innerHTML != "Oops :(") + module.status.innerHTML = message; + }, + + setStatusDescription: function(message) { + if(module.statusDescription) + module.statusDescription.innerHTML = message; + }, + + totalDependencies: 0, + + monitorRunDependencies: function(left) { + this.totalDependencies = Math.max(this.totalDependencies, left); + + if(left) { + module.setStatus('Downloading...'); + module.setStatusDescription((this.totalDependencies - left) + ' / ' + this.totalDependencies); + } else { + module.setStatus('Download complete'); + module.setStatusDescription(''); + } } + }); + + /* Parse arguments, e.g. /app/?foo=bar&fizz&buzz=3 goes to the app as + ['--foo', 'bar', '--fizz', '--buzz', '3'] */ + const args = decodeURIComponent(window.location.search.substr(1)).trim().split('&'); + for(let i = 0; i != args.length; ++i) { + let j = args[i].indexOf('='); + /* Key + value */ + if(j != -1) { + module.arguments.push('--' + args[i].substring(0, j)); + module.arguments.push(args[i].substring(j + 1)); + + /* Just key */ + } else module.arguments.push('--' + args[i]); } -}; - -/* Parse arguments, e.g. /app/?foo=bar&fizz&buzz=3 goes to the app as - ['--foo', 'bar', '--fizz', '--buzz', '3'] */ -var args = decodeURIComponent(window.location.search.substr(1)).trim().split('&'); -for(var i = 0; i != args.length; ++i) { - var j = args[i].indexOf('='); - /* Key + value */ - if(j != -1) { - Module.arguments.push('--' + args[i].substring(0, j)); - Module.arguments.push(args[i].substring(j + 1)); - - /* Just key */ - } else Module.arguments.push('--' + args[i]); + + /* Let the user-supplied object overwrite all the above */ + Object.assign(module, init); + + /* We can do this here because at this point `module.status` should be correct */ + module.setStatus("Downloading..."); + + return module; } -Module.setStatus('Downloading...'); +/* Default global Module object */ +var Module = createMagnumModule(); + +/* UMD export */ +if(typeof exports === 'object' && typeof module === 'object') /* CommonJS/Node */ + module.exports = createMagnumModule; +else if(typeof define === 'function' && define['amd']) /* AMD */ + define([], function() { return createMagnumModule; }); +else if(typeof exports === 'object') /* CommonJS strict */ + exports["createMagnumModule"] = createMagnumModule; diff --git a/src/Magnum/Platform/WindowlessEmscriptenApplication.js b/src/Magnum/Platform/WindowlessEmscriptenApplication.js index 9ef86a063..810adf9ef 100644 --- a/src/Magnum/Platform/WindowlessEmscriptenApplication.js +++ b/src/Magnum/Platform/WindowlessEmscriptenApplication.js @@ -23,75 +23,98 @@ DEALINGS IN THE SOFTWARE. */ -var Module = { - preRun: [], - postRun: [], - - arguments: [], - - doNotCaptureKeyboard: true, - - printErr: function(message) { - var log = document.getElementById('log'); - log.innerHTML += Array.prototype.slice.call(arguments).join(' ') - .replace(/[\"&<>]/g, function (a) { - return { '"': '"', '&': '&', '<': '<', '>': '>' }[a]; - }) + '\n'; - }, - - print: function(message) { - var log = document.getElementById('log'); - log.innerHTML += Array.prototype.slice.call(arguments).join(' ') - .replace(/[\"&<>]/g, function (a) { - return { '"': '"', '&': '&', '<': '<', '>': '>' }[a]; - }) + '\n'; - }, - - /* onAbort not handled here, as the output is printed directly on the page */ - - canvas: document.getElementById('canvas'), - status: document.getElementById('status'), - statusDescription: document.getElementById('status-description'), - log: document.getElementById('log'), - - setStatus: function(message) { - if(Module.status) Module.status.innerHTML = message; - }, - - setStatusDescription: function(message) { - if(Module.statusDescription) - Module.statusDescription.innerHTML = message; - }, - - totalDependencies: 0, - - monitorRunDependencies: function(left) { - this.totalDependencies = Math.max(this.totalDependencies, left); - - if(left) { - Module.setStatus('Downloading...'); - Module.setStatusDescription((this.totalDependencies - left) + ' / ' + this.totalDependencies); - } else { - Module.setStatus('Download complete'); - Module.setStatusDescription(''); - Module.log.style.display = 'block'; +"use strict"; + +function createMagnumModule(init) { + const module = Object.assign({}, Module); + + Object.assign(module, { + preRun: [], + postRun: [], + + arguments: [], + + printErr: function(_message) { + if(module.log) { + module.log.innerHTML += Array.prototype.slice.call(arguments).join(' ') + .replace(/[\"&<>]/g, function (a) { + return { '"': '"', '&': '&', '<': '<', '>': '>' }[a]; + }) + '\n'; + } + }, + + print: function(_message) { + if(module.log) { + module.log.innerHTML += Array.prototype.slice.call(arguments).join(' ') + .replace(/[\"&<>]/g, function (a) { + return { '"': '"', '&': '&', '<': '<', '>': '>' }[a]; + }) + '\n'; + } + }, + + /* onAbort not handled here, as the output is printed directly on the page */ + + canvas: document.getElementById('canvas'), + status: document.getElementById('status'), + statusDescription: document.getElementById('status-description'), + log: document.getElementById('log'), + + setStatus: function(message) { + if(module.status) + module.status.innerHTML = message; + }, + + setStatusDescription: function(message) { + if(module.statusDescription) + module.statusDescription.innerHTML = message; + }, + + totalDependencies: 0, + + monitorRunDependencies: function(left) { + this.totalDependencies = Math.max(this.totalDependencies, left); + + if(left) { + module.setStatus('Downloading...'); + module.setStatusDescription((this.totalDependencies - left) + ' / ' + this.totalDependencies); + } else { + module.setStatus('Download complete'); + module.setStatusDescription(''); + module.log.style.display = 'block'; + } } + }); + + /* Parse arguments, e.g. /app/?foo=bar&fizz&buzz=3 goes to the app as + ['--foo', 'bar', '--fizz', '--buzz', '3'] */ + const args = decodeURIComponent(window.location.search.substr(1)).trim().split('&'); + for(let i = 0; i != args.length; ++i) { + let j = args[i].indexOf('='); + /* Key + value */ + if(j != -1) { + module.arguments.push('--' + args[i].substring(0, j)); + module.arguments.push(args[i].substring(j + 1)); + + /* Just key */ + } else module.arguments.push('--' + args[i]); } -}; - -/* Parse arguments, e.g. /app/?foo=bar&fizz&buzz=3 goes to the app as - ['--foo', 'bar', '--fizz', '--buzz', '3'] */ -var args = decodeURIComponent(window.location.search.substr(1)).trim().split('&'); -for(var i = 0; i != args.length; ++i) { - var j = args[i].indexOf('='); - /* Key + value */ - if(j != -1) { - Module.arguments.push('--' + args[i].substring(0, j)); - Module.arguments.push(args[i].substring(j + 1)); - - /* Just key */ - } else Module.arguments.push('--' + args[i]); + + Object.assign(module, init); + + module.setStatus("Downloading..."); + if(module.log) + module.log.style.display = 'none'; + + return module; } -Module.setStatus('Downloading...'); -Module.log.style.display = 'none'; +/* Default global Module object */ +var Module = createMagnumModule(); + +/* UMD export */ +if(typeof exports === 'object' && typeof module === 'object') /* CommonJS/Node */ + module.exports = createMagnumModule; +else if(typeof define === 'function' && define['amd']) /* AMD */ + define([], function() { return createMagnumModule; }); +else if(typeof exports === 'object') /* CommonJS strict */ + exports["createMagnumModule"] = createMagnumModule;