• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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