eaglercraft-1.8/sources/wasm-gc-teavm/js/platformRuntime.js

216 lines
5.5 KiB
JavaScript

/*
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
const platfRuntimeName = "platformRuntime";
var allowImmediateContinue = false;
const immediateContinueChannel = new MessageChannel();
var immediateContinueHandler = null;
immediateContinueChannel.port2.addEventListener("message", function(evt) {
immediateContinueHandler();
});
async function initializePlatfRuntime() {
immediateContinueChannel.port1.start();
immediateContinueChannel.port2.start();
immediateContinueHandler = function() {
immediateContinueHandler = null;
};
immediateContinueChannel.port1.postMessage(0);
if(immediateContinueHandler) {
await new Promise(function(resolve) {
setTimeout(function() {
if(!immediateContinueHandler) {
allowImmediateContinue = true;
}else {
eagError("Immediate continue hack is not supported");
}
resolve();
}, 25);
});
}else {
eagError("Immediate continue hack is not supported");
}
}
/**
* @return {HTMLElement}
*/
eagruntimeImpl.platformRuntime["getRootElement"] = function() {
return rootElement;
};
/**
* @return {HTMLElement}
*/
eagruntimeImpl.platformRuntime["getParentElement"] = function() {
return parentElement;
};
/**
* @return {HTMLCanvasElement}
*/
eagruntimeImpl.platformRuntime["getCanvasElement"] = function() {
return canvasElement;
};
/**
* @return {Object}
*/
eagruntimeImpl.platformRuntime["getEaglercraftXOpts"] = function() {
return eaglercraftXOpts;
};
eagruntimeImpl.platformRuntime["getEventCount"] = mainEventQueue.getLength.bind(mainEventQueue);
eagruntimeImpl.platformRuntime["getNextEvent"] = mainEventQueue.shift.bind(mainEventQueue);
const EVENT_RUNTIME_ASYNC_DOWNLOAD = 0;
/**
* @param {string} uri
* @param {number} forceCache
* @param {number} id
*/
eagruntimeImpl.platformRuntime["queueAsyncDownload"] = function(uri, forceCache, id) {
try {
fetch(uri, /** @type {!RequestInit} */ ({
"cache": forceCache ? "force-cache" : "no-store",
"mode": "cors"
})).then(function(res) {
return res.arrayBuffer();
}).then(function(arr) {
pushEvent(EVENT_TYPE_RUNTIME, EVENT_RUNTIME_ASYNC_DOWNLOAD, {
"requestId": id,
"arrayBuffer": arr
});
}).catch(function(err) {
eagError("Failed to complete async download: {}", uri);
eagStackTrace(ERROR, "Exception Caught", /** @type {Error} */ (err));
pushEvent(EVENT_TYPE_RUNTIME, EVENT_RUNTIME_ASYNC_DOWNLOAD, {
"requestId": id,
"arrayBuffer": null
});
});
}catch(/** Error */ ex) {
eagError("Failed to fetch: {}", uri);
eagStackTrace(ERROR, "Exception Caught", ex);
pushEvent(EVENT_TYPE_RUNTIME, EVENT_RUNTIME_ASYNC_DOWNLOAD, {
"requestId": id,
"arrayBuffer": null
});
}
};
/**
* @param {string} uri
* @param {number} forceCache
* @return {Promise}
*/
function downloadImpl(uri, forceCache) {
return new Promise(function(resolve) {
try {
fetch(uri, /** @type {!RequestInit} */ ({
"cache": forceCache ? "force-cache" : "no-store",
"mode": "cors"
})).then(function(res) {
return res.arrayBuffer();
}).then(function(arr) {
resolve(arr);
}).catch(function(err) {
eagError("Failed to complete download: {}", uri);
eagStackTrace(ERROR, "Exception Caught", /** @type {Error} */ (err));
resolve(null);
});
}catch(/** Error */ ex) {
eagError("Failed to fetch: {}", uri);
eagStackTrace(ERROR, "Exception Caught", ex);
resolve(null);
}
});
}
eagruntimeImpl.platformRuntime["download"] = new WebAssembly.Suspending(downloadImpl);
/**
* @param {string} crashDump
*/
eagruntimeImpl.platformRuntime["writeCrashReport"] = function(crashDump) {
displayCrashReport(crashDump, false);
};
eagruntimeImpl.platformRuntime["steadyTimeMillis"] = performance.now.bind(performance);
/**
* @param {number} millis
* @return {Promise}
*/
function sleepImpl(millis) {
return new Promise(function(resolve) {
setTimeout(resolve, millis);
});
}
eagruntimeImpl.platformRuntime["sleep"] = new WebAssembly.Suspending(sleepImpl);
function immediateContinueResolver(resolve) {
if(allowImmediateContinue) {
immediateContinueHandler = resolve;
immediateContinueChannel.port1.postMessage(0);
}else {
setTimeout(resolve, 0);
}
}
/**
* @return {Promise}
*/
function immediateContinueImpl() {
return new Promise(immediateContinueResolver);
}
/**
* @return {Promise}
*/
function swapDelayImpl() {
if(!runtimeOpts.useDelayOnSwap) {
return immediateContinueImpl();
}else {
return sleepImpl(0);
}
}
eagruntimeImpl.platformRuntime["immediateContinue"] = new WebAssembly.Suspending(immediateContinueImpl);
/**
* @return {boolean}
*/
eagruntimeImpl.platformRuntime["immediateContinueSupported"] = function() {
return allowImmediateContinue;
};
/**
* @param {number} id
* @param {string} str
*/
eagruntimeImpl.platformRuntime["setCrashReportString"] = function(id, str) {
crashReportStrings[id] = str;
};