diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts new file mode 100644 index 00000000..e6a862d8 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/jsbplugin.ts @@ -0,0 +1,1732 @@ +/** + * 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 & { + $unityJsbState: typeof unityJsbState; + $unityJsbState__postset?: string; +} + +const UnityJSBPlugin: PluginType = { + $unityJsbState__postset: 'unityJsbState.atoms = unityJsbState.createAtoms();\n', + $unityJsbState: { + 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 === '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; + }; + + const record: ObjectReferences['record'] = {}; + + const map = new Map(); + + const payloadMap: ObjectReferences['payloadMap'] = new Map(); + + const res: ObjectReferences = { + record, + lastId: 0, + + allocate(object) { + const ptr = _malloc(Sizes.JSValue) as JSValue; + const id = res.push(object, ptr); + return [ptr as JSValue, id]; + }, + batchAllocate(objects) { + const size = Sizes.JSValue; + const len = objects.length; + const arr = _malloc(size * len) as PointerArray; + const ids = Array(len); + + for (let index = 0; index < len; index++) { + const object = objects[index]; + const id = res.push(object, arr + (index * size) as JSValue); + ids[index] = id; + } + + return [arr, ids]; + }, + batchGet(ptrs, count) { + const size = Sizes.JSValue; + + const 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.duplicateId(0, 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.duplicateId(foundId, ptr); + return foundId; + } + + const id = ++res.lastId; + + record[id] = { + id, + refCount: 0, + value: object, + tag: getTag(object), + }; + + map.set(object, id); + + res.duplicateId(id, ptr); + + return id; + }, + get(val) { + const 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 { + const id = HEAP32[val >> 2]; + if (id === 0) return undefined; + const ho = record[id]; + return ho.value; + } + }, + getRecord(val) { + const tag = Number(unityJsbState.HEAP64()[(val >> 3) + 1]); + + if (tag === Tags.JS_TAG_INT) { + const value = HEAP32[val >> 2]; + return { + id: -1, + refCount: 0, + value, + tag, + }; + } + else if (tag === Tags.JS_TAG_BOOL) { + const boolValue = !!HEAP32[val >> 2]; + return { + id: -1, + refCount: 0, + value: boolValue, + tag, + }; + } + else if (tag === Tags.JS_TAG_FLOAT64) { + const value = HEAPF64[val >> 3]; + return { + id: -1, + refCount: 0, + value, + tag, + }; + } + else { + const id = HEAP32[val >> 2]; + if (id === 0) return { + id: 0, + refCount: 0, + value: undefined, + tag: Tags.JS_TAG_UNDEFINED, + type: BridgeObjectType.None, + payload: -1, + }; + const ho = record[id]; + return ho; + } + }, + duplicate(obj, ptr) { + const tag = Number(unityJsbState.HEAP64()[(obj >> 3) + 1]); + + if (tag === Tags.JS_TAG_FLOAT64) { + if (typeof ptr === 'number') { + const 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') { + const 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') { + const valBool = !!HEAP32[(obj >> 2)]; + HEAP32[(ptr >> 2)] = valBool ? 1 : 0; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(tag); + } + return; + } + + const id = HEAP32[obj >> 2]; + res.duplicateId(id, ptr); + }, + duplicateId(id, 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; + } + + const ho = record[id]; + + ho.refCount += 1; + + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = id; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(ho.tag); + } + }, + 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); + }, + payloadMap, + setPayload(obj, type, payload) { + payloadMap.set(obj, { + type, + payload, + }); + }, + getPayload(obj) { + const res = payloadMap.get(obj); + + if (res) return res; + else { + return { + type: BridgeObjectType.None, + payload: 0, + }; + } + }, + clearPayload(obj) { + payloadMap.delete(obj); + }, + }; + + return res; + }, + createAtoms(): AtomReferences { + const record: AtomReferences['record'] = {}; + const map = new Map(); + + const res: AtomReferences = { + record, + lastId: 0, + get(ref) { + if (ref === 0) return undefined; + return record[ref].value; + }, + push(str) { + if (str === undefined) return 0; + const mapped = map.get(str); + let id; + + if (!mapped) { + id = ++res.lastId; + const item = record[id] = { + id, + value: str, + refCount: 1, + }; + map.set(str, item); + } else { + id = mapped.id; + mapped.refCount++; + } + + return id; + }, + pushId(id) { + if (id === 0) return; + + const recorded = record[id]; + console.assert(!!recorded); + if (!recorded) return 0; + recorded.refCount++; + + return id; + }, + pop(id) { + if (id === 0) return; + + const recorded = record[id]; + console.assert(!!recorded); + if (!recorded) return; + + recorded.refCount--; + console.assert(recorded.refCount >= 0); + + if (recorded.refCount == 0) { + map.delete(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) { + const bufferSize = lengthBytesUTF8(arg) + 1; + const 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) { + const rtId = rt; + return unityJsbState.runtimes[rtId]; + }, + getContext: function (ctx) { + const 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 + + const id = unityJsbState.lastRuntimeId++; + const refs = unityJsbState.createObjectReferences(); + + unityJsbState.runtimes[id] = { + id, + contexts: {}, + refs, + garbageCollect() { + const lastId = refs.lastId; + const record = refs.record; + + let aliveItemCount = 0; + + for (let index = 0; index <= lastId; index++) { + const element = record[index]; + + if (element) { + if (element.refCount <= 0) { + refs.deleteRecord(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) { + const runtime = unityJsbState.getRuntime(rtId); + const 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) { + const context = unityJsbState.getContext(ctxId); + return context.runtimeId; + }, + + JS_NewContext(rtId) { + const id = unityJsbState.lastContextId++; + const runtime = unityJsbState.getRuntime(rtId); + + const extraGlobals: any = { + location: undefined, + document: undefined, + addEventListener: undefined, + btoa: window.btoa?.bind(window), + atob: window.atob?.bind(window), + $$webglWindow: window, + }; + + const 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; + + const evaluate = function (code: string, filename?: string) { + const sourceMap = !filename ? '' : '\n//# sourceURL=unity-jsb:///' + filename; + + return (function (evalCode) { + //@ts-ignore + with (globals) { + return eval(evalCode); + } + }).call(globals, code + sourceMap); + }; + + + const context: PluginContext = { + id, + runtime, + runtimeId: rtId, + window, + globalObject: globals, + evaluate, + }; + + runtime.contexts[id] = context; + unityJsbState.contexts[id] = context; + return id; + }, + + JS_FreeContext(ctxId) { + 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) { + const context = unityJsbState.getContext(ctxId); + + if (!context.globalObjectId) { + context.runtime.refs.push(context.globalObject, returnValue); + } + else { + context.runtime.refs.duplicateId(context.globalObjectId, returnValue); + } + }, + + JS_Eval(ptr, ctx, input, input_len, filename, eval_flags) { + const context = unityJsbState.getContext(ctx); + try { + const code = unityJsbState.stringify(input, input_len); + const filenameStr = unityJsbState.stringify(filename); + + const res = context.evaluate(code, filenameStr); + + context.runtime.refs.push(res, ptr); + } catch (err) { + context.lastException = err; + context.runtime.refs.push(err, ptr); + console.error(err); + } + }, + + JS_IsInstanceOf(ctxId, val, obj) { + const context = unityJsbState.getContext(ctxId); + 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.refs.push(context.lastException, ptr); + }, + + JSB_FreeValue(ctx, v) { + const context = unityJsbState.getContext(ctx); + context.runtime.refs.pop(v); + }, + + JSB_FreeValueRT(rt, v) { + const runtime = unityJsbState.getRuntime(rt); + runtime.refs.pop(v); + }, + + JSB_FreePayload(ret, ctx, val) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.get(val); + + const payload = context.runtime.refs.getPayload(obj); + HEAP32[ret >> 2] = payload.type; + HEAP32[(ret >> 2) + 1] = payload.payload; + + context.runtime.refs.clearPayload(obj); + }, + + JSB_DupValue(ptr, ctx, v) { + const context = unityJsbState.getContext(ctx); + context.runtime.refs.duplicate(v, ptr); + }, + + JS_RunGC(rt) { + const 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) { + const context = unityJsbState.getContext(ctxId); + const obj = context.runtime.refs.get(val); + const res = obj[index]; + + context.runtime.refs.push(res, ptr); + }, + + JS_GetPropertyInternal(ptr, ctxId, val, prop, receiver, throwRefError) { + const context = unityJsbState.getContext(ctxId); + const valObj = context.runtime.refs.get(val); + const propStr = unityJsbState.atoms.get(prop); + const res = valObj[propStr]; + + context.runtime.refs.push(res, ptr); + }, + + JS_GetPropertyStr(ptr, ctxId, val, prop) { + const context = unityJsbState.getContext(ctxId); + const valObj = context.runtime.refs.get(val); + const propStr = unityJsbState.stringify(prop); + const res = valObj[propStr]; + + 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.refs.get(this_obj); + const func = thisVal[propVal]; + + 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.refs.push(res, ptr); + }, + + JS_Call(ptr, ctx, func_obj, this_obj, argc, argv) { + const context = unityJsbState.getContext(ctx); + const func = context.runtime.refs.get(func_obj); + const thisVal = context.runtime.refs.get(this_obj); + + 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.refs.push(res, ptr); + }, + + JS_CallConstructor(ptr, ctx, func_obj, argc, argv) { + const context = unityJsbState.getContext(ctx); + const func = context.runtime.refs.get(func_obj); + + 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.refs.push(res, ptr); + }, + + JS_SetConstructor(ctx, ctor, proto) { + const context = unityJsbState.getContext(ctx); + 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.refs.get(obj); + const protoVal = context.runtime.refs.get(proto); + Reflect.setPrototypeOf(objVal, protoVal); + + return true; + }, + + JS_DefineProperty(ctx, this_obj, prop, val, getter, setter, flags) { + const context = unityJsbState.getContext(ctx); + + 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); + 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) { + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; + + 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); + 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); + + // SetProperty frees the value automatically + runtime.refs.pop(val); + + 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) { + const context = unityJsbState.getContext(ctx); + const thisVal = context.runtime.refs.get(this_obj); + const propVal = unityJsbState.atoms.get(prop); + + const res = Reflect.has(thisVal, propVal); + + return !!res; + }, + + JS_SetPropertyInternal(ctx, this_obj, prop, val, flags) { + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; + + 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.refs.pop(val); + + const shouldThrow = !!(flags & JSPropFlags.JS_PROP_THROW) || !!(flags & JSPropFlags.JS_PROP_THROW_STRICT); + + try { + 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) { + const context = unityJsbState.getContext(ctx); + const runtime = context.runtime; + + const thisVal = context.runtime.refs.get(this_obj); + const valVal = context.runtime.refs.get(val); + const propVal = idx; + + // SetProperty frees the value automatically + runtime.refs.pop(val); + + try { + thisVal[propVal] = valVal; + return true; + } catch (err) { + context.lastException = err; + } + + return false; + }, + + jsb_get_payload_header(ret, ctx, val) { + + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.get(val); + + const rec = context.runtime.refs.getPayload(obj); + + HEAP32[ret >> 2] = rec.type; + HEAP32[(ret >> 2) + 1] = rec.payload; + }, + + JS_ToCStringLen2(ctx, len, val, cesu8) { + const context = unityJsbState.getContext(ctx); + + const str = context.runtime.refs.get(val); + + + if (typeof str === 'undefined') { + HEAP32[(len >> 2)] = 0; + return 0 as IntPtr; + } + + const [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.refs.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) { + const context = unityJsbState.getContext(ctx); + const val = unityJsbState.stringify(str, len); + + return unityJsbState.atoms.push(val); + }, + + JS_AtomToString(ptr, ctx, atom) { + const context = unityJsbState.getContext(ctx); + + const str = unityJsbState.atoms.get(atom); + + context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + 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.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.refs.get(val); + const res = valVal instanceof Error; + return !!res; + }, + + JS_IsFunction(ctx, val) { + const context = unityJsbState.getContext(ctx); + const valVal = context.runtime.refs.get(val); + const res = typeof valVal === 'function'; + return !!res; + }, + + // #endregion + + JS_ParseJSON(ptr, ctx, buf, buf_len, filename) { + const context = unityJsbState.getContext(ctx); + const str = unityJsbState.stringify(buf as any, buf_len); + const res = JSON.parse(str); + context.runtime.refs.push(res, ptr); + }, + + JS_JSONStringify(ptr, ctx, obj, replacer, space) { + const context = unityJsbState.getContext(ctx); + 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.refs.push(res, ptr); + }, + + // #region New + + JS_NewArray(ptr, ctx) { + const context = unityJsbState.getContext(ctx); + const res = []; + context.runtime.refs.push(res, ptr); + }, + + JS_NewArrayBufferCopy(ptr, ctx, buf, len) { + const context = unityJsbState.getContext(ctx); + + 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.refs.push(res, ptr); + }, + + JSB_NewFloat64(ptr, ctx, d) { + const context = unityJsbState.getContext(ctx); + context.runtime.refs.push(d, ptr); + }, + + JSB_NewInt64(ptr, ctx, d) { + const context = unityJsbState.getContext(ctx); + context.runtime.refs.push(d, ptr); + }, + + JS_NewObject(ptr, ctx) { + const context = unityJsbState.getContext(ctx); + const res = {}; + context.runtime.refs.push(res, ptr); + }, + + JS_NewString(ptr, ctx, str) { + const context = unityJsbState.getContext(ctx); + const res = unityJsbState.stringify(str); + context.runtime.refs.push(res, ptr); + }, + + JS_NewStringLen(ptr, ctx, str, len) { + const context = unityJsbState.getContext(ctx); + + const val = unityJsbState.stringify(str as any, len); + + context.runtime.refs.push(val, ptr); + }, + + JSB_NewEmptyString(ptr, ctx) { + const context = unityJsbState.getContext(ctx); + const res = ""; + context.runtime.refs.push(res, ptr); + }, + + // #endregion + + // #region Bridge + + JSB_NewCFunction(ret, ctx, func, atom, length, cproto, magic) { + const context = unityJsbState.getContext(ctx); + const refs = context.runtime.refs; + + const name = unityJsbState.atoms.get(atom) || 'jscFunction'; + + function jscFunction() { + const args = arguments; + + const thisObj = this === window ? context.globalObject : this; + 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] = refs.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); + argIds.forEach(refs.popId); + _free(argv); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_setter) { + const [val, valId] = refs.allocate(args[0]); + unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); + 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: name=${name} type=${cproto}`); + } + refs.popId(thisId); + _free(thisPtr); + + const returnValue = refs.get(ret); + refs.pop(ret); + _free(ret); + return returnValue; + } + + jscFunction['$$csharpFunctionName'] = name; + refs.push(jscFunction, ret); + }, + + JSB_NewCFunctionMagic(ret, ctx, func, atom, length, cproto, magic) { + const context = unityJsbState.getContext(ctx); + const refs = context.runtime.refs; + + const name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; + + function jscFunctionMagic() { + const args = arguments; + + const thisObj = this === window ? context.globalObject : this; + 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] = refs.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(refs.popId); + _free(argv); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_constructor_magic) { + const argc = args.length; + const [argv, argIds] = refs.batchAllocate(Array.from(args)); + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(refs.popId); + _free(argv); + } + else if (cproto === JSCFunctionEnum.JS_CFUNC_setter_magic) { + const [val, valId] = refs.allocate(args[0]); + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); + 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: name=${name} type=${cproto}`); + } + refs.popId(thisId); + _free(thisPtr); + + const returnValue = refs.get(ret); + refs.pop(ret); + _free(ret); + return returnValue; + }; + jscFunctionMagic['$$csharpFunctionName'] = name; + refs.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.refs.get(proto); + const res = Object.create(protoVal); + 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.refs.get(proto); + const res = Object.create(protoVal) as BridgeStruct; + res.$$values = new Array(size).fill(0); + context.runtime.refs.push(res, ret); + }, + + JSB_NewBridgeClassObject(ret, ctx, new_target, object_id) { + const context = unityJsbState.getContext(ctx); + const res = context.runtime.refs.get(new_target); + + 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.refs.get(new_target) as BridgeStruct; + res.$$values = new Array(size).fill(0); + context.runtime.refs.push(res, ret); + }, + + JSB_GetBridgeClassID() { + // TODO: I have no idea + return 0; + }, + + jsb_construct_bridge_object(ret, ctx, ctor, object_id) { + const context = unityJsbState.getContext(ctx); + const ctorVal = context.runtime.refs.get(ctor); + const res = Reflect.construct(ctorVal, []); + 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.refs.get(new_target); + // TODO: I have no idea + const res = function () { + return new target(); + }; + context.runtime.refs.push(res, ret); + }, + + // #endregion + + // #region Errors + + JSB_ThrowError(ret, ctx, buf, buf_len) { + const context = unityJsbState.getContext(ctx); + const str = unityJsbState.stringify(buf as any, buf_len); + const err = new Error(str); + console.error(err); + context.runtime.refs.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowTypeError(ret, ctx, msg) { + const context = unityJsbState.getContext(ctx); + const str = 'Type Error'; + const err = new Error(str); + console.error(err); + context.runtime.refs.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowRangeError(ret, ctx, msg) { + const context = unityJsbState.getContext(ctx); + const str = 'Range Error'; + const err = new Error(str); + console.error(err); + context.runtime.refs.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowInternalError(ret, ctx, msg) { + const context = unityJsbState.getContext(ctx); + const str = 'Internal Error'; + const err = new Error(str); + console.error(err); + context.runtime.refs.push(err, ret); + // TODO: throw? + }, + + JSB_ThrowReferenceError(ret, ctx, msg) { + const context = unityJsbState.getContext(ctx); + const str = 'Reference Error'; + const err = new Error(str); + console.error(err); + context.runtime.refs.push(err, ret); + // TODO: throw? + }, + + // #endregion + + // #region Low level Set + + js_strndup(ctx, s, n) { + const buffer = _malloc(n + 1); + _memcpy(buffer, s, n); + HEAPU8[buffer + n] = 0; + return buffer as IntPtr; + }, + + jsb_set_floats(ctx, val, n, v0) { + const context = unityJsbState.getContext(ctx); + 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; + + 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) { + const context = unityJsbState.getContext(ctx); + 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; + + 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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + 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; + + 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) { + const context = unityJsbState.getContext(ctx); + 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; + + 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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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) { + const context = unityJsbState.getContext(ctx); + const obj = context.runtime.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.get(val); + + if (typeof value === 'number' || typeof value === 'bigint') { + HEAPU32[pres >> 2] = Number(value); + return false; + } + return -1; + }, + + JS_ToBool(ctx, val) { + const context = unityJsbState.getContext(ctx); + const objVal = context.runtime.refs.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(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 new file mode 100644 index 00000000..43259186 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/tsconfig.json @@ -0,0 +1,44 @@ +{ + "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": "../jsbplugin.jslib", + "noImplicitAny": false, + "strict": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "removeComments": false, + "noImplicitUseStrict": true, + "noUncheckedIndexedAccess": false, + "suppressExcessPropertyErrors": true, + "suppressImplicitAnyIndexErrors": true, + "noPropertyAccessFromIndexSignature": false, + "strictNullChecks": false + }, + "files": [ + "jsbplugin.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/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..2916b351 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/.source/typings/plugin.d.ts @@ -0,0 +1,222 @@ +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?: AtomReferences; + createObjectReferences: () => ObjectReferences; + createAtoms: () => AtomReferences; + + getRuntime: (ctx: JSRuntime) => PluginRuntime; + getContext: (ctx: JSContext) => PluginContext; + + HEAP64: () => BigInt64Array; + HEAPU64: () => BigUint64Array; + } + + export declare type PluginRuntime = { + id: number; + opaque?: any; + contexts: Record; + refs: ObjectReferences; + 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 AtomReferences = { + record: Record; + get: ((ref: JSAtom) => string); + lastId: number; + push: ((str: string) => JSAtom); + pushId: ((id: JSAtom) => JSAtom); + pop: ((ref: JSAtom) => void); + }; + + export declare type AtomReference = { + id: number; + value: string; + refCount: number; + } + + export declare type ObjectReferences = { + deleteRecord: (id: number) => void; + record: Record; + get: ((ref: JSValue) => any); + getRecord: ((ref: JSValue) => ObjectReference); + 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[]); + lastId: number; + setPayload: ((obj: any, type: BridgeObjectType, payload: number) => void); + getPayload: ((obj: any) => ObjectReferencePayload); + clearPayload: ((obj: any) => void); + payloadMap: Map; + }; + + export declare type ObjectReference = { + id: number; + refCount: number; + tag: Tags; + value: any; + }; + + export declare type ObjectReferencePayload = { + 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/jsbplugin.jslib b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib new file mode 100644 index 00000000..56c5a8da --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib @@ -0,0 +1,1426 @@ +/** + * 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: { + createObjectReferences: 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 === '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 */); + var id = res.push(object, ptr); + return [ptr, id]; + }, + batchAllocate: function (objects) { + var size = 16 /* Sizes.JSValue */; + var len = objects.length; + var arr = _malloc(size * len); + var ids = Array(len); + for (var index = 0; index < len; index++) { + var object = objects[index]; + var id = res.push(object, arr + (index * size)); + ids[index] = id; + } + return [arr, ids]; + }, + 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.duplicateId(0, 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.duplicateId(foundId, ptr); + return foundId; + } + var id = ++res.lastId; + record[id] = { + id: id, + refCount: 0, + value: object, + tag: getTag(object), + }; + map.set(object, id); + res.duplicateId(id, 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; + } + }, + duplicate: function (obj, 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.duplicateId(id, ptr); + }, + duplicateId: function (id, 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 += 1; + if (typeof ptr === 'number') { + HEAP32[ptr >> 2] = id; + HEAP32[(ptr >> 2) + 1] = 0; + unityJsbState.HEAP64()[(ptr >> 3) + 1] = BigInt(ho.tag); + } + }, + 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); + }, + payloadMap: payloadMap, + setPayload: function (obj, type, payload) { + payloadMap.set(obj, { + type: 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 = new Map(); + var res = { + record: record, + 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.get(str); + var id; + if (!mapped) { + id = ++res.lastId; + var item = record[id] = { + id: id, + value: str, + refCount: 1, + }; + map.set(str, item); + } + 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) { + map.delete(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 refs = unityJsbState.createObjectReferences(); + unityJsbState.runtimes[id] = { + id: id, + contexts: {}, + refs: refs, + garbageCollect: function () { + 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) { + refs.deleteRecord(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, + 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, + }; + 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.refs.push(context.globalObject, returnValue); + } + else { + context.runtime.refs.duplicateId(context.globalObjectId, returnValue); + } + }, + JS_Eval: function (ptr, ctx, input, input_len, filename, eval_flags) { + var context = unityJsbState.getContext(ctx); + try { + var code = unityJsbState.stringify(input, input_len); + var filenameStr = unityJsbState.stringify(filename); + var res = context.evaluate(code, filenameStr); + context.runtime.refs.push(res, ptr); + } + catch (err) { + context.lastException = err; + context.runtime.refs.push(err, ptr); + console.error(err); + } + }, + JS_IsInstanceOf: function (ctxId, val, obj) { + var context = unityJsbState.getContext(ctxId); + 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.refs.push(context.lastException, ptr); + }, + JSB_FreeValue: function (ctx, v) { + var context = unityJsbState.getContext(ctx); + context.runtime.refs.pop(v); + }, + JSB_FreeValueRT: function (rt, v) { + var runtime = unityJsbState.getRuntime(rt); + runtime.refs.pop(v); + }, + JSB_FreePayload: function (ret, ctx, val) { + var context = unityJsbState.getContext(ctx); + 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.refs.clearPayload(obj); + }, + JSB_DupValue: function (ptr, ctx, v) { + var context = unityJsbState.getContext(ctx); + context.runtime.refs.duplicate(v, 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.refs.get(val); + var res = obj[index]; + context.runtime.refs.push(res, ptr); + }, + JS_GetPropertyInternal: function (ptr, ctxId, val, prop, receiver, throwRefError) { + var context = unityJsbState.getContext(ctxId); + var valObj = context.runtime.refs.get(val); + var propStr = unityJsbState.atoms.get(prop); + var res = valObj[propStr]; + context.runtime.refs.push(res, ptr); + }, + JS_GetPropertyStr: function (ptr, ctxId, val, prop) { + var context = unityJsbState.getContext(ctxId); + var valObj = context.runtime.refs.get(val); + var propStr = unityJsbState.stringify(prop); + var res = valObj[propStr]; + 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.refs.get(this_obj); + var func = thisVal[propVal]; + 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.refs.push(res, ptr); + }, + JS_Call: function (ptr, ctx, func_obj, this_obj, argc, argv) { + var context = unityJsbState.getContext(ctx); + 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.refs.push(res, ptr); + }, + JS_CallConstructor: function (ptr, ctx, func_obj, argc, argv) { + var context = unityJsbState.getContext(ctx); + 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.refs.push(res, ptr); + }, + JS_SetConstructor: function (ctx, ctor, proto) { + var context = unityJsbState.getContext(ctx); + 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.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.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 */); + 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 runtime = context.runtime; + 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 */); + 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 */); + // SetProperty frees the value automatically + runtime.refs.pop(val); + 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.refs.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 runtime = context.runtime; + 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.refs.pop(val); + var shouldThrow = !!(flags & 16384 /* JSPropFlags.JS_PROP_THROW */) || !!(flags & 32768 /* JSPropFlags.JS_PROP_THROW_STRICT */); + try { + 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 runtime = context.runtime; + var thisVal = context.runtime.refs.get(this_obj); + var valVal = context.runtime.refs.get(val); + var propVal = idx; + // SetProperty frees the value automatically + runtime.refs.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); + 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.refs.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.refs.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.refs.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.refs.get(val); + var res = Array.isArray(valVal); + return !!res; + }, + JS_IsConstructor: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + 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.refs.get(val); + var res = valVal instanceof Error; + return !!res; + }, + JS_IsFunction: function (ctx, val) { + var context = unityJsbState.getContext(ctx); + var valVal = context.runtime.refs.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.refs.push(res, ptr); + }, + JS_JSONStringify: function (ptr, ctx, obj, replacer, space) { + var context = unityJsbState.getContext(ctx); + 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.refs.push(res, ptr); + }, + // #region New + JS_NewArray: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = []; + context.runtime.refs.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.refs.push(res, ptr); + }, + JSB_NewFloat64: function (ptr, ctx, d) { + var context = unityJsbState.getContext(ctx); + context.runtime.refs.push(d, ptr); + }, + JSB_NewInt64: function (ptr, ctx, d) { + var context = unityJsbState.getContext(ctx); + context.runtime.refs.push(d, ptr); + }, + JS_NewObject: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = {}; + context.runtime.refs.push(res, ptr); + }, + JS_NewString: function (ptr, ctx, str) { + var context = unityJsbState.getContext(ctx); + var res = unityJsbState.stringify(str); + 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.refs.push(val, ptr); + }, + JSB_NewEmptyString: function (ptr, ctx) { + var context = unityJsbState.getContext(ctx); + var res = ""; + 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 refs = context.runtime.refs; + var name = unityJsbState.atoms.get(atom) || 'jscFunction'; + function jscFunction() { + var args = arguments; + var thisObj = this === window ? context.globalObject : this; + 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 = refs.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, argc, argv]); + argIds.forEach(refs.popId); + _free(argv); + } + else if (cproto === 9 /* JSCFunctionEnum.JS_CFUNC_setter */) { + var _c = refs.allocate(args[0]), val = _c[0], valId = _c[1]; + unityJsbState.dynCall('viiii', func, [ret, ctx, thisPtr, val]); + 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: name=".concat(name, " type=").concat(cproto)); + } + refs.popId(thisId); + _free(thisPtr); + var returnValue = refs.get(ret); + refs.pop(ret); + _free(ret); + return returnValue; + } + jscFunction['$$csharpFunctionName'] = name; + refs.push(jscFunction, ret); + }, + JSB_NewCFunctionMagic: function (ret, ctx, func, atom, length, cproto, magic) { + var context = unityJsbState.getContext(ctx); + var refs = context.runtime.refs; + var name = unityJsbState.atoms.get(atom) || 'jscFunctionMagic'; + function jscFunctionMagic() { + var args = arguments; + var thisObj = this === window ? context.globalObject : this; + 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 = refs.batchAllocate(Array.from(args)), argv = _b[0], argIds = _b[1]; + unityJsbState.dynCall('viiiiii', func, [ret, ctx, thisPtr, argc, argv, magic]); + argIds.forEach(refs.popId); + _free(argv); + } + else if (cproto === 3 /* JSCFunctionEnum.JS_CFUNC_constructor_magic */) { + var argc = args.length; + 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(refs.popId); + _free(argv); + } + else if (cproto === 11 /* JSCFunctionEnum.JS_CFUNC_setter_magic */) { + var _d = refs.allocate(args[0]), val = _d[0], valId = _d[1]; + unityJsbState.dynCall('viiiii', func, [ret, ctx, thisPtr, val, magic]); + 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: name=".concat(name, " type=").concat(cproto)); + } + refs.popId(thisId); + _free(thisPtr); + var returnValue = refs.get(ret); + refs.pop(ret); + _free(ret); + return returnValue; + } + ; + 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.refs.get(proto); + var res = Object.create(protoVal); + 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.refs.get(proto); + var res = Object.create(protoVal); + res.$$values = new Array(size).fill(0); + context.runtime.refs.push(res, ret); + }, + JSB_NewBridgeClassObject: function (ret, ctx, new_target, object_id) { + var context = unityJsbState.getContext(ctx); + 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.refs.get(new_target); + res.$$values = new Array(size).fill(0); + context.runtime.refs.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.refs.get(ctor); + var res = Reflect.construct(ctorVal, []); + 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.refs.get(new_target); + // TODO: I have no idea + var res = function () { + return new target(); + }; + context.runtime.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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.refs.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(UnityJSBPlugin, '$unityJsbState'); +mergeInto(LibraryManager.library, UnityJSBPlugin); diff --git a/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib.meta b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.jslib.meta new file mode 100644 index 00000000..e53b9600 --- /dev/null +++ b/Packages/cc.starlessnight.unity-jsb/Plugins/WebGL/jsbplugin.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: 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: