1"use strict"; 2/* 3 * Copyright (c) 2022-2025 Huawei Device Co., Ltd. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18Object.defineProperty(exports, "__esModule", { value: true }); 19exports.unsafeCast = exports.SerializerBase = exports.CustomSerializer = exports.registerMaterialized = exports.registerCallback = exports.isInstanceOf = exports.isResource = exports.runtimeType = exports.Tags = exports.RuntimeType = void 0; 20const InteropOps_1 = require("./InteropOps"); 21const InteropNativeModule_1 = require("./InteropNativeModule"); 22const ResourceManager_1 = require("../arkts/ResourceManager"); 23// imports required interfaces (now generation is disabled) 24// import { Resource } from "@arkoala/arkui" 25/** 26 * Value representing possible JS runtime object type. 27 * Must be synced with "enum RuntimeType" in C++. 28 */ 29var RuntimeType; 30(function (RuntimeType) { 31 RuntimeType[RuntimeType["UNEXPECTED"] = -1] = "UNEXPECTED"; 32 RuntimeType[RuntimeType["NUMBER"] = 1] = "NUMBER"; 33 RuntimeType[RuntimeType["STRING"] = 2] = "STRING"; 34 RuntimeType[RuntimeType["OBJECT"] = 3] = "OBJECT"; 35 RuntimeType[RuntimeType["BOOLEAN"] = 4] = "BOOLEAN"; 36 RuntimeType[RuntimeType["UNDEFINED"] = 5] = "UNDEFINED"; 37 RuntimeType[RuntimeType["BIGINT"] = 6] = "BIGINT"; 38 RuntimeType[RuntimeType["FUNCTION"] = 7] = "FUNCTION"; 39 RuntimeType[RuntimeType["SYMBOL"] = 8] = "SYMBOL"; 40 RuntimeType[RuntimeType["MATERIALIZED"] = 9] = "MATERIALIZED"; 41})(RuntimeType = exports.RuntimeType || (exports.RuntimeType = {})); 42/** 43 * Value representing object type in serialized data. 44 * Must be synced with "enum Tags" in C++. 45 */ 46var Tags; 47(function (Tags) { 48 Tags[Tags["UNDEFINED"] = 101] = "UNDEFINED"; 49 Tags[Tags["INT32"] = 102] = "INT32"; 50 Tags[Tags["FLOAT32"] = 103] = "FLOAT32"; 51 Tags[Tags["STRING"] = 104] = "STRING"; 52 Tags[Tags["LENGTH"] = 105] = "LENGTH"; 53 Tags[Tags["RESOURCE"] = 106] = "RESOURCE"; 54 Tags[Tags["OBJECT"] = 107] = "OBJECT"; 55})(Tags = exports.Tags || (exports.Tags = {})); 56function runtimeType(value) { 57 let type = typeof value; 58 if (type == "number") 59 return RuntimeType.NUMBER; 60 if (type == "string") 61 return RuntimeType.STRING; 62 if (type == "undefined") 63 return RuntimeType.UNDEFINED; 64 if (type == "object") 65 return RuntimeType.OBJECT; 66 if (type == "boolean") 67 return RuntimeType.BOOLEAN; 68 if (type == "bigint") 69 return RuntimeType.BIGINT; 70 if (type == "function") 71 return RuntimeType.FUNCTION; 72 if (type == "symbol") 73 return RuntimeType.SYMBOL; 74 throw new Error(`bug: ${value} is ${type}`); 75} 76exports.runtimeType = runtimeType; 77function isResource(value) { 78 return value !== undefined 79 && typeof value === 'object' 80 && value !== null 81 && value.hasOwnProperty("bundleName") 82 && value.hasOwnProperty("moduleName"); 83} 84exports.isResource = isResource; 85// Poor man's instanceof, fails on subclasses 86function isInstanceOf(className, value) { 87 return (value === null || value === void 0 ? void 0 : value.constructor.name) === className; 88} 89exports.isInstanceOf = isInstanceOf; 90function registerCallback(value) { 91 return (0, InteropOps_1.wrapCallback)((args, length) => { 92 // TBD: deserialize the callback arguments and call the callback 93 return 42; 94 }); 95} 96exports.registerCallback = registerCallback; 97function registerMaterialized(value) { 98 // TODO: fix me! 99 return 42; 100} 101exports.registerMaterialized = registerMaterialized; 102/* Serialization extension point */ 103class CustomSerializer { 104 constructor(supported) { 105 this.supported = supported; 106 this.next = undefined; 107 } 108 supports(kind) { return this.supported.includes(kind); } 109} 110exports.CustomSerializer = CustomSerializer; 111class SerializerBase { 112 static registerCustomSerializer(serializer) { 113 if (SerializerBase.customSerializers == undefined) { 114 SerializerBase.customSerializers = serializer; 115 } 116 else { 117 let current = SerializerBase.customSerializers; 118 while (current.next != undefined) { 119 current = current.next; 120 } 121 current.next = serializer; 122 } 123 } 124 constructor() { 125 this.position = 0; 126 this.heldResources = []; 127 this.buffer = new ArrayBuffer(96); 128 this.view = new DataView(this.buffer); 129 } 130 release() { 131 this.releaseResources(); 132 this.position = 0; 133 } 134 asArray() { 135 return new Uint8Array(this.buffer); 136 } 137 length() { 138 return this.position; 139 } 140 currentPosition() { return this.position; } 141 checkCapacity(value) { 142 if (value < 1) { 143 throw new Error(`${value} is less than 1`); 144 } 145 let buffSize = this.buffer.byteLength; 146 if (this.position > buffSize - value) { 147 const minSize = this.position + value; 148 const resizedSize = Math.max(minSize, Math.round(3 * buffSize / 2)); 149 let resizedBuffer = new ArrayBuffer(resizedSize); 150 // TODO: can we grow without new? 151 new Uint8Array(resizedBuffer).set(new Uint8Array(this.buffer)); 152 this.buffer = resizedBuffer; 153 this.view = new DataView(resizedBuffer); 154 } 155 } 156 holdAndWriteCallback(callback, hold = 0, release = 0, call = 0, callSync = 0) { 157 const resourceId = ResourceManager_1.ResourceHolder.instance().registerAndHold(callback); 158 this.heldResources.push(resourceId); 159 this.writeInt32(resourceId); 160 this.writePointer(hold); 161 this.writePointer(release); 162 this.writePointer(call); 163 this.writePointer(callSync); 164 return resourceId; 165 } 166 holdAndWriteCallbackForPromiseVoid(hold = 0, release = 0, call = 0, callSync = 0) { 167 let resourceId; 168 const promise = new Promise((resolve, reject) => { 169 const callback = (err) => { 170 if (err !== undefined) 171 reject(err); 172 else 173 resolve(); 174 }; 175 resourceId = this.holdAndWriteCallback(callback, hold, release, call, callSync); 176 }); 177 return [promise, resourceId]; 178 } 179 holdAndWriteCallbackForPromise(hold = 0, release = 0, call = 0) { 180 let resourceId; 181 const promise = new Promise((resolve, reject) => { 182 const callback = (value, err) => { 183 if (err !== undefined) 184 reject(err); 185 else 186 resolve(value); 187 }; 188 resourceId = this.holdAndWriteCallback(callback, hold, release, call); 189 }); 190 return [promise, resourceId]; 191 } 192 writeCallbackResource(resource) { 193 this.writeInt32(resource.resourceId); 194 this.writePointer(resource.hold); 195 this.writePointer(resource.release); 196 } 197 releaseResources() { 198 for (const resourceId of this.heldResources) 199 InteropNativeModule_1.InteropNativeModule._ReleaseCallbackResource(resourceId); 200 // todo think about effective array clearing/pushing 201 this.heldResources = []; 202 } 203 writeCustomObject(kind, value) { 204 let current = SerializerBase.customSerializers; 205 while (current) { 206 if (current.supports(kind)) { 207 current.serialize(this, value, kind); 208 return; 209 } 210 current = current.next; 211 } 212 console.log(`Unsupported custom serialization for ${kind}, write undefined`); 213 this.writeInt8(Tags.UNDEFINED); 214 } 215 writeNumber(value) { 216 this.checkCapacity(5); 217 if (value == undefined) { 218 this.view.setInt8(this.position, Tags.UNDEFINED); 219 this.position++; 220 return; 221 } 222 if (value == Math.round(value)) { 223 this.view.setInt8(this.position, Tags.INT32); 224 this.view.setInt32(this.position + 1, value, true); 225 this.position += 5; 226 return; 227 } 228 this.view.setInt8(this.position, Tags.FLOAT32); 229 this.view.setFloat32(this.position + 1, value, true); 230 this.position += 5; 231 } 232 writeInt8(value) { 233 this.checkCapacity(1); 234 this.view.setInt8(this.position, value); 235 this.position += 1; 236 } 237 writeInt32(value) { 238 this.checkCapacity(4); 239 this.view.setInt32(this.position, value, true); 240 this.position += 4; 241 } 242 writeInt64(value) { 243 this.checkCapacity(8); 244 this.view.setBigInt64(this.position, BigInt(value), true); 245 this.position += 8; 246 } 247 writePointer(value) { 248 this.checkCapacity(8); 249 this.view.setBigInt64(this.position, BigInt(value !== null && value !== void 0 ? value : 0), true); 250 this.position += 8; 251 } 252 writeFloat32(value) { 253 this.checkCapacity(4); 254 this.view.setFloat32(this.position, value, true); 255 this.position += 4; 256 } 257 writeBoolean(value) { 258 this.checkCapacity(1); 259 this.view.setInt8(this.position, value == undefined ? RuntimeType.UNDEFINED : +value); 260 this.position++; 261 } 262 writeFunction(value) { 263 this.writeInt32(registerCallback(value)); 264 } 265 writeString(value) { 266 this.checkCapacity(4 + value.length * 4); // length, data 267 let encodedLength = InteropNativeModule_1.InteropNativeModule._ManagedStringWrite(value, new Uint8Array(this.view.buffer, 0), this.position + 4); 268 this.view.setInt32(this.position, encodedLength, true); 269 this.position += encodedLength + 4; 270 } 271 writeBuffer(buffer) { 272 const resourceId = ResourceManager_1.ResourceHolder.instance().registerAndHold(buffer); 273 this.writeCallbackResource({ 274 resourceId, 275 hold: 0, 276 release: 0 277 }); 278 const ptr = InteropNativeModule_1.InteropNativeModule._GetNativeBufferPointer(buffer); 279 this.writePointer(ptr); 280 this.writeInt64(buffer.byteLength); 281 } 282} 283exports.SerializerBase = SerializerBase; 284SerializerBase.customSerializers = undefined; 285class DateSerializer extends CustomSerializer { 286 constructor() { 287 super(["Date"]); 288 } 289 serialize(serializer, value, kind) { 290 serializer.writeString(value.toISOString()); 291 } 292} 293SerializerBase.registerCustomSerializer(new DateSerializer()); 294function unsafeCast(value) { 295 return value; 296} 297exports.unsafeCast = unsafeCast; 298//# sourceMappingURL=SerializerBase.js.map