1/* 2 * Copyright (c) 2022-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { KPointer } from "../../interop/InteropTypes" 17import { CallbackRegistry } from "../../interop/Platform" 18 19class CallbackInfo { 20 cb: any 21 recv: any 22 constructor(callback: any, obj: any = null) { 23 this.cb = callback 24 this.recv = obj 25 } 26} 27 28const GLOBAL_SCOPE = new class CallbackScope { 29 static readonly CB_NULL = new CallbackInfo( 30 () => { throw new Error("attempted to call a callback at NULL") }, 31 null 32 ) 33 static readonly CB_UNDEFINED = new CallbackInfo( 34 () => { throw new Error("attempted to call an uninitialized callback") }, 35 null 36 ) 37 static readonly CB_NULL_ID = 0 38 nextId: number 39 callbackMap: Map<number, CallbackInfo> | null 40 41 constructor() { 42 this.nextId = 1 43 this.callbackMap = new Map() 44 this.callbackMap.set(CallbackScope.CB_NULL_ID, CallbackScope.CB_NULL) 45 } 46 47 addCallback(cb: any, obj: any): number { 48 let id = this.nextId++ 49 this.callbackMap?.set(id, new CallbackInfo(cb, obj)) 50 return id 51 } 52 53 getCallback(id: number): CallbackInfo { 54 return this.callbackMap?.get(id) || CallbackScope.CB_UNDEFINED 55 } 56 57 deleteCallback(id: number): void { 58 if (id > CallbackScope.CB_NULL_ID) { 59 this.callbackMap?.delete(id) 60 } 61 } 62 63 release(): void { 64 this.callbackMap = null 65 } 66} 67 68function callCallback(callbackId: number): any { 69 let CallbackInfo = GLOBAL_SCOPE.getCallback(callbackId) 70 try { 71 let cb = CallbackInfo.cb 72 if (CallbackInfo.recv !== null) { 73 cb = cb.bind(CallbackInfo.recv) 74 } 75 return cb() 76 } catch (e) { 77 console.error(e) 78 } 79} 80 81export function registerCallback(callback: any, obj: any = null): KPointer { 82 return GLOBAL_SCOPE.addCallback(callback, obj) 83} 84 85function releaseCallback(callbackId: number): void { 86 return GLOBAL_SCOPE.deleteCallback(callbackId) 87} 88 89declare namespace globalThis { 90 function callCallback(callbackId: number): any 91 function releaseCallback(callbackId: number): any 92} 93 94globalThis.callCallback = callCallback 95globalThis.releaseCallback = releaseCallback 96 97export function setCallbackRegistry(_ignoredRegistry: CallbackRegistry) { 98 // On WASM we don't need registry in current implementation. 99} 100