Looking into the console, it says that this is indeed the main.js that is loading the c3runtime.js. The main.js file is very large, but I think I found the piece of code that would load the other script (that I add below).
‘use strict’; {
const isiOSLike = /(iphone|ipod|ipad|macos|macintosh|mac os x)/i.test(navigator.userAgent);
function AddScript(url) {
if (url.isStringSrc) {
const elem = document.createElement("script");
elem.async = false;
elem.textContent = url.str;
document.head.appendChild(elem)
} else return new Promise((resolve, reject) => {
const elem = document.createElement("script");
elem.onload = resolve;
elem.onerror = reject;
elem.async = false;
elem.src = url;
document.head.appendChild(elem)
})
}
let tmpAudio = new Audio;
const supportedAudioFormats = {
"audio/webm; codecs=opus": !!tmpAudio.canPlayType("audio/webm; codecs=opus"),
"audio/ogg; codecs=opus": !!tmpAudio.canPlayType("audio/ogg; codecs=opus"),
"audio/webm; codecs=vorbis": !!tmpAudio.canPlayType("audio/webm; codecs=vorbis"),
"audio/ogg; codecs=vorbis": !!tmpAudio.canPlayType("audio/ogg; codecs=vorbis"),
"audio/mp4": !!tmpAudio.canPlayType("audio/mp4"),
"audio/mpeg": !!tmpAudio.canPlayType("audio/mpeg")
};
tmpAudio = null;
async function BlobToString(blob) {
const arrayBuffer = await BlobToArrayBuffer(blob);
const textDecoder = new TextDecoder("utf-8");
return textDecoder.decode(arrayBuffer)
}
function BlobToArrayBuffer(blob) {
return new Promise((resolve, reject) => {
const fileReader = new FileReader;
fileReader.onload = e => resolve(e.target.result);
fileReader.onerror = err => reject(err);
fileReader.readAsArrayBuffer(blob)
})
}
const queuedArrayBufferReads = [];
let activeArrayBufferReads = 0;
const MAX_ARRAYBUFFER_READS = 8;
window["RealFile"] = window["File"];
const domHandlerClasses = [];
const runtimeEventHandlers = new Map;
const pendingResponsePromises =
new Map;
let nextResponseId = 0;
const runOnStartupFunctions = [];
self.runOnStartup = function runOnStartup(f) {
if (typeof f !== "function") throw new Error("runOnStartup called without a function");
runOnStartupFunctions.push(f)
};
const WEBVIEW_EXPORT_TYPES = new Set(["cordova", "playable-ad", "instant-games"]);
function IsWebViewExportType(exportType) {
return WEBVIEW_EXPORT_TYPES.has(exportType)
}
window.RuntimeInterface = class RuntimeInterface {
constructor(opts) {
this._useWorker = opts.useWorker;
this._messageChannelPort =
null;
this._baseUrl = "";
this._scriptFolder = opts.scriptFolder;
this._workerScriptBlobURLs = {};
this._worker = null;
this._localRuntime = null;
this._domHandlers = [];
this._runtimeDomHandler = null;
this._canvas = null;
this._jobScheduler = null;
this._rafId = -1;
this._rafFunc = () => this._OnRAFCallback();
this._rafCallbacks = [];
this._exportType = opts.exportType;
if (this._useWorker && (typeof OffscreenCanvas === "undefined" || !navigator["userActivation"])) this._useWorker = false;
if (IsWebViewExportType(this._exportType) && this._useWorker) {
console.warn("[C3 runtime] Worker mode is enabled and supported, but is disabled in WebViews due to crbug.com/923007. Reverting to DOM mode.");
this._useWorker = false
}
this._transferablesBroken = false;
this._localFileBlobs = null;
this._localFileStrings = null;
if ((this._exportType === "html5" || this._exportType === "playable-ad") && location.protocol.substr(0, 4) === "file") alert("Exported games won't work until you upload them. (When running on the file: protocol, browsers block many features from working for security reasons.)");
this.AddRuntimeComponentMessageHandler("runtime", "cordova-fetch-local-file", e => this._OnCordovaFetchLocalFile(e));
this.AddRuntimeComponentMessageHandler("runtime",
"create-job-worker", e => this._OnCreateJobWorker(e));
if (this._exportType === "cordova") document.addEventListener("deviceready", () => this._Init(opts));
else this._Init(opts)
}
Release() {
this._CancelAnimationFrame();
if (this._messageChannelPort) {
this._messageChannelPort.onmessage = null;
this._messageChannelPort = null
}
if (this._worker) {
this._worker.terminate();
this._worker = null
}
if (this._localRuntime) {
this._localRuntime.Release();
this._localRuntime = null
}
if (this._canvas) {
this._canvas.parentElement.removeChild(this._canvas);
this._canvas = null
}
}
GetCanvas() {
return this._canvas
}
GetBaseURL() {
return this._baseUrl
}
UsesWorker() {
return this._useWorker
}
GetExportType() {
return this._exportType
}
IsiOSCordova() {
return isiOSLike && this._exportType === "cordova"
}
IsiOSWebView() {
return isiOSLike && IsWebViewExportType(this._exportType) || navigator["standalone"]
}
async _Init(opts) {
if (this._exportType === "playable-ad") {
this._localFileBlobs = self["c3_base64files"];
this._localFileStrings = {};
await this._ConvertDataUrisToBlobs();
for (let i = 0, len = opts.engineScripts.length; i <
len; ++i) {
const src = opts.engineScripts[i].toLowerCase();
if (this._localFileStrings.hasOwnProperty(src)) opts.engineScripts[i] = {
isStringSrc: true,
str: this._localFileStrings[src]
};
else if (this._localFileBlobs.hasOwnProperty(src)) opts.engineScripts[i] = URL.createObjectURL(this._localFileBlobs[src])
}
}
if (opts.baseUrl) this._baseUrl = opts.baseUrl;
else {
const origin = location.origin;
this._baseUrl = (origin === "null" ? "file:///" : origin) + location.pathname;
const i = this._baseUrl.lastIndexOf("/");
if (i !== -1) this._baseUrl =
this._baseUrl.substr(0, i + 1)
}
if (opts.workerScripts)
for (const [url, blob] of Object.entries(opts.workerScripts)) this._workerScriptBlobURLs[url] = URL.createObjectURL(blob);
const messageChannel = new MessageChannel;
this._messageChannelPort = messageChannel.port1;
this._messageChannelPort.onmessage = e => this["_OnMessageFromRuntime"](e.data);
if (window["c3_addPortMessageHandler"]) window["c3_addPortMessageHandler"](e => this._OnMessageFromDebugger(e));
this._jobScheduler = new self.JobSchedulerDOM(this);
await this._jobScheduler.Init();
this.MaybeForceBodySize();
if (typeof window["StatusBar"] === "object") window["StatusBar"]["hide"]();
if (typeof window["AndroidFullScreen"] === "object") window["AndroidFullScreen"]["immersiveMode"]();
await this._TestTransferablesWork();
if (this._useWorker) await this._InitWorker(opts, messageChannel.port2);
else await this._InitDOM(opts, messageChannel.port2)
}
_GetWorkerURL(url) {
if (this._workerScriptBlobURLs.hasOwnProperty(url)) return this._workerScriptBlobURLs[url];
else if (url.endsWith("/workermain.js") && this._workerScriptBlobURLs.hasOwnProperty("workermain.js")) return this._workerScriptBlobURLs["workermain.js"];
else if (this._exportType === "playable-ad" && this._localFileBlobs.hasOwnProperty(url.toLowerCase())) return URL.createObjectURL(this._localFileBlobs[url.toLowerCase()]);
else return url
}
async CreateWorker(url, baseUrl, workerOpts) {
if (url.startsWith("blob:")) return new Worker(url, workerOpts);
if (this.IsiOSCordova() && location.protocol === "file:") {
const arrayBuffer = await this.CordovaFetchLocalFileAsArrayBuffer(this._scriptFolder + url);
const blob = new Blob([arrayBuffer], {
type: "application/javascript"
});
return new Worker(URL.createObjectURL(blob),
workerOpts)
}
const absUrl = new URL(url, baseUrl);
const isCrossOrigin = location.origin !== absUrl.origin;
if (isCrossOrigin) {
const response = await fetch(absUrl);
if (!response.ok) throw new Error("failed to fetch worker script");
const blob = await response.blob();
return new Worker(URL.createObjectURL(blob), workerOpts)
} else return new Worker(absUrl, workerOpts)
}
MaybeForceBodySize() {
if (this.IsiOSWebView()) {
const docStyle = document["documentElement"].style;
const bodyStyle = document["body"].style;
const isPortrait = window.innerWidth <
window.innerHeight;
const width = isPortrait ? window["screen"]["width"] : window["screen"]["height"];
const height = isPortrait ? window["screen"]["height"] : window["screen"]["width"];
bodyStyle["height"] = docStyle["height"] = height + "px";
bodyStyle["width"] = docStyle["width"] = width + "px"
}
}
_GetCommonRuntimeOptions(opts) {
return {
"baseUrl": this._baseUrl,
"windowInnerWidth": window.innerWidth,
"windowInnerHeight": window.innerHeight,
"devicePixelRatio": window.devicePixelRatio,
"isFullscreen": RuntimeInterface.IsDocumentFullscreen(),
"projectData": opts.projectData,
"previewImageBlobs": window["cr_previewImageBlobs"] || this._localFileBlobs,
"previewProjectFileBlobs": window["cr_previewProjectFileBlobs"],
"exportType": opts.exportType,
"isDebug": self.location.search.indexOf("debug") > -1,
"ife": !!self.ife,
"jobScheduler": this._jobScheduler.GetPortData(),
"supportedAudioFormats": supportedAudioFormats,
"opusWasmScriptUrl": window["cr_opusWasmScriptUrl"] || this._scriptFolder + "opus.wasm.js",
"opusWasmBinaryUrl": window["cr_opusWasmBinaryUrl"] || this._scriptFolder +
"opus.wasm.wasm",
"isiOSCordova": this.IsiOSCordova(),
"isiOSWebView": this.IsiOSWebView(),
"isFBInstantAvailable": typeof self["FBInstant"] !== "undefined"
}
}
async _InitWorker(opts, port2) {
const workerMainUrl = this._GetWorkerURL(opts.workerMainUrl);
this._worker = await this.CreateWorker(workerMainUrl, this._baseUrl, {
name: "Runtime"
});
this._canvas = document.createElement("canvas");
this._canvas.style.display = "none";
const offscreenCanvas = this._canvas["transferControlToOffscreen"]();
document.body.appendChild(this._canvas);
window["c3canvas"] = this._canvas;
this._worker.postMessage(Object.assign(this._GetCommonRuntimeOptions(opts), {
"type": "init-runtime",
"isInWorker": true,
"messagePort": port2,
"canvas": offscreenCanvas,
"workerDependencyScripts": opts.workerDependencyScripts || [],
"engineScripts": opts.engineScripts,
"projectScripts": window.cr_allProjectScripts,
"projectScriptsStatus": self["C3_ProjectScriptsStatus"]
}), [port2, offscreenCanvas, ...this._jobScheduler.GetPortTransferables()]);
this._domHandlers = domHandlerClasses.map(C =>
new C(this));
this._FindRuntimeDOMHandler();
self["c3_callFunction"] = (name, params) => this._runtimeDomHandler._InvokeFunctionFromJS(name, params);
if (this._exportType === "preview") self["goToLastErrorScript"] = () => this.PostToRuntimeComponent("runtime", "go-to-last-error-script")
}
async _InitDOM(opts, port2) {
this._canvas = document.createElement("canvas");
this._canvas.style.display = "none";
document.body.appendChild(this._canvas);
window["c3canvas"] = this._canvas;
this._domHandlers = domHandlerClasses.map(C => new C(this));
this._FindRuntimeDOMHandler();
const engineScripts = opts.engineScripts.map(url => typeof url === "string" ? (new URL(url, this._baseUrl)).toString() : url);
if (Array.isArray(opts.workerDependencyScripts)) engineScripts.unshift(...opts.workerDependencyScripts);
await Promise.all(engineScripts.map(url => AddScript(url)));
if (opts.projectScripts && opts.projectScripts.length > 0) {
const scriptsStatus = self["C3_ProjectScriptsStatus"];
try {
await Promise.all(opts.projectScripts.map(e => AddScript(e[1])));
if (Object.values(scriptsStatus).some(f =>
!f)) {
self.setTimeout(() => this._ReportProjectScriptError(scriptsStatus), 100);
return
}
} catch (err) {
console.error("[Preview] Error loading project scripts: ", err);
self.setTimeout(() => this._ReportProjectScriptError(scriptsStatus), 100);
return
}
}
if (this._exportType === "preview" && typeof self.C3.ScriptsInEvents !== "object") {
const msg = "Failed to load JavaScript code used in events. Check all your JavaScript code has valid syntax.";
console.error("[C3 runtime] " + msg);
alert(msg);
return
}
const runtimeOpts = Object.assign(this._GetCommonRuntimeOptions(opts), {
"isInWorker": false,
"messagePort": port2,
"canvas": this._canvas,
"runOnStartupFunctions": runOnStartupFunctions
});
this._localRuntime = self["C3_CreateRuntime"](runtimeOpts);
await self["C3_InitRuntime"](this._localRuntime, runtimeOpts)
}
_ReportProjectScriptError(scriptsStatus) {
const failedScripts = Object.entries(scriptsStatus).filter(e => !e[1]).map(e => e[0]);
const msg = `Failed to load project script '${failedScripts[0]}'. Check all your JavaScript code has valid syntax.`;
console.error("[Preview] " + msg);
alert(msg)
}
async _OnCreateJobWorker(e) {
const outputPort =
await this._jobScheduler._CreateJobWorker();
return {
"outputPort": outputPort,
"transferables": [outputPort]
}
}
_GetLocalRuntime() {
if (this._useWorker) throw new Error("not available in worker mode");
return this._localRuntime
}
PostToRuntimeComponent(component, handler, data, dispatchOpts, transferables) {
this._messageChannelPort.postMessage({
"type": "event",
"component": component,
"handler": handler,
"dispatchOpts": dispatchOpts || null,
"data": data,
"responseId": null
}, this._transferablesBroken ? void 0 : transferables)
}
PostToRuntimeComponentAsync(component,
handler, data, dispatchOpts, transferables) {
const responseId = nextResponseId++;
const ret = new Promise((resolve, reject) => {
pendingResponsePromises.set(responseId, {
resolve,
reject
})
});
this._messageChannelPort.postMessage({
"type": "event",
"component": component,
"handler": handler,
"dispatchOpts": dispatchOpts || null,
"data": data,
"responseId": responseId
}, this._transferablesBroken ? void 0 : transferables);
return ret
}["_OnMessageFromRuntime"](data) {
const type = data["type"];
if (type === "event") return this._OnEventFromRuntime(data);
else if (type === "result") this._OnResultFromRuntime(data);
else if (type === "runtime-ready") this._OnRuntimeReady();
else if (type === "alert") alert(data["message"]);
else throw new Error(`unknown message '${type}'`);
}
_OnEventFromRuntime(e) {
const component = e["component"];
const handler = e["handler"];
const data = e["data"];
const responseId = e["responseId"];
const handlerMap = runtimeEventHandlers.get(component);
if (!handlerMap) {
console.warn(`[DOM] No event handlers for component '${component}'`);
return
}
const func = handlerMap.get(handler);
if (!func) {
console.warn(`[DOM] No handler '${handler}' for component '${component}'`);
return
}
let ret = null;
try {
ret = func(data)
} catch (err) {
console.error(`Exception in '${component}' handler '${handler}':`, err);
if (responseId !== null) this._PostResultToRuntime(responseId, false, "" + err);
return
}
if (responseId === null) return ret;
else if (ret && ret.then) ret.then(result => this._PostResultToRuntime(responseId, true, result)).catch(err => {
console.error(`Rejection from '${component}' handler '${handler}':`, err);
this._PostResultToRuntime(responseId,
false, "" + err)
});
else this._PostResultToRuntime(responseId, true, ret)
}
_PostResultToRuntime(responseId, isOk, result) {
let transferables;
if (result && result["transferables"]) transferables = result["transferables"];
this._messageChannelPort.postMessage({
"type": "result",
"responseId": responseId,
"isOk": isOk,
"result": result
}, transferables)
}
_OnResultFromRuntime(data) {
const responseId = data["responseId"];
const isOk = data["isOk"];
const result = data["result"];
const pendingPromise = pendingResponsePromises.get(responseId);
if (isOk) pendingPromise.resolve(result);
else pendingPromise.reject(result);
pendingResponsePromises.delete(responseId)
}
AddRuntimeComponentMessageHandler(component, handler, func) {
let handlerMap = runtimeEventHandlers.get(component);
if (!handlerMap) {
handlerMap = new Map;
runtimeEventHandlers.set(component, handlerMap)
}
if (handlerMap.has(handler)) throw new Error(`[DOM] Component '${component}' already has handler '${handler}'`);
handlerMap.set(handler, func)
}
static AddDOMHandlerClass(Class) {
if (domHandlerClasses.includes(Class)) throw new Error("DOM handler already added");
domHandlerClasses.push(Class)
}
_FindRuntimeDOMHandler() {
for (const dh of this._domHandlers)
if (dh.GetComponentID() === "runtime") {
this._runtimeDomHandler = dh;
return
}
throw new Error("cannot find runtime DOM handler");
}
_OnMessageFromDebugger(e) {
this.PostToRuntimeComponent("debugger", "message", e)
}
_OnRuntimeReady() {
for (const h of this._domHandlers) h.Attach()
}
static IsDocumentFullscreen() {
return !!(document["fullscreenElement"] || document["webkitFullscreenElement"] || document["mozFullScreenElement"])
}
async GetRemotePreviewStatusInfo() {
return await this.PostToRuntimeComponentAsync("runtime",
"get-remote-preview-status-info")
}
_AddRAFCallback(f) {
this._rafCallbacks.push(f);
this._RequestAnimationFrame()
}
_RemoveRAFCallback(f) {
const i = this._rafCallbacks.indexOf(f);
if (i === -1) throw new Error("invalid callback");
this._rafCallbacks.splice(i, 1);
if (!this._rafCallbacks.length) this._CancelAnimationFrame()
}
_RequestAnimationFrame() {
if (this._rafId === -1 && this._rafCallbacks.length) this._rafId = requestAnimationFrame(this._rafFunc)
}
_CancelAnimationFrame() {
if (this._rafId !== -1) {
cancelAnimationFrame(this._rafId);
this._rafId = -1
}
}
_OnRAFCallback() {
this._rafId = -1;
for (const f of this._rafCallbacks) f();
this._RequestAnimationFrame()
}
TryPlayMedia(mediaElem) {
this._runtimeDomHandler.TryPlayMedia(mediaElem)
}
RemovePendingPlay(mediaElem) {
this._runtimeDomHandler.RemovePendingPlay(mediaElem)
}
_PlayPendingMedia() {
this._runtimeDomHandler._PlayPendingMedia()
}
SetSilent(s) {
this._runtimeDomHandler.SetSilent(s)
}
IsAudioFormatSupported(typeStr) {
return !!supportedAudioFormats[typeStr]
}
async _WasmDecodeWebMOpus(arrayBuffer) {
const result =
await this.PostToRuntimeComponentAsync("runtime", "opus-decode", {
"arrayBuffer": arrayBuffer
}, null, [arrayBuffer]);
return new Float32Array(result)
}
IsAbsoluteURL(url) {
return /^(?:[a-z]+:)?\/\//.test(url) || url.substr(0, 5) === "data:" || url.substr(0, 5) === "blob:"
}
IsRelativeURL(url) {
return !this.IsAbsoluteURL(url)
}
async _OnCordovaFetchLocalFile(e) {
const filename = e["filename"];
switch (e["as"]) {
case "text":
return await this.CordovaFetchLocalFileAsText(filename);
case "buffer":
return await this.CordovaFetchLocalFileAsArrayBuffer(filename);
default:
throw new Error("unsupported type");
}
}
_GetPermissionAPI() {
const api = window["cordova"] && window["cordova"]["plugins"] && window["cordova"]["plugins"]["permissions"];
if (typeof api !== "object") throw new Error("Permission API is not loaded");
return api
}
_MapPermissionID(api, permission) {
const permissionID = api[permission];
if (typeof permissionID !== "string") throw new Error("Invalid permission name");
return permissionID
}
_HasPermission(id) {
const api = this._GetPermissionAPI();
return new Promise((resolve, reject) =>
api["checkPermission"](this._MapPermissionID(api, id), status => resolve(!!status["hasPermission"]), reject))
}
_RequestPermission(id) {
const api = this._GetPermissionAPI();
return new Promise((resolve, reject) => api["requestPermission"](this._MapPermissionID(api, id), status => resolve(!!status["hasPermission"]), reject))
}
async RequestPermissions(permissions) {
if (this.GetExportType() !== "cordova") return true;
if (this.IsiOSCordova()) return true;
for (const id of permissions) {
const alreadyGranted = await this._HasPermission(id);
if (alreadyGranted) continue;
const granted = await this._RequestPermission(id);
if (granted === false) return false
}
return true
}
async RequirePermissions(...permissions) {
if (await this.RequestPermissions(permissions) === false) throw new Error("Permission not granted");
}
CordovaFetchLocalFile(filename) {
const path = window["cordova"]["file"]["applicationDirectory"] + "www/" + filename.toLowerCase();
return new Promise((resolve, reject) => {
window["resolveLocalFileSystemURL"](path, entry => {
entry["file"](resolve, reject)
}, reject)
})
}
async CordovaFetchLocalFileAsText(filename) {
const file =
await this.CordovaFetchLocalFile(filename);
return await BlobToString(file)
}
_CordovaMaybeStartNextArrayBufferRead() {
if (!queuedArrayBufferReads.length) return;
if (activeArrayBufferReads >= MAX_ARRAYBUFFER_READS) return;
activeArrayBufferReads++;
const job = queuedArrayBufferReads.shift();
this._CordovaDoFetchLocalFileAsAsArrayBuffer(job.filename, job.successCallback, job.errorCallback)
}
CordovaFetchLocalFileAsArrayBuffer(filename) {
return new Promise((resolve, reject) => {
queuedArrayBufferReads.push({
filename: filename,
successCallback: result => {
activeArrayBufferReads--;
this._CordovaMaybeStartNextArrayBufferRead();
resolve(result)
},
errorCallback: err => {
activeArrayBufferReads--;
this._CordovaMaybeStartNextArrayBufferRead();
reject(err)
}
});
this._CordovaMaybeStartNextArrayBufferRead()
})
}
async _CordovaDoFetchLocalFileAsAsArrayBuffer(filename, successCallback, errorCallback) {
try {
const file = await this.CordovaFetchLocalFile(filename);
const arrayBuffer = await BlobToArrayBuffer(file);
successCallback(arrayBuffer)
} catch (err) {
errorCallback(err)
}
}
async _ConvertDataUrisToBlobs() {
const promises = [];
for (const [filename, data] of Object.entries(this._localFileBlobs)) promises.push(this._ConvertDataUriToBlobs(filename, data));
await Promise.all(promises)
}
async _ConvertDataUriToBlobs(filename, data) {
if (typeof data === "object") {
this._localFileBlobs[filename] = new Blob([data["str"]], {
"type": data["type"]
});
this._localFileStrings[filename] = data["str"]
} else {
let blob = await this._FetchDataUri(data);
if (!blob) blob = this._DataURIToBinaryBlobSync(data);
this._localFileBlobs[filename] = blob
}
}
async _FetchDataUri(dataUri) {
try {
const response =
await fetch(dataUri);
return await response.blob()
} catch (err) {
console.warn("Failed to fetch a data: URI. Falling back to a slower workaround. This is probably because the Content Security Policy unnecessarily blocked it. Allow data: URIs in your CSP to avoid this.", err);
return null
}
}
_DataURIToBinaryBlobSync(datauri) {
const o = this._ParseDataURI(datauri);
return this._BinaryStringToBlob(o.data, o.mime_type)
}
_ParseDataURI(datauri) {
const comma = datauri.indexOf(",");
if (comma < 0) throw new URIError("expected comma in data: uri");
const typepart = datauri.substring(5, comma);
const datapart = datauri.substring(comma + 1);
const typearr = typepart.split(";");
const mimetype = typearr[0] || "";
const encoding1 = typearr[1];
const encoding2 = typearr[2];
let decodeddata;
if (encoding1 === "base64" || encoding2 === "base64") decodeddata = atob(datapart);
else decodeddata = decodeURIComponent(datapart);
return {
mime_type: mimetype,
data: decodeddata
}
}
_BinaryStringToBlob(binstr, mime_type) {
let len = binstr.length;
let len32 = len >> 2;
let a8 = new Uint8Array(len);
let a32 = new Uint32Array(a8.buffer,
0, len32);
let i, j;
for (i = 0, j = 0; i < len32; ++i) a32[i] = binstr.charCodeAt(j++) | binstr.charCodeAt(j++) << 8 | binstr.charCodeAt(j++) << 16 | binstr.charCodeAt(j++) << 24;
let tailLength = len & 3;
while (tailLength--) {
a8[j] = binstr.charCodeAt(j);
++j
}
return new Blob([a8], {
"type": mime_type
})
}
_TestTransferablesWork() {
let resolve = null;
const ret = new Promise(r => resolve = r);
const arrayBuffer = new ArrayBuffer(1);
const messageChannel = new MessageChannel;
messageChannel.port2.onmessage = e => {
if (!e.data || !e.data["arrayBuffer"]) {
this._transferablesBroken =
true;
console.warn("MessageChannel transfers determined to be broken. Disabling transferables.")
}
resolve()
};
messageChannel.port1.postMessage({
"arrayBuffer": arrayBuffer
}, [arrayBuffer]);
return ret
}
}
};