From da46478118dc8f14b18013c87c1501101588c2a4 Mon Sep 17 00:00:00 2001 From: Gokhan Kurt Date: Mon, 20 Jun 2022 21:11:42 +0300 Subject: [PATCH 1/4] add webgl backend with native browser engine --- .../Plugins/WebGL/.source/quickjs.ts | 1647 +++++++++++++++++ .../Plugins/WebGL/.source/tsconfig.json | 45 + .../WebGL/.source/typings/emscripten.d.ts | 357 ++++ .../WebGL/.source/typings/environment.d.ts | 79 + .../Plugins/WebGL/.source/typings/jsapi.d.ts | 190 ++ .../Plugins/WebGL/.source/typings/plugin.d.ts | 221 +++ .../Plugins/WebGL/libquickjs.c | 42 - .../Plugins/WebGL/libquickjs.c.meta | 111 -- .../Plugins/WebGL/quickjs.jslib | 1346 ++++++++++++++ .../Plugins/WebGL/quickjs.jslib.meta | 32 + 10 files changed, 3917 insertions(+), 153 deletions(-) create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/environment.d.ts create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/jsapi.d.ts create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts delete mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c delete mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c.meta create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib create mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib.meta diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts new file mode 100644 index 00000000..d15c49c4 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts @@ -0,0 +1,1647 @@ +/** + * Build with the following command: + * npx -p typescript tsc + */ + +type PluginType = JSApiExternals & { + $unityJsbState: typeof unityJsbState; + $unityJsbState__postset?: string; +} + +var QuickJSPlugin: PluginType = { + $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', + $unityJsbState: { + createObjects: function (): PluginObjects { + var getTag = function (object): Tags { + if (object === undefined) return Tags.JS_TAG_UNDEFINED; + if (object === null) return Tags.JS_TAG_NULL; + if (typeof object === 'number') return Tags.JS_TAG_FLOAT64; + if (typeof object === 'boolean') return Tags.JS_TAG_BOOL; + if (typeof object === 'function') return Tags.JS_TAG_FUNCTION_BYTECODE; + if (typeof object === 'symbol') return Tags.JS_TAG_SYMBOL; + if (typeof object === 'string') return Tags.JS_TAG_STRING; + if (typeof object === 'bigint') return Tags.JS_TAG_BIG_INT; + if (object instanceof Error) return Tags.JS_TAG_EXCEPTION; + return Tags.JS_TAG_OBJECT; + }; + + var record: PluginObjects['record'] = {}; + + const map = new Map(); + + var payloadMap: PluginObjects['payloadMap'] = new Map(); + + const res: PluginObjects = { + record, + lastId: 0, + + allocate(object) { + var ptr = _malloc(Sizes.JSValue) as JSValue; + res.push(object, ptr); + return ptr as JSValue; + }, + batchAllocate(objects) { + var size = Sizes.JSValue; + var arr = _malloc(size * objects.length) as PointerArray; + + for (let index = 0; index < objects.length; index++) { + const object = objects[index]; + res.push(object, arr + (index * size) as JSValue); + } + + return arr; + }, + batchGet(ptrs, count) { + var size = Sizes.JSValue; + + var arr = new Array(count); + for (let index = 0; index < count; index++) { + const object = res.get(ptrs + index * size as JSValue); + arr[index] = object; + } + + return arr; + }, + push(object, ptr) { + if (typeof object === 'undefined') { + res.refIndex(0, 1, ptr); + return; + } + + if (typeof object === 'number') { + if (typeof ptr === 'number') { + HEAPF64[ptr >> 3] = object; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(Tags.JS_TAG_FLOAT64); + } + + return; + } + + if (typeof object === 'boolean') { + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = object ? 1 : 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(Tags.JS_TAG_BOOL); + } + + return; + } + + const foundId = map.get(object); + + if (foundId > 0) { + res.refIndex(foundId, 1, ptr); + return; + } + + var id = ++res.lastId; + + record[id] = { + id, + refCount: 0, + value: object, + tag: getTag(object), + }; + + map.set(object, id); + + res.refIndex(id, 1, ptr); + + return id; + }, + get(val) { + var tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + + if (tag === Tags.JS_TAG_INT) { + return HEAP32[val >> 2]; + } + else if (tag === Tags.JS_TAG_BOOL) { + return !!HEAP32[val >> 2]; + } + else if (tag === Tags.JS_TAG_FLOAT64) { + return HEAPF64[val >> 3]; + } + else { + var id = HEAP32[val >> 2]; + if (id === 0) return undefined; + var ho = record[id]; + return ho.value; + } + }, + getRecord(val) { + var tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + + if (tag === Tags.JS_TAG_INT) { + var value = HEAP32[val >> 2]; + return { + id: -1, + refCount: 0, + value, + tag, + }; + } + else if (tag === Tags.JS_TAG_BOOL) { + var boolValue = !!HEAP32[val >> 2]; + return { + id: -1, + refCount: 0, + value: boolValue, + tag, + }; + } + else if (tag === Tags.JS_TAG_FLOAT64) { + var value = HEAPF64[val >> 3]; + return { + id: -1, + refCount: 0, + value, + tag, + }; + } + else { + var id = HEAP32[val >> 2]; + if (id === 0) return { + id: 0, + refCount: 0, + value: undefined, + tag: Tags.JS_TAG_UNDEFINED, + type: BridgeObjectType.None, + payload: -1, + }; + var ho = record[id]; + return ho; + } + }, + ref(obj, diff, ptr) { + var tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); + + if (tag === Tags.JS_TAG_FLOAT64) { + if (typeof ptr === 'number') { + var val = HEAPF64[(obj >> 3)]; + HEAPF64[ptr >> 3] = val; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + else if (tag === Tags.JS_TAG_INT) { + if (typeof ptr === 'number') { + var val = HEAP32[(obj >> 2)]; + HEAP32[(ptr >> 2)] = val; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + else if (tag === Tags.JS_TAG_BOOL) { + if (typeof ptr === 'number') { + var valBool = !!HEAP32[(obj >> 2)]; + HEAP32[(ptr >> 2)] = valBool ? 1 : 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + + var id = HEAP32[obj >> 2]; + res.refIndex(id, diff, ptr); + }, + refIndex(id, diff, ptr) { + if (id === 0) { + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(Tags.JS_TAG_UNDEFINED); + } + return; + } + + var ho = record[id]; + + ho.refCount += diff; + + console.assert(ho.refCount >= 0); + + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = id; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(ho.tag); + } + }, + deleteIndex(id) { + var rec = record[id]; + delete record[id]; + map.delete(rec.value); + }, + payloadMap, + setPayload(obj, type, payload) { + payloadMap.set(obj, { + type: BridgeObjectType.None || type, + payload, + }); + }, + getPayload(obj) { + var res = payloadMap.get(obj); + + if (res) return res; + else { + return { + type: BridgeObjectType.None, + payload: 0, + }; + } + }, + clearPayload(obj) { + payloadMap.delete(obj); + }, + }; + + return res; + }, + createAtoms(): PluginAtoms { + var record: PluginAtoms['record'] = {}; + var map: PluginAtoms['map'] = {}; + + var res: PluginAtoms = { + record, + map, + lastId: 0, + get(ref) { + if (ref === 0) return undefined; + return record[ref].value; + }, + push(str) { + if (str === undefined) return 0; + var mapped = map[str]; + var id; + + if (!mapped) { + id = ++res.lastId; + map[str] = record[id] = { + id, + value: str, + refCount: 1, + }; + } else { + id = mapped.id; + mapped.refCount++; + } + + return id; + }, + pushId(id) { + if (id === 0) return; + + var recorded = record[id]; + console.assert(!!recorded); + if (!recorded) return 0; + recorded.refCount++; + + return id; + }, + pop(id) { + if (id === 0) return; + + var recorded = record[id]; + console.assert(!!recorded); + if (!recorded) return; + + recorded.refCount--; + console.assert(recorded.refCount >= 0); + + if (recorded.refCount == 0) { + delete map[recorded.value]; + delete record[id]; + } + }, + }; + + return res; + }, + stringify: function (ptr: number | Pointer, bufferLength?: number) { return (typeof UTF8ToString !== 'undefined' ? UTF8ToString : Pointer_stringify)(ptr, bufferLength); }, + bufferify: function (arg: string) { + var bufferSize = lengthBytesUTF8(arg) + 1; + var buffer = _malloc(bufferSize); + stringToUTF8(arg, buffer, bufferSize); + return [buffer, bufferSize]; + }, + + dynCall: function () { return (typeof Runtime !== 'undefined' ? Runtime.dynCall : dynCall).apply(typeof Runtime !== 'undefined' ? Runtime : undefined, arguments); }, + runtimes: {}, + contexts: {}, + lastRuntimeId: 1, + lastContextId: 1, + getRuntime: function (rt) { + var rtId = rt; + return unityJsbState.runtimes[rtId]; + }, + getContext: function (ctx) { + var ctxId = ctx; + return unityJsbState.contexts[ctxId]; + }, + HEAP64: function () { + return new BigInt64Array(HEAPF64.buffer); + }, + HEAPU64: function () { + return new BigUint64Array(HEAPF64.buffer); + }, + }, + + JSB_Init() { + return Constants.CS_JSB_VERSION; + }, + + JSB_NewRuntime(finalizer) { + // TODO: understand what to do with finalizer + + var id = unityJsbState.lastRuntimeId++; + var objects = unityJsbState.createObjects(); + + unityJsbState.runtimes[id] = { + id, + contexts: {}, + objects, + garbageCollect() { + var lastId = objects.lastId; + var record = objects.record; + + var aliveItemCount = 0; + + for (let index = 0; index < lastId; index++) { + const element = record[index]; + + if (element) { + if (element.refCount <= 0) { + objects.deleteIndex(index); + } + else { + aliveItemCount++; + } + } + } + + return aliveItemCount; + }, + }; + + return id; + }, + + JSB_GetRuntimeOpaque(rtId) { + return unityJsbState.getRuntime(rtId).opaque; + }, + + JSB_SetRuntimeOpaque(rtId, opaque) { + unityJsbState.getRuntime(rtId).opaque = opaque; + }, + + JS_GetContextOpaque(ctx) { + return unityJsbState.getContext(ctx).opaque; + }, + + JS_SetContextOpaque(ctx, opaque) { + unityJsbState.getContext(ctx).opaque = opaque; + }, + + JSB_FreeRuntime(rtId) { + var runtime = unityJsbState.getRuntime(rtId); + var aliveItemCount = runtime.garbageCollect(); + + for (const key in runtime.contexts) { + if (Object.hasOwnProperty.call(runtime.contexts, key)) { + delete unityJsbState.contexts[key]; + } + } + + delete unityJsbState.runtimes[runtime.id]; + + return aliveItemCount === 0; + }, + + JS_GetRuntime(ctxId) { + var context = unityJsbState.getContext(ctxId); + return context.runtimeId; + }, + + JS_NewContext(rtId) { + var id = unityJsbState.lastContextId++; + var runtime = unityJsbState.getRuntime(rtId); + + var extraGlobals: any = { + location: undefined, + document: undefined, + btoa: window.btoa?.bind(window), + atob: window.atob?.bind(window), + $$webglWindow: window, + }; + + var globals: typeof window = new Proxy(extraGlobals, { + get(target, p, receiver) { + if (p in target) return target[p]; + else return window[p]; + }, + set(target, p, val, receiver) { + target[p] = val; + return true; + }, + has(target, key) { + return (key in window) || (key in target); + }, + }) as any; + + extraGlobals.globalThis = + extraGlobals.global = + extraGlobals.window = + extraGlobals.parent = + extraGlobals.self = + extraGlobals.this = + globals; + + var evaluate = function (code: string, filename?: string) { + var sourceMap = !filename ? '' : '\n//# sourceURL=unity-jsb:///' + filename; + + return (function (evalCode) { + //@ts-ignore + with (globals) { + return eval(evalCode); + } + }).call(globals, code + sourceMap); + }; + + + var context: PluginContext = { + id, + runtime, + runtimeId: rtId, + window, + globalObject: globals, + evaluate, + }; + + runtime.contexts[id] = context; + unityJsbState.contexts[id] = context; + return id; + }, + + JS_FreeContext(ctxId) { + var context = unityJsbState.getContext(ctxId); + var runtime = unityJsbState.runtimes[context.runtimeId]; + + delete runtime.contexts[context.id]; + delete unityJsbState.contexts[context.id]; + }, + + JS_GetGlobalObject(returnValue, ctxId) { + var context = unityJsbState.getContext(ctxId); + + if (!context.globalObjectId) { + context.runtime.objects.push(context.globalObject, returnValue); + } + else { + context.runtime.objects.refIndex(context.globalObjectId, 1, returnValue); + } + }, + + JS_Eval(ptr, ctx, input, input_len, filename, eval_flags) { + try { + var context = unityJsbState.getContext(ctx); + var code = unityJsbState.stringify(input, input_len); + var filenameStr = unityJsbState.stringify(filename); + + var res = context.evaluate(code, filenameStr); + + context.runtime.objects.push(res, ptr); + } catch (err) { + context.lastException = err; + context.runtime.objects.push(err, ptr); + console.error(err); + } + }, + + JS_IsInstanceOf(ctxId, val, obj) { + var context = unityJsbState.getContext(ctxId); + var valVal = context.runtime.objects.get(val); + var ctorVal = context.runtime.objects.get(obj); + return !!(valVal instanceof ctorVal); + }, + + JS_GetException(ptr, ctx) { + var context = unityJsbState.getContext(ctx); + + context.runtime.objects.push(context.lastException, ptr); + }, + + JSB_FreeValue(ctx, v) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.ref(v, -1, undefined); + }, + + JSB_FreeValueRT(rt, v) { + var runtime = unityJsbState.getRuntime(rt); + runtime.objects.ref(v, -1, undefined); + }, + + JSB_FreePayload(ret, ctx, val) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + + var payload = context.runtime.objects.getPayload(obj); + HEAP32[ret >> 2] = payload.type; + HEAP32[(ret >> 2) + 1] = payload.payload; + + context.runtime.objects.clearPayload(obj); + }, + + JSB_DupValue(ptr, ctx, v) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.ref(v, 1, ptr); + }, + + JS_RunGC(rt) { + var runtime = unityJsbState.getRuntime(rt); + + runtime.garbageCollect(); + }, + + JS_ComputeMemoryUsage(rt, s) { + // TODO: https://blog.unity.com/technology/unity-webgl-memory-the-unity-heap + }, + + JS_GetPropertyUint32(ptr, ctxId, val, index) { + var context = unityJsbState.getContext(ctxId); + var obj = context.runtime.objects.get(val); + var res = obj[index]; + + context.runtime.objects.push(res, ptr); + }, + + JS_GetPropertyInternal(ptr, ctxId, val, prop, receiver, throwRefError) { + var context = unityJsbState.getContext(ctxId); + var valObj = context.runtime.objects.get(val); + var receiverObj = context.runtime.objects.get(receiver); + var propStr = unityJsbState.atoms.get(prop); + var res = valObj[propStr]; + // var res = Reflect.get(valObj, propStr, receiverObj); + + context.runtime.objects.push(res, ptr); + }, + + JS_GetPropertyStr(ptr, ctxId, val, prop) { + var context = unityJsbState.getContext(ctxId); + var valObj = context.runtime.objects.get(val); + var propStr = unityJsbState.stringify(prop); + var res = valObj[propStr]; + // var res = Reflect.get(valObj, propStr); + + context.runtime.objects.push(res, ptr); + }, + + JS_Invoke(ptr, ctx, this_obj, prop, argc, argv) { + var context = unityJsbState.getContext(ctx); + const propVal = unityJsbState.atoms.get(prop); + const thisVal = context.runtime.objects.get(this_obj); + const func = thisVal[propVal]; + // const func = Reflect.get(thisVal, propVal); + + const args = context.runtime.objects.batchGet(argv, argc); + + const val = func.apply(thisVal, args); + + context.runtime.objects.push(val, ptr); + }, + + JS_Call(ptr, ctx, func_obj, this_obj, argc, argv) { + var context = unityJsbState.getContext(ctx); + const func = context.runtime.objects.get(func_obj); + const thisVal = context.runtime.objects.get(this_obj); + + const args = context.runtime.objects.batchGet(argv, argc); + + const val = func.apply(thisVal, args); + + context.runtime.objects.push(val, ptr); + }, + + JS_CallConstructor(ptr, ctx, func_obj, argc, argv) { + var context = unityJsbState.getContext(ctx); + const func = context.runtime.objects.get(func_obj); + + const args = context.runtime.objects.batchGet(argv, argc); + + const val = Reflect.construct(func, args); + + context.runtime.objects.push(val, ptr); + }, + + JS_SetConstructor(ctx, ctor, proto) { + var context = unityJsbState.getContext(ctx); + var ctorVal = context.runtime.objects.get(ctor); + var protoVal = context.runtime.objects.get(proto); + ctorVal.prototype = protoVal; + }, + + JS_SetPrototype(ctx, obj, proto) { + var context = unityJsbState.getContext(ctx); + var objVal = context.runtime.objects.get(obj); + var protoVal = context.runtime.objects.get(proto); + Reflect.setPrototypeOf(objVal, protoVal); + + return true; + }, + + JS_DefineProperty(ctx, this_obj, prop, val, getter, setter, flags) { + var context = unityJsbState.getContext(ctx); + + const thisVal = context.runtime.objects.get(this_obj); + const getterVal = context.runtime.objects.get(getter); + const setterVal = context.runtime.objects.get(setter); + const valVal = context.runtime.objects.get(val); + const propVal = unityJsbState.atoms.get(prop); + + const configurable = !!(flags & JSPropFlags.JS_PROP_CONFIGURABLE); + const hasConfigurable = configurable || !!(flags & JSPropFlags.JS_PROP_HAS_CONFIGURABLE); + const enumerable = !!(flags & JSPropFlags.JS_PROP_ENUMERABLE); + const hasEnumerable = enumerable || !!(flags & JSPropFlags.JS_PROP_HAS_ENUMERABLE); + const writable = !!(flags & JSPropFlags.JS_PROP_WRITABLE); + const hasWritable = writable || !!(flags & JSPropFlags.JS_PROP_HAS_WRITABLE); + + const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); + + + try { + const opts: PropertyDescriptor = { + get: getterVal, + set: setterVal, + }; + + if (!getter && !setter) { + opts.value = valVal; + } + + if (hasConfigurable) opts.configurable = configurable; + if (hasEnumerable) opts.enumerable = enumerable; + if (!getter && !setter && hasWritable) opts.writable = writable; + + Object.defineProperty(thisVal, propVal, opts); + + return true; + } catch (err) { + context.lastException = err; + if (shouldThrow) { + console.error(err); + return -1; + } + } + + return false; + }, + + JS_DefinePropertyValue(ctx, this_obj, prop, val, flags) { + var context = unityJsbState.getContext(ctx); + + const thisVal = context.runtime.objects.get(this_obj); + const valVal = context.runtime.objects.get(val); + const propVal = unityJsbState.atoms.get(prop); + + const configurable = !!(flags & JSPropFlags.JS_PROP_CONFIGURABLE); + const hasConfigurable = configurable || !!(flags & JSPropFlags.JS_PROP_HAS_CONFIGURABLE); + const enumerable = !!(flags & JSPropFlags.JS_PROP_ENUMERABLE); + const hasEnumerable = enumerable || !!(flags & JSPropFlags.JS_PROP_HAS_ENUMERABLE); + const writable = !!(flags & JSPropFlags.JS_PROP_WRITABLE); + const hasWritable = writable || !!(flags & JSPropFlags.JS_PROP_HAS_WRITABLE); + + const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); + + try { + const opts: PropertyDescriptor = { + value: valVal, + }; + + if (hasConfigurable) opts.configurable = configurable; + if (hasEnumerable) opts.enumerable = enumerable; + if (hasWritable) opts.writable = writable; + + Object.defineProperty(thisVal, propVal, opts); + return true; + } + catch (err) { + context.lastException = err; + if (shouldThrow) { + console.error(err); + return -1; + } + } + + return false; + }, + + JS_HasProperty(ctx, this_obj, prop) { + var context = unityJsbState.getContext(ctx); + var thisVal = context.runtime.objects.get(this_obj); + var propVal = unityJsbState.atoms.get(prop); + + var res = Reflect.has(thisVal, propVal); + + return !!res; + }, + + JS_SetPropertyInternal(ctx, this_obj, prop, val, flags) { + var context = unityJsbState.getContext(ctx); + + const thisVal = context.runtime.objects.get(this_obj); + const valVal = context.runtime.objects.get(val); + const propVal = unityJsbState.atoms.get(prop); + + const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); + + try { + // return !!Reflect.set(thisVal, propVal, valVal); + thisVal[propVal] = valVal; + return true; + } catch (err) { + context.lastException = err; + if (shouldThrow) { + console.error(err); + return -1; + } + } + + return false; + }, + + JS_SetPropertyUint32(ctx, this_obj, idx, val) { + var context = unityJsbState.getContext(ctx); + + const thisVal = context.runtime.objects.get(this_obj); + const valVal = context.runtime.objects.get(val); + const propVal = idx; + + // return !!Reflect.set(thisVal, propVal, valVal); + thisVal[propVal] = valVal; + return true; + }, + + jsb_get_payload_header(ret, ctx, val) { + + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + + var rec = context.runtime.objects.getPayload(obj); + + HEAP32[ret >> 2] = rec.type; + HEAP32[(ret >> 2) + 1] = rec.payload; + }, + + JS_ToCStringLen2(ctx, len, val, cesu8) { + var context = unityJsbState.getContext(ctx); + + var str = context.runtime.objects.get(val); + + + if (typeof str === 'undefined') { + HEAP32[(len >> 2)] = 0; + return 0 as IntPtr; + } + + var [buffer, length] = unityJsbState.bufferify(str); + HEAP32[(len >> 2)] = length - 1; + return buffer as IntPtr; + }, + + JS_FreeCString(ctx, ptr) { + _free(ptr); + }, + + JS_GetArrayBuffer(ctx, psize, obj) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(obj); + + if (value instanceof ArrayBuffer) { + HEAP32[psize >> 2] = value.byteLength; + + return value as any; + } + + return 0 as IntPtr; + }, + + // #region Atoms + + JS_NewAtomLen(ctx, str, len) { + var context = unityJsbState.getContext(ctx); + var val = unityJsbState.stringify(str, len); + + return unityJsbState.atoms.push(val); + }, + + JS_AtomToString(ptr, ctx, atom) { + var context = unityJsbState.getContext(ctx); + + var str = unityJsbState.atoms.get(atom); + + context.runtime.objects.push(str, ptr); + }, + + JS_FreeAtom(ctx, v) { + unityJsbState.atoms.pop(v); + }, + + JS_DupAtom(ctx, v) { + return unityJsbState.atoms.pushId(v); + }, + + JSB_ATOM_constructor() { + return unityJsbState.atoms.push('constructor'); + }, + + JSB_ATOM_Error() { + return unityJsbState.atoms.push('Error'); + }, + + JSB_ATOM_fileName() { + return unityJsbState.atoms.push('fileName'); + }, + + JSB_ATOM_Function() { + return unityJsbState.atoms.push('Function'); + }, + + JSB_ATOM_length() { + return unityJsbState.atoms.push('length'); + }, + + JSB_ATOM_lineNumber() { + return unityJsbState.atoms.push('lineNumber'); + }, + + JSB_ATOM_message() { + return unityJsbState.atoms.push('message'); + }, + + JSB_ATOM_name() { + return unityJsbState.atoms.push('name'); + }, + + JSB_ATOM_Number() { + return unityJsbState.atoms.push('Number'); + }, + + JSB_ATOM_prototype() { + return unityJsbState.atoms.push('prototype'); + }, + + JSB_ATOM_Proxy() { + return unityJsbState.atoms.push('Proxy'); + }, + + JSB_ATOM_stack() { + return unityJsbState.atoms.push('stack'); + }, + + JSB_ATOM_String() { + return unityJsbState.atoms.push('String'); + }, + + JSB_ATOM_Object() { + return unityJsbState.atoms.push('Object'); + }, + + JSB_ATOM_Operators() { + return unityJsbState.atoms.push('Operators'); + }, + + JSB_ATOM_Symbol_operatorSet() { + return unityJsbState.atoms.push('operatorSet'); + }, + + // #endregion + + // #region Is + + JS_IsArray(ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.objects.get(val); + var res = Array.isArray(valVal); + return !!res; + }, + + JS_IsConstructor(ctx, val) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var res = !!obj.prototype && !!obj.prototype.constructor.name; + return !!res; + }, + + JS_IsError(ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.objects.get(val); + var res = valVal instanceof Error; + return !!res; + }, + + JS_IsFunction(ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.objects.get(val); + var res = typeof valVal === 'function'; + return !!res; + }, + + // #endregion + + JS_ParseJSON(ptr, ctx, buf, buf_len, filename) { + var context = unityJsbState.getContext(ctx); + var str = unityJsbState.stringify(buf as any, buf_len); + var res = JSON.parse(str); + context.runtime.objects.push(res, ptr); + }, + + JS_JSONStringify(ptr, ctx, obj, replacer, space) { + var context = unityJsbState.getContext(ctx); + var objVal = context.runtime.objects.get(obj); + var rpVal = context.runtime.objects.get(replacer); + var spVal = context.runtime.objects.get(space); + + var res = JSON.stringify(objVal, rpVal, spVal); + context.runtime.objects.push(res, ptr); + }, + + // #region New + + JS_NewArray(ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = []; + context.runtime.objects.push(res, ptr); + }, + + JS_NewArrayBufferCopy(ptr, ctx, buf, len) { + var context = unityJsbState.getContext(ctx); + + var nptr = _malloc(len); + var res = new Uint8Array(HEAPU8.buffer, nptr, len); + var existing = new Uint8Array(HEAPU8.buffer, buf, len); + res.set(existing); + + context.runtime.objects.push(res, ptr); + }, + + JSB_NewFloat64(ptr, ctx, d) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.push(d, ptr); + }, + + JSB_NewInt64(ptr, ctx, d) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.push(d, ptr); + }, + + JS_NewObject(ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = {}; + context.runtime.objects.push(res, ptr); + }, + + JS_NewString(ptr, ctx, str) { + var context = unityJsbState.getContext(ctx); + var res = unityJsbState.stringify(str); + context.runtime.objects.push(res, ptr); + }, + + JS_NewStringLen(ptr, ctx, str, len) { + var context = unityJsbState.getContext(ctx); + + var val = unityJsbState.stringify(str as any, len); + + context.runtime.objects.push(val, ptr); + }, + + JSB_NewEmptyString(ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = ""; + context.runtime.objects.push(res, ptr); + }, + + // #endregion + + // #region Bridge + + JSB_NewCFunction(ret, ctx, func, atom, length, cproto, magic) { + var context = unityJsbState.getContext(ctx); + + var name = unityJsbState.atoms.get(atom) || 'jscFunction'; + + function jscFunction() { + void name; + const args = arguments; + + const thisObj = this === window ? context.globalObject : this; + const thisPtr = context.runtime.objects.allocate(thisObj); + const ret = _malloc(Sizes.JSValue) as JSValue; + + if (cproto === JSCFunctionEnum.JS_CFUNC_generic) { + const argc = args.length; + const argv = context.runtime.objects.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_setter) { + const val = context.runtime.objects.allocate(args[0]); + unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_getter) { + unityJsbState.dynCall('viii', func, [ret, ctx, thisPtr]); + } + else { + throw new Error('Unknown type of function specified: ' + cproto); + } + + return context.runtime.objects.get(ret); + }; + + context.runtime.objects.push(jscFunction, ret); + }, + + JSB_NewCFunctionMagic(ret, ctx, func, atom, length, cproto, magic) { + var context = unityJsbState.getContext(ctx); + + var name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; + + function jscFunctionMagic() { + void name; + const args = arguments; + + const thisObj = this === window ? context.globalObject : this; + const thisPtr = context.runtime.objects.allocate(thisObj); + const ret = _malloc(Sizes.JSValue) as JSValue; + + if (cproto === JSCFunctionEnum.JS_CFUNC_generic_magic) { + const argc = args.length; + const argv = context.runtime.objects.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_constructor_magic) { + const argc = args.length; + const argv = context.runtime.objects.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_setter_magic) { + const val = context.runtime.objects.allocate(args[0]); + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_getter_magic) { + unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, magic]); + } + else { + throw new Error('Unknown type of function specified: ' + cproto); + } + + return context.runtime.objects.get(ret); + }; + + context.runtime.objects.push(jscFunctionMagic, ret); + }, + + jsb_new_bridge_object(ret, ctx, proto, object_id) { + var context = unityJsbState.getContext(ctx); + var protoVal = context.runtime.objects.get(proto); + var res = Object.create(protoVal); + context.runtime.objects.push(res, ret); + context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); + }, + + jsb_new_bridge_value(ret, ctx, proto, size) { + var context = unityJsbState.getContext(ctx); + var protoVal = context.runtime.objects.get(proto); + var res = Object.create(protoVal) as BridgeStruct; + res.$$values = new Array(size).fill(0); + context.runtime.objects.push(res, ret); + }, + + JSB_NewBridgeClassObject(ret, ctx, new_target, object_id) { + var context = unityJsbState.getContext(ctx); + var res = context.runtime.objects.get(new_target); + + context.runtime.objects.push(res, ret); + context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); + }, + + JSB_NewBridgeClassValue(ret, ctx, new_target, size) { + var context = unityJsbState.getContext(ctx); + var res = context.runtime.objects.get(new_target) as BridgeStruct; + res.$$values = new Array(size).fill(0); + context.runtime.objects.push(res, ret); + }, + + JSB_GetBridgeClassID() { + // TODO: I have no idea + return 0; + }, + + jsb_construct_bridge_object(ret, ctx, ctor, object_id) { + var context = unityJsbState.getContext(ctx); + var ctorVal = context.runtime.objects.get(ctor); + var res = Reflect.construct(ctorVal, []); + context.runtime.objects.push(res, ret); + context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); + }, + + jsb_crossbind_constructor(ret, ctx, new_target) { + var context = unityJsbState.getContext(ctx); + var target = context.runtime.objects.get(new_target); + // TODO: I have no idea + var res = function () { + return new target(); + }; + context.runtime.objects.push(res, ret); + }, + + // #endregion + + // #region Errors + + JSB_ThrowError(ret, ctx, buf, buf_len) { + var context = unityJsbState.getContext(ctx); + var str = unityJsbState.stringify(buf as any, buf_len); + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowTypeError(ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Type Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowRangeError(ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Range Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowInternalError(ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Internal Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowReferenceError(ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Reference Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + + // #endregion + + // #region Low level Set + + js_strndup(ctx, s, n) { + var buffer = _malloc(n + 1); + _memcpy(buffer, s, n); + HEAPU8[buffer + n] = 0; + return buffer as IntPtr; + }, + + jsb_set_floats(ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = n / Sizes.Single; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + for (let index = 0; index < count; index++) { + const val = HEAPF32[(v0 >> 2) + index]; + obj.$$values[index] = val; + } + + return true; + }, + + jsb_set_bytes(ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = n / Sizes.Single; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + for (let index = 0; index < count; index++) { + const val = HEAP32[(v0 >> 2) + index]; + obj.$$values[index] = val; + } + + return true; + }, + + jsb_set_byte_4(ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + obj.$$values[2] = HEAP32[(v2 >> 2)]; + obj.$$values[3] = HEAP32[(v3 >> 2)]; + + return true; + }, + + jsb_set_float_2(ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAPF32[(v0 >> 2)]; + obj.$$values[1] = HEAPF32[(v1 >> 2)]; + + return true; + }, + + jsb_set_float_3(ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAPF32[(v0 >> 2)]; + obj.$$values[1] = HEAPF32[(v1 >> 2)]; + obj.$$values[2] = HEAPF32[(v2 >> 2)]; + + return true; + }, + + jsb_set_float_4(ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAPF32[(v0 >> 2)]; + obj.$$values[1] = HEAPF32[(v1 >> 2)]; + obj.$$values[2] = HEAPF32[(v2 >> 2)]; + obj.$$values[3] = HEAPF32[(v3 >> 2)]; + + return true; + }, + + jsb_set_int_1(ctx, val, v0) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 1; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAP32[(v0 >> 2)]; + + return true; + }, + + jsb_set_int_2(ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + + return true; + }, + + jsb_set_int_3(ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + obj.$$values[2] = HEAP32[(v2 >> 2)]; + + return true; + }, + + jsb_set_int_4(ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + obj.$$values[2] = HEAP32[(v2 >> 2)]; + obj.$$values[3] = HEAP32[(v3 >> 2)]; + + return true; + }, + + // #endregion + + // #region Low Level Get + + jsb_get_bytes(ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = n / Sizes.Single; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + for (let index = 0; index < count; index++) { + const val = obj.$$values[index]; + HEAP32[(v0 >> 2) + index] = val; + } + + return true; + }, + + jsb_get_floats(ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = n / Sizes.Single; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + for (let index = 0; index < count; index++) { + const val = obj.$$values[index]; + HEAPF32[(v0 >> 2) + index] = val; + } + + return true; + }, + + jsb_get_byte_4(ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + HEAP32[(v2 >> 2)] = obj.$$values[2]; + HEAP32[(v3 >> 2)] = obj.$$values[3]; + + return true; + }, + + jsb_get_float_2(ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAPF32[(v0 >> 2)] = obj.$$values[0]; + HEAPF32[(v1 >> 2)] = obj.$$values[1]; + + return true; + }, + + jsb_get_float_3(ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAPF32[(v0 >> 2)] = obj.$$values[0]; + HEAPF32[(v1 >> 2)] = obj.$$values[1]; + HEAPF32[(v2 >> 2)] = obj.$$values[2]; + + return true; + }, + + jsb_get_float_4(ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAPF32[(v0 >> 2)] = obj.$$values[0]; + HEAPF32[(v1 >> 2)] = obj.$$values[1]; + HEAPF32[(v2 >> 2)] = obj.$$values[2]; + HEAPF32[(v3 >> 2)] = obj.$$values[3]; + + return true; + }, + + jsb_get_int_1(ctx, val, v0) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 1; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAP32[(v0 >> 2)] = obj.$$values[0]; + + return true; + }, + + jsb_get_int_2(ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + + return true; + }, + + jsb_get_int_3(ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + HEAP32[(v2 >> 2)] = obj.$$values[2]; + + return true; + }, + + jsb_get_int_4(ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val) as BridgeStruct; + + const count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; + + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + HEAP32[(v2 >> 2)] = obj.$$values[2]; + HEAP32[(v3 >> 2)] = obj.$$values[3]; + + return true; + }, + + // #endregion + + // #region To + + JS_ToFloat64(ctx, pres, val) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(val); + + if (typeof value === 'number' || typeof value === 'bigint') { + HEAPF64[pres >> 3] = Number(value); + return false; + } + return -1; + }, + + + JS_ToInt32(ctx, pres, val) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(val); + + if (typeof value === 'number' || typeof value === 'bigint') { + HEAP32[pres >> 2] = Number(value); + return false; + } + + return -1; + }, + + JS_ToInt64(ctx, pres, val) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + unityJsbState.HEAP64()[pres >> 3] = BigInt(value); + return false; + } + return -1; + }, + + JS_ToBigInt64(ctx, pres, val) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + unityJsbState.HEAP64()[pres >> 3] = BigInt(value); + return false; + } + return -1; + }, + + JS_ToIndex(ctx, pres, val) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + unityJsbState.HEAPU64()[pres >> 3] = BigInt(value); + return false; + } + return -1; + }, + + JSB_ToUint32(ctx, pres, val) { + const context = unityJsbState.getContext(ctx); + const value = context.runtime.objects.get(val); + + if (typeof value === 'number' || typeof value === 'bigint') { + HEAPU32[pres >> 2] = Number(value); + return false; + } + return -1; + }, + + JS_ToBool(ctx, val) { + var context = unityJsbState.getContext(ctx); + var objVal = context.runtime.objects.get(val); + return !!objVal; + }, + + // #endregion + + // #region Bytecode + + JS_ReadObject(ptr, ctx, buf, buf_len, flags) { + console.warn('Bytecode is not supported in WebGL Backend'); + }, + + JS_WriteObject(ctx, psize, obj, flags) { + console.warn('Bytecode is not supported in WebGL Backend'); + return 0 as IntPtr; + }, + + JS_EvalFunction(ptr, ctx, fun_obj) { + console.warn('Bytecode is not supported in WebGL Backend'); + }, + + js_free(ctx, ptr) { + // TODO: Not sure what this is but seems related to Bytecode + }, + + // #endregion + + // #region Misc features + + JS_NewPromiseCapability(ret, ctx, resolving_funcs) { + // TODO + return 0; + }, + + JS_SetHostPromiseRejectionTracker(rt, cb, opaque) { + // TODO: + }, + + JS_SetInterruptHandler(rt, cb, opaque) { + // TODO: + }, + + JS_SetModuleLoaderFunc(rt, module_normalize, module_loader, opaque) { + // TODO: + }, + + JS_GetImportMeta(ret, ctx, m) { + // TODO: + return 0; + }, + + JS_ResolveModule(ctx, obj) { + // TODO: + return 0; + }, + + JS_AddIntrinsicOperators(ctx) { + console.warn('Operator overloading is not supported in WebGL Backend'); + }, + + JS_ExecutePendingJob(rt, pctx) { + // Automatically handled by browsers + return false; + }, + + JS_IsJobPending(rt, pctx) { + // Automatically handled by browsers + return false; + }, + + // #endregion + +}; + +autoAddDeps(QuickJSPlugin, '$unityJsbState'); +mergeInto(LibraryManager.library, QuickJSPlugin); diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json new file mode 100644 index 00000000..fe287dd6 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json @@ -0,0 +1,45 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "types": [], + "typeRoots": [ + "typings" + ], + "baseUrl": "./", + "pretty": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "module": "none", + "allowUmdGlobalAccess": true, + "moduleResolution": "node", + "outDir": "..", + "outFile": "../quickjs.jslib", + "noImplicitAny": false, + "strict": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "removeComments": false, + "noImplicitUseStrict": true, + "noUncheckedIndexedAccess": false, + "suppressExcessPropertyErrors": true, + "suppressImplicitAnyIndexErrors": true, + "noPropertyAccessFromIndexSignature": false, + "strictNullChecks": false + }, + "files": [ + "quickjs.ts", + "typings/emscripten.d.ts", + "typings/environment.d.ts", + "typings/jsapi.d.ts", + "typings/plugin.d.ts" + ], + "include": [ + "typings/*.d.ts", + ] +} diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts new file mode 100644 index 00000000..5b0c1cda --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts @@ -0,0 +1,357 @@ +export { }; + +// Type definitions for Emscripten 1.39.16 +// Project: https://emscripten.org +// Definitions by: Kensuke Matsuzaki +// Periklis Tsirakidis +// Bumsik Kim +// Louis DeScioli +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +/** Other WebAssembly declarations, for compatibility with older versions of Typescript */ +declare namespace WebAssembly { + interface Module { } +} + +declare namespace Emscripten { + interface FileSystemType { } + type EnvironmentType = 'WEB' | 'NODE' | 'SHELL' | 'WORKER'; + + type JSType = 'number' | 'string' | 'array' | 'boolean'; + type TypeCompatibleWithC = number | string | any[] | boolean; + + type CIntType = 'i8' | 'i16' | 'i32' | 'i64'; + type CFloatType = 'float' | 'double'; + type CPointerType = 'i8*' | 'i16*' | 'i32*' | 'i64*' | 'float*' | 'double*' | '*'; + type CType = CIntType | CFloatType | CPointerType; + + type WebAssemblyImports = Array<{ + name: string; + kind: string; + }>; + + type WebAssemblyExports = Array<{ + module: string; + name: string; + kind: string; + }>; + + interface CCallOpts { + async?: boolean | undefined; + } +} + +interface EmscriptenModule { + print(str: string): void; + printErr(str: string): void; + arguments: string[]; + environment: Emscripten.EnvironmentType; + preInit: Array<{ (): void }>; + preRun: Array<{ (): void }>; + postRun: Array<{ (): void }>; + onAbort: { (what: any): void }; + onRuntimeInitialized: { (): void }; + preinitializedWebGLContext: WebGLRenderingContext; + noInitialRun: boolean; + noExitRuntime: boolean; + logReadFiles: boolean; + filePackagePrefixURL: string; + wasmBinary: ArrayBuffer; + + destroy(object: object): void; + getPreloadedPackage(remotePackageName: string, remotePackageSize: number): ArrayBuffer; + instantiateWasm( + imports: Emscripten.WebAssemblyImports, + successCallback: (module: WebAssembly.Module) => void, + ): Emscripten.WebAssemblyExports; + locateFile(url: string, scriptDirectory: string): string; + onCustomMessage(event: MessageEvent): void; + + // USE_TYPED_ARRAYS == 1 + HEAP: Int32Array; + IHEAP: Int32Array; + FHEAP: Float64Array; + + // USE_TYPED_ARRAYS == 2 + HEAP8: Int8Array; + HEAP16: Int16Array; + HEAP32: Int32Array; + HEAPU8: Uint8Array; + HEAPU16: Uint16Array; + HEAPU32: Uint32Array; + HEAPF32: Float32Array; + HEAPF64: Float64Array; + + TOTAL_STACK: number; + TOTAL_MEMORY: number; + FAST_MEMORY: number; + + addOnPreRun(cb: () => any): void; + addOnInit(cb: () => any): void; + addOnPreMain(cb: () => any): void; + addOnExit(cb: () => any): void; + addOnPostRun(cb: () => any): void; + + preloadedImages: any; + preloadedAudios: any; + + _malloc(size: number): number; + _free(ptr: number): void; +} + +/** +* A factory function is generated when setting the `MODULARIZE` build option +* to `1` in your Emscripten build. It return a Promise that resolves to an +* initialized, ready-to-call `EmscriptenModule` instance. +* +* By default, the factory function will be named `Module`. It's recommended to +* use the `EXPORT_ES6` option, in which the factory function will be the +* default export. If used without `EXPORT_ES6`, the factory function will be a +* global variable. You can rename the variable using the `EXPORT_NAME` build +* option. It's left to you to declare any global variables as needed in your +* application's types. +* @param moduleOverrides Default properties for the initialized module. +*/ +type EmscriptenModuleFactory = ( + moduleOverrides?: Partial, +) => Promise; + +declare namespace FS { + interface Lookup { + path: string; + node: FSNode; + } + + interface FSStream { } + interface FSNode { } + interface ErrnoError { } + + let ignorePermissions: boolean; + let trackingDelegate: any; + let tracking: any; + let genericErrors: any; + + // + // paths + // + function lookupPath(path: string, opts: any): Lookup; + function getPath(node: FSNode): string; + + // + // nodes + // + function isFile(mode: number): boolean; + function isDir(mode: number): boolean; + function isLink(mode: number): boolean; + function isChrdev(mode: number): boolean; + function isBlkdev(mode: number): boolean; + function isFIFO(mode: number): boolean; + function isSocket(mode: number): boolean; + + // + // devices + // + function major(dev: number): number; + function minor(dev: number): number; + function makedev(ma: number, mi: number): number; + function registerDevice(dev: number, ops: any): void; + + // + // core + // + function syncfs(populate: boolean, callback: (e: any) => any): void; + function syncfs(callback: (e: any) => any, populate?: boolean): void; + function mount(type: Emscripten.FileSystemType, opts: any, mountpoint: string): any; + function unmount(mountpoint: string): void; + + function mkdir(path: string, mode?: number): any; + function mkdev(path: string, mode?: number, dev?: number): any; + function symlink(oldpath: string, newpath: string): any; + function rename(old_path: string, new_path: string): void; + function rmdir(path: string): void; + function readdir(path: string): any; + function unlink(path: string): void; + function readlink(path: string): string; + function stat(path: string, dontFollow?: boolean): any; + function lstat(path: string): any; + function chmod(path: string, mode: number, dontFollow?: boolean): void; + function lchmod(path: string, mode: number): void; + function fchmod(fd: number, mode: number): void; + function chown(path: string, uid: number, gid: number, dontFollow?: boolean): void; + function lchown(path: string, uid: number, gid: number): void; + function fchown(fd: number, uid: number, gid: number): void; + function truncate(path: string, len: number): void; + function ftruncate(fd: number, len: number): void; + function utime(path: string, atime: number, mtime: number): void; + function open(path: string, flags: string, mode?: number, fd_start?: number, fd_end?: number): FSStream; + function close(stream: FSStream): void; + function llseek(stream: FSStream, offset: number, whence: number): any; + function read(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number): number; + function write( + stream: FSStream, + buffer: ArrayBufferView, + offset: number, + length: number, + position?: number, + canOwn?: boolean, + ): number; + function allocate(stream: FSStream, offset: number, length: number): void; + function mmap( + stream: FSStream, + buffer: ArrayBufferView, + offset: number, + length: number, + position: number, + prot: number, + flags: number, + ): any; + function ioctl(stream: FSStream, cmd: any, arg: any): any; + function readFile(path: string, opts: { encoding: 'binary'; flags?: string | undefined }): Uint8Array; + function readFile(path: string, opts: { encoding: 'utf8'; flags?: string | undefined }): string; + function readFile(path: string, opts?: { flags?: string | undefined }): Uint8Array; + function writeFile(path: string, data: string | ArrayBufferView, opts?: { flags?: string | undefined }): void; + + // + // module-level FS code + // + function cwd(): string; + function chdir(path: string): void; + function init( + input: null | (() => number | null), + output: null | ((c: number) => any), + error: null | ((c: number) => any), + ): void; + + function createLazyFile( + parent: string | FSNode, + name: string, + url: string, + canRead: boolean, + canWrite: boolean, + ): FSNode; + function createPreloadedFile( + parent: string | FSNode, + name: string, + url: string, + canRead: boolean, + canWrite: boolean, + onload?: () => void, + onerror?: () => void, + dontCreateFile?: boolean, + canOwn?: boolean, + ): void; + function createDataFile( + parent: string | FSNode, + name: string, + data: ArrayBufferView, + canRead: boolean, + canWrite: boolean, + canOwn: boolean, + ): FSNode; +} + +declare var MEMFS: Emscripten.FileSystemType; +declare var NODEFS: Emscripten.FileSystemType; +declare var IDBFS: Emscripten.FileSystemType; + +// https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html +type StringToType = R extends Emscripten.JSType + ? { + number: number; + string: string; + array: number[] | string[] | boolean[] | Uint8Array | Int8Array; + boolean: boolean; + null: null; + }[R] + : never; + +type ArgsToType> = Extract< + { + [P in keyof T]: StringToType; + }, + any[] +>; + +type ReturnToType = R extends null + ? null + : StringToType>; + +// Below runtime function/variable declarations are exportable by +// -s EXTRA_EXPORTED_RUNTIME_METHODS. You can extend or merge +// EmscriptenModule interface to add runtime functions. +// +// For example, by using -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" +// You can access ccall() via Module["ccall"]. In this case, you should +// extend EmscriptenModule to pass the compiler check like the following: +// +// interface YourOwnEmscriptenModule extends EmscriptenModule { +// ccall: typeof ccall; +// } +// +// See: https://emscripten.org/docs/getting_started/FAQ.html#why-do-i-get-typeerror-module-something-is-not-a-function + +declare function cwrap< + I extends Array | [], + R extends Emscripten.JSType | null +>( + ident: string, + returnType: R, + argTypes: I, + opts?: Emscripten.CCallOpts +): (...arg: ArgsToType) => ReturnToType; + +declare function ccall< + I extends Array | [], + R extends Emscripten.JSType | null +>( + ident: string, + returnType: R, + argTypes: I, + args: ArgsToType, + opts?: Emscripten.CCallOpts +): ReturnToType; + +declare function setValue(ptr: number, value: any, type: Emscripten.CType, noSafe?: boolean): void; +declare function getValue(ptr: number, type: Emscripten.CType, noSafe?: boolean): number; + +declare function allocate( + slab: number[] | ArrayBufferView | number, + types: Emscripten.CType | Emscripten.CType[], + allocator: number, + ptr?: number, +): number; + +declare function stackAlloc(size: number): number; +declare function stackSave(): number; +declare function stackRestore(ptr: number): void; + +declare function UTF8ToString(ptr: number, maxBytesToRead?: number): string; +declare function stringToUTF8(str: string, outPtr: number, maxBytesToRead?: number): void; +declare function lengthBytesUTF8(str: string): number; +declare function allocateUTF8(str: string): number; +declare function allocateUTF8OnStack(str: string): number; +declare function UTF16ToString(ptr: number): string; +declare function stringToUTF16(str: string, outPtr: number, maxBytesToRead?: number): void; +declare function lengthBytesUTF16(str: string): number; +declare function UTF32ToString(ptr: number): string; +declare function stringToUTF32(str: string, outPtr: number, maxBytesToRead?: number): void; +declare function lengthBytesUTF32(str: string): number; + +declare function intArrayFromString(stringy: string, dontAddNull?: boolean, length?: number): number[]; +declare function intArrayToString(array: number[]): string; +declare function writeStringToMemory(str: string, buffer: number, dontAddNull: boolean): void; +declare function writeArrayToMemory(array: number[], buffer: number): void; +declare function writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void; + +declare function addRunDependency(id: any): void; +declare function removeRunDependency(id: any): void; + +declare function addFunction(func: (...args: any[]) => any, signature?: string): number; +declare function removeFunction(funcPtr: number): void; + +declare var ALLOC_NORMAL: number; +declare var ALLOC_STACK: number; +declare var ALLOC_STATIC: number; +declare var ALLOC_DYNAMIC: number; +declare var ALLOC_NONE: number; diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/environment.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/environment.d.ts new file mode 100644 index 00000000..f34b2733 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/environment.d.ts @@ -0,0 +1,79 @@ +export { }; + +declare global { + + const UTF8ToString: (ptr: number, maxBytesToRead?: number) => string; + const stringToUTF8: (str: string, outPtr: number, maxBytesToRead?: number) => void; + + const Pointer_stringify: (val: any) => string; + const lengthBytesUTF8: (val: any) => number; + + const dynCall: ( + signature: T extends void ? string : string, + ptr: number | Pointer, + args: T extends void ? (number | Pointer)[] : Parameters + ) => void; + const Runtime: any; + const LibraryManager: any; + const autoAddDeps: any; + const mergeInto: any; + + + + function print(str: string): void; + function printErr(str: string): void; + const arguments: string[]; + const environment: Emscripten.EnvironmentType; + const preInit: Array<{ (): void }>; + const preRun: Array<{ (): void }>; + const postRun: Array<{ (): void }>; + const onAbort: { (what: any): void }; + const onRuntimeInitialized: { (): void }; + const preinitializedWebGLContext: WebGLRenderingContext; + const noInitialRun: boolean; + const noExitRuntime: boolean; + const logReadFiles: boolean; + const filePackagePrefixURL: string; + const wasmBinary: ArrayBuffer; + + function destroy(object: object): void; + function getPreloadedPackage(remotePackageName: string, remotePackageSize: number): ArrayBuffer; + function instantiateWasm( + imports: Emscripten.WebAssemblyImports, + successCallback: (module: WebAssembly.Module) => void, + ): Emscripten.WebAssemblyExports; + function locateFile(url: string, scriptDirectory: string): string; + function onCustomMessage(event: MessageEvent): void; + + // USE_TYPED_ARRAYS == 1 + const HEAP: Int32Array; + const IHEAP: Int32Array; + const FHEAP: Float64Array; + + // USE_TYPED_ARRAYS == 2 + const HEAP8: Int8Array; + const HEAP16: Int16Array; + const HEAP32: Int32Array; + const HEAPU8: Uint8Array; + const HEAPU16: Uint16Array; + const HEAPU32: Uint32Array; + const HEAPF32: Float32Array; + const HEAPF64: Float64Array; + + const TOTAL_STACK: number; + const TOTAL_MEMORY: number; + const FAST_MEMORY: number; + + function addOnPreRun(cb: () => any): void; + function addOnInit(cb: () => any): void; + function addOnPreMain(cb: () => any): void; + function addOnExit(cb: () => any): void; + function addOnPostRun(cb: () => any): void; + + const preloadedImages: any; + const preloadedAudios: any; + + function _malloc(size: number): number; + function _memcpy(target: number, src: number, size: number): void; + function _free(ptr: number): void; +} diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/jsapi.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/jsapi.d.ts new file mode 100644 index 00000000..5b6fe8a1 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/jsapi.d.ts @@ -0,0 +1,190 @@ +export { }; + +declare global { + // export type Pointer = number & { + // type?: T; + // __pointer: true; + // }; + + export type Pointer = number & { + type?: T; + __pointer: true; + }; + + export type PointerArray = number & { + type?: T; + __pointerArray: true; + }; + + export type Out = number & { + type?: T; + __out: true; + }; + + export type Boolish = boolean | -1; + + export type int = number; + export type Byte = number; + export type Int64 = number; + export type UInt32 = number; + + export type IntPtr = Pointer<'IntPtr'>; + export type JSPayloadHeader = Pointer<'JSPayloadHeader'>; + export type JSValue = Pointer<'JSValue'>; + export type JSValueConst = JSValue; + export type JSAtom = UInt32; + export type JSContext = UInt32; + export type JSRuntime = UInt32; + export type JSModuleDef = UInt32; + export type JSClassID = UInt32; + export type JSMemoryUsage = Pointer<'JSMemoryUsage'>; + export type size_t = number; + + export declare interface JSApiExternals { + static JS_SetModuleLoaderFunc(rt: JSRuntime, module_normalize: IntPtr, module_loader: IntPtr, opaque: IntPtr): void; + static JS_GetImportMeta(returnValue: JSValue, ctx: JSContext, m: JSModuleDef); + static JSB_GetBridgeClassID(): JSClassID; + static jsb_construct_bridge_object(returnValue: JSValue, ctx: JSContext, proto: JSValue, object_id: number); + static jsb_new_bridge_object(returnValue: JSValue, ctx: JSContext, proto: JSValue, object_id: number); + static JSB_NewBridgeClassObject(returnValue: JSValue, ctx: JSContext, new_target: JSValue, object_id: number); + static jsb_new_bridge_value(returnValue: JSValue, ctx: JSContext, proto: JSValue, size: UInt32); + static JSB_NewBridgeClassValue(returnValue: JSValue, ctx: JSContext, new_target: JSValue, size: number); + static JSB_FreePayload(returnValue: JSPayloadHeader, ctx: JSContext, val: JSValue); + static jsb_get_payload_header(returnValue: JSPayloadHeader, ctx: JSContext, val: JSValue); + static JSB_NewRuntime(class_finalizer: IntPtr): JSRuntime; + static JSB_GetRuntimeOpaque(rt: JSRuntime): IntPtr; + static JSB_SetRuntimeOpaque(rt: JSRuntime, opaque: IntPtr): void; + static JSB_FreeRuntime(rt: JSRuntime): Boolish; + static JS_GetRuntime(ctx: JSContext): JSRuntime; + static JS_NewContext(rt: JSRuntime): JSContext; + static JS_FreeContext(ctx: JSContext): void; + static JS_GetGlobalObject(returnValue: JSValue, ctx: JSContext); + static JS_IsInstanceOf(ctx: JSContext, val: JSValue, obj: JSValue): Boolish; + static JS_NewPromiseCapability(returnValue: JSValue, ctx: JSContext, resolving_funcs: Pointer); + static JS_SetHostPromiseRejectionTracker(rt: JSRuntime, cb: IntPtr, opaque: IntPtr): void; + static JS_GetPropertyUint32(returnValue: JSValue, ctx: JSContext, this_obj: JSValue, idx: UInt32); + static JS_GetPropertyInternal(returnValue: JSValue, ctx: JSContext, obj: JSValue, prop: JSAtom, receiver: JSValue, throw_ref_error: number); + static JS_GetPropertyStr(returnValue: JSValue, ctx: JSContext, this_obj: JSValue, prop: Pointer); + static JS_DefineProperty(ctx: JSContext, this_obj: JSValue, prop: JSAtom, val: JSValue, getter: JSValue, setter: JSValue, flags: JSPropFlags): Boolish; + static JS_DefinePropertyValue(ctx: JSContext, this_obj: JSValue, prop: JSAtom, val: JSValue, flags: JSPropFlags): Boolish; + static JS_GetException(returnValue: JSValue, ctx: JSContext); + static JS_IsError(ctx: JSContext, val: JSValue): Boolish; + static JSB_ThrowError(returnValue: JSValue, ctx: JSContext, buf: Pointer, buf_len: size_t); + static JSB_ThrowTypeError(returnValue: JSValue, ctx: JSContext, msg: Pointer); + static JSB_ThrowInternalError(returnValue: JSValue, ctx: JSContext, msg: Pointer); + static JSB_ThrowRangeError(returnValue: JSValue, ctx: JSContext, msg: Pointer); + static JSB_ThrowReferenceError(returnValue: JSValue, ctx: JSContext, msg: Pointer); + static JSB_NewEmptyString(returnValue: JSValue, ctx: JSContext); + static JS_NewString(returnValue: JSValue, ctx: JSContext, str: Pointer); + static JS_NewStringLen(returnValue: JSValue, ctx: JSContext, buf: Pointer, buf_len: size_t); + static JSB_NewInt64(returnValue: JSValue, ctx: JSContext, val: Int64); + static JSB_NewFloat64(returnValue: JSValue, ctx: JSContext, d: number); + static JS_NewAtomLen(ctx: JSContext, str: Pointer, len: size_t): JSAtom; + static JS_DupAtom(ctx: JSContext, v: JSAtom): JSAtom; + static JS_FreeAtom(ctx: JSContext, v: JSAtom): void; + static JS_AtomToString(returnValue: JSValue, ctx: JSContext, atom: JSAtom); + static jsb_crossbind_constructor(returnValue: JSValue, ctx: JSContext, new_target: JSValue); + static JS_NewObject(returnValue: JSValue, ctx: JSContext); + static JS_IsFunction(ctx: JSContext, val: JSValue): Boolish; + static JS_IsConstructor(ctx: JSContext, val: JSValue): Boolish; + static JS_NewArray(returnValue: JSValue, ctx: JSContext); + static JS_IsArray(ctx: JSContext, val: JSValue): Boolish; + static JS_GetContextOpaque(ctx: JSContext): IntPtr; + static JS_SetContextOpaque(ctx: JSContext, opaque: IntPtr): void; + static JSB_NewCFunctionMagic(returnValue: JSValue, ctx: JSContext, func: IntPtr, atom: JSAtom, length: number, cproto: JSCFunctionEnum, magic: number); + static JSB_NewCFunction(returnValue: JSValue, ctx: JSContext, func: IntPtr, atom: JSAtom, length: number, cproto: JSCFunctionEnum, magic: number); + static JS_SetConstructor(ctx: JSContext, func_obj: JSValue, proto: JSValue): void; + static JS_SetPropertyInternal(ctx: JSContext, this_obj: JSValue, prop: JSAtom, val: JSValue, flags: number): Boolish; + static JS_SetPropertyUint32(ctx: JSContext, this_obj: JSValue, idx: UInt32, val: JSValue): Boolish; + static JS_HasProperty(ctx: JSContext, this_obj: JSValue, prop: JSAtom): Boolish; + static JS_ParseJSON(returnValue: JSValue, ctx: JSContext, buf: Pointer, buf_len: size_t, filename: Pointer); + static JS_JSONStringify(returnValue: JSValue, ctx: JSContext, obj: JSValue, replacer: JSValue, space0: JSValue); + static JS_CallConstructor(returnValue: JSValue, ctx: JSContext, func_obj: JSValue, argc: number, argv: PointerArray); + static JS_Call(returnValue: JSValue, ctx: JSContext, func_obj: JSValue, this_obj: JSValue, argc: number, argv: PointerArray); + static JS_Invoke(returnValue: JSValue, ctx: JSContext, this_val: JSValue, atom: JSAtom, argc: number, argv: PointerArray); + static JS_SetPrototype(ctx: JSContext, obj: JSValue, proto_val: JSValue): Boolish; + static JS_RunGC(rt: JSRuntime): void; + static JS_ToBool(ctx: JSContext, val: JSValue): Boolish; + static js_free(ctx: JSContext, ptr: IntPtr): void; + static JS_ReadObject(returnValue: JSValue, ctx: JSContext, buf: Pointer, buf_len: size_t, flags: number); + static JS_Eval(returnValue: JSValue, ctx: JSContext, input: Pointer, input_len: size_t, filename: Pointer, eval_flags: JSEvalFlags); + static JS_EvalFunction(returnValue: JSValue, ctx: JSContext, fun_obj: JSValue); + static JS_ResolveModule(ctx: JSContext, obj: JSValue): number; + static JSB_DupValue(returnValue: JSValue, ctx: JSContext, v: JSValue); + static JSB_FreeValue(ctx: JSContext, v: JSValue): void; + static JSB_FreeValueRT(rt: JSRuntime, v: JSValue): void; + static JS_AddIntrinsicOperators(ctx: JSContext): void; + static JSB_ATOM_Proxy(): JSAtom; + static JSB_ATOM_constructor(): JSAtom; + static JSB_ATOM_Number(): JSAtom; + static JSB_ATOM_Object(): JSAtom; + static JSB_ATOM_String(): JSAtom; + static JSB_ATOM_Function(): JSAtom; + static JSB_ATOM_Error(): JSAtom; + static JSB_ATOM_Operators(): JSAtom; + static JSB_ATOM_Symbol_operatorSet(): JSAtom; + static JSB_ATOM_name(): JSAtom; + static JSB_ATOM_message(): JSAtom; + static JSB_ATOM_fileName(): JSAtom; + static JSB_ATOM_lineNumber(): JSAtom; + static JSB_ATOM_length(): JSAtom; + static JSB_ATOM_stack(): JSAtom; + static JSB_ATOM_prototype(): JSAtom; + static JSB_Init(): number; + static JS_FreeCString(ctx: JSContext, ptr: IntPtr): void; + static js_strndup(ctx: JSContext, s: Pointer, n: size_t): IntPtr; + static JS_NewArrayBufferCopy(returnValue: JSValue, ctx: JSContext, buf: Pointer, len: size_t); + static JS_ComputeMemoryUsage(rt: JSRuntime, s: Pointer): void; + static JS_SetInterruptHandler(rt: JSRuntime, cb: IntPtr, opaque: IntPtr): void; + + static JS_IsJobPending(rt: JSRuntime, pctx: Out): Boolish; + static JS_ExecutePendingJob(rt: JSRuntime, pctx: Out): Boolish; + static JS_ToInt32(ctx: JSContext, pres: Out, val: JSValue): Boolish; + static JS_ToInt64(ctx: JSContext, pres: Out, val: JSValue): Boolish; + static JS_ToBigInt64(ctx: JSContext, pres: Out, val: JSValue): Boolish; + static JS_ToIndex(ctx: JSContext, plen: Out, val: JSValue): Boolish; + static JS_ToFloat64(ctx: JSContext, pres: Out, val: JSValue): Boolish; + static JSB_ToUint32(ctx: JSContext, pres: Out, val: JSValue): Boolish; + static JS_WriteObject(ctx: JSContext, psize: Out, obj: JSValue, flags: number): IntPtr; + static JS_ToCStringLen2(ctx: JSContext, len: Out, val: JSValue, cesu8: boolean): IntPtr; + static JS_GetArrayBuffer(ctx: JSContext, psize: Out, obj: JSValue): IntPtr; + + static jsb_get_float_2(ctx: JSContext, val: JSValue, v0: Out, v1: Out): Boolish; + static jsb_get_float_3(ctx: JSContext, val: JSValue, v0: Out, v1: Out, v2: Out): Boolish; + static jsb_get_float_4(ctx: JSContext, val: JSValue, v0: Out, v1: Out, v2: Out, v3: Out): Boolish; + static jsb_get_int_1(ctx: JSContext, val: JSValue, v0: Out): Boolish; + static jsb_get_int_2(ctx: JSContext, val: JSValue, v0: Out, v1: Out): Boolish; + static jsb_get_int_3(ctx: JSContext, val: JSValue, v0: Out, v1: Out, v2: Out): Boolish; + static jsb_get_int_4(ctx: JSContext, val: JSValue, v0: Out, v1: Out, v2: Out, v3: Out): Boolish; + static jsb_get_byte_4(ctx: JSContext, val: JSValue, v0: Out, v1: Out, v2: Out, v3: Out): Boolish; + static jsb_get_floats(ctx: JSContext, val: JSValue, n: number, v0: Pointer): Boolish; + static jsb_get_bytes(ctx: JSContext, val: JSValue, n: number, v0: Pointer): Boolish; + + static jsb_set_floats(ctx: JSContext, val: JSValue, n: number, v0: Pointer): Boolish; + static jsb_set_float_2(ctx: JSContext, val: JSValue, v0: number, v1: number): Boolish; + static jsb_set_float_3(ctx: JSContext, val: JSValue, v0: number, v1: number, v2: number): Boolish; + static jsb_set_float_4(ctx: JSContext, val: JSValue, v0: number, v1: number, v2: number, v3: number): Boolish; + static jsb_set_int_1(ctx: JSContext, val: JSValue, v0: number): Boolish; + static jsb_set_int_2(ctx: JSContext, val: JSValue, v0: number, v1: number): Boolish; + static jsb_set_int_3(ctx: JSContext, val: JSValue, v0: number, v1: number, v2: number): Boolish; + static jsb_set_int_4(ctx: JSContext, val: JSValue, v0: number, v1: number, v2: number, v3: number): Boolish; + static jsb_set_byte_4(ctx: JSContext, val: JSValue, v0: Byte, v1: Byte, v2: Byte, v3: Byte): Boolish; + static jsb_set_bytes(ctx: JSContext, val: JSValue, n: number, v0: Pointer): Boolish; + } + + export declare class JSApiDelegates { + static JSInterruptHandler(rt: JSRuntime, opaque: IntPtr): int; + static JSHostPromiseRejectionTracker(ctx: JSContext, promise: JSValueConst, reason: JSValueConst, is_handled: bool, opaque: IntPtr): void; + static JSModuleNormalizeFunc(ctx: JSContext, module_base_name: Pointer, module_name: Pointer, opaque: IntPtr): IntPtr; + static JSModuleLoaderFunc(ctx: JSContext, module_name: Pointer, opaque: IntPtr): JSModuleDef; + static JSGCObjectFinalizer(rt: JSRuntime, header: JSPayloadHeader): void; + static JSCFunction(returnValue: JSValue, ctx: JSContext, this_obj: JSValueConst, argc: int, argv: PointerArray); + static JSCFunctionMagic(returnValue: JSValue, ctx: JSContext, this_obj: JSValueConst, argc: int, argv: PointerArray, magic: int); + static JSSetterCFunction(returnValue: JSValue, ctx: JSContext, this_val: JSValueConst, val: JSValueConst); + static JSSetterCFunctionMagic(returnValue: JSValue, ctx: JSContext, this_val: JSValueConst, val: JSValueConst, magic: int); + static JSGetterCFunction(returnValue: JSValue, ctx: JSContext, this_val: JSValueConst); + static JSGetterCFunctionMagic(returnValue: JSValue, ctx: JSContext, this_val: JSValueConst, magic: int); + static JSLogCFunction(level: number, line: Pointer): void; + static JSWaitingForDebuggerCFunction(ctx: JSContext): void; + } +} diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts new file mode 100644 index 00000000..a0c1cdf2 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts @@ -0,0 +1,221 @@ +export { }; + +declare global { + var unityJsbState: PluginState; + + export declare type PluginState = { + stringify: ((ptr: number | Pointer, bufferLength?: number) => string); + bufferify: ((str: string) => [number, number]); + dynCall: typeof dynCall; + runtimes: Record; + contexts: Record; + lastRuntimeId: number; + lastContextId: number; + atoms?: PluginAtoms; + createObjects: () => PluginObjects; + createAtoms: () => PluginAtoms; + + getRuntime: (ctx: JSRuntime) => PluginRuntime; + getContext: (ctx: JSContext) => PluginContext; + + HEAP64: () => BigInt64Array; + HEAPU64: () => BigUint64Array; + } + + export declare type PluginRuntime = { + id: number; + opaque?: any; + contexts: Record; + objects: PluginObjects; + garbageCollect(): number; + }; + + export declare type PluginContext = { + id: number; + opaque?: any; + runtime: PluginRuntime; + runtimeId: number; + + window: Window; + globalObject: Window; + globalObjectId?: number; + + evaluate: ((script: string, filename?: string) => any); + lastException?: Error; + }; + + export declare type PluginAtoms = { + record: Record; + map: Record; + get: ((ref: JSAtom) => string); + lastId: number; + push: ((str: string) => JSAtom); + pushId: ((id: JSAtom) => JSAtom); + pop: ((ref: JSAtom) => void); + }; + + export declare type PluginAtom = { + id: number; + value: string; + refCount: number; + } + + export declare type PluginObjects = { + deleteIndex: (id: number) => void; + record: Record; + get: ((ref: JSValue) => any); + getRecord: ((ref: JSValue) => PluginObject); + push: ((obj: any, ptr: JSValue) => void); + allocate: ((obj: any) => JSValue); + batchAllocate: ((objs: any[]) => PointerArray); + batchGet: ((arr: PointerArray, count: number) => any[]); + ref: ((obj: JSValue, diff: number, ptr: JSValue) => void); + refIndex: ((obj: number, diff: number, ptr: JSValue) => void); + lastId: number; + setPayload: ((obj: any, type: BridgeObjectType, payload: number) => void); + getPayload: ((obj: any) => PluginObjectPayload); + clearPayload: ((obj: any) => void); + payloadMap: Map; + }; + + export declare type PluginObject = { + id: number; + refCount: number; + tag: Tags; + value: any; + }; + + export declare type PluginObjectPayload = { + type: BridgeObjectType; + payload: number; + }; + + export declare type BridgeStruct = { + $$values: number[]; + }; + + const enum JSPropFlags { + /* flags for object properties */ + JS_PROP_CONFIGURABLE = (1 << 0), + JS_PROP_WRITABLE = (1 << 1), + JS_PROP_ENUMERABLE = (1 << 2), + JS_PROP_C_W_E = (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE), + JS_PROP_LENGTH = (1 << 3) /* used internally in Arrays */, + JS_PROP_TMASK = (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */, + JS_PROP_NORMAL = (0 << 4), + JS_PROP_GETSET = (1 << 4), + JS_PROP_VARREF = (2 << 4) /* used internally */, + JS_PROP_AUTOINIT = (3 << 4) /* used internally */, + + /* flags for JS_DefineProperty */ + JS_PROP_HAS_SHIFT = 8, + JS_PROP_HAS_CONFIGURABLE = (1 << 8), + JS_PROP_HAS_WRITABLE = (1 << 9), + JS_PROP_HAS_ENUMERABLE = (1 << 10), + JS_PROP_HAS_GET = (1 << 11), + JS_PROP_HAS_SET = (1 << 12), + JS_PROP_HAS_VALUE = (1 << 13), + + /* throw an exception if false would be returned + (JS_DefineProperty/JS_SetProperty) */ + JS_PROP_THROW = (1 << 14), + + /* throw an exception if false would be returned in strict mode + (JS_SetProperty) */ + JS_PROP_THROW_STRICT = (1 << 15), + + JS_PROP_NO_ADD = (1 << 16) /* internal use */, + JS_PROP_NO_EXOTIC = (1 << 17) /* internal use */, + + // custom values + CONST_VALUE = JS_PROP_HAS_VALUE | JS_PROP_ENUMERABLE, + DEFAULT = JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, + NONE = 0, + } + + const enum Tags { + JS_TAG_FIRST = -11, /* first negative tag */ + JS_TAG_BIG_DECIMAL = -11, + JS_TAG_BIG_INT = -10, + JS_TAG_BIG_FLOAT = -9, + JS_TAG_SYMBOL = -8, + JS_TAG_STRING = -7, + JS_TAG_MODULE = -3, /* used internally */ + JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */ + JS_TAG_OBJECT = -1, + JS_TAG_INT = 0, + JS_TAG_BOOL = 1, + JS_TAG_NULL = 2, + JS_TAG_UNDEFINED = 3, + JS_TAG_EXCEPTION = 6, + JS_TAG_FLOAT64 = 7, + } + + const enum Constants { + VERSION = 0x010704, + CS_JSB_VERSION = 0xa, + + JS_WRITE_OBJ_BYTECODE = 1 << 0, /* allow function/module */ + JS_WRITE_OBJ_BSWAP = 1 << 1, /* byte swapped output */ + JS_WRITE_OBJ_SAB = 1 << 2, /* allow SharedArrayBuffer */ + JS_WRITE_OBJ_REFERENCE = 1 << 3, /* allow object references to encode arbitrary object graph */ + JS_READ_OBJ_BYTECODE = 1 << 0, /* allow function/module */ + JS_READ_OBJ_ROM_DATA = 1 << 1, /* avoid duplicating 'buf' data */ + JS_READ_OBJ_SAB = 1 << 2, /* allow SharedArrayBuffer */ + JS_READ_OBJ_REFERENCE = 1 << 3, /* allow object references */ + } + + const enum JSEvalFlags { + JS_EVAL_TYPE_GLOBAL = (0 << 0) /* global code (default) */, + JS_EVAL_TYPE_MODULE = (1 << 0) /* module code */, + JS_EVAL_TYPE_DIRECT = (2 << 0) /* direct call (internal use) */, + JS_EVAL_TYPE_INDIRECT = (3 << 0) /* indirect call (internal use) */, + JS_EVAL_TYPE_MASK = (3 << 0), + + JS_EVAL_FLAG_STRICT = (1 << 3) /* force 'strict' mode */, + JS_EVAL_FLAG_STRIP = (1 << 4) /* force 'strip' mode */, + + /* compile but do not run. The result is an object with a + JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed + with JS_EvalFunction(). */ + JS_EVAL_FLAG_COMPILE_ONLY = (1 << 5), + + /* don't include the stack frames before this eval in the Error() backtraces */ + JS_EVAL_FLAG_BACKTRACE_BARRIER = (1 << 6), + } + + + const enum BridgeObjectType { + None = 0, + TypeRef = 1, + ObjectRef = 2, + ValueType = 3, + } + + const enum JSCFunctionEnum { + /* XXX: should rename for namespace isolation */ + JS_CFUNC_generic = 0, + JS_CFUNC_generic_magic = 1, + JS_CFUNC_constructor = 2, // unused in jsb + JS_CFUNC_constructor_magic = 3, + JS_CFUNC_constructor_or_func = 4, // unused in jsb + JS_CFUNC_constructor_or_func_magic = 5, // unused in jsb + JS_CFUNC_f_f = 6, // unused in jsb + JS_CFUNC_f_f_f = 7, // unused in jsb + JS_CFUNC_getter = 8, + JS_CFUNC_setter = 9, + JS_CFUNC_getter_magic = 10, + JS_CFUNC_setter_magic = 11, + JS_CFUNC_iterator_next = 12, // unused in jsb + } + + + const enum Sizes { + JSPayloadHeader = 8, + JSValueUnion = 8, + JSValue = 16, + JSAtom = 4, + Single = 4, + Double = 8, + } +} diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c deleted file mode 100644 index 71321b5a..00000000 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef UNITY_WEBGL -#define UNITY_WEBGL -#endif - -#ifndef EMSCRIPTEN -#define EMSCRIPTEN -#endif - -// #define DUMP_MEM -// #define CONFIG_BIGNUM - -#define CONFIG_VERSION "quickjs-latest" - -#define compute_stack_size compute_stack_size_regexp -#define is_digit is_digit_regexp -#include "../../../../jsb_build/quickjs/quickjs-latest/libregexp.c" -#undef is_digit -#undef compute_stack_size - -#include "../../../../jsb_build/quickjs/quickjs-latest/cutils.c" -#include "../../../../jsb_build/quickjs/quickjs-latest/libunicode.c" - -#ifdef CONFIG_BIGNUM -#define floor_div floor_div_bbf -#define to_digit to_digit_bbf -#include "../../../../jsb_build/quickjs/quickjs-latest/libbf.c" -#undef floor_div -#undef to_digit -#undef malloc -#undef free -#undef realloc -#endif - -#include "../../../../jsb_build/quickjs/quickjs-latest/quickjs.c" - -#define DEF(name, str) \ - JSAtom JSB_ATOM_##name() { return JS_ATOM_##name; } -#include "../../../../jsb_build/quickjs/quickjs-latest/quickjs-atom.h" -#undef DEF - -#include "../../../../jsb_build/quickjs/unity_qjs.c" diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c.meta b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c.meta deleted file mode 100644 index 202151fc..00000000 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/libquickjs.c.meta +++ /dev/null @@ -1,111 +0,0 @@ -fileFormatVersion: 2 -guid: f35b070bd3d247043a0aa8683fda5f51 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - : Any - second: - enabled: 0 - settings: - Exclude Android: 1 - Exclude Editor: 1 - Exclude Linux: 1 - Exclude Linux64: 1 - Exclude LinuxUniversal: 1 - Exclude OSXUniversal: 1 - Exclude WebGL: 0 - Exclude Win: 1 - Exclude Win64: 1 - Exclude iOS: 1 - - first: - Android: Android - second: - enabled: 0 - settings: - CPU: ARMv7 - - first: - Any: - second: - enabled: 0 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - CPU: AnyCPU - DefaultValueInitialized: true - OS: AnyOS - - first: - Facebook: Win - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Facebook: Win64 - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: Linux - second: - enabled: 0 - settings: - CPU: x86 - - first: - Standalone: Linux64 - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: LinuxUniversal - second: - enabled: 0 - settings: - CPU: None - - first: - Standalone: OSXUniversal - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: Win - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - Standalone: Win64 - second: - enabled: 0 - settings: - CPU: AnyCPU - - first: - WebGL: WebGL - second: - enabled: 1 - settings: {} - - first: - iPhone: iOS - second: - enabled: 0 - settings: - AddToEmbeddedBinaries: false - CompileFlags: - FrameworkDependencies: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib new file mode 100644 index 00000000..f7afc798 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib @@ -0,0 +1,1346 @@ +/** + * Build with the following command: + * npx -p typescript tsc + */ +var QuickJSPlugin = { + $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', + $unityJsbState: { + createObjects: function () { + var getTag = function (object) { + if (object === undefined) + return 3 /* Tags.JS_TAG_UNDEFINED */; + if (object === null) + return 2 /* Tags.JS_TAG_NULL */; + if (typeof object === 'number') + return 7 /* Tags.JS_TAG_FLOAT64 */; + if (typeof object === 'boolean') + return 1 /* Tags.JS_TAG_BOOL */; + if (typeof object === 'function') + return -2 /* Tags.JS_TAG_FUNCTION_BYTECODE */; + if (typeof object === 'symbol') + return -8 /* Tags.JS_TAG_SYMBOL */; + if (typeof object === 'string') + return -7 /* Tags.JS_TAG_STRING */; + if (typeof object === 'bigint') + return -10 /* Tags.JS_TAG_BIG_INT */; + if (object instanceof Error) + return 6 /* Tags.JS_TAG_EXCEPTION */; + return -1 /* Tags.JS_TAG_OBJECT */; + }; + var record = {}; + var map = new Map(); + var payloadMap = new Map(); + var res = { + record: record, + lastId: 0, + allocate: function (object) { + var ptr = _malloc(16 /* Sizes.JSValue */); + res.push(object, ptr); + return ptr; + }, + batchAllocate: function (objects) { + var size = 16 /* Sizes.JSValue */; + var arr = _malloc(size * objects.length); + for (var index = 0; index < objects.length; index++) { + var object = objects[index]; + res.push(object, arr + (index * size)); + } + return arr; + }, + batchGet: function (ptrs, count) { + var size = 16 /* Sizes.JSValue */; + var arr = new Array(count); + for (var index = 0; index < count; index++) { + var object = res.get(ptrs + index * size); + arr[index] = object; + } + return arr; + }, + push: function (object, ptr) { + if (typeof object === 'undefined') { + res.refIndex(0, 1, ptr); + return; + } + if (typeof object === 'number') { + if (typeof ptr === 'number') { + HEAPF64[ptr >> 3] = object; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(7 /* Tags.JS_TAG_FLOAT64 */); + } + return; + } + if (typeof object === 'boolean') { + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = object ? 1 : 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(1 /* Tags.JS_TAG_BOOL */); + } + return; + } + var foundId = map.get(object); + if (foundId > 0) { + res.refIndex(foundId, 1, ptr); + return; + } + var id = ++res.lastId; + record[id] = { + id: id, + refCount: 0, + value: object, + tag: getTag(object), + }; + map.set(object, id); + res.refIndex(id, 1, ptr); + return id; + }, + get: function (val) { + var tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + if (tag === 0 /* Tags.JS_TAG_INT */) { + return HEAP32[val >> 2]; + } + else if (tag === 1 /* Tags.JS_TAG_BOOL */) { + return !!HEAP32[val >> 2]; + } + else if (tag === 7 /* Tags.JS_TAG_FLOAT64 */) { + return HEAPF64[val >> 3]; + } + else { + var id = HEAP32[val >> 2]; + if (id === 0) + return undefined; + var ho = record[id]; + return ho.value; + } + }, + getRecord: function (val) { + var tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + if (tag === 0 /* Tags.JS_TAG_INT */) { + var value = HEAP32[val >> 2]; + return { + id: -1, + refCount: 0, + value: value, + tag: tag, + }; + } + else if (tag === 1 /* Tags.JS_TAG_BOOL */) { + var boolValue = !!HEAP32[val >> 2]; + return { + id: -1, + refCount: 0, + value: boolValue, + tag: tag, + }; + } + else if (tag === 7 /* Tags.JS_TAG_FLOAT64 */) { + var value = HEAPF64[val >> 3]; + return { + id: -1, + refCount: 0, + value: value, + tag: tag, + }; + } + else { + var id = HEAP32[val >> 2]; + if (id === 0) + return { + id: 0, + refCount: 0, + value: undefined, + tag: 3 /* Tags.JS_TAG_UNDEFINED */, + type: 0 /* BridgeObjectType.None */, + payload: -1, + }; + var ho = record[id]; + return ho; + } + }, + ref: function (obj, diff, ptr) { + var tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); + if (tag === 7 /* Tags.JS_TAG_FLOAT64 */) { + if (typeof ptr === 'number') { + var val = HEAPF64[(obj >> 3)]; + HEAPF64[ptr >> 3] = val; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + else if (tag === 0 /* Tags.JS_TAG_INT */) { + if (typeof ptr === 'number') { + var val = HEAP32[(obj >> 2)]; + HEAP32[(ptr >> 2)] = val; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + else if (tag === 1 /* Tags.JS_TAG_BOOL */) { + if (typeof ptr === 'number') { + var valBool = !!HEAP32[(obj >> 2)]; + HEAP32[(ptr >> 2)] = valBool ? 1 : 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + var id = HEAP32[obj >> 2]; + res.refIndex(id, diff, ptr); + }, + refIndex: function (id, diff, ptr) { + if (id === 0) { + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(3 /* Tags.JS_TAG_UNDEFINED */); + } + return; + } + var ho = record[id]; + ho.refCount += diff; + console.assert(ho.refCount >= 0); + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = id; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(ho.tag); + } + }, + deleteIndex: function (id) { + var rec = record[id]; + delete record[id]; + map.delete(rec.value); + }, + payloadMap: payloadMap, + setPayload: function (obj, type, payload) { + payloadMap.set(obj, { + type: 0 /* BridgeObjectType.None */ || type, + payload: payload, + }); + }, + getPayload: function (obj) { + var res = payloadMap.get(obj); + if (res) + return res; + else { + return { + type: 0 /* BridgeObjectType.None */, + payload: 0, + }; + } + }, + clearPayload: function (obj) { + payloadMap.delete(obj); + }, + }; + return res; + }, + createAtoms: function () { + var record = {}; + var map = {}; + var res = { + record: record, + map: map, + lastId: 0, + get: function (ref) { + if (ref === 0) + return undefined; + return record[ref].value; + }, + push: function (str) { + if (str === undefined) + return 0; + var mapped = map[str]; + var id; + if (!mapped) { + id = ++res.lastId; + map[str] = record[id] = { + id: id, + value: str, + refCount: 1, + }; + } + else { + id = mapped.id; + mapped.refCount++; + } + return id; + }, + pushId: function (id) { + if (id === 0) + return; + var recorded = record[id]; + console.assert(!!recorded); + if (!recorded) + return 0; + recorded.refCount++; + return id; + }, + pop: function (id) { + if (id === 0) + return; + var recorded = record[id]; + console.assert(!!recorded); + if (!recorded) + return; + recorded.refCount--; + console.assert(recorded.refCount >= 0); + if (recorded.refCount == 0) { + delete map[recorded.value]; + delete record[id]; + } + }, + }; + return res; + }, + stringify: function (ptr, bufferLength) { return (typeof UTF8ToString !== 'undefined' ? UTF8ToString : Pointer_stringify)(ptr, bufferLength); }, + bufferify: function (arg) { + var bufferSize = lengthBytesUTF8(arg) + 1; + var buffer = _malloc(bufferSize); + stringToUTF8(arg, buffer, bufferSize); + return [buffer, bufferSize]; + }, + dynCall: function () { return (typeof Runtime !== 'undefined' ? Runtime.dynCall : dynCall).apply(typeof Runtime !== 'undefined' ? Runtime : undefined, arguments); }, + runtimes: {}, + contexts: {}, + lastRuntimeId: 1, + lastContextId: 1, + getRuntime: function (rt) { + var rtId = rt; + return unityJsbState.runtimes[rtId]; + }, + getContext: function (ctx) { + var ctxId = ctx; + return unityJsbState.contexts[ctxId]; + }, + HEAP64: function () { + return new BigInt64Array(HEAPF64.buffer); + }, + HEAPU64: function () { + return new BigUint64Array(HEAPF64.buffer); + }, + }, + JSB_Init: function () { + return 10 /* Constants.CS_JSB_VERSION */; + }, + JSB_NewRuntime: function (finalizer) { + // TODO: understand what to do with finalizer + var id = unityJsbState.lastRuntimeId++; + var objects = unityJsbState.createObjects(); + unityJsbState.runtimes[id] = { + id: id, + contexts: {}, + objects: objects, + garbageCollect: function () { + var lastId = objects.lastId; + var record = objects.record; + var aliveItemCount = 0; + for (var index = 0; index < lastId; index++) { + var element = record[index]; + if (element) { + if (element.refCount <= 0) { + objects.deleteIndex(index); + } + else { + aliveItemCount++; + } + } + } + return aliveItemCount; + }, + }; + return id; + }, + JSB_GetRuntimeOpaque: function (rtId) { + return unityJsbState.getRuntime(rtId).opaque; + }, + JSB_SetRuntimeOpaque: function (rtId, opaque) { + unityJsbState.getRuntime(rtId).opaque = opaque; + }, + JS_GetContextOpaque: function (ctx) { + return unityJsbState.getContext(ctx).opaque; + }, + JS_SetContextOpaque: function (ctx, opaque) { + unityJsbState.getContext(ctx).opaque = opaque; + }, + JSB_FreeRuntime: function (rtId) { + var runtime = unityJsbState.getRuntime(rtId); + var aliveItemCount = runtime.garbageCollect(); + for (var key in runtime.contexts) { + if (Object.hasOwnProperty.call(runtime.contexts, key)) { + delete unityJsbState.contexts[key]; + } + } + delete unityJsbState.runtimes[runtime.id]; + return aliveItemCount === 0; + }, + JS_GetRuntime: function (ctxId) { + var context = unityJsbState.getContext(ctxId); + return context.runtimeId; + }, + JS_NewContext: function (rtId) { + var _a, _b; + var id = unityJsbState.lastContextId++; + var runtime = unityJsbState.getRuntime(rtId); + var extraGlobals = { + location: undefined, + document: undefined, + btoa: (_a = window.btoa) === null || _a === void 0 ? void 0 : _a.bind(window), + atob: (_b = window.atob) === null || _b === void 0 ? void 0 : _b.bind(window), + $$webglWindow: window, + }; + var globals = new Proxy(extraGlobals, { + get: function (target, p, receiver) { + if (p in target) + return target[p]; + else + return window[p]; + }, + set: function (target, p, val, receiver) { + target[p] = val; + return true; + }, + has: function (target, key) { + return (key in window) || (key in target); + }, + }); + extraGlobals.globalThis = + extraGlobals.global = + extraGlobals.window = + extraGlobals.parent = + extraGlobals.self = + extraGlobals.this = + globals; + var evaluate = function (code, filename) { + var sourceMap = !filename ? '' : '\n//# sourceURL=unity-jsb:///' + filename; + return (function (evalCode) { + //@ts-ignore + with (globals) { + return eval(evalCode); + } + }).call(globals, code + sourceMap); + }; + var context = { + id: id, + runtime: runtime, + runtimeId: rtId, + window: window, + globalObject: globals, + evaluate: evaluate, + }; + runtime.contexts[id] = context; + unityJsbState.contexts[id] = context; + return id; + }, + JS_FreeContext: function (ctxId) { + var context = unityJsbState.getContext(ctxId); + var runtime = unityJsbState.runtimes[context.runtimeId]; + delete runtime.contexts[context.id]; + delete unityJsbState.contexts[context.id]; + }, + JS_GetGlobalObject: function (returnValue, ctxId) { + var context = unityJsbState.getContext(ctxId); + if (!context.globalObjectId) { + context.runtime.objects.push(context.globalObject, returnValue); + } + else { + context.runtime.objects.refIndex(context.globalObjectId, 1, returnValue); + } + }, + JS_Eval: function (ptr, ctx, input, input_len, filename, eval_flags) { + try { + var context = unityJsbState.getContext(ctx); + var code = unityJsbState.stringify(input, input_len); + var filenameStr = unityJsbState.stringify(filename); + var res = context.evaluate(code, filenameStr); + context.runtime.objects.push(res, ptr); + } + catch (err) { + context.lastException = err; + context.runtime.objects.push(err, ptr); + console.error(err); + } + }, + JS_IsInstanceOf: function (ctxId, val, obj) { + var context = unityJsbState.getContext(ctxId); + var valVal = context.runtime.objects.get(val); + var ctorVal = context.runtime.objects.get(obj); + return !!(valVal instanceof ctorVal); + }, + JS_GetException: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.push(context.lastException, ptr); + }, + JSB_FreeValue: function (ctx, v) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.ref(v, -1, undefined); + }, + JSB_FreeValueRT: function (rt, v) { + var runtime = unityJsbState.getRuntime(rt); + runtime.objects.ref(v, -1, undefined); + }, + JSB_FreePayload: function (ret, ctx, val) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var payload = context.runtime.objects.getPayload(obj); + HEAP32[ret >> 2] = payload.type; + HEAP32[(ret >> 2) + 1] = payload.payload; + context.runtime.objects.clearPayload(obj); + }, + JSB_DupValue: function (ptr, ctx, v) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.ref(v, 1, ptr); + }, + JS_RunGC: function (rt) { + var runtime = unityJsbState.getRuntime(rt); + runtime.garbageCollect(); + }, + JS_ComputeMemoryUsage: function (rt, s) { + // TODO: https://blog.unity.com/technology/unity-webgl-memory-the-unity-heap + }, + JS_GetPropertyUint32: function (ptr, ctxId, val, index) { + var context = unityJsbState.getContext(ctxId); + var obj = context.runtime.objects.get(val); + var res = obj[index]; + context.runtime.objects.push(res, ptr); + }, + JS_GetPropertyInternal: function (ptr, ctxId, val, prop, receiver, throwRefError) { + var context = unityJsbState.getContext(ctxId); + var valObj = context.runtime.objects.get(val); + var receiverObj = context.runtime.objects.get(receiver); + var propStr = unityJsbState.atoms.get(prop); + var res = valObj[propStr]; + // var res = Reflect.get(valObj, propStr, receiverObj); + context.runtime.objects.push(res, ptr); + }, + JS_GetPropertyStr: function (ptr, ctxId, val, prop) { + var context = unityJsbState.getContext(ctxId); + var valObj = context.runtime.objects.get(val); + var propStr = unityJsbState.stringify(prop); + var res = valObj[propStr]; + // var res = Reflect.get(valObj, propStr); + context.runtime.objects.push(res, ptr); + }, + JS_Invoke: function (ptr, ctx, this_obj, prop, argc, argv) { + var context = unityJsbState.getContext(ctx); + var propVal = unityJsbState.atoms.get(prop); + var thisVal = context.runtime.objects.get(this_obj); + var func = thisVal[propVal]; + // const func = Reflect.get(thisVal, propVal); + var args = context.runtime.objects.batchGet(argv, argc); + var val = func.apply(thisVal, args); + context.runtime.objects.push(val, ptr); + }, + JS_Call: function (ptr, ctx, func_obj, this_obj, argc, argv) { + var context = unityJsbState.getContext(ctx); + var func = context.runtime.objects.get(func_obj); + var thisVal = context.runtime.objects.get(this_obj); + var args = context.runtime.objects.batchGet(argv, argc); + var val = func.apply(thisVal, args); + context.runtime.objects.push(val, ptr); + }, + JS_CallConstructor: function (ptr, ctx, func_obj, argc, argv) { + var context = unityJsbState.getContext(ctx); + var func = context.runtime.objects.get(func_obj); + var args = context.runtime.objects.batchGet(argv, argc); + var val = Reflect.construct(func, args); + context.runtime.objects.push(val, ptr); + }, + JS_SetConstructor: function (ctx, ctor, proto) { + var context = unityJsbState.getContext(ctx); + var ctorVal = context.runtime.objects.get(ctor); + var protoVal = context.runtime.objects.get(proto); + ctorVal.prototype = protoVal; + }, + JS_SetPrototype: function (ctx, obj, proto) { + var context = unityJsbState.getContext(ctx); + var objVal = context.runtime.objects.get(obj); + var protoVal = context.runtime.objects.get(proto); + Reflect.setPrototypeOf(objVal, protoVal); + return true; + }, + JS_DefineProperty: function (ctx, this_obj, prop, val, getter, setter, flags) { + var context = unityJsbState.getContext(ctx); + var thisVal = context.runtime.objects.get(this_obj); + var getterVal = context.runtime.objects.get(getter); + var setterVal = context.runtime.objects.get(setter); + var valVal = context.runtime.objects.get(val); + var propVal = unityJsbState.atoms.get(prop); + var configurable = !!(flags & 1 /* JSPropFlags.JS_PROP_CONFIGURABLE */); + var hasConfigurable = configurable || !!(flags & 256 /* JSPropFlags.JS_PROP_HAS_CONFIGURABLE */); + var enumerable = !!(flags & 4 /* JSPropFlags.JS_PROP_ENUMERABLE */); + var hasEnumerable = enumerable || !!(flags & 1024 /* JSPropFlags.JS_PROP_HAS_ENUMERABLE */); + var writable = !!(flags & 2 /* JSPropFlags.JS_PROP_WRITABLE */); + var hasWritable = writable || !!(flags & 512 /* JSPropFlags.JS_PROP_HAS_WRITABLE */); + var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); + try { + var opts = { + get: getterVal, + set: setterVal, + }; + if (!getter && !setter) { + opts.value = valVal; + } + if (hasConfigurable) + opts.configurable = configurable; + if (hasEnumerable) + opts.enumerable = enumerable; + if (!getter && !setter && hasWritable) + opts.writable = writable; + Object.defineProperty(thisVal, propVal, opts); + return true; + } + catch (err) { + context.lastException = err; + if (shouldThrow) { + console.error(err); + return -1; + } + } + return false; + }, + JS_DefinePropertyValue: function (ctx, this_obj, prop, val, flags) { + var context = unityJsbState.getContext(ctx); + var thisVal = context.runtime.objects.get(this_obj); + var valVal = context.runtime.objects.get(val); + var propVal = unityJsbState.atoms.get(prop); + var configurable = !!(flags & 1 /* JSPropFlags.JS_PROP_CONFIGURABLE */); + var hasConfigurable = configurable || !!(flags & 256 /* JSPropFlags.JS_PROP_HAS_CONFIGURABLE */); + var enumerable = !!(flags & 4 /* JSPropFlags.JS_PROP_ENUMERABLE */); + var hasEnumerable = enumerable || !!(flags & 1024 /* JSPropFlags.JS_PROP_HAS_ENUMERABLE */); + var writable = !!(flags & 2 /* JSPropFlags.JS_PROP_WRITABLE */); + var hasWritable = writable || !!(flags & 512 /* JSPropFlags.JS_PROP_HAS_WRITABLE */); + var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); + try { + var opts = { + value: valVal, + }; + if (hasConfigurable) + opts.configurable = configurable; + if (hasEnumerable) + opts.enumerable = enumerable; + if (hasWritable) + opts.writable = writable; + Object.defineProperty(thisVal, propVal, opts); + return true; + } + catch (err) { + context.lastException = err; + if (shouldThrow) { + console.error(err); + return -1; + } + } + return false; + }, + JS_HasProperty: function (ctx, this_obj, prop) { + var context = unityJsbState.getContext(ctx); + var thisVal = context.runtime.objects.get(this_obj); + var propVal = unityJsbState.atoms.get(prop); + var res = Reflect.has(thisVal, propVal); + return !!res; + }, + JS_SetPropertyInternal: function (ctx, this_obj, prop, val, flags) { + var context = unityJsbState.getContext(ctx); + var thisVal = context.runtime.objects.get(this_obj); + var valVal = context.runtime.objects.get(val); + var propVal = unityJsbState.atoms.get(prop); + var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); + try { + // return !!Reflect.set(thisVal, propVal, valVal); + thisVal[propVal] = valVal; + return true; + } + catch (err) { + context.lastException = err; + if (shouldThrow) { + console.error(err); + return -1; + } + } + return false; + }, + JS_SetPropertyUint32: function (ctx, this_obj, idx, val) { + var context = unityJsbState.getContext(ctx); + var thisVal = context.runtime.objects.get(this_obj); + var valVal = context.runtime.objects.get(val); + var propVal = idx; + // return !!Reflect.set(thisVal, propVal, valVal); + thisVal[propVal] = valVal; + return true; + }, + jsb_get_payload_header: function (ret, ctx, val) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var rec = context.runtime.objects.getPayload(obj); + HEAP32[ret >> 2] = rec.type; + HEAP32[(ret >> 2) + 1] = rec.payload; + }, + JS_ToCStringLen2: function (ctx, len, val, cesu8) { + var context = unityJsbState.getContext(ctx); + var str = context.runtime.objects.get(val); + if (typeof str === 'undefined') { + HEAP32[(len >> 2)] = 0; + return 0; + } + var _a = unityJsbState.bufferify(str), buffer = _a[0], length = _a[1]; + HEAP32[(len >> 2)] = length - 1; + return buffer; + }, + JS_FreeCString: function (ctx, ptr) { + _free(ptr); + }, + JS_GetArrayBuffer: function (ctx, psize, obj) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(obj); + if (value instanceof ArrayBuffer) { + HEAP32[psize >> 2] = value.byteLength; + return value; + } + return 0; + }, + // #region Atoms + JS_NewAtomLen: function (ctx, str, len) { + var context = unityJsbState.getContext(ctx); + var val = unityJsbState.stringify(str, len); + return unityJsbState.atoms.push(val); + }, + JS_AtomToString: function (ptr, ctx, atom) { + var context = unityJsbState.getContext(ctx); + var str = unityJsbState.atoms.get(atom); + context.runtime.objects.push(str, ptr); + }, + JS_FreeAtom: function (ctx, v) { + unityJsbState.atoms.pop(v); + }, + JS_DupAtom: function (ctx, v) { + return unityJsbState.atoms.pushId(v); + }, + JSB_ATOM_constructor: function () { + return unityJsbState.atoms.push('constructor'); + }, + JSB_ATOM_Error: function () { + return unityJsbState.atoms.push('Error'); + }, + JSB_ATOM_fileName: function () { + return unityJsbState.atoms.push('fileName'); + }, + JSB_ATOM_Function: function () { + return unityJsbState.atoms.push('Function'); + }, + JSB_ATOM_length: function () { + return unityJsbState.atoms.push('length'); + }, + JSB_ATOM_lineNumber: function () { + return unityJsbState.atoms.push('lineNumber'); + }, + JSB_ATOM_message: function () { + return unityJsbState.atoms.push('message'); + }, + JSB_ATOM_name: function () { + return unityJsbState.atoms.push('name'); + }, + JSB_ATOM_Number: function () { + return unityJsbState.atoms.push('Number'); + }, + JSB_ATOM_prototype: function () { + return unityJsbState.atoms.push('prototype'); + }, + JSB_ATOM_Proxy: function () { + return unityJsbState.atoms.push('Proxy'); + }, + JSB_ATOM_stack: function () { + return unityJsbState.atoms.push('stack'); + }, + JSB_ATOM_String: function () { + return unityJsbState.atoms.push('String'); + }, + JSB_ATOM_Object: function () { + return unityJsbState.atoms.push('Object'); + }, + JSB_ATOM_Operators: function () { + return unityJsbState.atoms.push('Operators'); + }, + JSB_ATOM_Symbol_operatorSet: function () { + return unityJsbState.atoms.push('operatorSet'); + }, + // #endregion + // #region Is + JS_IsArray: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.objects.get(val); + var res = Array.isArray(valVal); + return !!res; + }, + JS_IsConstructor: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var res = !!obj.prototype && !!obj.prototype.constructor.name; + return !!res; + }, + JS_IsError: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.objects.get(val); + var res = valVal instanceof Error; + return !!res; + }, + JS_IsFunction: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.objects.get(val); + var res = typeof valVal === 'function'; + return !!res; + }, + // #endregion + JS_ParseJSON: function (ptr, ctx, buf, buf_len, filename) { + var context = unityJsbState.getContext(ctx); + var str = unityJsbState.stringify(buf, buf_len); + var res = JSON.parse(str); + context.runtime.objects.push(res, ptr); + }, + JS_JSONStringify: function (ptr, ctx, obj, replacer, space) { + var context = unityJsbState.getContext(ctx); + var objVal = context.runtime.objects.get(obj); + var rpVal = context.runtime.objects.get(replacer); + var spVal = context.runtime.objects.get(space); + var res = JSON.stringify(objVal, rpVal, spVal); + context.runtime.objects.push(res, ptr); + }, + // #region New + JS_NewArray: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = []; + context.runtime.objects.push(res, ptr); + }, + JS_NewArrayBufferCopy: function (ptr, ctx, buf, len) { + var context = unityJsbState.getContext(ctx); + var nptr = _malloc(len); + var res = new Uint8Array(HEAPU8.buffer, nptr, len); + var existing = new Uint8Array(HEAPU8.buffer, buf, len); + res.set(existing); + context.runtime.objects.push(res, ptr); + }, + JSB_NewFloat64: function (ptr, ctx, d) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.push(d, ptr); + }, + JSB_NewInt64: function (ptr, ctx, d) { + var context = unityJsbState.getContext(ctx); + context.runtime.objects.push(d, ptr); + }, + JS_NewObject: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = {}; + context.runtime.objects.push(res, ptr); + }, + JS_NewString: function (ptr, ctx, str) { + var context = unityJsbState.getContext(ctx); + var res = unityJsbState.stringify(str); + context.runtime.objects.push(res, ptr); + }, + JS_NewStringLen: function (ptr, ctx, str, len) { + var context = unityJsbState.getContext(ctx); + var val = unityJsbState.stringify(str, len); + context.runtime.objects.push(val, ptr); + }, + JSB_NewEmptyString: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = ""; + context.runtime.objects.push(res, ptr); + }, + // #endregion + // #region Bridge + JSB_NewCFunction: function (ret, ctx, func, atom, length, cproto, magic) { + var context = unityJsbState.getContext(ctx); + var name = unityJsbState.atoms.get(atom) || 'jscFunction'; + function jscFunction() { + void name; + var args = arguments; + var thisObj = this === window ? context.globalObject : this; + var thisPtr = context.runtime.objects.allocate(thisObj); + var ret = _malloc(16 /* Sizes.JSValue */); + if (cproto === 0 /* JSCFunctionEnum.JS_CFUNC_generic */) { + var argc = args.length; + var argv = context.runtime.objects.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); + } + else if (cproto === 9 /* JSCFunctionEnum.JS_CFUNC_setter */) { + var val = context.runtime.objects.allocate(args[0]); + unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); + } + else if (cproto === 8 /* JSCFunctionEnum.JS_CFUNC_getter */) { + unityJsbState.dynCall('viii', func, [ret, ctx, thisPtr]); + } + else { + throw new Error('Unknown type of function specified: ' + cproto); + } + return context.runtime.objects.get(ret); + } + ; + context.runtime.objects.push(jscFunction, ret); + }, + JSB_NewCFunctionMagic: function (ret, ctx, func, atom, length, cproto, magic) { + var context = unityJsbState.getContext(ctx); + var name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; + function jscFunctionMagic() { + void name; + var args = arguments; + var thisObj = this === window ? context.globalObject : this; + var thisPtr = context.runtime.objects.allocate(thisObj); + var ret = _malloc(16 /* Sizes.JSValue */); + if (cproto === 1 /* JSCFunctionEnum.JS_CFUNC_generic_magic */) { + var argc = args.length; + var argv = context.runtime.objects.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + } + else if (cproto === 3 /* JSCFunctionEnum.JS_CFUNC_constructor_magic */) { + var argc = args.length; + var argv = context.runtime.objects.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + } + else if (cproto === 11 /* JSCFunctionEnum.JS_CFUNC_setter_magic */) { + var val = context.runtime.objects.allocate(args[0]); + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); + } + else if (cproto === 10 /* JSCFunctionEnum.JS_CFUNC_getter_magic */) { + unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, magic]); + } + else { + throw new Error('Unknown type of function specified: ' + cproto); + } + return context.runtime.objects.get(ret); + } + ; + context.runtime.objects.push(jscFunctionMagic, ret); + }, + jsb_new_bridge_object: function (ret, ctx, proto, object_id) { + var context = unityJsbState.getContext(ctx); + var protoVal = context.runtime.objects.get(proto); + var res = Object.create(protoVal); + context.runtime.objects.push(res, ret); + context.runtime.objects.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); + }, + jsb_new_bridge_value: function (ret, ctx, proto, size) { + var context = unityJsbState.getContext(ctx); + var protoVal = context.runtime.objects.get(proto); + var res = Object.create(protoVal); + res.$$values = new Array(size).fill(0); + context.runtime.objects.push(res, ret); + }, + JSB_NewBridgeClassObject: function (ret, ctx, new_target, object_id) { + var context = unityJsbState.getContext(ctx); + var res = context.runtime.objects.get(new_target); + context.runtime.objects.push(res, ret); + context.runtime.objects.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); + }, + JSB_NewBridgeClassValue: function (ret, ctx, new_target, size) { + var context = unityJsbState.getContext(ctx); + var res = context.runtime.objects.get(new_target); + res.$$values = new Array(size).fill(0); + context.runtime.objects.push(res, ret); + }, + JSB_GetBridgeClassID: function () { + // TODO: I have no idea + return 0; + }, + jsb_construct_bridge_object: function (ret, ctx, ctor, object_id) { + var context = unityJsbState.getContext(ctx); + var ctorVal = context.runtime.objects.get(ctor); + var res = Reflect.construct(ctorVal, []); + context.runtime.objects.push(res, ret); + context.runtime.objects.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); + }, + jsb_crossbind_constructor: function (ret, ctx, new_target) { + var context = unityJsbState.getContext(ctx); + var target = context.runtime.objects.get(new_target); + // TODO: I have no idea + var res = function () { + return new target(); + }; + context.runtime.objects.push(res, ret); + }, + // #endregion + // #region Errors + JSB_ThrowError: function (ret, ctx, buf, buf_len) { + var context = unityJsbState.getContext(ctx); + var str = unityJsbState.stringify(buf, buf_len); + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + JSB_ThrowTypeError: function (ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Type Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + JSB_ThrowRangeError: function (ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Range Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + JSB_ThrowInternalError: function (ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Internal Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + JSB_ThrowReferenceError: function (ret, ctx, msg) { + var context = unityJsbState.getContext(ctx); + var str = 'Reference Error'; + var err = new Error(str); + console.error(err); + context.runtime.objects.push(err, ret); + // TODO: throw? + }, + // #endregion + // #region Low level Set + js_strndup: function (ctx, s, n) { + var buffer = _malloc(n + 1); + _memcpy(buffer, s, n); + HEAPU8[buffer + n] = 0; + return buffer; + }, + jsb_set_floats: function (ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = n / 4 /* Sizes.Single */; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + for (var index = 0; index < count; index++) { + var val_1 = HEAPF32[(v0 >> 2) + index]; + obj.$$values[index] = val_1; + } + return true; + }, + jsb_set_bytes: function (ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = n / 4 /* Sizes.Single */; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + for (var index = 0; index < count; index++) { + var val_2 = HEAP32[(v0 >> 2) + index]; + obj.$$values[index] = val_2; + } + return true; + }, + jsb_set_byte_4: function (ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + obj.$$values[2] = HEAP32[(v2 >> 2)]; + obj.$$values[3] = HEAP32[(v3 >> 2)]; + return true; + }, + jsb_set_float_2: function (ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAPF32[(v0 >> 2)]; + obj.$$values[1] = HEAPF32[(v1 >> 2)]; + return true; + }, + jsb_set_float_3: function (ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAPF32[(v0 >> 2)]; + obj.$$values[1] = HEAPF32[(v1 >> 2)]; + obj.$$values[2] = HEAPF32[(v2 >> 2)]; + return true; + }, + jsb_set_float_4: function (ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAPF32[(v0 >> 2)]; + obj.$$values[1] = HEAPF32[(v1 >> 2)]; + obj.$$values[2] = HEAPF32[(v2 >> 2)]; + obj.$$values[3] = HEAPF32[(v3 >> 2)]; + return true; + }, + jsb_set_int_1: function (ctx, val, v0) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 1; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAP32[(v0 >> 2)]; + return true; + }, + jsb_set_int_2: function (ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + return true; + }, + jsb_set_int_3: function (ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + obj.$$values[2] = HEAP32[(v2 >> 2)]; + return true; + }, + jsb_set_int_4: function (ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + obj.$$values[0] = HEAP32[(v0 >> 2)]; + obj.$$values[1] = HEAP32[(v1 >> 2)]; + obj.$$values[2] = HEAP32[(v2 >> 2)]; + obj.$$values[3] = HEAP32[(v3 >> 2)]; + return true; + }, + // #endregion + // #region Low Level Get + jsb_get_bytes: function (ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = n / 4 /* Sizes.Single */; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + for (var index = 0; index < count; index++) { + var val_3 = obj.$$values[index]; + HEAP32[(v0 >> 2) + index] = val_3; + } + return true; + }, + jsb_get_floats: function (ctx, val, n, v0) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = n / 4 /* Sizes.Single */; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + for (var index = 0; index < count; index++) { + var val_4 = obj.$$values[index]; + HEAPF32[(v0 >> 2) + index] = val_4; + } + return true; + }, + jsb_get_byte_4: function (ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + HEAP32[(v2 >> 2)] = obj.$$values[2]; + HEAP32[(v3 >> 2)] = obj.$$values[3]; + return true; + }, + jsb_get_float_2: function (ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAPF32[(v0 >> 2)] = obj.$$values[0]; + HEAPF32[(v1 >> 2)] = obj.$$values[1]; + return true; + }, + jsb_get_float_3: function (ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAPF32[(v0 >> 2)] = obj.$$values[0]; + HEAPF32[(v1 >> 2)] = obj.$$values[1]; + HEAPF32[(v2 >> 2)] = obj.$$values[2]; + return true; + }, + jsb_get_float_4: function (ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAPF32[(v0 >> 2)] = obj.$$values[0]; + HEAPF32[(v1 >> 2)] = obj.$$values[1]; + HEAPF32[(v2 >> 2)] = obj.$$values[2]; + HEAPF32[(v3 >> 2)] = obj.$$values[3]; + return true; + }, + jsb_get_int_1: function (ctx, val, v0) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 1; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAP32[(v0 >> 2)] = obj.$$values[0]; + return true; + }, + jsb_get_int_2: function (ctx, val, v0, v1) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 2; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + return true; + }, + jsb_get_int_3: function (ctx, val, v0, v1, v2) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 3; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + HEAP32[(v2 >> 2)] = obj.$$values[2]; + return true; + }, + jsb_get_int_4: function (ctx, val, v0, v1, v2, v3) { + var context = unityJsbState.getContext(ctx); + var obj = context.runtime.objects.get(val); + var count = 4; + if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) + return false; + HEAP32[(v0 >> 2)] = obj.$$values[0]; + HEAP32[(v1 >> 2)] = obj.$$values[1]; + HEAP32[(v2 >> 2)] = obj.$$values[2]; + HEAP32[(v3 >> 2)] = obj.$$values[3]; + return true; + }, + // #endregion + // #region To + JS_ToFloat64: function (ctx, pres, val) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + HEAPF64[pres >> 3] = Number(value); + return false; + } + return -1; + }, + JS_ToInt32: function (ctx, pres, val) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + HEAP32[pres >> 2] = Number(value); + return false; + } + return -1; + }, + JS_ToInt64: function (ctx, pres, val) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + unityJsbState.HEAP64()[pres >> 3] = BigInt(value); + return false; + } + return -1; + }, + JS_ToBigInt64: function (ctx, pres, val) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + unityJsbState.HEAP64()[pres >> 3] = BigInt(value); + return false; + } + return -1; + }, + JS_ToIndex: function (ctx, pres, val) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + unityJsbState.HEAPU64()[pres >> 3] = BigInt(value); + return false; + } + return -1; + }, + JSB_ToUint32: function (ctx, pres, val) { + var context = unityJsbState.getContext(ctx); + var value = context.runtime.objects.get(val); + if (typeof value === 'number' || typeof value === 'bigint') { + HEAPU32[pres >> 2] = Number(value); + return false; + } + return -1; + }, + JS_ToBool: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + var objVal = context.runtime.objects.get(val); + return !!objVal; + }, + // #endregion + // #region Bytecode + JS_ReadObject: function (ptr, ctx, buf, buf_len, flags) { + console.warn('Bytecode is not supported in WebGL Backend'); + }, + JS_WriteObject: function (ctx, psize, obj, flags) { + console.warn('Bytecode is not supported in WebGL Backend'); + return 0; + }, + JS_EvalFunction: function (ptr, ctx, fun_obj) { + console.warn('Bytecode is not supported in WebGL Backend'); + }, + js_free: function (ctx, ptr) { + // TODO: Not sure what this is but seems related to Bytecode + }, + // #endregion + // #region Misc features + JS_NewPromiseCapability: function (ret, ctx, resolving_funcs) { + // TODO + return 0; + }, + JS_SetHostPromiseRejectionTracker: function (rt, cb, opaque) { + // TODO: + }, + JS_SetInterruptHandler: function (rt, cb, opaque) { + // TODO: + }, + JS_SetModuleLoaderFunc: function (rt, module_normalize, module_loader, opaque) { + // TODO: + }, + JS_GetImportMeta: function (ret, ctx, m) { + // TODO: + return 0; + }, + JS_ResolveModule: function (ctx, obj) { + // TODO: + return 0; + }, + JS_AddIntrinsicOperators: function (ctx) { + console.warn('Operator overloading is not supported in WebGL Backend'); + }, + JS_ExecutePendingJob: function (rt, pctx) { + // Automatically handled by browsers + return false; + }, + JS_IsJobPending: function (rt, pctx) { + // Automatically handled by browsers + return false; + }, + // #endregion +}; +autoAddDeps(QuickJSPlugin, '$unityJsbState'); +mergeInto(LibraryManager.library, QuickJSPlugin); diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib.meta b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib.meta new file mode 100644 index 00000000..e53b9600 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: 02906906a6f163f47adcf793967e7728 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + WebGL: WebGL + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: From 17943ef27f6c09883e0e47bf2d2093e4b21cb256 Mon Sep 17 00:00:00 2001 From: Gokhan Kurt Date: Mon, 20 Jun 2022 21:16:34 +0300 Subject: [PATCH 2/4] refactor file names --- .../.source/{quickjs.ts => jsbplugin.ts} | 6 +- .../Plugins/WebGL/.source/tsconfig.json | 5 +- .../WebGL/.source/typings/emscripten.d.ts | 357 ------------------ .../WebGL/{quickjs.jslib => jsbplugin.jslib} | 6 +- ...uickjs.jslib.meta => jsbplugin.jslib.meta} | 0 5 files changed, 8 insertions(+), 366 deletions(-) rename Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/{quickjs.ts => jsbplugin.ts} (96%) delete mode 100644 Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts rename Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/{quickjs.jslib => jsbplugin.jslib} (97%) rename Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/{quickjs.jslib.meta => jsbplugin.jslib.meta} (100%) diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts similarity index 96% rename from Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts rename to Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts index d15c49c4..fc20693e 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/quickjs.ts +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts @@ -8,7 +8,7 @@ type PluginType = JSApiExternals & { $unityJsbState__postset?: string; } -var QuickJSPlugin: PluginType = { +var UnityJSBPlugin: PluginType = { $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', $unityJsbState: { createObjects: function (): PluginObjects { @@ -1643,5 +1643,5 @@ var QuickJSPlugin: PluginType = { }; -autoAddDeps(QuickJSPlugin, '$unityJsbState'); -mergeInto(LibraryManager.library, QuickJSPlugin); +autoAddDeps(UnityJSBPlugin, '$unityJsbState'); +mergeInto(LibraryManager.library, UnityJSBPlugin); diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json index fe287dd6..43259186 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json @@ -19,7 +19,7 @@ "allowUmdGlobalAccess": true, "moduleResolution": "node", "outDir": "..", - "outFile": "../quickjs.jslib", + "outFile": "../jsbplugin.jslib", "noImplicitAny": false, "strict": false, "noUnusedLocals": false, @@ -33,8 +33,7 @@ "strictNullChecks": false }, "files": [ - "quickjs.ts", - "typings/emscripten.d.ts", + "jsbplugin.ts", "typings/environment.d.ts", "typings/jsapi.d.ts", "typings/plugin.d.ts" diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts deleted file mode 100644 index 5b0c1cda..00000000 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/emscripten.d.ts +++ /dev/null @@ -1,357 +0,0 @@ -export { }; - -// Type definitions for Emscripten 1.39.16 -// Project: https://emscripten.org -// Definitions by: Kensuke Matsuzaki -// Periklis Tsirakidis -// Bumsik Kim -// Louis DeScioli -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.2 - -/** Other WebAssembly declarations, for compatibility with older versions of Typescript */ -declare namespace WebAssembly { - interface Module { } -} - -declare namespace Emscripten { - interface FileSystemType { } - type EnvironmentType = 'WEB' | 'NODE' | 'SHELL' | 'WORKER'; - - type JSType = 'number' | 'string' | 'array' | 'boolean'; - type TypeCompatibleWithC = number | string | any[] | boolean; - - type CIntType = 'i8' | 'i16' | 'i32' | 'i64'; - type CFloatType = 'float' | 'double'; - type CPointerType = 'i8*' | 'i16*' | 'i32*' | 'i64*' | 'float*' | 'double*' | '*'; - type CType = CIntType | CFloatType | CPointerType; - - type WebAssemblyImports = Array<{ - name: string; - kind: string; - }>; - - type WebAssemblyExports = Array<{ - module: string; - name: string; - kind: string; - }>; - - interface CCallOpts { - async?: boolean | undefined; - } -} - -interface EmscriptenModule { - print(str: string): void; - printErr(str: string): void; - arguments: string[]; - environment: Emscripten.EnvironmentType; - preInit: Array<{ (): void }>; - preRun: Array<{ (): void }>; - postRun: Array<{ (): void }>; - onAbort: { (what: any): void }; - onRuntimeInitialized: { (): void }; - preinitializedWebGLContext: WebGLRenderingContext; - noInitialRun: boolean; - noExitRuntime: boolean; - logReadFiles: boolean; - filePackagePrefixURL: string; - wasmBinary: ArrayBuffer; - - destroy(object: object): void; - getPreloadedPackage(remotePackageName: string, remotePackageSize: number): ArrayBuffer; - instantiateWasm( - imports: Emscripten.WebAssemblyImports, - successCallback: (module: WebAssembly.Module) => void, - ): Emscripten.WebAssemblyExports; - locateFile(url: string, scriptDirectory: string): string; - onCustomMessage(event: MessageEvent): void; - - // USE_TYPED_ARRAYS == 1 - HEAP: Int32Array; - IHEAP: Int32Array; - FHEAP: Float64Array; - - // USE_TYPED_ARRAYS == 2 - HEAP8: Int8Array; - HEAP16: Int16Array; - HEAP32: Int32Array; - HEAPU8: Uint8Array; - HEAPU16: Uint16Array; - HEAPU32: Uint32Array; - HEAPF32: Float32Array; - HEAPF64: Float64Array; - - TOTAL_STACK: number; - TOTAL_MEMORY: number; - FAST_MEMORY: number; - - addOnPreRun(cb: () => any): void; - addOnInit(cb: () => any): void; - addOnPreMain(cb: () => any): void; - addOnExit(cb: () => any): void; - addOnPostRun(cb: () => any): void; - - preloadedImages: any; - preloadedAudios: any; - - _malloc(size: number): number; - _free(ptr: number): void; -} - -/** -* A factory function is generated when setting the `MODULARIZE` build option -* to `1` in your Emscripten build. It return a Promise that resolves to an -* initialized, ready-to-call `EmscriptenModule` instance. -* -* By default, the factory function will be named `Module`. It's recommended to -* use the `EXPORT_ES6` option, in which the factory function will be the -* default export. If used without `EXPORT_ES6`, the factory function will be a -* global variable. You can rename the variable using the `EXPORT_NAME` build -* option. It's left to you to declare any global variables as needed in your -* application's types. -* @param moduleOverrides Default properties for the initialized module. -*/ -type EmscriptenModuleFactory = ( - moduleOverrides?: Partial, -) => Promise; - -declare namespace FS { - interface Lookup { - path: string; - node: FSNode; - } - - interface FSStream { } - interface FSNode { } - interface ErrnoError { } - - let ignorePermissions: boolean; - let trackingDelegate: any; - let tracking: any; - let genericErrors: any; - - // - // paths - // - function lookupPath(path: string, opts: any): Lookup; - function getPath(node: FSNode): string; - - // - // nodes - // - function isFile(mode: number): boolean; - function isDir(mode: number): boolean; - function isLink(mode: number): boolean; - function isChrdev(mode: number): boolean; - function isBlkdev(mode: number): boolean; - function isFIFO(mode: number): boolean; - function isSocket(mode: number): boolean; - - // - // devices - // - function major(dev: number): number; - function minor(dev: number): number; - function makedev(ma: number, mi: number): number; - function registerDevice(dev: number, ops: any): void; - - // - // core - // - function syncfs(populate: boolean, callback: (e: any) => any): void; - function syncfs(callback: (e: any) => any, populate?: boolean): void; - function mount(type: Emscripten.FileSystemType, opts: any, mountpoint: string): any; - function unmount(mountpoint: string): void; - - function mkdir(path: string, mode?: number): any; - function mkdev(path: string, mode?: number, dev?: number): any; - function symlink(oldpath: string, newpath: string): any; - function rename(old_path: string, new_path: string): void; - function rmdir(path: string): void; - function readdir(path: string): any; - function unlink(path: string): void; - function readlink(path: string): string; - function stat(path: string, dontFollow?: boolean): any; - function lstat(path: string): any; - function chmod(path: string, mode: number, dontFollow?: boolean): void; - function lchmod(path: string, mode: number): void; - function fchmod(fd: number, mode: number): void; - function chown(path: string, uid: number, gid: number, dontFollow?: boolean): void; - function lchown(path: string, uid: number, gid: number): void; - function fchown(fd: number, uid: number, gid: number): void; - function truncate(path: string, len: number): void; - function ftruncate(fd: number, len: number): void; - function utime(path: string, atime: number, mtime: number): void; - function open(path: string, flags: string, mode?: number, fd_start?: number, fd_end?: number): FSStream; - function close(stream: FSStream): void; - function llseek(stream: FSStream, offset: number, whence: number): any; - function read(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number): number; - function write( - stream: FSStream, - buffer: ArrayBufferView, - offset: number, - length: number, - position?: number, - canOwn?: boolean, - ): number; - function allocate(stream: FSStream, offset: number, length: number): void; - function mmap( - stream: FSStream, - buffer: ArrayBufferView, - offset: number, - length: number, - position: number, - prot: number, - flags: number, - ): any; - function ioctl(stream: FSStream, cmd: any, arg: any): any; - function readFile(path: string, opts: { encoding: 'binary'; flags?: string | undefined }): Uint8Array; - function readFile(path: string, opts: { encoding: 'utf8'; flags?: string | undefined }): string; - function readFile(path: string, opts?: { flags?: string | undefined }): Uint8Array; - function writeFile(path: string, data: string | ArrayBufferView, opts?: { flags?: string | undefined }): void; - - // - // module-level FS code - // - function cwd(): string; - function chdir(path: string): void; - function init( - input: null | (() => number | null), - output: null | ((c: number) => any), - error: null | ((c: number) => any), - ): void; - - function createLazyFile( - parent: string | FSNode, - name: string, - url: string, - canRead: boolean, - canWrite: boolean, - ): FSNode; - function createPreloadedFile( - parent: string | FSNode, - name: string, - url: string, - canRead: boolean, - canWrite: boolean, - onload?: () => void, - onerror?: () => void, - dontCreateFile?: boolean, - canOwn?: boolean, - ): void; - function createDataFile( - parent: string | FSNode, - name: string, - data: ArrayBufferView, - canRead: boolean, - canWrite: boolean, - canOwn: boolean, - ): FSNode; -} - -declare var MEMFS: Emscripten.FileSystemType; -declare var NODEFS: Emscripten.FileSystemType; -declare var IDBFS: Emscripten.FileSystemType; - -// https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html -type StringToType = R extends Emscripten.JSType - ? { - number: number; - string: string; - array: number[] | string[] | boolean[] | Uint8Array | Int8Array; - boolean: boolean; - null: null; - }[R] - : never; - -type ArgsToType> = Extract< - { - [P in keyof T]: StringToType; - }, - any[] ->; - -type ReturnToType = R extends null - ? null - : StringToType>; - -// Below runtime function/variable declarations are exportable by -// -s EXTRA_EXPORTED_RUNTIME_METHODS. You can extend or merge -// EmscriptenModule interface to add runtime functions. -// -// For example, by using -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" -// You can access ccall() via Module["ccall"]. In this case, you should -// extend EmscriptenModule to pass the compiler check like the following: -// -// interface YourOwnEmscriptenModule extends EmscriptenModule { -// ccall: typeof ccall; -// } -// -// See: https://emscripten.org/docs/getting_started/FAQ.html#why-do-i-get-typeerror-module-something-is-not-a-function - -declare function cwrap< - I extends Array | [], - R extends Emscripten.JSType | null ->( - ident: string, - returnType: R, - argTypes: I, - opts?: Emscripten.CCallOpts -): (...arg: ArgsToType) => ReturnToType; - -declare function ccall< - I extends Array | [], - R extends Emscripten.JSType | null ->( - ident: string, - returnType: R, - argTypes: I, - args: ArgsToType, - opts?: Emscripten.CCallOpts -): ReturnToType; - -declare function setValue(ptr: number, value: any, type: Emscripten.CType, noSafe?: boolean): void; -declare function getValue(ptr: number, type: Emscripten.CType, noSafe?: boolean): number; - -declare function allocate( - slab: number[] | ArrayBufferView | number, - types: Emscripten.CType | Emscripten.CType[], - allocator: number, - ptr?: number, -): number; - -declare function stackAlloc(size: number): number; -declare function stackSave(): number; -declare function stackRestore(ptr: number): void; - -declare function UTF8ToString(ptr: number, maxBytesToRead?: number): string; -declare function stringToUTF8(str: string, outPtr: number, maxBytesToRead?: number): void; -declare function lengthBytesUTF8(str: string): number; -declare function allocateUTF8(str: string): number; -declare function allocateUTF8OnStack(str: string): number; -declare function UTF16ToString(ptr: number): string; -declare function stringToUTF16(str: string, outPtr: number, maxBytesToRead?: number): void; -declare function lengthBytesUTF16(str: string): number; -declare function UTF32ToString(ptr: number): string; -declare function stringToUTF32(str: string, outPtr: number, maxBytesToRead?: number): void; -declare function lengthBytesUTF32(str: string): number; - -declare function intArrayFromString(stringy: string, dontAddNull?: boolean, length?: number): number[]; -declare function intArrayToString(array: number[]): string; -declare function writeStringToMemory(str: string, buffer: number, dontAddNull: boolean): void; -declare function writeArrayToMemory(array: number[], buffer: number): void; -declare function writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void; - -declare function addRunDependency(id: any): void; -declare function removeRunDependency(id: any): void; - -declare function addFunction(func: (...args: any[]) => any, signature?: string): number; -declare function removeFunction(funcPtr: number): void; - -declare var ALLOC_NORMAL: number; -declare var ALLOC_STACK: number; -declare var ALLOC_STATIC: number; -declare var ALLOC_DYNAMIC: number; -declare var ALLOC_NONE: number; diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib similarity index 97% rename from Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib rename to Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib index f7afc798..c8a1c4d7 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib @@ -2,7 +2,7 @@ * Build with the following command: * npx -p typescript tsc */ -var QuickJSPlugin = { +var UnityJSBPlugin = { $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', $unityJsbState: { createObjects: function () { @@ -1342,5 +1342,5 @@ var QuickJSPlugin = { }, // #endregion }; -autoAddDeps(QuickJSPlugin, '$unityJsbState'); -mergeInto(LibraryManager.library, QuickJSPlugin); +autoAddDeps(UnityJSBPlugin, '$unityJsbState'); +mergeInto(LibraryManager.library, UnityJSBPlugin); diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib.meta b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib.meta similarity index 100% rename from Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/quickjs.jslib.meta rename to Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib.meta From cd0fca5e5d9e75a0c212cac8ab08d93136d0418e Mon Sep 17 00:00:00 2001 From: Gokhan Kurt Date: Tue, 21 Jun 2022 01:54:37 +0300 Subject: [PATCH 3/4] fix GC issues --- .../Plugins/WebGL/.source/jsbplugin.ts | 574 ++++++++++-------- .../Plugins/WebGL/.source/typings/plugin.d.ts | 14 +- .../Plugins/WebGL/jsbplugin.jslib | 166 +++-- 3 files changed, 447 insertions(+), 307 deletions(-) diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts index fc20693e..eac50877 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts @@ -8,11 +8,11 @@ type PluginType = JSApiExternals & { $unityJsbState__postset?: string; } -var UnityJSBPlugin: PluginType = { +const UnityJSBPlugin: PluginType = { $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', $unityJsbState: { createObjects: function (): PluginObjects { - var getTag = function (object): Tags { + const getTag = function (object): Tags { if (object === undefined) return Tags.JS_TAG_UNDEFINED; if (object === null) return Tags.JS_TAG_NULL; if (typeof object === 'number') return Tags.JS_TAG_FLOAT64; @@ -25,36 +25,39 @@ var UnityJSBPlugin: PluginType = { return Tags.JS_TAG_OBJECT; }; - var record: PluginObjects['record'] = {}; + const record: PluginObjects['record'] = {}; const map = new Map(); - var payloadMap: PluginObjects['payloadMap'] = new Map(); + const payloadMap: PluginObjects['payloadMap'] = new Map(); const res: PluginObjects = { record, lastId: 0, allocate(object) { - var ptr = _malloc(Sizes.JSValue) as JSValue; - res.push(object, ptr); - return ptr as JSValue; + const ptr = _malloc(Sizes.JSValue) as JSValue; + const id = res.push(object, ptr); + return [ptr as JSValue, id]; }, batchAllocate(objects) { - var size = Sizes.JSValue; - var arr = _malloc(size * objects.length) as PointerArray; + const size = Sizes.JSValue; + const len = objects.length; + const arr = _malloc(size * len) as PointerArray; + const ids = Array(len); - for (let index = 0; index < objects.length; index++) { + for (let index = 0; index < len; index++) { const object = objects[index]; - res.push(object, arr + (index * size) as JSValue); + const id = res.push(object, arr + (index * size) as JSValue); + ids[index] = id; } - return arr; + return [arr, ids]; }, batchGet(ptrs, count) { - var size = Sizes.JSValue; + const size = Sizes.JSValue; - var arr = new Array(count); + const arr = new Array(count); for (let index = 0; index < count; index++) { const object = res.get(ptrs + index * size as JSValue); arr[index] = object; @@ -64,7 +67,7 @@ var UnityJSBPlugin: PluginType = { }, push(object, ptr) { if (typeof object === 'undefined') { - res.refIndex(0, 1, ptr); + res.duplicateId(0, ptr); return; } @@ -90,11 +93,11 @@ var UnityJSBPlugin: PluginType = { const foundId = map.get(object); if (foundId > 0) { - res.refIndex(foundId, 1, ptr); - return; + res.duplicateId(foundId, ptr); + return foundId; } - var id = ++res.lastId; + const id = ++res.lastId; record[id] = { id, @@ -105,12 +108,12 @@ var UnityJSBPlugin: PluginType = { map.set(object, id); - res.refIndex(id, 1, ptr); + res.duplicateId(id, ptr); return id; }, get(val) { - var tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + const tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); if (tag === Tags.JS_TAG_INT) { return HEAP32[val >> 2]; @@ -122,17 +125,17 @@ var UnityJSBPlugin: PluginType = { return HEAPF64[val >> 3]; } else { - var id = HEAP32[val >> 2]; + const id = HEAP32[val >> 2]; if (id === 0) return undefined; - var ho = record[id]; + const ho = record[id]; return ho.value; } }, getRecord(val) { - var tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + const tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); if (tag === Tags.JS_TAG_INT) { - var value = HEAP32[val >> 2]; + const value = HEAP32[val >> 2]; return { id: -1, refCount: 0, @@ -141,7 +144,7 @@ var UnityJSBPlugin: PluginType = { }; } else if (tag === Tags.JS_TAG_BOOL) { - var boolValue = !!HEAP32[val >> 2]; + const boolValue = !!HEAP32[val >> 2]; return { id: -1, refCount: 0, @@ -150,7 +153,7 @@ var UnityJSBPlugin: PluginType = { }; } else if (tag === Tags.JS_TAG_FLOAT64) { - var value = HEAPF64[val >> 3]; + const value = HEAPF64[val >> 3]; return { id: -1, refCount: 0, @@ -159,7 +162,7 @@ var UnityJSBPlugin: PluginType = { }; } else { - var id = HEAP32[val >> 2]; + const id = HEAP32[val >> 2]; if (id === 0) return { id: 0, refCount: 0, @@ -168,16 +171,16 @@ var UnityJSBPlugin: PluginType = { type: BridgeObjectType.None, payload: -1, }; - var ho = record[id]; + const ho = record[id]; return ho; } }, - ref(obj, diff, ptr) { - var tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); + duplicate(obj, ptr) { + const tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); if (tag === Tags.JS_TAG_FLOAT64) { if (typeof ptr === 'number') { - var val = HEAPF64[(obj >> 3)]; + const val = HEAPF64[(obj >> 3)]; HEAPF64[ptr >> 3] = val; unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); } @@ -185,7 +188,7 @@ var UnityJSBPlugin: PluginType = { } else if (tag === Tags.JS_TAG_INT) { if (typeof ptr === 'number') { - var val = HEAP32[(obj >> 2)]; + const val = HEAP32[(obj >> 2)]; HEAP32[(ptr >> 2)] = val; HEAP32[(ptr >> 2) + 1] = 0; unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); @@ -194,7 +197,7 @@ var UnityJSBPlugin: PluginType = { } else if (tag === Tags.JS_TAG_BOOL) { if (typeof ptr === 'number') { - var valBool = !!HEAP32[(obj >> 2)]; + const valBool = !!HEAP32[(obj >> 2)]; HEAP32[(ptr >> 2)] = valBool ? 1 : 0; HEAP32[(ptr >> 2) + 1] = 0; unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); @@ -202,10 +205,10 @@ var UnityJSBPlugin: PluginType = { return; } - var id = HEAP32[obj >> 2]; - res.refIndex(id, diff, ptr); + const id = HEAP32[obj >> 2]; + res.duplicateId(id, ptr); }, - refIndex(id, diff, ptr) { + duplicateId(id, ptr) { if (id === 0) { if (typeof ptr === 'number') { HEAP32[ptr >> 2] = 0; @@ -215,11 +218,9 @@ var UnityJSBPlugin: PluginType = { return; } - var ho = record[id]; + const ho = record[id]; - ho.refCount += diff; - - console.assert(ho.refCount >= 0); + ho.refCount += 1; if (typeof ptr === 'number') { HEAP32[ptr >> 2] = id; @@ -227,8 +228,24 @@ var UnityJSBPlugin: PluginType = { unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(ho.tag); } }, - deleteIndex(id) { - var rec = record[id]; + pop(obj) { + const tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); + + if (tag === Tags.JS_TAG_FLOAT64 + || tag === Tags.JS_TAG_INT + || tag === Tags.JS_TAG_BOOL) return; + + const id = HEAP32[obj >> 2]; + res.popId(id); + }, + popId(id) { + if (!id) return; + const ho = record[id]; + ho.refCount -= 1; + console.assert(ho.refCount >= 0); + }, + deleteRecord(id) { + const rec = record[id]; delete record[id]; map.delete(rec.value); }, @@ -240,7 +257,7 @@ var UnityJSBPlugin: PluginType = { }); }, getPayload(obj) { - var res = payloadMap.get(obj); + const res = payloadMap.get(obj); if (res) return res; else { @@ -258,10 +275,10 @@ var UnityJSBPlugin: PluginType = { return res; }, createAtoms(): PluginAtoms { - var record: PluginAtoms['record'] = {}; - var map: PluginAtoms['map'] = {}; + const record: PluginAtoms['record'] = {}; + const map: PluginAtoms['map'] = {}; - var res: PluginAtoms = { + const res: PluginAtoms = { record, map, lastId: 0, @@ -271,8 +288,8 @@ var UnityJSBPlugin: PluginType = { }, push(str) { if (str === undefined) return 0; - var mapped = map[str]; - var id; + const mapped = map[str]; + let id; if (!mapped) { id = ++res.lastId; @@ -291,7 +308,7 @@ var UnityJSBPlugin: PluginType = { pushId(id) { if (id === 0) return; - var recorded = record[id]; + const recorded = record[id]; console.assert(!!recorded); if (!recorded) return 0; recorded.refCount++; @@ -301,7 +318,7 @@ var UnityJSBPlugin: PluginType = { pop(id) { if (id === 0) return; - var recorded = record[id]; + const recorded = record[id]; console.assert(!!recorded); if (!recorded) return; @@ -319,8 +336,8 @@ var UnityJSBPlugin: PluginType = { }, stringify: function (ptr: number | Pointer, bufferLength?: number) { return (typeof UTF8ToString !== 'undefined' ? UTF8ToString : Pointer_stringify)(ptr, bufferLength); }, bufferify: function (arg: string) { - var bufferSize = lengthBytesUTF8(arg) + 1; - var buffer = _malloc(bufferSize); + const bufferSize = lengthBytesUTF8(arg) + 1; + const buffer = _malloc(bufferSize); stringToUTF8(arg, buffer, bufferSize); return [buffer, bufferSize]; }, @@ -331,11 +348,11 @@ var UnityJSBPlugin: PluginType = { lastRuntimeId: 1, lastContextId: 1, getRuntime: function (rt) { - var rtId = rt; + const rtId = rt; return unityJsbState.runtimes[rtId]; }, getContext: function (ctx) { - var ctxId = ctx; + const ctxId = ctx; return unityJsbState.contexts[ctxId]; }, HEAP64: function () { @@ -353,25 +370,25 @@ var UnityJSBPlugin: PluginType = { JSB_NewRuntime(finalizer) { // TODO: understand what to do with finalizer - var id = unityJsbState.lastRuntimeId++; - var objects = unityJsbState.createObjects(); + const id = unityJsbState.lastRuntimeId++; + const objects = unityJsbState.createObjects(); unityJsbState.runtimes[id] = { id, contexts: {}, objects, garbageCollect() { - var lastId = objects.lastId; - var record = objects.record; + const lastId = objects.lastId; + const record = objects.record; - var aliveItemCount = 0; + let aliveItemCount = 0; - for (let index = 0; index < lastId; index++) { + for (let index = 0; index <= lastId; index++) { const element = record[index]; if (element) { if (element.refCount <= 0) { - objects.deleteIndex(index); + objects.deleteRecord(index); } else { aliveItemCount++; @@ -403,8 +420,8 @@ var UnityJSBPlugin: PluginType = { }, JSB_FreeRuntime(rtId) { - var runtime = unityJsbState.getRuntime(rtId); - var aliveItemCount = runtime.garbageCollect(); + const runtime = unityJsbState.getRuntime(rtId); + const aliveItemCount = runtime.garbageCollect(); for (const key in runtime.contexts) { if (Object.hasOwnProperty.call(runtime.contexts, key)) { @@ -418,15 +435,15 @@ var UnityJSBPlugin: PluginType = { }, JS_GetRuntime(ctxId) { - var context = unityJsbState.getContext(ctxId); + const context = unityJsbState.getContext(ctxId); return context.runtimeId; }, JS_NewContext(rtId) { - var id = unityJsbState.lastContextId++; - var runtime = unityJsbState.getRuntime(rtId); + const id = unityJsbState.lastContextId++; + const runtime = unityJsbState.getRuntime(rtId); - var extraGlobals: any = { + const extraGlobals: any = { location: undefined, document: undefined, btoa: window.btoa?.bind(window), @@ -434,7 +451,7 @@ var UnityJSBPlugin: PluginType = { $$webglWindow: window, }; - var globals: typeof window = new Proxy(extraGlobals, { + const globals: typeof window = new Proxy(extraGlobals, { get(target, p, receiver) { if (p in target) return target[p]; else return window[p]; @@ -456,8 +473,8 @@ var UnityJSBPlugin: PluginType = { extraGlobals.this = globals; - var evaluate = function (code: string, filename?: string) { - var sourceMap = !filename ? '' : '\n//# sourceURL=unity-jsb:///' + filename; + const evaluate = function (code: string, filename?: string) { + const sourceMap = !filename ? '' : '\n//# sourceURL=unity-jsb:///' + filename; return (function (evalCode) { //@ts-ignore @@ -468,7 +485,7 @@ var UnityJSBPlugin: PluginType = { }; - var context: PluginContext = { + const context: PluginContext = { id, runtime, runtimeId: rtId, @@ -483,31 +500,31 @@ var UnityJSBPlugin: PluginType = { }, JS_FreeContext(ctxId) { - var context = unityJsbState.getContext(ctxId); - var runtime = unityJsbState.runtimes[context.runtimeId]; + const context = unityJsbState.getContext(ctxId); + const runtime = unityJsbState.runtimes[context.runtimeId]; delete runtime.contexts[context.id]; delete unityJsbState.contexts[context.id]; }, JS_GetGlobalObject(returnValue, ctxId) { - var context = unityJsbState.getContext(ctxId); + const context = unityJsbState.getContext(ctxId); if (!context.globalObjectId) { context.runtime.objects.push(context.globalObject, returnValue); } else { - context.runtime.objects.refIndex(context.globalObjectId, 1, returnValue); + context.runtime.objects.duplicateId(context.globalObjectId, returnValue); } }, JS_Eval(ptr, ctx, input, input_len, filename, eval_flags) { + const context = unityJsbState.getContext(ctx); try { - var context = unityJsbState.getContext(ctx); - var code = unityJsbState.stringify(input, input_len); - var filenameStr = unityJsbState.stringify(filename); + const code = unityJsbState.stringify(input, input_len); + const filenameStr = unityJsbState.stringify(filename); - var res = context.evaluate(code, filenameStr); + const res = context.evaluate(code, filenameStr); context.runtime.objects.push(res, ptr); } catch (err) { @@ -518,33 +535,33 @@ var UnityJSBPlugin: PluginType = { }, JS_IsInstanceOf(ctxId, val, obj) { - var context = unityJsbState.getContext(ctxId); - var valVal = context.runtime.objects.get(val); - var ctorVal = context.runtime.objects.get(obj); + const context = unityJsbState.getContext(ctxId); + const valVal = context.runtime.objects.get(val); + const ctorVal = context.runtime.objects.get(obj); return !!(valVal instanceof ctorVal); }, JS_GetException(ptr, ctx) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); context.runtime.objects.push(context.lastException, ptr); }, JSB_FreeValue(ctx, v) { - var context = unityJsbState.getContext(ctx); - context.runtime.objects.ref(v, -1, undefined); + const context = unityJsbState.getContext(ctx); + context.runtime.objects.pop(v); }, JSB_FreeValueRT(rt, v) { - var runtime = unityJsbState.getRuntime(rt); - runtime.objects.ref(v, -1, undefined); + const runtime = unityJsbState.getRuntime(rt); + runtime.objects.pop(v); }, JSB_FreePayload(ret, ctx, val) { - var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val); - var payload = context.runtime.objects.getPayload(obj); + const payload = context.runtime.objects.getPayload(obj); HEAP32[ret >> 2] = payload.type; HEAP32[(ret >> 2) + 1] = payload.payload; @@ -552,12 +569,12 @@ var UnityJSBPlugin: PluginType = { }, JSB_DupValue(ptr, ctx, v) { - var context = unityJsbState.getContext(ctx); - context.runtime.objects.ref(v, 1, ptr); + const context = unityJsbState.getContext(ctx); + context.runtime.objects.duplicate(v, ptr); }, JS_RunGC(rt) { - var runtime = unityJsbState.getRuntime(rt); + const runtime = unityJsbState.getRuntime(rt); runtime.garbageCollect(); }, @@ -567,89 +584,104 @@ var UnityJSBPlugin: PluginType = { }, JS_GetPropertyUint32(ptr, ctxId, val, index) { - var context = unityJsbState.getContext(ctxId); - var obj = context.runtime.objects.get(val); - var res = obj[index]; + const context = unityJsbState.getContext(ctxId); + const obj = context.runtime.objects.get(val); + const res = obj[index]; context.runtime.objects.push(res, ptr); }, JS_GetPropertyInternal(ptr, ctxId, val, prop, receiver, throwRefError) { - var context = unityJsbState.getContext(ctxId); - var valObj = context.runtime.objects.get(val); - var receiverObj = context.runtime.objects.get(receiver); - var propStr = unityJsbState.atoms.get(prop); - var res = valObj[propStr]; - // var res = Reflect.get(valObj, propStr, receiverObj); + const context = unityJsbState.getContext(ctxId); + const valObj = context.runtime.objects.get(val); + const receiverObj = context.runtime.objects.get(receiver); + const propStr = unityJsbState.atoms.get(prop); + const res = valObj[propStr]; context.runtime.objects.push(res, ptr); }, JS_GetPropertyStr(ptr, ctxId, val, prop) { - var context = unityJsbState.getContext(ctxId); - var valObj = context.runtime.objects.get(val); - var propStr = unityJsbState.stringify(prop); - var res = valObj[propStr]; - // var res = Reflect.get(valObj, propStr); + const context = unityJsbState.getContext(ctxId); + const valObj = context.runtime.objects.get(val); + const propStr = unityJsbState.stringify(prop); + const res = valObj[propStr]; context.runtime.objects.push(res, ptr); }, JS_Invoke(ptr, ctx, this_obj, prop, argc, argv) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const propVal = unityJsbState.atoms.get(prop); const thisVal = context.runtime.objects.get(this_obj); const func = thisVal[propVal]; - // const func = Reflect.get(thisVal, propVal); const args = context.runtime.objects.batchGet(argv, argc); - const val = func.apply(thisVal, args); + let res; + try { + res = func.apply(thisVal, args); + } + catch (err) { + res = err; + } - context.runtime.objects.push(val, ptr); + context.runtime.objects.push(res, ptr); }, JS_Call(ptr, ctx, func_obj, this_obj, argc, argv) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const func = context.runtime.objects.get(func_obj); const thisVal = context.runtime.objects.get(this_obj); const args = context.runtime.objects.batchGet(argv, argc); - const val = func.apply(thisVal, args); + let res; + try { + res = func.apply(thisVal, args); + } + catch (err) { + res = err; + } - context.runtime.objects.push(val, ptr); + context.runtime.objects.push(res, ptr); }, JS_CallConstructor(ptr, ctx, func_obj, argc, argv) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const func = context.runtime.objects.get(func_obj); const args = context.runtime.objects.batchGet(argv, argc); - const val = Reflect.construct(func, args); + let res; + try { + res = Reflect.construct(func, args); + } + catch (err) { + res = err; + } - context.runtime.objects.push(val, ptr); + context.runtime.objects.push(res, ptr); }, JS_SetConstructor(ctx, ctor, proto) { - var context = unityJsbState.getContext(ctx); - var ctorVal = context.runtime.objects.get(ctor); - var protoVal = context.runtime.objects.get(proto); + const context = unityJsbState.getContext(ctx); + const ctorVal = context.runtime.objects.get(ctor); + const protoVal = context.runtime.objects.get(proto); ctorVal.prototype = protoVal; }, JS_SetPrototype(ctx, obj, proto) { - var context = unityJsbState.getContext(ctx); - var objVal = context.runtime.objects.get(obj); - var protoVal = context.runtime.objects.get(proto); + const context = unityJsbState.getContext(ctx); + const objVal = context.runtime.objects.get(obj); + const protoVal = context.runtime.objects.get(proto); Reflect.setPrototypeOf(objVal, protoVal); return true; }, JS_DefineProperty(ctx, this_obj, prop, val, getter, setter, flags) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const thisVal = context.runtime.objects.get(this_obj); const getterVal = context.runtime.objects.get(getter); @@ -696,10 +728,11 @@ var UnityJSBPlugin: PluginType = { }, JS_DefinePropertyValue(ctx, this_obj, prop, val, flags) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; - const thisVal = context.runtime.objects.get(this_obj); - const valVal = context.runtime.objects.get(val); + const thisVal = runtime.objects.get(this_obj); + const valVal = runtime.objects.get(val); const propVal = unityJsbState.atoms.get(prop); const configurable = !!(flags & JSPropFlags.JS_PROP_CONFIGURABLE); @@ -711,6 +744,9 @@ var UnityJSBPlugin: PluginType = { const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); + // SetProperty frees the value automatically + runtime.objects.pop(val); + try { const opts: PropertyDescriptor = { value: valVal, @@ -735,26 +771,29 @@ var UnityJSBPlugin: PluginType = { }, JS_HasProperty(ctx, this_obj, prop) { - var context = unityJsbState.getContext(ctx); - var thisVal = context.runtime.objects.get(this_obj); - var propVal = unityJsbState.atoms.get(prop); + const context = unityJsbState.getContext(ctx); + const thisVal = context.runtime.objects.get(this_obj); + const propVal = unityJsbState.atoms.get(prop); - var res = Reflect.has(thisVal, propVal); + const res = Reflect.has(thisVal, propVal); return !!res; }, JS_SetPropertyInternal(ctx, this_obj, prop, val, flags) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; - const thisVal = context.runtime.objects.get(this_obj); - const valVal = context.runtime.objects.get(val); + const thisVal = runtime.objects.get(this_obj); + const valVal = runtime.objects.get(val); const propVal = unityJsbState.atoms.get(prop); + // SetProperty frees the value automatically + runtime.objects.pop(val); + const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); try { - // return !!Reflect.set(thisVal, propVal, valVal); thisVal[propVal] = valVal; return true; } catch (err) { @@ -769,32 +808,41 @@ var UnityJSBPlugin: PluginType = { }, JS_SetPropertyUint32(ctx, this_obj, idx, val) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; const thisVal = context.runtime.objects.get(this_obj); const valVal = context.runtime.objects.get(val); const propVal = idx; - // return !!Reflect.set(thisVal, propVal, valVal); - thisVal[propVal] = valVal; - return true; + // SetProperty frees the value automatically + runtime.objects.pop(val); + + try { + thisVal[propVal] = valVal; + return true; + } catch (err) { + context.lastException = err; + } + + return false; }, jsb_get_payload_header(ret, ctx, val) { - var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val); - var rec = context.runtime.objects.getPayload(obj); + const rec = context.runtime.objects.getPayload(obj); HEAP32[ret >> 2] = rec.type; HEAP32[(ret >> 2) + 1] = rec.payload; }, JS_ToCStringLen2(ctx, len, val, cesu8) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); - var str = context.runtime.objects.get(val); + const str = context.runtime.objects.get(val); if (typeof str === 'undefined') { @@ -802,7 +850,7 @@ var UnityJSBPlugin: PluginType = { return 0 as IntPtr; } - var [buffer, length] = unityJsbState.bufferify(str); + const [buffer, length] = unityJsbState.bufferify(str); HEAP32[(len >> 2)] = length - 1; return buffer as IntPtr; }, @@ -827,16 +875,16 @@ var UnityJSBPlugin: PluginType = { // #region Atoms JS_NewAtomLen(ctx, str, len) { - var context = unityJsbState.getContext(ctx); - var val = unityJsbState.stringify(str, len); + const context = unityJsbState.getContext(ctx); + const val = unityJsbState.stringify(str, len); return unityJsbState.atoms.push(val); }, JS_AtomToString(ptr, ctx, atom) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); - var str = unityJsbState.atoms.get(atom); + const str = unityJsbState.atoms.get(atom); context.runtime.objects.push(str, ptr); }, @@ -918,104 +966,104 @@ var UnityJSBPlugin: PluginType = { // #region Is JS_IsArray(ctx, val) { - var context = unityJsbState.getContext(ctx); - var valVal = context.runtime.objects.get(val); - var res = Array.isArray(valVal); + const context = unityJsbState.getContext(ctx); + const valVal = context.runtime.objects.get(val); + const res = Array.isArray(valVal); return !!res; }, JS_IsConstructor(ctx, val) { - var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); - var res = !!obj.prototype && !!obj.prototype.constructor.name; + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.objects.get(val); + const res = !!obj.prototype && !!obj.prototype.constructor.name; return !!res; }, JS_IsError(ctx, val) { - var context = unityJsbState.getContext(ctx); - var valVal = context.runtime.objects.get(val); - var res = valVal instanceof Error; + const context = unityJsbState.getContext(ctx); + const valVal = context.runtime.objects.get(val); + const res = valVal instanceof Error; return !!res; }, JS_IsFunction(ctx, val) { - var context = unityJsbState.getContext(ctx); - var valVal = context.runtime.objects.get(val); - var res = typeof valVal === 'function'; + const context = unityJsbState.getContext(ctx); + const valVal = context.runtime.objects.get(val); + const res = typeof valVal === 'function'; return !!res; }, // #endregion JS_ParseJSON(ptr, ctx, buf, buf_len, filename) { - var context = unityJsbState.getContext(ctx); - var str = unityJsbState.stringify(buf as any, buf_len); - var res = JSON.parse(str); + const context = unityJsbState.getContext(ctx); + const str = unityJsbState.stringify(buf as any, buf_len); + const res = JSON.parse(str); context.runtime.objects.push(res, ptr); }, JS_JSONStringify(ptr, ctx, obj, replacer, space) { - var context = unityJsbState.getContext(ctx); - var objVal = context.runtime.objects.get(obj); - var rpVal = context.runtime.objects.get(replacer); - var spVal = context.runtime.objects.get(space); + const context = unityJsbState.getContext(ctx); + const objVal = context.runtime.objects.get(obj); + const rpVal = context.runtime.objects.get(replacer); + const spVal = context.runtime.objects.get(space); - var res = JSON.stringify(objVal, rpVal, spVal); + const res = JSON.stringify(objVal, rpVal, spVal); context.runtime.objects.push(res, ptr); }, // #region New JS_NewArray(ptr, ctx) { - var context = unityJsbState.getContext(ctx); - var res = []; + const context = unityJsbState.getContext(ctx); + const res = []; context.runtime.objects.push(res, ptr); }, JS_NewArrayBufferCopy(ptr, ctx, buf, len) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); - var nptr = _malloc(len); - var res = new Uint8Array(HEAPU8.buffer, nptr, len); - var existing = new Uint8Array(HEAPU8.buffer, buf, len); + const nptr = _malloc(len); + const res = new Uint8Array(HEAPU8.buffer, nptr, len); + const existing = new Uint8Array(HEAPU8.buffer, buf, len); res.set(existing); context.runtime.objects.push(res, ptr); }, JSB_NewFloat64(ptr, ctx, d) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); context.runtime.objects.push(d, ptr); }, JSB_NewInt64(ptr, ctx, d) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); context.runtime.objects.push(d, ptr); }, JS_NewObject(ptr, ctx) { - var context = unityJsbState.getContext(ctx); - var res = {}; + const context = unityJsbState.getContext(ctx); + const res = {}; context.runtime.objects.push(res, ptr); }, JS_NewString(ptr, ctx, str) { - var context = unityJsbState.getContext(ctx); - var res = unityJsbState.stringify(str); + const context = unityJsbState.getContext(ctx); + const res = unityJsbState.stringify(str); context.runtime.objects.push(res, ptr); }, JS_NewStringLen(ptr, ctx, str, len) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); - var val = unityJsbState.stringify(str as any, len); + const val = unityJsbState.stringify(str as any, len); context.runtime.objects.push(val, ptr); }, JSB_NewEmptyString(ptr, ctx) { - var context = unityJsbState.getContext(ctx); - var res = ""; + const context = unityJsbState.getContext(ctx); + const res = ""; context.runtime.objects.push(res, ptr); }, @@ -1024,26 +1072,31 @@ var UnityJSBPlugin: PluginType = { // #region Bridge JSB_NewCFunction(ret, ctx, func, atom, length, cproto, magic) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; - var name = unityJsbState.atoms.get(atom) || 'jscFunction'; + const name = unityJsbState.atoms.get(atom) || 'jscFunction'; function jscFunction() { void name; const args = arguments; const thisObj = this === window ? context.globalObject : this; - const thisPtr = context.runtime.objects.allocate(thisObj); + const [thisPtr, thisId] = runtime.objects.allocate(thisObj); const ret = _malloc(Sizes.JSValue) as JSValue; if (cproto === JSCFunctionEnum.JS_CFUNC_generic) { const argc = args.length; - const argv = context.runtime.objects.batchAllocate(Array.from(args)); + const [argv, argIds] = context.runtime.objects.batchAllocate(Array.from(args)); unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); + argIds.forEach(runtime.objects.popId); + _free(argv); } else if (cproto === JSCFunctionEnum.JS_CFUNC_setter) { - const val = context.runtime.objects.allocate(args[0]); + const [val, valId] = context.runtime.objects.allocate(args[0]); unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); + runtime.objects.popId(valId); + _free(val); } else if (cproto === JSCFunctionEnum.JS_CFUNC_getter) { unityJsbState.dynCall('viii', func, [ret, ctx, thisPtr]); @@ -1051,39 +1104,51 @@ var UnityJSBPlugin: PluginType = { else { throw new Error('Unknown type of function specified: ' + cproto); } + runtime.objects.popId(thisId); + _free(thisPtr); - return context.runtime.objects.get(ret); + const returnValue = context.runtime.objects.get(ret); + context.runtime.objects.pop(ret); + _free(ret); + return returnValue; }; context.runtime.objects.push(jscFunction, ret); }, JSB_NewCFunctionMagic(ret, ctx, func, atom, length, cproto, magic) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; - var name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; + const name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; function jscFunctionMagic() { void name; const args = arguments; const thisObj = this === window ? context.globalObject : this; - const thisPtr = context.runtime.objects.allocate(thisObj); + const [thisPtr, thisId] = runtime.objects.allocate(thisObj); const ret = _malloc(Sizes.JSValue) as JSValue; if (cproto === JSCFunctionEnum.JS_CFUNC_generic_magic) { const argc = args.length; - const argv = context.runtime.objects.batchAllocate(Array.from(args)); + const [argv, argIds] = context.runtime.objects.batchAllocate(Array.from(args)); unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(runtime.objects.popId); + _free(argv); } else if (cproto === JSCFunctionEnum.JS_CFUNC_constructor_magic) { const argc = args.length; - const argv = context.runtime.objects.batchAllocate(Array.from(args)); + const [argv, argIds] = context.runtime.objects.batchAllocate(Array.from(args)); unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(runtime.objects.popId); + _free(argv); } else if (cproto === JSCFunctionEnum.JS_CFUNC_setter_magic) { - const val = context.runtime.objects.allocate(args[0]); + const [val, valId] = context.runtime.objects.allocate(args[0]); unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); + runtime.objects.popId(valId); + _free(val); } else if (cproto === JSCFunctionEnum.JS_CFUNC_getter_magic) { unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, magic]); @@ -1091,40 +1156,45 @@ var UnityJSBPlugin: PluginType = { else { throw new Error('Unknown type of function specified: ' + cproto); } + runtime.objects.popId(thisId); + _free(thisPtr); - return context.runtime.objects.get(ret); + const returnValue = context.runtime.objects.get(ret); + context.runtime.objects.pop(ret); + _free(ret); + return returnValue; }; context.runtime.objects.push(jscFunctionMagic, ret); }, jsb_new_bridge_object(ret, ctx, proto, object_id) { - var context = unityJsbState.getContext(ctx); - var protoVal = context.runtime.objects.get(proto); - var res = Object.create(protoVal); + const context = unityJsbState.getContext(ctx); + const protoVal = context.runtime.objects.get(proto); + const res = Object.create(protoVal); context.runtime.objects.push(res, ret); context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); }, jsb_new_bridge_value(ret, ctx, proto, size) { - var context = unityJsbState.getContext(ctx); - var protoVal = context.runtime.objects.get(proto); - var res = Object.create(protoVal) as BridgeStruct; + const context = unityJsbState.getContext(ctx); + const protoVal = context.runtime.objects.get(proto); + const res = Object.create(protoVal) as BridgeStruct; res.$$values = new Array(size).fill(0); context.runtime.objects.push(res, ret); }, JSB_NewBridgeClassObject(ret, ctx, new_target, object_id) { - var context = unityJsbState.getContext(ctx); - var res = context.runtime.objects.get(new_target); + const context = unityJsbState.getContext(ctx); + const res = context.runtime.objects.get(new_target); context.runtime.objects.push(res, ret); context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); }, JSB_NewBridgeClassValue(ret, ctx, new_target, size) { - var context = unityJsbState.getContext(ctx); - var res = context.runtime.objects.get(new_target) as BridgeStruct; + const context = unityJsbState.getContext(ctx); + const res = context.runtime.objects.get(new_target) as BridgeStruct; res.$$values = new Array(size).fill(0); context.runtime.objects.push(res, ret); }, @@ -1135,18 +1205,18 @@ var UnityJSBPlugin: PluginType = { }, jsb_construct_bridge_object(ret, ctx, ctor, object_id) { - var context = unityJsbState.getContext(ctx); - var ctorVal = context.runtime.objects.get(ctor); - var res = Reflect.construct(ctorVal, []); + const context = unityJsbState.getContext(ctx); + const ctorVal = context.runtime.objects.get(ctor); + const res = Reflect.construct(ctorVal, []); context.runtime.objects.push(res, ret); context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); }, jsb_crossbind_constructor(ret, ctx, new_target) { - var context = unityJsbState.getContext(ctx); - var target = context.runtime.objects.get(new_target); + const context = unityJsbState.getContext(ctx); + const target = context.runtime.objects.get(new_target); // TODO: I have no idea - var res = function () { + const res = function () { return new target(); }; context.runtime.objects.push(res, ret); @@ -1157,45 +1227,45 @@ var UnityJSBPlugin: PluginType = { // #region Errors JSB_ThrowError(ret, ctx, buf, buf_len) { - var context = unityJsbState.getContext(ctx); - var str = unityJsbState.stringify(buf as any, buf_len); - var err = new Error(str); + const context = unityJsbState.getContext(ctx); + const str = unityJsbState.stringify(buf as any, buf_len); + const err = new Error(str); console.error(err); context.runtime.objects.push(err, ret); // TODO: throw? }, JSB_ThrowTypeError(ret, ctx, msg) { - var context = unityJsbState.getContext(ctx); - var str = 'Type Error'; - var err = new Error(str); + const context = unityJsbState.getContext(ctx); + const str = 'Type Error'; + const err = new Error(str); console.error(err); context.runtime.objects.push(err, ret); // TODO: throw? }, JSB_ThrowRangeError(ret, ctx, msg) { - var context = unityJsbState.getContext(ctx); - var str = 'Range Error'; - var err = new Error(str); + const context = unityJsbState.getContext(ctx); + const str = 'Range Error'; + const err = new Error(str); console.error(err); context.runtime.objects.push(err, ret); // TODO: throw? }, JSB_ThrowInternalError(ret, ctx, msg) { - var context = unityJsbState.getContext(ctx); - var str = 'Internal Error'; - var err = new Error(str); + const context = unityJsbState.getContext(ctx); + const str = 'Internal Error'; + const err = new Error(str); console.error(err); context.runtime.objects.push(err, ret); // TODO: throw? }, JSB_ThrowReferenceError(ret, ctx, msg) { - var context = unityJsbState.getContext(ctx); - var str = 'Reference Error'; - var err = new Error(str); + const context = unityJsbState.getContext(ctx); + const str = 'Reference Error'; + const err = new Error(str); console.error(err); context.runtime.objects.push(err, ret); // TODO: throw? @@ -1206,14 +1276,14 @@ var UnityJSBPlugin: PluginType = { // #region Low level Set js_strndup(ctx, s, n) { - var buffer = _malloc(n + 1); + const buffer = _malloc(n + 1); _memcpy(buffer, s, n); HEAPU8[buffer + n] = 0; return buffer as IntPtr; }, jsb_set_floats(ctx, val, n, v0) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = n / Sizes.Single; @@ -1228,7 +1298,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_bytes(ctx, val, n, v0) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = n / Sizes.Single; @@ -1243,7 +1313,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_byte_4(ctx, val, v0, v1, v2, v3) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 4; @@ -1258,7 +1328,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_float_2(ctx, val, v0, v1) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 2; @@ -1271,7 +1341,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_float_3(ctx, val, v0, v1, v2) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 3; @@ -1285,7 +1355,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_float_4(ctx, val, v0, v1, v2, v3) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 4; @@ -1300,7 +1370,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_int_1(ctx, val, v0) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 1; @@ -1312,7 +1382,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_int_2(ctx, val, v0, v1) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 2; @@ -1325,7 +1395,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_int_3(ctx, val, v0, v1, v2) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 3; @@ -1339,7 +1409,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_set_int_4(ctx, val, v0, v1, v2, v3) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 4; @@ -1358,7 +1428,7 @@ var UnityJSBPlugin: PluginType = { // #region Low Level Get jsb_get_bytes(ctx, val, n, v0) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = n / Sizes.Single; @@ -1373,7 +1443,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_floats(ctx, val, n, v0) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = n / Sizes.Single; @@ -1388,7 +1458,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_byte_4(ctx, val, v0, v1, v2, v3) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 4; @@ -1403,7 +1473,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_float_2(ctx, val, v0, v1) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 2; @@ -1416,7 +1486,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_float_3(ctx, val, v0, v1, v2) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 3; @@ -1430,7 +1500,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_float_4(ctx, val, v0, v1, v2, v3) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 4; @@ -1445,7 +1515,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_int_1(ctx, val, v0) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 1; @@ -1457,7 +1527,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_int_2(ctx, val, v0, v1) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 2; @@ -1470,7 +1540,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_int_3(ctx, val, v0, v1, v2) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 3; @@ -1484,7 +1554,7 @@ var UnityJSBPlugin: PluginType = { }, jsb_get_int_4(ctx, val, v0, v1, v2, v3) { - var context = unityJsbState.getContext(ctx); + const context = unityJsbState.getContext(ctx); const obj = context.runtime.objects.get(val) as BridgeStruct; const count = 4; @@ -1568,8 +1638,8 @@ var UnityJSBPlugin: PluginType = { }, JS_ToBool(ctx, val) { - var context = unityJsbState.getContext(ctx); - var objVal = context.runtime.objects.get(val); + const context = unityJsbState.getContext(ctx); + const objVal = context.runtime.objects.get(val); return !!objVal; }, diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts index a0c1cdf2..7d22d12a 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts @@ -61,16 +61,18 @@ declare global { } export declare type PluginObjects = { - deleteIndex: (id: number) => void; + deleteRecord: (id: number) => void; record: Record; get: ((ref: JSValue) => any); getRecord: ((ref: JSValue) => PluginObject); - push: ((obj: any, ptr: JSValue) => void); - allocate: ((obj: any) => JSValue); - batchAllocate: ((objs: any[]) => PointerArray); + push: ((obj: any, ptr: JSValue) => number | undefined); + duplicate: ((obj: JSValue, ptr: JSValue) => void); + duplicateId: ((id: number, ptr: JSValue) => void); + pop: ((obj: JSValue) => void); + popId: ((id: number | undefined) => void); + allocate: ((obj: any) => [JSValue, number | undefined]); + batchAllocate: ((objs: any[]) => [PointerArray, (number | undefined)[]]); batchGet: ((arr: PointerArray, count: number) => any[]); - ref: ((obj: JSValue, diff: number, ptr: JSValue) => void); - refIndex: ((obj: number, diff: number, ptr: JSValue) => void); lastId: number; setPayload: ((obj: any, type: BridgeObjectType, payload: number) => void); getPayload: ((obj: any) => PluginObjectPayload); diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib index c8a1c4d7..22534850 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib @@ -35,17 +35,20 @@ var UnityJSBPlugin = { lastId: 0, allocate: function (object) { var ptr = _malloc(16 /* Sizes.JSValue */); - res.push(object, ptr); - return ptr; + var id = res.push(object, ptr); + return [ptr, id]; }, batchAllocate: function (objects) { var size = 16 /* Sizes.JSValue */; - var arr = _malloc(size * objects.length); - for (var index = 0; index < objects.length; index++) { + var len = objects.length; + var arr = _malloc(size * len); + var ids = Array(len); + for (var index = 0; index < len; index++) { var object = objects[index]; - res.push(object, arr + (index * size)); + var id = res.push(object, arr + (index * size)); + ids[index] = id; } - return arr; + return [arr, ids]; }, batchGet: function (ptrs, count) { var size = 16 /* Sizes.JSValue */; @@ -58,7 +61,7 @@ var UnityJSBPlugin = { }, push: function (object, ptr) { if (typeof object === 'undefined') { - res.refIndex(0, 1, ptr); + res.duplicateId(0, ptr); return; } if (typeof object === 'number') { @@ -78,8 +81,8 @@ var UnityJSBPlugin = { } var foundId = map.get(object); if (foundId > 0) { - res.refIndex(foundId, 1, ptr); - return; + res.duplicateId(foundId, ptr); + return foundId; } var id = ++res.lastId; record[id] = { @@ -89,7 +92,7 @@ var UnityJSBPlugin = { tag: getTag(object), }; map.set(object, id); - res.refIndex(id, 1, ptr); + res.duplicateId(id, ptr); return id; }, get: function (val) { @@ -155,7 +158,7 @@ var UnityJSBPlugin = { return ho; } }, - ref: function (obj, diff, ptr) { + duplicate: function (obj, ptr) { var tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); if (tag === 7 /* Tags.JS_TAG_FLOAT64 */) { if (typeof ptr === 'number') { @@ -184,9 +187,9 @@ var UnityJSBPlugin = { return; } var id = HEAP32[obj >> 2]; - res.refIndex(id, diff, ptr); + res.duplicateId(id, ptr); }, - refIndex: function (id, diff, ptr) { + duplicateId: function (id, ptr) { if (id === 0) { if (typeof ptr === 'number') { HEAP32[ptr >> 2] = 0; @@ -196,15 +199,30 @@ var UnityJSBPlugin = { return; } var ho = record[id]; - ho.refCount += diff; - console.assert(ho.refCount >= 0); + ho.refCount += 1; if (typeof ptr === 'number') { HEAP32[ptr >> 2] = id; HEAP32[(ptr >> 2) + 1] = 0; unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(ho.tag); } }, - deleteIndex: function (id) { + pop: function (obj) { + var tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); + if (tag === 7 /* Tags.JS_TAG_FLOAT64 */ + || tag === 0 /* Tags.JS_TAG_INT */ + || tag === 1 /* Tags.JS_TAG_BOOL */) + return; + var id = HEAP32[obj >> 2]; + res.popId(id); + }, + popId: function (id) { + if (!id) + return; + var ho = record[id]; + ho.refCount -= 1; + console.assert(ho.refCount >= 0); + }, + deleteRecord: function (id) { var rec = record[id]; delete record[id]; map.delete(rec.value); @@ -333,11 +351,11 @@ var UnityJSBPlugin = { var lastId = objects.lastId; var record = objects.record; var aliveItemCount = 0; - for (var index = 0; index < lastId; index++) { + for (var index = 0; index <= lastId; index++) { var element = record[index]; if (element) { if (element.refCount <= 0) { - objects.deleteIndex(index); + objects.deleteRecord(index); } else { aliveItemCount++; @@ -442,12 +460,12 @@ var UnityJSBPlugin = { context.runtime.objects.push(context.globalObject, returnValue); } else { - context.runtime.objects.refIndex(context.globalObjectId, 1, returnValue); + context.runtime.objects.duplicateId(context.globalObjectId, returnValue); } }, JS_Eval: function (ptr, ctx, input, input_len, filename, eval_flags) { + var context = unityJsbState.getContext(ctx); try { - var context = unityJsbState.getContext(ctx); var code = unityJsbState.stringify(input, input_len); var filenameStr = unityJsbState.stringify(filename); var res = context.evaluate(code, filenameStr); @@ -471,11 +489,11 @@ var UnityJSBPlugin = { }, JSB_FreeValue: function (ctx, v) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.ref(v, -1, undefined); + context.runtime.objects.pop(v); }, JSB_FreeValueRT: function (rt, v) { var runtime = unityJsbState.getRuntime(rt); - runtime.objects.ref(v, -1, undefined); + runtime.objects.pop(v); }, JSB_FreePayload: function (ret, ctx, val) { var context = unityJsbState.getContext(ctx); @@ -487,7 +505,7 @@ var UnityJSBPlugin = { }, JSB_DupValue: function (ptr, ctx, v) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.ref(v, 1, ptr); + context.runtime.objects.duplicate(v, ptr); }, JS_RunGC: function (rt) { var runtime = unityJsbState.getRuntime(rt); @@ -508,7 +526,6 @@ var UnityJSBPlugin = { var receiverObj = context.runtime.objects.get(receiver); var propStr = unityJsbState.atoms.get(prop); var res = valObj[propStr]; - // var res = Reflect.get(valObj, propStr, receiverObj); context.runtime.objects.push(res, ptr); }, JS_GetPropertyStr: function (ptr, ctxId, val, prop) { @@ -516,7 +533,6 @@ var UnityJSBPlugin = { var valObj = context.runtime.objects.get(val); var propStr = unityJsbState.stringify(prop); var res = valObj[propStr]; - // var res = Reflect.get(valObj, propStr); context.runtime.objects.push(res, ptr); }, JS_Invoke: function (ptr, ctx, this_obj, prop, argc, argv) { @@ -524,25 +540,42 @@ var UnityJSBPlugin = { var propVal = unityJsbState.atoms.get(prop); var thisVal = context.runtime.objects.get(this_obj); var func = thisVal[propVal]; - // const func = Reflect.get(thisVal, propVal); var args = context.runtime.objects.batchGet(argv, argc); - var val = func.apply(thisVal, args); - context.runtime.objects.push(val, ptr); + var res; + try { + res = func.apply(thisVal, args); + } + catch (err) { + res = err; + } + context.runtime.objects.push(res, ptr); }, JS_Call: function (ptr, ctx, func_obj, this_obj, argc, argv) { var context = unityJsbState.getContext(ctx); var func = context.runtime.objects.get(func_obj); var thisVal = context.runtime.objects.get(this_obj); var args = context.runtime.objects.batchGet(argv, argc); - var val = func.apply(thisVal, args); - context.runtime.objects.push(val, ptr); + var res; + try { + res = func.apply(thisVal, args); + } + catch (err) { + res = err; + } + context.runtime.objects.push(res, ptr); }, JS_CallConstructor: function (ptr, ctx, func_obj, argc, argv) { var context = unityJsbState.getContext(ctx); var func = context.runtime.objects.get(func_obj); var args = context.runtime.objects.batchGet(argv, argc); - var val = Reflect.construct(func, args); - context.runtime.objects.push(val, ptr); + var res; + try { + res = Reflect.construct(func, args); + } + catch (err) { + res = err; + } + context.runtime.objects.push(res, ptr); }, JS_SetConstructor: function (ctx, ctor, proto) { var context = unityJsbState.getContext(ctx); @@ -599,8 +632,9 @@ var UnityJSBPlugin = { }, JS_DefinePropertyValue: function (ctx, this_obj, prop, val, flags) { var context = unityJsbState.getContext(ctx); - var thisVal = context.runtime.objects.get(this_obj); - var valVal = context.runtime.objects.get(val); + var runtime = context.runtime; + var thisVal = runtime.objects.get(this_obj); + var valVal = runtime.objects.get(val); var propVal = unityJsbState.atoms.get(prop); var configurable = !!(flags & 1 /* JSPropFlags.JS_PROP_CONFIGURABLE */); var hasConfigurable = configurable || !!(flags & 256 /* JSPropFlags.JS_PROP_HAS_CONFIGURABLE */); @@ -609,6 +643,8 @@ var UnityJSBPlugin = { var writable = !!(flags & 2 /* JSPropFlags.JS_PROP_WRITABLE */); var hasWritable = writable || !!(flags & 512 /* JSPropFlags.JS_PROP_HAS_WRITABLE */); var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); + // SetProperty frees the value automatically + runtime.objects.pop(val); try { var opts = { value: valVal, @@ -640,12 +676,14 @@ var UnityJSBPlugin = { }, JS_SetPropertyInternal: function (ctx, this_obj, prop, val, flags) { var context = unityJsbState.getContext(ctx); - var thisVal = context.runtime.objects.get(this_obj); - var valVal = context.runtime.objects.get(val); + var runtime = context.runtime; + var thisVal = runtime.objects.get(this_obj); + var valVal = runtime.objects.get(val); var propVal = unityJsbState.atoms.get(prop); + // SetProperty frees the value automatically + runtime.objects.pop(val); var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); try { - // return !!Reflect.set(thisVal, propVal, valVal); thisVal[propVal] = valVal; return true; } @@ -660,12 +698,20 @@ var UnityJSBPlugin = { }, JS_SetPropertyUint32: function (ctx, this_obj, idx, val) { var context = unityJsbState.getContext(ctx); + var runtime = context.runtime; var thisVal = context.runtime.objects.get(this_obj); var valVal = context.runtime.objects.get(val); var propVal = idx; - // return !!Reflect.set(thisVal, propVal, valVal); - thisVal[propVal] = valVal; - return true; + // SetProperty frees the value automatically + runtime.objects.pop(val); + try { + thisVal[propVal] = valVal; + return true; + } + catch (err) { + context.lastException = err; + } + return false; }, jsb_get_payload_header: function (ret, ctx, val) { var context = unityJsbState.getContext(ctx); @@ -849,21 +895,26 @@ var UnityJSBPlugin = { // #region Bridge JSB_NewCFunction: function (ret, ctx, func, atom, length, cproto, magic) { var context = unityJsbState.getContext(ctx); + var runtime = context.runtime; var name = unityJsbState.atoms.get(atom) || 'jscFunction'; function jscFunction() { void name; var args = arguments; var thisObj = this === window ? context.globalObject : this; - var thisPtr = context.runtime.objects.allocate(thisObj); + var _a = runtime.objects.allocate(thisObj), thisPtr = _a[0], thisId = _a[1]; var ret = _malloc(16 /* Sizes.JSValue */); if (cproto === 0 /* JSCFunctionEnum.JS_CFUNC_generic */) { var argc = args.length; - var argv = context.runtime.objects.batchAllocate(Array.from(args)); + var _b = context.runtime.objects.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); + argIds.forEach(runtime.objects.popId); + _free(argv); } else if (cproto === 9 /* JSCFunctionEnum.JS_CFUNC_setter */) { - var val = context.runtime.objects.allocate(args[0]); + var _c = context.runtime.objects.allocate(args[0]), val = _c[0], valId = _c[1]; unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); + runtime.objects.popId(valId); + _free(val); } else if (cproto === 8 /* JSCFunctionEnum.JS_CFUNC_getter */) { unityJsbState.dynCall('viii', func, [ret, ctx, thisPtr]); @@ -871,33 +922,45 @@ var UnityJSBPlugin = { else { throw new Error('Unknown type of function specified: ' + cproto); } - return context.runtime.objects.get(ret); + runtime.objects.popId(thisId); + _free(thisPtr); + var returnValue = context.runtime.objects.get(ret); + context.runtime.objects.pop(ret); + _free(ret); + return returnValue; } ; context.runtime.objects.push(jscFunction, ret); }, JSB_NewCFunctionMagic: function (ret, ctx, func, atom, length, cproto, magic) { var context = unityJsbState.getContext(ctx); + var runtime = context.runtime; var name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; function jscFunctionMagic() { void name; var args = arguments; var thisObj = this === window ? context.globalObject : this; - var thisPtr = context.runtime.objects.allocate(thisObj); + var _a = runtime.objects.allocate(thisObj), thisPtr = _a[0], thisId = _a[1]; var ret = _malloc(16 /* Sizes.JSValue */); if (cproto === 1 /* JSCFunctionEnum.JS_CFUNC_generic_magic */) { var argc = args.length; - var argv = context.runtime.objects.batchAllocate(Array.from(args)); + var _b = context.runtime.objects.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(runtime.objects.popId); + _free(argv); } else if (cproto === 3 /* JSCFunctionEnum.JS_CFUNC_constructor_magic */) { var argc = args.length; - var argv = context.runtime.objects.batchAllocate(Array.from(args)); + var _c = context.runtime.objects.batchAllocate(Array.from(args)), argv = _c[0], argIds = _c[1]; unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(runtime.objects.popId); + _free(argv); } else if (cproto === 11 /* JSCFunctionEnum.JS_CFUNC_setter_magic */) { - var val = context.runtime.objects.allocate(args[0]); + var _d = context.runtime.objects.allocate(args[0]), val = _d[0], valId = _d[1]; unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); + runtime.objects.popId(valId); + _free(val); } else if (cproto === 10 /* JSCFunctionEnum.JS_CFUNC_getter_magic */) { unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, magic]); @@ -905,7 +968,12 @@ var UnityJSBPlugin = { else { throw new Error('Unknown type of function specified: ' + cproto); } - return context.runtime.objects.get(ret); + runtime.objects.popId(thisId); + _free(thisPtr); + var returnValue = context.runtime.objects.get(ret); + context.runtime.objects.pop(ret); + _free(ret); + return returnValue; } ; context.runtime.objects.push(jscFunctionMagic, ret); From b99dc7e64d7ffd103f0727e5c575d2c32165f9a9 Mon Sep 17 00:00:00 2001 From: Gokhan Kurt Date: Wed, 22 Jun 2022 23:01:48 +0300 Subject: [PATCH 4/4] some refactors and fixes for object constructing, enums --- .../Plugins/WebGL/.source/jsbplugin.ts | 341 +++++++++--------- .../Plugins/WebGL/.source/typings/plugin.d.ts | 29 +- .../Plugins/WebGL/jsbplugin.jslib | 328 +++++++++-------- 3 files changed, 362 insertions(+), 336 deletions(-) diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts index eac50877..e6a862d8 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts @@ -1,6 +1,10 @@ /** * Build with the following command: * npx -p typescript tsc + * + * BEWARE: Using some syntaxes will make Emscripten fail while building + * Such known syntaxes: Object spread (...), BigInt literals + * The output is targeted for es5 as Emscripten only understands that syntax */ type PluginType = JSApiExternals & { @@ -11,13 +15,12 @@ type PluginType = JSApiExternals & { const UnityJSBPlugin: PluginType = { $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', $unityJsbState: { - createObjects: function (): PluginObjects { + createObjectReferences: function (): ObjectReferences { const getTag = function (object): Tags { if (object === undefined) return Tags.JS_TAG_UNDEFINED; if (object === null) return Tags.JS_TAG_NULL; if (typeof object === 'number') return Tags.JS_TAG_FLOAT64; if (typeof object === 'boolean') return Tags.JS_TAG_BOOL; - if (typeof object === 'function') return Tags.JS_TAG_FUNCTION_BYTECODE; if (typeof object === 'symbol') return Tags.JS_TAG_SYMBOL; if (typeof object === 'string') return Tags.JS_TAG_STRING; if (typeof object === 'bigint') return Tags.JS_TAG_BIG_INT; @@ -25,13 +28,13 @@ const UnityJSBPlugin: PluginType = { return Tags.JS_TAG_OBJECT; }; - const record: PluginObjects['record'] = {}; + const record: ObjectReferences['record'] = {}; const map = new Map(); - const payloadMap: PluginObjects['payloadMap'] = new Map(); + const payloadMap: ObjectReferences['payloadMap'] = new Map(); - const res: PluginObjects = { + const res: ObjectReferences = { record, lastId: 0, @@ -252,7 +255,7 @@ const UnityJSBPlugin: PluginType = { payloadMap, setPayload(obj, type, payload) { payloadMap.set(obj, { - type: BridgeObjectType.None || type, + type, payload, }); }, @@ -274,13 +277,12 @@ const UnityJSBPlugin: PluginType = { return res; }, - createAtoms(): PluginAtoms { - const record: PluginAtoms['record'] = {}; - const map: PluginAtoms['map'] = {}; + createAtoms(): AtomReferences { + const record: AtomReferences['record'] = {}; + const map = new Map(); - const res: PluginAtoms = { + const res: AtomReferences = { record, - map, lastId: 0, get(ref) { if (ref === 0) return undefined; @@ -288,16 +290,17 @@ const UnityJSBPlugin: PluginType = { }, push(str) { if (str === undefined) return 0; - const mapped = map[str]; + const mapped = map.get(str); let id; if (!mapped) { id = ++res.lastId; - map[str] = record[id] = { + const item = record[id] = { id, value: str, refCount: 1, }; + map.set(str, item); } else { id = mapped.id; mapped.refCount++; @@ -326,7 +329,7 @@ const UnityJSBPlugin: PluginType = { console.assert(recorded.refCount >= 0); if (recorded.refCount == 0) { - delete map[recorded.value]; + map.delete(recorded.value); delete record[id]; } }, @@ -371,15 +374,15 @@ const UnityJSBPlugin: PluginType = { // TODO: understand what to do with finalizer const id = unityJsbState.lastRuntimeId++; - const objects = unityJsbState.createObjects(); + const refs = unityJsbState.createObjectReferences(); unityJsbState.runtimes[id] = { id, contexts: {}, - objects, + refs, garbageCollect() { - const lastId = objects.lastId; - const record = objects.record; + const lastId = refs.lastId; + const record = refs.record; let aliveItemCount = 0; @@ -388,7 +391,7 @@ const UnityJSBPlugin: PluginType = { if (element) { if (element.refCount <= 0) { - objects.deleteRecord(index); + refs.deleteRecord(index); } else { aliveItemCount++; @@ -446,6 +449,7 @@ const UnityJSBPlugin: PluginType = { const extraGlobals: any = { location: undefined, document: undefined, + addEventListener: undefined, btoa: window.btoa?.bind(window), atob: window.atob?.bind(window), $$webglWindow: window, @@ -511,10 +515,10 @@ const UnityJSBPlugin: PluginType = { const context = unityJsbState.getContext(ctxId); if (!context.globalObjectId) { - context.runtime.objects.push(context.globalObject, returnValue); + context.runtime.refs.push(context.globalObject, returnValue); } else { - context.runtime.objects.duplicateId(context.globalObjectId, returnValue); + context.runtime.refs.duplicateId(context.globalObjectId, returnValue); } }, @@ -526,51 +530,51 @@ const UnityJSBPlugin: PluginType = { const res = context.evaluate(code, filenameStr); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); } catch (err) { context.lastException = err; - context.runtime.objects.push(err, ptr); + context.runtime.refs.push(err, ptr); console.error(err); } }, JS_IsInstanceOf(ctxId, val, obj) { const context = unityJsbState.getContext(ctxId); - const valVal = context.runtime.objects.get(val); - const ctorVal = context.runtime.objects.get(obj); + const valVal = context.runtime.refs.get(val); + const ctorVal = context.runtime.refs.get(obj); return !!(valVal instanceof ctorVal); }, JS_GetException(ptr, ctx) { const context = unityJsbState.getContext(ctx); - context.runtime.objects.push(context.lastException, ptr); + context.runtime.refs.push(context.lastException, ptr); }, JSB_FreeValue(ctx, v) { const context = unityJsbState.getContext(ctx); - context.runtime.objects.pop(v); + context.runtime.refs.pop(v); }, JSB_FreeValueRT(rt, v) { const runtime = unityJsbState.getRuntime(rt); - runtime.objects.pop(v); + runtime.refs.pop(v); }, JSB_FreePayload(ret, ctx, val) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val); + const obj = context.runtime.refs.get(val); - const payload = context.runtime.objects.getPayload(obj); + const payload = context.runtime.refs.getPayload(obj); HEAP32[ret >> 2] = payload.type; HEAP32[(ret >> 2) + 1] = payload.payload; - context.runtime.objects.clearPayload(obj); + context.runtime.refs.clearPayload(obj); }, JSB_DupValue(ptr, ctx, v) { const context = unityJsbState.getContext(ctx); - context.runtime.objects.duplicate(v, ptr); + context.runtime.refs.duplicate(v, ptr); }, JS_RunGC(rt) { @@ -585,96 +589,104 @@ const UnityJSBPlugin: PluginType = { JS_GetPropertyUint32(ptr, ctxId, val, index) { const context = unityJsbState.getContext(ctxId); - const obj = context.runtime.objects.get(val); + const obj = context.runtime.refs.get(val); const res = obj[index]; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_GetPropertyInternal(ptr, ctxId, val, prop, receiver, throwRefError) { const context = unityJsbState.getContext(ctxId); - const valObj = context.runtime.objects.get(val); - const receiverObj = context.runtime.objects.get(receiver); + const valObj = context.runtime.refs.get(val); const propStr = unityJsbState.atoms.get(prop); const res = valObj[propStr]; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_GetPropertyStr(ptr, ctxId, val, prop) { const context = unityJsbState.getContext(ctxId); - const valObj = context.runtime.objects.get(val); + const valObj = context.runtime.refs.get(val); const propStr = unityJsbState.stringify(prop); const res = valObj[propStr]; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_Invoke(ptr, ctx, this_obj, prop, argc, argv) { const context = unityJsbState.getContext(ctx); const propVal = unityJsbState.atoms.get(prop); - const thisVal = context.runtime.objects.get(this_obj); + const thisVal = context.runtime.refs.get(this_obj); const func = thisVal[propVal]; - const args = context.runtime.objects.batchGet(argv, argc); + const args = context.runtime.refs.batchGet(argv, argc); let res; try { res = func.apply(thisVal, args); } catch (err) { + context.lastException = err; res = err; } - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_Call(ptr, ctx, func_obj, this_obj, argc, argv) { const context = unityJsbState.getContext(ctx); - const func = context.runtime.objects.get(func_obj); - const thisVal = context.runtime.objects.get(this_obj); + const func = context.runtime.refs.get(func_obj); + const thisVal = context.runtime.refs.get(this_obj); - const args = context.runtime.objects.batchGet(argv, argc); + const args = context.runtime.refs.batchGet(argv, argc); let res; try { res = func.apply(thisVal, args); } catch (err) { + context.lastException = err; res = err; } - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_CallConstructor(ptr, ctx, func_obj, argc, argv) { const context = unityJsbState.getContext(ctx); - const func = context.runtime.objects.get(func_obj); + const func = context.runtime.refs.get(func_obj); - const args = context.runtime.objects.batchGet(argv, argc); + const args = context.runtime.refs.batchGet(argv, argc); let res; try { res = Reflect.construct(func, args); } catch (err) { + context.lastException = err; res = err; } - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_SetConstructor(ctx, ctor, proto) { const context = unityJsbState.getContext(ctx); - const ctorVal = context.runtime.objects.get(ctor); - const protoVal = context.runtime.objects.get(proto); + const ctorVal = context.runtime.refs.get(ctor); + const protoVal = context.runtime.refs.get(proto); ctorVal.prototype = protoVal; + protoVal.constructor = ctorVal; + + var ctorPayload = context.runtime.refs.getPayload(ctorVal); + if (ctorPayload.type === BridgeObjectType.TypeRef) { + context.runtime.refs.setPayload(protoVal, ctorPayload.type, ctorPayload.payload); + } }, JS_SetPrototype(ctx, obj, proto) { const context = unityJsbState.getContext(ctx); - const objVal = context.runtime.objects.get(obj); - const protoVal = context.runtime.objects.get(proto); + const objVal = context.runtime.refs.get(obj); + const protoVal = context.runtime.refs.get(proto); Reflect.setPrototypeOf(objVal, protoVal); return true; @@ -683,10 +695,10 @@ const UnityJSBPlugin: PluginType = { JS_DefineProperty(ctx, this_obj, prop, val, getter, setter, flags) { const context = unityJsbState.getContext(ctx); - const thisVal = context.runtime.objects.get(this_obj); - const getterVal = context.runtime.objects.get(getter); - const setterVal = context.runtime.objects.get(setter); - const valVal = context.runtime.objects.get(val); + const thisVal = context.runtime.refs.get(this_obj); + const getterVal = context.runtime.refs.get(getter); + const setterVal = context.runtime.refs.get(setter); + const valVal = context.runtime.refs.get(val); const propVal = unityJsbState.atoms.get(prop); const configurable = !!(flags & JSPropFlags.JS_PROP_CONFIGURABLE); @@ -731,8 +743,8 @@ const UnityJSBPlugin: PluginType = { const context = unityJsbState.getContext(ctx); const runtime = context.runtime; - const thisVal = runtime.objects.get(this_obj); - const valVal = runtime.objects.get(val); + const thisVal = runtime.refs.get(this_obj); + const valVal = runtime.refs.get(val); const propVal = unityJsbState.atoms.get(prop); const configurable = !!(flags & JSPropFlags.JS_PROP_CONFIGURABLE); @@ -745,7 +757,7 @@ const UnityJSBPlugin: PluginType = { const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); // SetProperty frees the value automatically - runtime.objects.pop(val); + runtime.refs.pop(val); try { const opts: PropertyDescriptor = { @@ -772,7 +784,7 @@ const UnityJSBPlugin: PluginType = { JS_HasProperty(ctx, this_obj, prop) { const context = unityJsbState.getContext(ctx); - const thisVal = context.runtime.objects.get(this_obj); + const thisVal = context.runtime.refs.get(this_obj); const propVal = unityJsbState.atoms.get(prop); const res = Reflect.has(thisVal, propVal); @@ -784,12 +796,12 @@ const UnityJSBPlugin: PluginType = { const context = unityJsbState.getContext(ctx); const runtime = context.runtime; - const thisVal = runtime.objects.get(this_obj); - const valVal = runtime.objects.get(val); + const thisVal = runtime.refs.get(this_obj); + const valVal = runtime.refs.get(val); const propVal = unityJsbState.atoms.get(prop); // SetProperty frees the value automatically - runtime.objects.pop(val); + runtime.refs.pop(val); const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); @@ -811,12 +823,12 @@ const UnityJSBPlugin: PluginType = { const context = unityJsbState.getContext(ctx); const runtime = context.runtime; - const thisVal = context.runtime.objects.get(this_obj); - const valVal = context.runtime.objects.get(val); + const thisVal = context.runtime.refs.get(this_obj); + const valVal = context.runtime.refs.get(val); const propVal = idx; // SetProperty frees the value automatically - runtime.objects.pop(val); + runtime.refs.pop(val); try { thisVal[propVal] = valVal; @@ -831,9 +843,9 @@ const UnityJSBPlugin: PluginType = { jsb_get_payload_header(ret, ctx, val) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val); + const obj = context.runtime.refs.get(val); - const rec = context.runtime.objects.getPayload(obj); + const rec = context.runtime.refs.getPayload(obj); HEAP32[ret >> 2] = rec.type; HEAP32[(ret >> 2) + 1] = rec.payload; @@ -842,7 +854,7 @@ const UnityJSBPlugin: PluginType = { JS_ToCStringLen2(ctx, len, val, cesu8) { const context = unityJsbState.getContext(ctx); - const str = context.runtime.objects.get(val); + const str = context.runtime.refs.get(val); if (typeof str === 'undefined') { @@ -861,7 +873,7 @@ const UnityJSBPlugin: PluginType = { JS_GetArrayBuffer(ctx, psize, obj) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(obj); + const value = context.runtime.refs.get(obj); if (value instanceof ArrayBuffer) { HEAP32[psize >> 2] = value.byteLength; @@ -886,7 +898,7 @@ const UnityJSBPlugin: PluginType = { const str = unityJsbState.atoms.get(atom); - context.runtime.objects.push(str, ptr); + context.runtime.refs.push(str, ptr); }, JS_FreeAtom(ctx, v) { @@ -967,28 +979,28 @@ const UnityJSBPlugin: PluginType = { JS_IsArray(ctx, val) { const context = unityJsbState.getContext(ctx); - const valVal = context.runtime.objects.get(val); + const valVal = context.runtime.refs.get(val); const res = Array.isArray(valVal); return !!res; }, JS_IsConstructor(ctx, val) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val); + const obj = context.runtime.refs.get(val); const res = !!obj.prototype && !!obj.prototype.constructor.name; return !!res; }, JS_IsError(ctx, val) { const context = unityJsbState.getContext(ctx); - const valVal = context.runtime.objects.get(val); + const valVal = context.runtime.refs.get(val); const res = valVal instanceof Error; return !!res; }, JS_IsFunction(ctx, val) { const context = unityJsbState.getContext(ctx); - const valVal = context.runtime.objects.get(val); + const valVal = context.runtime.refs.get(val); const res = typeof valVal === 'function'; return !!res; }, @@ -999,17 +1011,17 @@ const UnityJSBPlugin: PluginType = { const context = unityJsbState.getContext(ctx); const str = unityJsbState.stringify(buf as any, buf_len); const res = JSON.parse(str); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_JSONStringify(ptr, ctx, obj, replacer, space) { const context = unityJsbState.getContext(ctx); - const objVal = context.runtime.objects.get(obj); - const rpVal = context.runtime.objects.get(replacer); - const spVal = context.runtime.objects.get(space); + const objVal = context.runtime.refs.get(obj); + const rpVal = context.runtime.refs.get(replacer); + const spVal = context.runtime.refs.get(space); const res = JSON.stringify(objVal, rpVal, spVal); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, // #region New @@ -1017,7 +1029,7 @@ const UnityJSBPlugin: PluginType = { JS_NewArray(ptr, ctx) { const context = unityJsbState.getContext(ctx); const res = []; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_NewArrayBufferCopy(ptr, ctx, buf, len) { @@ -1028,29 +1040,29 @@ const UnityJSBPlugin: PluginType = { const existing = new Uint8Array(HEAPU8.buffer, buf, len); res.set(existing); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JSB_NewFloat64(ptr, ctx, d) { const context = unityJsbState.getContext(ctx); - context.runtime.objects.push(d, ptr); + context.runtime.refs.push(d, ptr); }, JSB_NewInt64(ptr, ctx, d) { const context = unityJsbState.getContext(ctx); - context.runtime.objects.push(d, ptr); + context.runtime.refs.push(d, ptr); }, JS_NewObject(ptr, ctx) { const context = unityJsbState.getContext(ctx); const res = {}; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_NewString(ptr, ctx, str) { const context = unityJsbState.getContext(ctx); const res = unityJsbState.stringify(str); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_NewStringLen(ptr, ctx, str, len) { @@ -1058,13 +1070,13 @@ const UnityJSBPlugin: PluginType = { const val = unityJsbState.stringify(str as any, len); - context.runtime.objects.push(val, ptr); + context.runtime.refs.push(val, ptr); }, JSB_NewEmptyString(ptr, ctx) { const context = unityJsbState.getContext(ctx); const res = ""; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, // #endregion @@ -1073,130 +1085,133 @@ const UnityJSBPlugin: PluginType = { JSB_NewCFunction(ret, ctx, func, atom, length, cproto, magic) { const context = unityJsbState.getContext(ctx); - const runtime = context.runtime; + const refs = context.runtime.refs; const name = unityJsbState.atoms.get(atom) || 'jscFunction'; function jscFunction() { - void name; const args = arguments; const thisObj = this === window ? context.globalObject : this; - const [thisPtr, thisId] = runtime.objects.allocate(thisObj); + const [thisPtr, thisId] = refs.allocate(thisObj); const ret = _malloc(Sizes.JSValue) as JSValue; if (cproto === JSCFunctionEnum.JS_CFUNC_generic) { const argc = args.length; - const [argv, argIds] = context.runtime.objects.batchAllocate(Array.from(args)); + const [argv, argIds] = refs.batchAllocate(Array.from(args)); unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); - argIds.forEach(runtime.objects.popId); + argIds.forEach(refs.popId); _free(argv); } else if (cproto === JSCFunctionEnum.JS_CFUNC_setter) { - const [val, valId] = context.runtime.objects.allocate(args[0]); + const [val, valId] = refs.allocate(args[0]); unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); - runtime.objects.popId(valId); + refs.popId(valId); _free(val); } else if (cproto === JSCFunctionEnum.JS_CFUNC_getter) { unityJsbState.dynCall('viii', func, [ret, ctx, thisPtr]); } else { - throw new Error('Unknown type of function specified: ' + cproto); + throw new Error(`Unknown type of function specified: name=${name} type=${cproto}`); } - runtime.objects.popId(thisId); + refs.popId(thisId); _free(thisPtr); - const returnValue = context.runtime.objects.get(ret); - context.runtime.objects.pop(ret); + const returnValue = refs.get(ret); + refs.pop(ret); _free(ret); return returnValue; - }; + } - context.runtime.objects.push(jscFunction, ret); + jscFunction['$$csharpFunctionName'] = name; + refs.push(jscFunction, ret); }, JSB_NewCFunctionMagic(ret, ctx, func, atom, length, cproto, magic) { const context = unityJsbState.getContext(ctx); - const runtime = context.runtime; + const refs = context.runtime.refs; const name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; function jscFunctionMagic() { - void name; const args = arguments; const thisObj = this === window ? context.globalObject : this; - const [thisPtr, thisId] = runtime.objects.allocate(thisObj); + const [thisPtr, thisId] = refs.allocate(thisObj); const ret = _malloc(Sizes.JSValue) as JSValue; if (cproto === JSCFunctionEnum.JS_CFUNC_generic_magic) { const argc = args.length; - const [argv, argIds] = context.runtime.objects.batchAllocate(Array.from(args)); + const [argv, argIds] = refs.batchAllocate(Array.from(args)); unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); - argIds.forEach(runtime.objects.popId); + argIds.forEach(refs.popId); _free(argv); } else if (cproto === JSCFunctionEnum.JS_CFUNC_constructor_magic) { const argc = args.length; - const [argv, argIds] = context.runtime.objects.batchAllocate(Array.from(args)); + const [argv, argIds] = refs.batchAllocate(Array.from(args)); unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); - argIds.forEach(runtime.objects.popId); + argIds.forEach(refs.popId); _free(argv); } else if (cproto === JSCFunctionEnum.JS_CFUNC_setter_magic) { - const [val, valId] = context.runtime.objects.allocate(args[0]); + const [val, valId] = refs.allocate(args[0]); unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); - runtime.objects.popId(valId); + refs.popId(valId); _free(val); } else if (cproto === JSCFunctionEnum.JS_CFUNC_getter_magic) { unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, magic]); } else { - throw new Error('Unknown type of function specified: ' + cproto); + throw new Error(`Unknown type of function specified: name=${name} type=${cproto}`); } - runtime.objects.popId(thisId); + refs.popId(thisId); _free(thisPtr); - const returnValue = context.runtime.objects.get(ret); - context.runtime.objects.pop(ret); + const returnValue = refs.get(ret); + refs.pop(ret); _free(ret); return returnValue; }; + jscFunctionMagic['$$csharpFunctionName'] = name; + refs.push(jscFunctionMagic, ret); - context.runtime.objects.push(jscFunctionMagic, ret); + if (cproto === JSCFunctionEnum.JS_CFUNC_constructor_magic) { + refs.setPayload(jscFunctionMagic, BridgeObjectType.TypeRef, magic); + } }, jsb_new_bridge_object(ret, ctx, proto, object_id) { const context = unityJsbState.getContext(ctx); - const protoVal = context.runtime.objects.get(proto); + const protoVal = context.runtime.refs.get(proto); const res = Object.create(protoVal); - context.runtime.objects.push(res, ret); - context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); + context.runtime.refs.push(res, ret); + context.runtime.refs.setPayload(res, BridgeObjectType.ObjectRef, object_id); }, jsb_new_bridge_value(ret, ctx, proto, size) { const context = unityJsbState.getContext(ctx); - const protoVal = context.runtime.objects.get(proto); + const protoVal = context.runtime.refs.get(proto); const res = Object.create(protoVal) as BridgeStruct; res.$$values = new Array(size).fill(0); - context.runtime.objects.push(res, ret); + context.runtime.refs.push(res, ret); }, JSB_NewBridgeClassObject(ret, ctx, new_target, object_id) { const context = unityJsbState.getContext(ctx); - const res = context.runtime.objects.get(new_target); + const res = context.runtime.refs.get(new_target); - context.runtime.objects.push(res, ret); - context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); + context.runtime.refs.push(res, ret); + context.runtime.refs.setPayload(res, BridgeObjectType.ObjectRef, object_id); }, JSB_NewBridgeClassValue(ret, ctx, new_target, size) { const context = unityJsbState.getContext(ctx); - const res = context.runtime.objects.get(new_target) as BridgeStruct; + const res = context.runtime.refs.get(new_target) as BridgeStruct; res.$$values = new Array(size).fill(0); - context.runtime.objects.push(res, ret); + context.runtime.refs.push(res, ret); }, JSB_GetBridgeClassID() { @@ -1206,20 +1221,20 @@ const UnityJSBPlugin: PluginType = { jsb_construct_bridge_object(ret, ctx, ctor, object_id) { const context = unityJsbState.getContext(ctx); - const ctorVal = context.runtime.objects.get(ctor); + const ctorVal = context.runtime.refs.get(ctor); const res = Reflect.construct(ctorVal, []); - context.runtime.objects.push(res, ret); - context.runtime.objects.setPayload(res, BridgeObjectType.ObjectRef, object_id); + context.runtime.refs.push(res, ret); + context.runtime.refs.setPayload(res, BridgeObjectType.ObjectRef, object_id); }, jsb_crossbind_constructor(ret, ctx, new_target) { const context = unityJsbState.getContext(ctx); - const target = context.runtime.objects.get(new_target); + const target = context.runtime.refs.get(new_target); // TODO: I have no idea const res = function () { return new target(); }; - context.runtime.objects.push(res, ret); + context.runtime.refs.push(res, ret); }, // #endregion @@ -1231,7 +1246,7 @@ const UnityJSBPlugin: PluginType = { const str = unityJsbState.stringify(buf as any, buf_len); const err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, @@ -1240,7 +1255,7 @@ const UnityJSBPlugin: PluginType = { const str = 'Type Error'; const err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, @@ -1249,7 +1264,7 @@ const UnityJSBPlugin: PluginType = { const str = 'Range Error'; const err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, @@ -1258,7 +1273,7 @@ const UnityJSBPlugin: PluginType = { const str = 'Internal Error'; const err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, @@ -1267,7 +1282,7 @@ const UnityJSBPlugin: PluginType = { const str = 'Reference Error'; const err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, @@ -1284,7 +1299,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_floats(ctx, val, n, v0) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = n / Sizes.Single; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1299,7 +1314,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_bytes(ctx, val, n, v0) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = n / Sizes.Single; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1314,7 +1329,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_byte_4(ctx, val, v0, v1, v2, v3) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1329,7 +1344,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_float_2(ctx, val, v0, v1) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1342,7 +1357,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_float_3(ctx, val, v0, v1, v2) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1356,7 +1371,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_float_4(ctx, val, v0, v1, v2, v3) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1371,7 +1386,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_int_1(ctx, val, v0) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 1; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1383,7 +1398,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_int_2(ctx, val, v0, v1) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1396,7 +1411,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_int_3(ctx, val, v0, v1, v2) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1410,7 +1425,7 @@ const UnityJSBPlugin: PluginType = { jsb_set_int_4(ctx, val, v0, v1, v2, v3) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1429,7 +1444,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_bytes(ctx, val, n, v0) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = n / Sizes.Single; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1444,7 +1459,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_floats(ctx, val, n, v0) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = n / Sizes.Single; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1459,7 +1474,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_byte_4(ctx, val, v0, v1, v2, v3) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1474,7 +1489,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_float_2(ctx, val, v0, v1) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1487,7 +1502,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_float_3(ctx, val, v0, v1, v2) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1501,7 +1516,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_float_4(ctx, val, v0, v1, v2, v3) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1516,7 +1531,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_int_1(ctx, val, v0) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 1; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1528,7 +1543,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_int_2(ctx, val, v0, v1) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1541,7 +1556,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_int_3(ctx, val, v0, v1, v2) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1555,7 +1570,7 @@ const UnityJSBPlugin: PluginType = { jsb_get_int_4(ctx, val, v0, v1, v2, v3) { const context = unityJsbState.getContext(ctx); - const obj = context.runtime.objects.get(val) as BridgeStruct; + const obj = context.runtime.refs.get(val) as BridgeStruct; const count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1574,7 +1589,7 @@ const UnityJSBPlugin: PluginType = { JS_ToFloat64(ctx, pres, val) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(val); + const value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { HEAPF64[pres >> 3] = Number(value); @@ -1586,7 +1601,7 @@ const UnityJSBPlugin: PluginType = { JS_ToInt32(ctx, pres, val) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(val); + const value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { HEAP32[pres >> 2] = Number(value); @@ -1598,7 +1613,7 @@ const UnityJSBPlugin: PluginType = { JS_ToInt64(ctx, pres, val) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(val); + const value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { unityJsbState.HEAP64()[pres >> 3] = BigInt(value); return false; @@ -1608,7 +1623,7 @@ const UnityJSBPlugin: PluginType = { JS_ToBigInt64(ctx, pres, val) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(val); + const value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { unityJsbState.HEAP64()[pres >> 3] = BigInt(value); return false; @@ -1618,7 +1633,7 @@ const UnityJSBPlugin: PluginType = { JS_ToIndex(ctx, pres, val) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(val); + const value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { unityJsbState.HEAPU64()[pres >> 3] = BigInt(value); return false; @@ -1628,7 +1643,7 @@ const UnityJSBPlugin: PluginType = { JSB_ToUint32(ctx, pres, val) { const context = unityJsbState.getContext(ctx); - const value = context.runtime.objects.get(val); + const value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { HEAPU32[pres >> 2] = Number(value); @@ -1639,7 +1654,7 @@ const UnityJSBPlugin: PluginType = { JS_ToBool(ctx, val) { const context = unityJsbState.getContext(ctx); - const objVal = context.runtime.objects.get(val); + const objVal = context.runtime.refs.get(val); return !!objVal; }, diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts index 7d22d12a..2916b351 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts @@ -11,9 +11,9 @@ declare global { contexts: Record; lastRuntimeId: number; lastContextId: number; - atoms?: PluginAtoms; - createObjects: () => PluginObjects; - createAtoms: () => PluginAtoms; + atoms?: AtomReferences; + createObjectReferences: () => ObjectReferences; + createAtoms: () => AtomReferences; getRuntime: (ctx: JSRuntime) => PluginRuntime; getContext: (ctx: JSContext) => PluginContext; @@ -26,7 +26,7 @@ declare global { id: number; opaque?: any; contexts: Record; - objects: PluginObjects; + refs: ObjectReferences; garbageCollect(): number; }; @@ -44,9 +44,8 @@ declare global { lastException?: Error; }; - export declare type PluginAtoms = { - record: Record; - map: Record; + export declare type AtomReferences = { + record: Record; get: ((ref: JSAtom) => string); lastId: number; push: ((str: string) => JSAtom); @@ -54,17 +53,17 @@ declare global { pop: ((ref: JSAtom) => void); }; - export declare type PluginAtom = { + export declare type AtomReference = { id: number; value: string; refCount: number; } - export declare type PluginObjects = { + export declare type ObjectReferences = { deleteRecord: (id: number) => void; - record: Record; + record: Record; get: ((ref: JSValue) => any); - getRecord: ((ref: JSValue) => PluginObject); + getRecord: ((ref: JSValue) => ObjectReference); push: ((obj: any, ptr: JSValue) => number | undefined); duplicate: ((obj: JSValue, ptr: JSValue) => void); duplicateId: ((id: number, ptr: JSValue) => void); @@ -75,19 +74,19 @@ declare global { batchGet: ((arr: PointerArray, count: number) => any[]); lastId: number; setPayload: ((obj: any, type: BridgeObjectType, payload: number) => void); - getPayload: ((obj: any) => PluginObjectPayload); + getPayload: ((obj: any) => ObjectReferencePayload); clearPayload: ((obj: any) => void); - payloadMap: Map; + payloadMap: Map; }; - export declare type PluginObject = { + export declare type ObjectReference = { id: number; refCount: number; tag: Tags; value: any; }; - export declare type PluginObjectPayload = { + export declare type ObjectReferencePayload = { type: BridgeObjectType; payload: number; }; diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib index 22534850..56c5a8da 100644 --- a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib @@ -1,11 +1,15 @@ /** * Build with the following command: * npx -p typescript tsc + * + * BEWARE: Using some syntaxes will make Emscripten fail while building + * Such known syntaxes: Object spread (...), BigInt literals + * The output is targeted for es5 as Emscripten only understands that syntax */ var UnityJSBPlugin = { $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', $unityJsbState: { - createObjects: function () { + createObjectReferences: function () { var getTag = function (object) { if (object === undefined) return 3 /* Tags.JS_TAG_UNDEFINED */; @@ -15,8 +19,6 @@ var UnityJSBPlugin = { return 7 /* Tags.JS_TAG_FLOAT64 */; if (typeof object === 'boolean') return 1 /* Tags.JS_TAG_BOOL */; - if (typeof object === 'function') - return -2 /* Tags.JS_TAG_FUNCTION_BYTECODE */; if (typeof object === 'symbol') return -8 /* Tags.JS_TAG_SYMBOL */; if (typeof object === 'string') @@ -230,7 +232,7 @@ var UnityJSBPlugin = { payloadMap: payloadMap, setPayload: function (obj, type, payload) { payloadMap.set(obj, { - type: 0 /* BridgeObjectType.None */ || type, + type: type, payload: payload, }); }, @@ -253,10 +255,9 @@ var UnityJSBPlugin = { }, createAtoms: function () { var record = {}; - var map = {}; + var map = new Map(); var res = { record: record, - map: map, lastId: 0, get: function (ref) { if (ref === 0) @@ -266,15 +267,16 @@ var UnityJSBPlugin = { push: function (str) { if (str === undefined) return 0; - var mapped = map[str]; + var mapped = map.get(str); var id; if (!mapped) { id = ++res.lastId; - map[str] = record[id] = { + var item = record[id] = { id: id, value: str, refCount: 1, }; + map.set(str, item); } else { id = mapped.id; @@ -302,7 +304,7 @@ var UnityJSBPlugin = { recorded.refCount--; console.assert(recorded.refCount >= 0); if (recorded.refCount == 0) { - delete map[recorded.value]; + map.delete(recorded.value); delete record[id]; } }, @@ -342,20 +344,20 @@ var UnityJSBPlugin = { JSB_NewRuntime: function (finalizer) { // TODO: understand what to do with finalizer var id = unityJsbState.lastRuntimeId++; - var objects = unityJsbState.createObjects(); + var refs = unityJsbState.createObjectReferences(); unityJsbState.runtimes[id] = { id: id, contexts: {}, - objects: objects, + refs: refs, garbageCollect: function () { - var lastId = objects.lastId; - var record = objects.record; + var lastId = refs.lastId; + var record = refs.record; var aliveItemCount = 0; for (var index = 0; index <= lastId; index++) { var element = record[index]; if (element) { if (element.refCount <= 0) { - objects.deleteRecord(index); + refs.deleteRecord(index); } else { aliveItemCount++; @@ -401,6 +403,7 @@ var UnityJSBPlugin = { var extraGlobals = { location: undefined, document: undefined, + addEventListener: undefined, btoa: (_a = window.btoa) === null || _a === void 0 ? void 0 : _a.bind(window), atob: (_b = window.atob) === null || _b === void 0 ? void 0 : _b.bind(window), $$webglWindow: window, @@ -457,10 +460,10 @@ var UnityJSBPlugin = { JS_GetGlobalObject: function (returnValue, ctxId) { var context = unityJsbState.getContext(ctxId); if (!context.globalObjectId) { - context.runtime.objects.push(context.globalObject, returnValue); + context.runtime.refs.push(context.globalObject, returnValue); } else { - context.runtime.objects.duplicateId(context.globalObjectId, returnValue); + context.runtime.refs.duplicateId(context.globalObjectId, returnValue); } }, JS_Eval: function (ptr, ctx, input, input_len, filename, eval_flags) { @@ -469,43 +472,43 @@ var UnityJSBPlugin = { var code = unityJsbState.stringify(input, input_len); var filenameStr = unityJsbState.stringify(filename); var res = context.evaluate(code, filenameStr); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); } catch (err) { context.lastException = err; - context.runtime.objects.push(err, ptr); + context.runtime.refs.push(err, ptr); console.error(err); } }, JS_IsInstanceOf: function (ctxId, val, obj) { var context = unityJsbState.getContext(ctxId); - var valVal = context.runtime.objects.get(val); - var ctorVal = context.runtime.objects.get(obj); + var valVal = context.runtime.refs.get(val); + var ctorVal = context.runtime.refs.get(obj); return !!(valVal instanceof ctorVal); }, JS_GetException: function (ptr, ctx) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.push(context.lastException, ptr); + context.runtime.refs.push(context.lastException, ptr); }, JSB_FreeValue: function (ctx, v) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.pop(v); + context.runtime.refs.pop(v); }, JSB_FreeValueRT: function (rt, v) { var runtime = unityJsbState.getRuntime(rt); - runtime.objects.pop(v); + runtime.refs.pop(v); }, JSB_FreePayload: function (ret, ctx, val) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); - var payload = context.runtime.objects.getPayload(obj); + var obj = context.runtime.refs.get(val); + var payload = context.runtime.refs.getPayload(obj); HEAP32[ret >> 2] = payload.type; HEAP32[(ret >> 2) + 1] = payload.payload; - context.runtime.objects.clearPayload(obj); + context.runtime.refs.clearPayload(obj); }, JSB_DupValue: function (ptr, ctx, v) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.duplicate(v, ptr); + context.runtime.refs.duplicate(v, ptr); }, JS_RunGC: function (rt) { var runtime = unityJsbState.getRuntime(rt); @@ -516,86 +519,93 @@ var UnityJSBPlugin = { }, JS_GetPropertyUint32: function (ptr, ctxId, val, index) { var context = unityJsbState.getContext(ctxId); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var res = obj[index]; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_GetPropertyInternal: function (ptr, ctxId, val, prop, receiver, throwRefError) { var context = unityJsbState.getContext(ctxId); - var valObj = context.runtime.objects.get(val); - var receiverObj = context.runtime.objects.get(receiver); + var valObj = context.runtime.refs.get(val); var propStr = unityJsbState.atoms.get(prop); var res = valObj[propStr]; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_GetPropertyStr: function (ptr, ctxId, val, prop) { var context = unityJsbState.getContext(ctxId); - var valObj = context.runtime.objects.get(val); + var valObj = context.runtime.refs.get(val); var propStr = unityJsbState.stringify(prop); var res = valObj[propStr]; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_Invoke: function (ptr, ctx, this_obj, prop, argc, argv) { var context = unityJsbState.getContext(ctx); var propVal = unityJsbState.atoms.get(prop); - var thisVal = context.runtime.objects.get(this_obj); + var thisVal = context.runtime.refs.get(this_obj); var func = thisVal[propVal]; - var args = context.runtime.objects.batchGet(argv, argc); + var args = context.runtime.refs.batchGet(argv, argc); var res; try { res = func.apply(thisVal, args); } catch (err) { + context.lastException = err; res = err; } - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_Call: function (ptr, ctx, func_obj, this_obj, argc, argv) { var context = unityJsbState.getContext(ctx); - var func = context.runtime.objects.get(func_obj); - var thisVal = context.runtime.objects.get(this_obj); - var args = context.runtime.objects.batchGet(argv, argc); + var func = context.runtime.refs.get(func_obj); + var thisVal = context.runtime.refs.get(this_obj); + var args = context.runtime.refs.batchGet(argv, argc); var res; try { res = func.apply(thisVal, args); } catch (err) { + context.lastException = err; res = err; } - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_CallConstructor: function (ptr, ctx, func_obj, argc, argv) { var context = unityJsbState.getContext(ctx); - var func = context.runtime.objects.get(func_obj); - var args = context.runtime.objects.batchGet(argv, argc); + var func = context.runtime.refs.get(func_obj); + var args = context.runtime.refs.batchGet(argv, argc); var res; try { res = Reflect.construct(func, args); } catch (err) { + context.lastException = err; res = err; } - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_SetConstructor: function (ctx, ctor, proto) { var context = unityJsbState.getContext(ctx); - var ctorVal = context.runtime.objects.get(ctor); - var protoVal = context.runtime.objects.get(proto); + var ctorVal = context.runtime.refs.get(ctor); + var protoVal = context.runtime.refs.get(proto); ctorVal.prototype = protoVal; + protoVal.constructor = ctorVal; + var ctorPayload = context.runtime.refs.getPayload(ctorVal); + if (ctorPayload.type === 1 /* BridgeObjectType.TypeRef */) { + context.runtime.refs.setPayload(protoVal, ctorPayload.type, ctorPayload.payload); + } }, JS_SetPrototype: function (ctx, obj, proto) { var context = unityJsbState.getContext(ctx); - var objVal = context.runtime.objects.get(obj); - var protoVal = context.runtime.objects.get(proto); + var objVal = context.runtime.refs.get(obj); + var protoVal = context.runtime.refs.get(proto); Reflect.setPrototypeOf(objVal, protoVal); return true; }, JS_DefineProperty: function (ctx, this_obj, prop, val, getter, setter, flags) { var context = unityJsbState.getContext(ctx); - var thisVal = context.runtime.objects.get(this_obj); - var getterVal = context.runtime.objects.get(getter); - var setterVal = context.runtime.objects.get(setter); - var valVal = context.runtime.objects.get(val); + var thisVal = context.runtime.refs.get(this_obj); + var getterVal = context.runtime.refs.get(getter); + var setterVal = context.runtime.refs.get(setter); + var valVal = context.runtime.refs.get(val); var propVal = unityJsbState.atoms.get(prop); var configurable = !!(flags & 1 /* JSPropFlags.JS_PROP_CONFIGURABLE */); var hasConfigurable = configurable || !!(flags & 256 /* JSPropFlags.JS_PROP_HAS_CONFIGURABLE */); @@ -633,8 +643,8 @@ var UnityJSBPlugin = { JS_DefinePropertyValue: function (ctx, this_obj, prop, val, flags) { var context = unityJsbState.getContext(ctx); var runtime = context.runtime; - var thisVal = runtime.objects.get(this_obj); - var valVal = runtime.objects.get(val); + var thisVal = runtime.refs.get(this_obj); + var valVal = runtime.refs.get(val); var propVal = unityJsbState.atoms.get(prop); var configurable = !!(flags & 1 /* JSPropFlags.JS_PROP_CONFIGURABLE */); var hasConfigurable = configurable || !!(flags & 256 /* JSPropFlags.JS_PROP_HAS_CONFIGURABLE */); @@ -644,7 +654,7 @@ var UnityJSBPlugin = { var hasWritable = writable || !!(flags & 512 /* JSPropFlags.JS_PROP_HAS_WRITABLE */); var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); // SetProperty frees the value automatically - runtime.objects.pop(val); + runtime.refs.pop(val); try { var opts = { value: valVal, @@ -669,7 +679,7 @@ var UnityJSBPlugin = { }, JS_HasProperty: function (ctx, this_obj, prop) { var context = unityJsbState.getContext(ctx); - var thisVal = context.runtime.objects.get(this_obj); + var thisVal = context.runtime.refs.get(this_obj); var propVal = unityJsbState.atoms.get(prop); var res = Reflect.has(thisVal, propVal); return !!res; @@ -677,11 +687,11 @@ var UnityJSBPlugin = { JS_SetPropertyInternal: function (ctx, this_obj, prop, val, flags) { var context = unityJsbState.getContext(ctx); var runtime = context.runtime; - var thisVal = runtime.objects.get(this_obj); - var valVal = runtime.objects.get(val); + var thisVal = runtime.refs.get(this_obj); + var valVal = runtime.refs.get(val); var propVal = unityJsbState.atoms.get(prop); // SetProperty frees the value automatically - runtime.objects.pop(val); + runtime.refs.pop(val); var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); try { thisVal[propVal] = valVal; @@ -699,11 +709,11 @@ var UnityJSBPlugin = { JS_SetPropertyUint32: function (ctx, this_obj, idx, val) { var context = unityJsbState.getContext(ctx); var runtime = context.runtime; - var thisVal = context.runtime.objects.get(this_obj); - var valVal = context.runtime.objects.get(val); + var thisVal = context.runtime.refs.get(this_obj); + var valVal = context.runtime.refs.get(val); var propVal = idx; // SetProperty frees the value automatically - runtime.objects.pop(val); + runtime.refs.pop(val); try { thisVal[propVal] = valVal; return true; @@ -715,14 +725,14 @@ var UnityJSBPlugin = { }, jsb_get_payload_header: function (ret, ctx, val) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); - var rec = context.runtime.objects.getPayload(obj); + var obj = context.runtime.refs.get(val); + var rec = context.runtime.refs.getPayload(obj); HEAP32[ret >> 2] = rec.type; HEAP32[(ret >> 2) + 1] = rec.payload; }, JS_ToCStringLen2: function (ctx, len, val, cesu8) { var context = unityJsbState.getContext(ctx); - var str = context.runtime.objects.get(val); + var str = context.runtime.refs.get(val); if (typeof str === 'undefined') { HEAP32[(len >> 2)] = 0; return 0; @@ -736,7 +746,7 @@ var UnityJSBPlugin = { }, JS_GetArrayBuffer: function (ctx, psize, obj) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(obj); + var value = context.runtime.refs.get(obj); if (value instanceof ArrayBuffer) { HEAP32[psize >> 2] = value.byteLength; return value; @@ -752,7 +762,7 @@ var UnityJSBPlugin = { JS_AtomToString: function (ptr, ctx, atom) { var context = unityJsbState.getContext(ctx); var str = unityJsbState.atoms.get(atom); - context.runtime.objects.push(str, ptr); + context.runtime.refs.push(str, ptr); }, JS_FreeAtom: function (ctx, v) { unityJsbState.atoms.pop(v); @@ -812,25 +822,25 @@ var UnityJSBPlugin = { // #region Is JS_IsArray: function (ctx, val) { var context = unityJsbState.getContext(ctx); - var valVal = context.runtime.objects.get(val); + var valVal = context.runtime.refs.get(val); var res = Array.isArray(valVal); return !!res; }, JS_IsConstructor: function (ctx, val) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var res = !!obj.prototype && !!obj.prototype.constructor.name; return !!res; }, JS_IsError: function (ctx, val) { var context = unityJsbState.getContext(ctx); - var valVal = context.runtime.objects.get(val); + var valVal = context.runtime.refs.get(val); var res = valVal instanceof Error; return !!res; }, JS_IsFunction: function (ctx, val) { var context = unityJsbState.getContext(ctx); - var valVal = context.runtime.objects.get(val); + var valVal = context.runtime.refs.get(val); var res = typeof valVal === 'function'; return !!res; }, @@ -839,21 +849,21 @@ var UnityJSBPlugin = { var context = unityJsbState.getContext(ctx); var str = unityJsbState.stringify(buf, buf_len); var res = JSON.parse(str); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_JSONStringify: function (ptr, ctx, obj, replacer, space) { var context = unityJsbState.getContext(ctx); - var objVal = context.runtime.objects.get(obj); - var rpVal = context.runtime.objects.get(replacer); - var spVal = context.runtime.objects.get(space); + var objVal = context.runtime.refs.get(obj); + var rpVal = context.runtime.refs.get(replacer); + var spVal = context.runtime.refs.get(space); var res = JSON.stringify(objVal, rpVal, spVal); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, // #region New JS_NewArray: function (ptr, ctx) { var context = unityJsbState.getContext(ctx); var res = []; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_NewArrayBufferCopy: function (ptr, ctx, buf, len) { var context = unityJsbState.getContext(ctx); @@ -861,148 +871,150 @@ var UnityJSBPlugin = { var res = new Uint8Array(HEAPU8.buffer, nptr, len); var existing = new Uint8Array(HEAPU8.buffer, buf, len); res.set(existing); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JSB_NewFloat64: function (ptr, ctx, d) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.push(d, ptr); + context.runtime.refs.push(d, ptr); }, JSB_NewInt64: function (ptr, ctx, d) { var context = unityJsbState.getContext(ctx); - context.runtime.objects.push(d, ptr); + context.runtime.refs.push(d, ptr); }, JS_NewObject: function (ptr, ctx) { var context = unityJsbState.getContext(ctx); var res = {}; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_NewString: function (ptr, ctx, str) { var context = unityJsbState.getContext(ctx); var res = unityJsbState.stringify(str); - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, JS_NewStringLen: function (ptr, ctx, str, len) { var context = unityJsbState.getContext(ctx); var val = unityJsbState.stringify(str, len); - context.runtime.objects.push(val, ptr); + context.runtime.refs.push(val, ptr); }, JSB_NewEmptyString: function (ptr, ctx) { var context = unityJsbState.getContext(ctx); var res = ""; - context.runtime.objects.push(res, ptr); + context.runtime.refs.push(res, ptr); }, // #endregion // #region Bridge JSB_NewCFunction: function (ret, ctx, func, atom, length, cproto, magic) { var context = unityJsbState.getContext(ctx); - var runtime = context.runtime; + var refs = context.runtime.refs; var name = unityJsbState.atoms.get(atom) || 'jscFunction'; function jscFunction() { - void name; var args = arguments; var thisObj = this === window ? context.globalObject : this; - var _a = runtime.objects.allocate(thisObj), thisPtr = _a[0], thisId = _a[1]; + var _a = refs.allocate(thisObj), thisPtr = _a[0], thisId = _a[1]; var ret = _malloc(16 /* Sizes.JSValue */); if (cproto === 0 /* JSCFunctionEnum.JS_CFUNC_generic */) { var argc = args.length; - var _b = context.runtime.objects.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; + var _b = refs.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); - argIds.forEach(runtime.objects.popId); + argIds.forEach(refs.popId); _free(argv); } else if (cproto === 9 /* JSCFunctionEnum.JS_CFUNC_setter */) { - var _c = context.runtime.objects.allocate(args[0]), val = _c[0], valId = _c[1]; + var _c = refs.allocate(args[0]), val = _c[0], valId = _c[1]; unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); - runtime.objects.popId(valId); + refs.popId(valId); _free(val); } else if (cproto === 8 /* JSCFunctionEnum.JS_CFUNC_getter */) { unityJsbState.dynCall('viii', func, [ret, ctx, thisPtr]); } else { - throw new Error('Unknown type of function specified: ' + cproto); + throw new Error("Unknown type of function specified: name=".concat(name, " type=").concat(cproto)); } - runtime.objects.popId(thisId); + refs.popId(thisId); _free(thisPtr); - var returnValue = context.runtime.objects.get(ret); - context.runtime.objects.pop(ret); + var returnValue = refs.get(ret); + refs.pop(ret); _free(ret); return returnValue; } - ; - context.runtime.objects.push(jscFunction, ret); + jscFunction['$$csharpFunctionName'] = name; + refs.push(jscFunction, ret); }, JSB_NewCFunctionMagic: function (ret, ctx, func, atom, length, cproto, magic) { var context = unityJsbState.getContext(ctx); - var runtime = context.runtime; + var refs = context.runtime.refs; var name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; function jscFunctionMagic() { - void name; var args = arguments; var thisObj = this === window ? context.globalObject : this; - var _a = runtime.objects.allocate(thisObj), thisPtr = _a[0], thisId = _a[1]; + var _a = refs.allocate(thisObj), thisPtr = _a[0], thisId = _a[1]; var ret = _malloc(16 /* Sizes.JSValue */); if (cproto === 1 /* JSCFunctionEnum.JS_CFUNC_generic_magic */) { var argc = args.length; - var _b = context.runtime.objects.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; + var _b = refs.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); - argIds.forEach(runtime.objects.popId); + argIds.forEach(refs.popId); _free(argv); } else if (cproto === 3 /* JSCFunctionEnum.JS_CFUNC_constructor_magic */) { var argc = args.length; - var _c = context.runtime.objects.batchAllocate(Array.from(args)), argv = _c[0], argIds = _c[1]; + var _c = refs.batchAllocate(Array.from(args)), argv = _c[0], argIds = _c[1]; unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); - argIds.forEach(runtime.objects.popId); + argIds.forEach(refs.popId); _free(argv); } else if (cproto === 11 /* JSCFunctionEnum.JS_CFUNC_setter_magic */) { - var _d = context.runtime.objects.allocate(args[0]), val = _d[0], valId = _d[1]; + var _d = refs.allocate(args[0]), val = _d[0], valId = _d[1]; unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); - runtime.objects.popId(valId); + refs.popId(valId); _free(val); } else if (cproto === 10 /* JSCFunctionEnum.JS_CFUNC_getter_magic */) { unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, magic]); } else { - throw new Error('Unknown type of function specified: ' + cproto); + throw new Error("Unknown type of function specified: name=".concat(name, " type=").concat(cproto)); } - runtime.objects.popId(thisId); + refs.popId(thisId); _free(thisPtr); - var returnValue = context.runtime.objects.get(ret); - context.runtime.objects.pop(ret); + var returnValue = refs.get(ret); + refs.pop(ret); _free(ret); return returnValue; } ; - context.runtime.objects.push(jscFunctionMagic, ret); + jscFunctionMagic['$$csharpFunctionName'] = name; + refs.push(jscFunctionMagic, ret); + if (cproto === 3 /* JSCFunctionEnum.JS_CFUNC_constructor_magic */) { + refs.setPayload(jscFunctionMagic, 1 /* BridgeObjectType.TypeRef */, magic); + } }, jsb_new_bridge_object: function (ret, ctx, proto, object_id) { var context = unityJsbState.getContext(ctx); - var protoVal = context.runtime.objects.get(proto); + var protoVal = context.runtime.refs.get(proto); var res = Object.create(protoVal); - context.runtime.objects.push(res, ret); - context.runtime.objects.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); + context.runtime.refs.push(res, ret); + context.runtime.refs.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); }, jsb_new_bridge_value: function (ret, ctx, proto, size) { var context = unityJsbState.getContext(ctx); - var protoVal = context.runtime.objects.get(proto); + var protoVal = context.runtime.refs.get(proto); var res = Object.create(protoVal); res.$$values = new Array(size).fill(0); - context.runtime.objects.push(res, ret); + context.runtime.refs.push(res, ret); }, JSB_NewBridgeClassObject: function (ret, ctx, new_target, object_id) { var context = unityJsbState.getContext(ctx); - var res = context.runtime.objects.get(new_target); - context.runtime.objects.push(res, ret); - context.runtime.objects.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); + var res = context.runtime.refs.get(new_target); + context.runtime.refs.push(res, ret); + context.runtime.refs.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); }, JSB_NewBridgeClassValue: function (ret, ctx, new_target, size) { var context = unityJsbState.getContext(ctx); - var res = context.runtime.objects.get(new_target); + var res = context.runtime.refs.get(new_target); res.$$values = new Array(size).fill(0); - context.runtime.objects.push(res, ret); + context.runtime.refs.push(res, ret); }, JSB_GetBridgeClassID: function () { // TODO: I have no idea @@ -1010,19 +1022,19 @@ var UnityJSBPlugin = { }, jsb_construct_bridge_object: function (ret, ctx, ctor, object_id) { var context = unityJsbState.getContext(ctx); - var ctorVal = context.runtime.objects.get(ctor); + var ctorVal = context.runtime.refs.get(ctor); var res = Reflect.construct(ctorVal, []); - context.runtime.objects.push(res, ret); - context.runtime.objects.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); + context.runtime.refs.push(res, ret); + context.runtime.refs.setPayload(res, 2 /* BridgeObjectType.ObjectRef */, object_id); }, jsb_crossbind_constructor: function (ret, ctx, new_target) { var context = unityJsbState.getContext(ctx); - var target = context.runtime.objects.get(new_target); + var target = context.runtime.refs.get(new_target); // TODO: I have no idea var res = function () { return new target(); }; - context.runtime.objects.push(res, ret); + context.runtime.refs.push(res, ret); }, // #endregion // #region Errors @@ -1031,7 +1043,7 @@ var UnityJSBPlugin = { var str = unityJsbState.stringify(buf, buf_len); var err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, JSB_ThrowTypeError: function (ret, ctx, msg) { @@ -1039,7 +1051,7 @@ var UnityJSBPlugin = { var str = 'Type Error'; var err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, JSB_ThrowRangeError: function (ret, ctx, msg) { @@ -1047,7 +1059,7 @@ var UnityJSBPlugin = { var str = 'Range Error'; var err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, JSB_ThrowInternalError: function (ret, ctx, msg) { @@ -1055,7 +1067,7 @@ var UnityJSBPlugin = { var str = 'Internal Error'; var err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, JSB_ThrowReferenceError: function (ret, ctx, msg) { @@ -1063,7 +1075,7 @@ var UnityJSBPlugin = { var str = 'Reference Error'; var err = new Error(str); console.error(err); - context.runtime.objects.push(err, ret); + context.runtime.refs.push(err, ret); // TODO: throw? }, // #endregion @@ -1076,7 +1088,7 @@ var UnityJSBPlugin = { }, jsb_set_floats: function (ctx, val, n, v0) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = n / 4 /* Sizes.Single */; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1088,7 +1100,7 @@ var UnityJSBPlugin = { }, jsb_set_bytes: function (ctx, val, n, v0) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = n / 4 /* Sizes.Single */; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1100,7 +1112,7 @@ var UnityJSBPlugin = { }, jsb_set_byte_4: function (ctx, val, v0, v1, v2, v3) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1112,7 +1124,7 @@ var UnityJSBPlugin = { }, jsb_set_float_2: function (ctx, val, v0, v1) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1122,7 +1134,7 @@ var UnityJSBPlugin = { }, jsb_set_float_3: function (ctx, val, v0, v1, v2) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1133,7 +1145,7 @@ var UnityJSBPlugin = { }, jsb_set_float_4: function (ctx, val, v0, v1, v2, v3) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1145,7 +1157,7 @@ var UnityJSBPlugin = { }, jsb_set_int_1: function (ctx, val, v0) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 1; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1154,7 +1166,7 @@ var UnityJSBPlugin = { }, jsb_set_int_2: function (ctx, val, v0, v1) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1164,7 +1176,7 @@ var UnityJSBPlugin = { }, jsb_set_int_3: function (ctx, val, v0, v1, v2) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1175,7 +1187,7 @@ var UnityJSBPlugin = { }, jsb_set_int_4: function (ctx, val, v0, v1, v2, v3) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1189,7 +1201,7 @@ var UnityJSBPlugin = { // #region Low Level Get jsb_get_bytes: function (ctx, val, n, v0) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = n / 4 /* Sizes.Single */; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1201,7 +1213,7 @@ var UnityJSBPlugin = { }, jsb_get_floats: function (ctx, val, n, v0) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = n / 4 /* Sizes.Single */; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1213,7 +1225,7 @@ var UnityJSBPlugin = { }, jsb_get_byte_4: function (ctx, val, v0, v1, v2, v3) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1225,7 +1237,7 @@ var UnityJSBPlugin = { }, jsb_get_float_2: function (ctx, val, v0, v1) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1235,7 +1247,7 @@ var UnityJSBPlugin = { }, jsb_get_float_3: function (ctx, val, v0, v1, v2) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1246,7 +1258,7 @@ var UnityJSBPlugin = { }, jsb_get_float_4: function (ctx, val, v0, v1, v2, v3) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1258,7 +1270,7 @@ var UnityJSBPlugin = { }, jsb_get_int_1: function (ctx, val, v0) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 1; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1267,7 +1279,7 @@ var UnityJSBPlugin = { }, jsb_get_int_2: function (ctx, val, v0, v1) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 2; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1277,7 +1289,7 @@ var UnityJSBPlugin = { }, jsb_get_int_3: function (ctx, val, v0, v1, v2) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 3; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1288,7 +1300,7 @@ var UnityJSBPlugin = { }, jsb_get_int_4: function (ctx, val, v0, v1, v2, v3) { var context = unityJsbState.getContext(ctx); - var obj = context.runtime.objects.get(val); + var obj = context.runtime.refs.get(val); var count = 4; if (!Array.isArray(obj.$$values) || count >= obj.$$values.length) return false; @@ -1302,7 +1314,7 @@ var UnityJSBPlugin = { // #region To JS_ToFloat64: function (ctx, pres, val) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(val); + var value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { HEAPF64[pres >> 3] = Number(value); return false; @@ -1311,7 +1323,7 @@ var UnityJSBPlugin = { }, JS_ToInt32: function (ctx, pres, val) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(val); + var value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { HEAP32[pres >> 2] = Number(value); return false; @@ -1320,7 +1332,7 @@ var UnityJSBPlugin = { }, JS_ToInt64: function (ctx, pres, val) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(val); + var value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { unityJsbState.HEAP64()[pres >> 3] = BigInt(value); return false; @@ -1329,7 +1341,7 @@ var UnityJSBPlugin = { }, JS_ToBigInt64: function (ctx, pres, val) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(val); + var value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { unityJsbState.HEAP64()[pres >> 3] = BigInt(value); return false; @@ -1338,7 +1350,7 @@ var UnityJSBPlugin = { }, JS_ToIndex: function (ctx, pres, val) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(val); + var value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { unityJsbState.HEAPU64()[pres >> 3] = BigInt(value); return false; @@ -1347,7 +1359,7 @@ var UnityJSBPlugin = { }, JSB_ToUint32: function (ctx, pres, val) { var context = unityJsbState.getContext(ctx); - var value = context.runtime.objects.get(val); + var value = context.runtime.refs.get(val); if (typeof value === 'number' || typeof value === 'bigint') { HEAPU32[pres >> 2] = Number(value); return false; @@ -1356,7 +1368,7 @@ var UnityJSBPlugin = { }, JS_ToBool: function (ctx, val) { var context = unityJsbState.getContext(ctx); - var objVal = context.runtime.objects.get(val); + var objVal = context.runtime.refs.get(val); return !!objVal; }, // #endregion