Spaces:
Build error
Build error
/* | |
* Copyright 2024 Alexey Andreev. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
/** @type {Object} */ | |
var wasmGC; | |
(function() { | |
let globalsCache = new Map(); | |
let exceptionFrameRegex = /.+:wasm-function\[[0-9]+]:0x([0-9a-f]+).*/; | |
/** | |
* @param {string} name | |
*/ | |
let getGlobalName = function(name) { | |
let result = globalsCache.get(name); | |
if (typeof result === "undefined") { | |
result = new Function("return " + name + ";"); | |
globalsCache.set(name, result); | |
} | |
return result(); | |
} | |
/** | |
* @param {string} name | |
* @param {Object} value | |
*/ | |
let setGlobalName = function(name, value) { | |
new Function("value", name + " = value;")(value); | |
} | |
/** | |
* @param {Object} imports | |
*/ | |
function defaults(imports) { | |
let context = { | |
/** @type {Object} */ | |
exports: null, | |
/** @type {function(number)|null} */ | |
stackDeobfuscator: null, | |
/** @type {function(function())|null} */ | |
asyncRunnableQueue: null | |
}; | |
dateImports(imports); | |
consoleImports(imports); | |
coreImports(imports, context); | |
jsoImports(imports, context); | |
imports["teavmMath"] = Math; | |
return { | |
supplyExports(/** Object */ exports) { | |
context.exports = exports; | |
}, | |
supplyStackDeobfuscator(/** function(number) */ deobfuscator) { | |
context.stackDeobfuscator = deobfuscator; | |
}, | |
supplyAsyncRunnableQueue(/** function(function()) */ queueFunc) { | |
context.asyncRunnableQueue = queueFunc; | |
} | |
} | |
} | |
let javaExceptionSymbol = Symbol("javaException"); | |
class JavaError extends Error { | |
constructor(context, javaException) { | |
super(); | |
this.context = context; | |
this[javaExceptionSymbol] = javaException; | |
context.exports["teavm.setJsException"](javaException, this); | |
} | |
get message() { | |
let exceptionMessage = this.context.exports["teavm.exceptionMessage"]; | |
if (typeof exceptionMessage === "function") { | |
let message = exceptionMessage(this[javaExceptionSymbol]); | |
if (message != null) { | |
return message; | |
} | |
} | |
return "(could not fetch message)"; | |
} | |
} | |
/** | |
* @param {Object} imports | |
*/ | |
function dateImports(imports) { | |
imports["teavmDate"] = { | |
"currentTimeMillis": () => new Date().getTime(), | |
"dateToString": (/** number */ timestamp) => new Date(timestamp).toString(), | |
"getYear": (/** number */ timestamp) => new Date(timestamp).getFullYear(), | |
"setYear": (/** number */ timestamp, /** number */ year) => { | |
let date = new Date(timestamp); | |
date.setFullYear(year); | |
return date.getTime(); | |
}, | |
"getMonth": (/** number */ timestamp) =>new Date(timestamp).getMonth(), | |
"setMonth": (/** number */ timestamp, /** number */ month) => { | |
let date = new Date(timestamp); | |
date.setMonth(month); | |
return date.getTime(); | |
}, | |
"getDate": (/** number */ timestamp) =>new Date(timestamp).getDate(), | |
"setDate": (/** number */ timestamp, /** number */ value) => { | |
let date = new Date(timestamp); | |
date.setDate(value); | |
return date.getTime(); | |
}, | |
"create": (/** number */ year, /** number */ month, /** number */ date, /** number */ hrs, /** number */ min, /** number */ sec) => new Date(year, month, date, hrs, min, sec).getTime(), | |
"createFromUTC": (/** number */ year, /** number */ month, /** number */ date, /** number */ hrs, /** number */ min, /** number */ sec) => Date.UTC(year, month, date, hrs, min, sec) | |
}; | |
} | |
/** | |
* @param {Object} imports | |
*/ | |
function consoleImports(imports) { | |
let stderr = []; | |
let stdout = []; | |
imports["teavmConsole"] = { | |
"putcharStderr": function(/** number */ c) { | |
if (c === 10) { | |
let stderrStr = String.fromCharCode(...stderr); | |
console.error(stderrStr); | |
if(currentRedirectorFunc) { | |
currentRedirectorFunc(stderrStr, true); | |
} | |
stderr.length = 0; | |
} else { | |
stderr.push(c); | |
} | |
}, | |
"putcharStdout": function(/** number */ c) { | |
if (c === 10) { | |
let stdoutStr = String.fromCharCode(...stdout); | |
console.log(stdoutStr); | |
if(currentRedirectorFunc) { | |
currentRedirectorFunc(stdoutStr, false); | |
} | |
stdout.length = 0; | |
} else { | |
stdout.push(c); | |
} | |
}, | |
}; | |
} | |
/** | |
* @param {Object} imports | |
* @param {Object} context | |
*/ | |
function coreImports(imports, context) { | |
let finalizationRegistry = new FinalizationRegistry(heldValue => { | |
let report = context.exports["teavm.reportGarbageCollectedValue"]; | |
if (typeof report !== "undefined") { | |
context.asyncRunnableQueue(function() { | |
report(heldValue.queue, heldValue.ref); | |
}); | |
} | |
}); | |
let stringFinalizationRegistry = new FinalizationRegistry(heldValue => { | |
let report = context.exports["teavm.reportGarbageCollectedString"]; | |
if (typeof report === "function") { | |
context.asyncRunnableQueue(function() { | |
report(heldValue); | |
}); | |
} | |
}); | |
imports["teavm"] = { | |
"createWeakRef": (value, ref, queue) => { | |
if (queue !== null) { | |
finalizationRegistry.register(value, { ref: ref, queue: queue }); | |
} | |
return new WeakRef(value); | |
}, | |
"deref": weakRef => weakRef.deref(), | |
"createStringWeakRef": (value, heldValue) => { | |
stringFinalizationRegistry.register(value, heldValue) | |
return new WeakRef(value); | |
}, | |
"stringDeref": weakRef => weakRef.deref(), | |
"takeStackTrace": () => { | |
let stack = new Error().stack; | |
let addresses = []; | |
for (let line of stack.split("\n")) { | |
let match = exceptionFrameRegex.exec(line); | |
if (match !== null && match.length >= 2) { | |
let address = parseInt(match[1], 16); | |
addresses.push(address); | |
} | |
} | |
return { | |
"getStack": function() { | |
let result; | |
if (context.stackDeobfuscator) { | |
try { | |
result = context.stackDeobfuscator(addresses); | |
} catch (e) { | |
console.warn("Could not deobfuscate stack", e); | |
} | |
} | |
if (!result) { | |
result = addresses.map(address => { | |
return { | |
className: "java.lang.Throwable$FakeClass", | |
method: "fakeMethod", | |
file: "Throwable.java", | |
line: address | |
}; | |
}); | |
} | |
return result; | |
} | |
}; | |
}, | |
"decorateException": (javaException) => { | |
new JavaError(context, javaException); | |
} | |
}; | |
} | |
/** | |
* @param {Object} imports | |
* @param {Object} context | |
*/ | |
function jsoImports(imports, context) { | |
let javaObjectSymbol = Symbol("javaObject"); | |
let functionsSymbol = Symbol("functions"); | |
let functionOriginSymbol = Symbol("functionOrigin"); | |
let wrapperCallMarkerSymbol = Symbol("wrapperCallMarker"); | |
let jsWrappers = new WeakMap(); | |
let javaWrappers = new WeakMap(); | |
let primitiveWrappers = new Map(); | |
let primitiveFinalization = new FinalizationRegistry(token => primitiveWrappers.delete(token)); | |
let hashCodes = new WeakMap(); | |
let lastHashCode = 2463534242; | |
let nextHashCode = () => { | |
let x = lastHashCode; | |
x ^= x << 13; | |
x ^= x >>> 17; | |
x ^= x << 5; | |
lastHashCode = x; | |
return x; | |
} | |
function identity(value) { | |
return value; | |
} | |
function sanitizeName(str) { | |
let result = ""; | |
let firstChar = str.charAt(0); | |
result += isIdentifierStart(firstChar) ? firstChar : '_'; | |
for (let i = 1; i < str.length; ++i) { | |
let c = str.charAt(i) | |
result += isIdentifierPart(c) ? c : '_'; | |
} | |
return result; | |
} | |
function isIdentifierStart(s) { | |
return s >= 'A' && s <= 'Z' || s >= 'a' && s <= 'z' || s === '_' || s === '$'; | |
} | |
function isIdentifierPart(s) { | |
return isIdentifierStart(s) || s >= '0' && s <= '9'; | |
} | |
function setProperty(obj, prop, value) { | |
if (obj === null) { | |
setGlobalName(prop, value); | |
} else { | |
obj[prop] = value; | |
} | |
} | |
function javaExceptionToJs(e) { | |
if (e instanceof WebAssembly.Exception) { | |
let tag = context.exports["teavm.javaException"]; | |
let getJsException = context.exports["teavm.getJsException"]; | |
if (e.is(tag)) { | |
let javaException = e.getArg(tag, 0); | |
let extracted = extractException(javaException); | |
if (extracted !== null) { | |
return extracted; | |
} | |
let wrapper = getJsException(javaException); | |
if (typeof wrapper === "undefined") { | |
wrapper = new JavaError(context, javaException); | |
} | |
return wrapper; | |
} | |
} | |
return e; | |
} | |
function jsExceptionAsJava(e) { | |
if (javaExceptionSymbol in e) { | |
return e[javaExceptionSymbol]; | |
} else { | |
return context.exports["teavm.js.wrapException"](e); | |
} | |
} | |
function rethrowJsAsJava(e) { | |
context.exports["teavm.js.throwException"](jsExceptionAsJava(e)); | |
} | |
function extractException(e) { | |
return context.exports["teavm.js.extractException"](e); | |
} | |
function rethrowJavaAsJs(e) { | |
throw javaExceptionToJs(e); | |
} | |
function getProperty(obj, prop) { | |
try { | |
return obj !== null ? obj[prop] : getGlobalName(prop) | |
} catch (e) { | |
rethrowJsAsJava(e); | |
} | |
} | |
function defineFunction(fn) { | |
let params = []; | |
for (let i = 0; i < fn.length; ++i) { | |
params.push("p" + i); | |
} | |
let paramsAsString = params.length === 0 ? "" : params.join(", "); | |
let ret = new Function("rethrowJavaAsJs", "fn", | |
`return function(${paramsAsString}) {\n` + | |
` try {\n` + | |
` return fn(${paramsAsString});\n` + | |
` } catch (e) {\n` + | |
` rethrowJavaAsJs(e);\n` + | |
` }\n` + | |
`};` | |
)(rethrowJavaAsJs, fn); | |
ret["__impl"] = fn; | |
ret["__rethrow"] = rethrowJavaAsJs; | |
return ret; | |
} | |
function renameConstructor(name, c) { | |
return new Function( | |
"constructor", | |
`return function ${name}(marker, javaObject) {\n` + | |
` return constructor.call(this, marker, javaObject);\n` + | |
`}\n` | |
)(c); | |
} | |
imports["teavmJso"] = { | |
"emptyString": () => "", | |
"stringFromCharCode": code => String.fromCharCode(code), | |
"concatStrings": (a, b) => a + b, | |
"stringLength": s => s.length, | |
"charAt": (s, index) => s.charCodeAt(index), | |
"emptyArray": () => [], | |
"appendToArray": (array, e) => array.push(e), | |
"unwrapBoolean": value => value ? 1 : 0, | |
"wrapBoolean": value => !!value, | |
"getProperty": getProperty, | |
"setProperty": setProperty, | |
"setPropertyPure": setProperty, | |
"global": (name) => { | |
try { | |
return getGlobalName(name); | |
} catch (e) { | |
rethrowJsAsJava(e); | |
} | |
}, | |
"createClass": (name, parent, constructor) => { | |
name = sanitizeName(name || "JavaObject"); | |
let action; | |
if (parent === null) { | |
action = function (javaObject) { | |
this[javaObjectSymbol] = javaObject; | |
this[functionsSymbol] = null; | |
}; | |
} else { | |
action = function (javaObject) { | |
parent.call(this, javaObject); | |
}; | |
//TODO: what are these for | |
//fn.prototype = Object.create(parent); | |
//fn.prototype.constructor = parent; | |
} | |
let fn = renameConstructor(name, function (marker, javaObject) { | |
if (marker === wrapperCallMarkerSymbol) { | |
action.call(this, javaObject); | |
} else if (constructor === null) { | |
throw new Error("This class can't be instantiated directly"); | |
} else { | |
try { | |
return constructor.apply(null, arguments); | |
} catch (e) { | |
rethrowJavaAsJs(e); | |
} | |
} | |
}); | |
fn.prototype = Object.create(parent || Object.prototype); | |
fn.prototype.constructor = fn; | |
let boundFn = renameConstructor(name, function(javaObject) { | |
return fn.call(this, wrapperCallMarkerSymbol, javaObject); | |
}); | |
boundFn[wrapperCallMarkerSymbol] = fn; | |
boundFn.prototype = fn.prototype; | |
return boundFn; | |
}, | |
"exportClass": (cls) => { | |
return cls[wrapperCallMarkerSymbol]; | |
}, | |
"defineMethod": (cls, name, fn) => { | |
let params = []; | |
for (let i = 1; i < fn.length; ++i) { | |
params.push("p" + i); | |
} | |
let paramsAsString = params.length === 0 ? "" : params.join(", "); | |
cls.prototype[name] = new Function("rethrowJavaAsJs", "fn", | |
`return function(${paramsAsString}) {\n` + | |
` try {\n` + | |
` return fn(${['this', params].join(", ")});\n` + | |
` } catch (e) {\n` + | |
` rethrowJavaAsJs(e);\n` + | |
` }\n` + | |
`};` | |
)(rethrowJavaAsJs, fn); | |
}, | |
"defineStaticMethod": (cls, name, fn) => { | |
cls[name] = defineFunction(fn); | |
}, | |
"defineFunction": defineFunction, | |
"defineProperty": (cls, name, getFn, setFn) => { | |
let descriptor = { | |
get() { | |
try { | |
return getFn(this); | |
} catch (e) { | |
rethrowJavaAsJs(e); | |
} | |
} | |
}; | |
if (setFn !== null) { | |
descriptor.set = function(value) { | |
try { | |
setFn(this, value); | |
} catch (e) { | |
rethrowJavaAsJs(e); | |
} | |
} | |
} | |
Object.defineProperty(cls.prototype, name, descriptor); | |
}, | |
"defineStaticProperty": (cls, name, getFn, setFn) => { | |
let descriptor = { | |
get() { | |
try { | |
return getFn(); | |
} catch (e) { | |
rethrowJavaAsJs(e); | |
} | |
} | |
}; | |
if (setFn !== null) { | |
descriptor.set = function(value) { | |
try { | |
setFn(value); | |
} catch (e) { | |
rethrowJavaAsJs(e); | |
} | |
} | |
} | |
Object.defineProperty(cls, name, descriptor); | |
}, | |
"javaObjectToJS": (instance, cls) => { | |
if (instance === null) { | |
return null; | |
} | |
let existing = jsWrappers.get(instance); | |
if (typeof existing != "undefined") { | |
let result = existing.deref(); | |
if (typeof result !== "undefined") { | |
return result; | |
} | |
} | |
let obj = new cls(instance); | |
jsWrappers.set(instance, new WeakRef(obj)); | |
return obj; | |
}, | |
"unwrapJavaObject": (instance) => { | |
return instance[javaObjectSymbol]; | |
}, | |
"asFunction": (instance, propertyName) => { | |
let functions = instance[functionsSymbol]; | |
if (functions === null) { | |
functions = Object.create(null); | |
instance[functionsSymbol] = functions; | |
} | |
let result = functions[propertyName]; | |
if (typeof result !== 'function') { | |
result = function() { | |
return instance[propertyName].apply(instance, arguments); | |
} | |
result[functionOriginSymbol] = instance; | |
functions[propertyName] = result; | |
} | |
return result; | |
}, | |
"functionAsObject": (fn, property) => { | |
let origin = fn[functionOriginSymbol]; | |
if (typeof origin !== 'undefined') { | |
let functions = origin[functionsSymbol]; | |
if (functions !== void 0 && functions[property] === fn) { | |
return origin; | |
} | |
} | |
return { | |
[property]: function(...args) { | |
try { | |
return fn(...args); | |
} catch (e) { | |
rethrowJavaAsJs(e); | |
} | |
} | |
}; | |
}, | |
"wrapObject": (obj) => { | |
if (obj === null) { | |
return null; | |
} | |
if (typeof obj === "object" || typeof obj === "function" || typeof "obj" === "symbol") { | |
let result = obj[javaObjectSymbol]; | |
if (typeof result === "object") { | |
return result; | |
} | |
result = javaWrappers.get(obj); | |
if (result !== void 0) { | |
result = result.deref(); | |
if (result !== void 0) { | |
return result; | |
} | |
} | |
result = context.exports["teavm.jso.createWrapper"](obj); | |
javaWrappers.set(obj, new WeakRef(result)); | |
return result; | |
} else { | |
let result = primitiveWrappers.get(obj); | |
if (result !== void 0) { | |
result = result.deref(); | |
if (result !== void 0) { | |
return result; | |
} | |
} | |
result = context.exports["teavm.jso.createWrapper"](obj); | |
primitiveWrappers.set(obj, new WeakRef(result)); | |
primitiveFinalization.register(result, obj); | |
return result; | |
} | |
}, | |
"isPrimitive": (value, type) => typeof value === type, | |
"instanceOf": (value, type) => value instanceof type, | |
"instanceOfOrNull": (value, type) => value === null || value instanceof type, | |
"sameRef": (a, b) => a === b, | |
"hashCode": (obj) => { | |
if (typeof obj === "object" || typeof obj === "function" || typeof obj === "symbol") { | |
let code = hashCodes.get(obj); | |
if (typeof code === "number") { | |
return code; | |
} | |
code = nextHashCode(); | |
hashCodes.set(obj, code); | |
return code; | |
} else if (typeof obj === "number") { | |
return obj | 0; | |
} else if (typeof obj === "bigint") { | |
return BigInt.asIntN(32, obj); | |
} else if (typeof obj === "boolean") { | |
return obj ? 1 : 0; | |
} else { | |
return 0; | |
} | |
}, | |
"apply": (instance, method, args) => { | |
try { | |
if (instance === null) { | |
let fn = getGlobalName(method); | |
return fn(...args); | |
} else { | |
return instance[method](...args); | |
} | |
} catch (e) { | |
rethrowJsAsJava(e); | |
} | |
}, | |
"concatArray": (a, b) => a.concat(b), | |
"getJavaException": e => e[javaExceptionSymbol] | |
}; | |
for (let name of ["wrapByte", "wrapShort", "wrapChar", "wrapInt", "wrapFloat", "wrapDouble", "unwrapByte", | |
"unwrapShort", "unwrapChar", "unwrapInt", "unwrapFloat", "unwrapDouble"]) { | |
imports["teavmJso"][name] = identity; | |
} | |
function wrapCallFromJavaToJs(call) { | |
try { | |
return call(); | |
} catch (e) { | |
rethrowJsAsJava(e); | |
} | |
} | |
let argumentList = []; | |
for (let i = 0; i < 32; ++i) { | |
let args = argumentList.length === 0 ? "" : argumentList.join(", "); | |
let argsAndBody = [...argumentList, "body"].join(", "); | |
imports["teavmJso"]["createFunction" + i] = new Function("wrapCallFromJavaToJs", ...argumentList, "body", | |
`return new Function('wrapCallFromJavaToJs', ${argsAndBody}).bind(this, wrapCallFromJavaToJs);` | |
).bind(null, wrapCallFromJavaToJs); | |
imports["teavmJso"]["bindFunction" + i] = (f, ...args) => f.bind(null, ...args); | |
imports["teavmJso"]["callFunction" + i] = new Function("rethrowJsAsJava", "fn", ...argumentList, | |
`try {\n` + | |
` return fn(${args});\n` + | |
`} catch (e) {\n` + | |
` rethrowJsAsJava(e);\n` + | |
`}` | |
).bind(null, rethrowJsAsJava); | |
imports["teavmJso"]["callMethod" + i] = new Function("rethrowJsAsJava", "getGlobalName", "instance", | |
"method", ...argumentList, | |
`try {\n`+ | |
` return instance !== null\n` + | |
` ? instance[method](${args})\n` + | |
` : getGlobalName(method)(${args});\n` + | |
`} catch (e) {\n` + | |
` rethrowJsAsJava(e);\n` + | |
`}` | |
).bind(null, rethrowJsAsJava, getGlobalName); | |
imports["teavmJso"]["construct" + i] = new Function("rethrowJsAsJava", "constructor", ...argumentList, | |
`try {\n` + | |
` return new constructor(${args});\n` + | |
`} catch (e) {\n` + | |
` rethrowJsAsJava(e);\n` + | |
`}` | |
).bind(null, rethrowJsAsJava); | |
imports["teavmJso"]["arrayOf" + i] = new Function(...argumentList, "return [" + args + "]"); | |
let param = "p" + (i + 1); | |
argumentList.push(param); | |
} | |
} | |
/** | |
* @param {Object} importObj | |
*/ | |
function wrapImport(importObj) { | |
return new Proxy(importObj, { | |
get(target, prop) { | |
let result = target[prop]; | |
return new WebAssembly.Global({ "value": "externref", "mutable": false }, result); | |
} | |
}); | |
} | |
/* | |
* @param {!WebAssembly.Module} wasmModule | |
* @param {Object} imports | |
* @return {!Promise} | |
* | |
async function wrapImports(wasmModule, imports) { | |
let promises = []; | |
let propertiesToAdd = {}; | |
for (let { module, name, kind } of WebAssembly.Module.imports(wasmModule)) { | |
if (kind !== "global" || module in imports) { | |
continue; | |
} | |
let names = propertiesToAdd[module]; | |
if (names === void 0) { | |
let namesByModule = []; | |
names = namesByModule; | |
propertiesToAdd[module] = names; | |
promises.push((async () => { | |
let moduleInstance = await import(module); | |
let importsByModule = {}; | |
for (let name of namesByModule) { | |
let importedName = name === "__self__" ? moduleInstance : moduleInstance[name]; | |
importsByModule[name] = new WebAssembly.Global( | |
{ value: "externref", mutable: false }, | |
importedName | |
); | |
} | |
imports[module] = importsByModule; | |
})()); | |
} | |
names.push(name); | |
} | |
if (promises.length === 0) { | |
return; | |
} | |
await Promise.all(promises); | |
}*/ | |
/** | |
* @param {string|!WebAssembly.Module} path | |
* @param {Object} options | |
* @return {!Promise<Object>} | |
*/ | |
async function load(path, options) { | |
if (!options) { | |
options = {}; | |
} | |
let deobfuscatorOptions = options.stackDeobfuscator || {}; | |
let [deobfuscatorFactory, module, debugInfo] = await Promise.all([ | |
deobfuscatorOptions.enabled ? getDeobfuscator(deobfuscatorOptions) : Promise.resolve(null), | |
(path instanceof WebAssembly.Module) ? Promise.resolve(path) : WebAssembly.compileStreaming(fetch(path)), | |
fetchExternalDebugInfo(deobfuscatorOptions.infoLocation, deobfuscatorOptions) | |
]); | |
const importObj = {}; | |
const defaultsResult = defaults(importObj); | |
if (typeof options.installImports !== "undefined") { | |
options.installImports(importObj); | |
} | |
//if (!options.noAutoImports) { | |
// await wrapImports(module, importObj); | |
//} | |
defaultsResult.supplyAsyncRunnableQueue(setupAsyncCallbackPoll(importObj)); | |
let instance = /** @type {!WebAssembly.Instance} */ (await WebAssembly.instantiate(module, importObj)); | |
let userExports = {}; | |
defaultsResult.supplyExports(instance.exports); | |
if (deobfuscatorFactory) { | |
let deobfuscator = createDeobfuscator(null, debugInfo, deobfuscatorFactory.instance); | |
if (deobfuscator !== null) { | |
defaultsResult.supplyStackDeobfuscator(deobfuscator); | |
userExports["deobfuscator"] = deobfuscator; | |
} | |
} | |
let teavm = { | |
exports: userExports, | |
instance: instance, | |
modules: { | |
classes: module, | |
deobfuscator: (deobfuscatorFactory ? deobfuscatorFactory.module : null) | |
} | |
}; | |
for (let key in instance.exports) { | |
let exportObj = instance.exports[key]; | |
if (exportObj instanceof WebAssembly.Global) { | |
Object.defineProperty(userExports, key, { | |
get: () => exportObj.value | |
}); | |
}else if (typeof exportObj === "function") { | |
userExports[key] = exportObj; | |
} | |
} | |
userExports.memory = instance.exports["teavm.memory"]; | |
userExports.debugInfo = debugInfo; | |
return teavm; | |
} | |
/** | |
* @param {Object} options | |
* @return {!Promise<?{module:!WebAssembly.Module,instance:!WebAssembly.Instance}>} | |
*/ | |
async function getDeobfuscator(options) { | |
try { | |
const importObj = {}; | |
const defaultsResult = defaults(importObj); | |
const module = (options.path instanceof WebAssembly.Module) ? | |
options.path : await WebAssembly.compileStreaming(fetch(options.path)); | |
const instance = new WebAssembly.Instance(module, importObj); | |
defaultsResult.supplyExports(instance.exports) | |
return { module, instance }; | |
} catch (e) { | |
console.warn("Could not load deobfuscator", e); | |
return null; | |
} | |
} | |
/** | |
* @param {WebAssembly.Module} module | |
* @param {Int8Array} externalData | |
* @param {WebAssembly.Instance} deobfuscatorFactory | |
* @return {function(number)} | |
*/ | |
function createDeobfuscator(module, externalData, deobfuscatorFactory) { | |
let deobfuscator = null; | |
let deobfuscatorInitialized = false; | |
function ensureDeobfuscator() { | |
if (!deobfuscatorInitialized) { | |
deobfuscatorInitialized = true; | |
if (externalData !== null) { | |
try { | |
deobfuscator = deobfuscatorFactory.exports["createFromExternalFile"].value(externalData); | |
} catch (e) { | |
console.warn("Could not load create deobfuscator", e); | |
} | |
} | |
if (deobfuscator == null && module !== null) { | |
try { | |
deobfuscator = deobfuscatorFactory.exports["createForModule"].value(module); | |
} catch (e) { | |
console.warn("Could not create deobfuscator from module data", e); | |
} | |
} | |
} | |
} | |
return addresses => { | |
ensureDeobfuscator(); | |
return deobfuscator !== null ? deobfuscator["deobfuscate"](addresses) : []; | |
} | |
} | |
/** | |
* @param {string} debugInfoLocation | |
* @param {Object} options | |
* @return {!Promise<Int8Array>} | |
*/ | |
async function fetchExternalDebugInfo(debugInfoLocation, options) { | |
if (!options.enabled) { | |
return null; | |
} | |
if (debugInfoLocation !== "auto" && debugInfoLocation !== "external") { | |
return null; | |
} | |
if(options.externalInfoPath instanceof ArrayBuffer) { | |
return new Int8Array(options.externalInfoPath); | |
}else { | |
let response = await fetch(options.externalInfoPath); | |
if (!response.ok) { | |
return null; | |
} | |
return new Int8Array(await response.arrayBuffer()); | |
} | |
} | |
/** | |
* @param {Object} importObj | |
* @return {function(function())} | |
*/ | |
function setupAsyncCallbackPoll(importObj) { | |
const queueObj = new EaglerLinkedQueue(); | |
importObj["teavm"]["pollAsyncCallbacks"] = function() { | |
var v; | |
while(v = queueObj.shift()) { | |
v["fn"](); | |
} | |
}; | |
return function(/** function() */ fn) { | |
queueObj.push({ | |
"fn": fn, | |
"_next": null | |
}); | |
}; | |
} | |
wasmGC = (function() { | |
//include(); | |
return { load, defaults, wrapImport }; | |
})(); | |
})(); | |