216 lines
5.5 KiB
JavaScript
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;
|
|
};
|