diff --git a/interfaces/kits/js/declaration/BUILD.gn b/interfaces/kits/js/declaration/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..bbd7f75a88c524dd7a473ae42d599e9399a007c9
--- /dev/null
+++ b/interfaces/kits/js/declaration/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/config/ohos/rules.gni")
+import("//build/ohos.gni")
+import("//build/ohos/ace/ace.gni")
+
+ohos_copy("rpc_declaration") {
+ part_name = "ipc_js"
+ sources = [ "./api/@ohos.rpc.d.ts" ]
+ outputs = [ target_out_dir + "/$target_name/" ]
+ module_source_dir = target_out_dir + "/$target_name"
+ module_install_name = ""
+}
diff --git a/interfaces/kits/js/declaration/api/@ohos.rpc.d.ts b/interfaces/kits/js/declaration/api/@ohos.rpc.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..538bda03378dccb1a0de15f4eedc2f4301692988
--- /dev/null
+++ b/interfaces/kits/js/declaration/api/@ohos.rpc.d.ts
@@ -0,0 +1,452 @@
+declare namespace rpc {
+ class MessageParcel {
+ static create(): MessageParcel;
+ reclaim(): void;
+ writeRemoteObject(object: IRemoteObject): boolean;
+ readRemoteObject(): IRemoteObject;
+ writeInterfaceToken(token: string): boolean;
+ readInterfaceToken(): string;
+ getSize(): number;
+ getCapacity(): number;
+ setSize(size: number): boolean;
+ setCapacity(size: number): boolean;
+ getWritableBytes(): number;
+ getReadableBytes(): number;
+ getReadPosition(): number;
+ getWritePosition(): number;
+ rewindRead(pos: number): boolean;
+ rewindWrite(pos: number): boolean;
+ writeByte(val: number): boolean;
+ writeShort(val: number): boolean;
+ writeInt(val: number): boolean;
+ writeLong(val: number): boolean;
+ writeFloat(val: number): boolean;
+ writeDouble(val: number): boolean;
+ writeBoolean(val: boolean): boolean;
+ writeChar(val: number): boolean;
+ writeString(val: string): boolean;
+ writeSequenceable(val: Sequenceable): boolean;
+ writeByteArray(byteArray: number[]): boolean;
+ writeShortArray(shortArray: number[]): boolean;
+ writeIntArray(intArray: number[]): boolean;
+ writeLongArray(longArray: number[]): boolean;
+ writeFloatArray(floatArray: number[]): boolean;
+ writeDoubleArray(doubleArray: number[]): boolean;
+ writeBooleanArray(booleanArray: boolean[]): boolean;
+ writeCharArray(charArray: number[]): boolean;
+ writeStringArray(stringArray: string[]): boolean;
+ writeSequenceableArray(sequenceableArray: Sequenceable[]): boolean;
+ readByte(): number;
+ readShort(): number;
+ readInt(): number;
+ readLong(): number;
+ readFloat(): number;
+ readDouble(): number;
+ readBoolean(): boolean;
+ readChar(): number;
+ readString(): string;
+ readSequenceable(dataIn: Sequenceable) : boolean;
+ readByteArray(dataIn: number[]) : void;
+ readByteArray(): number[];
+ readShortArray(dataIn: number[]) : void;
+ readShortArray(): number[];
+ readIntArray(dataIn: number[]) : void;
+ readIntArray(): number[];
+ readLongArray(dataIn: number[]) : void;
+ readLongArray(): number[];
+ readFloatArray(dataIn: number[]) : void;
+ readFloatArray(): number[];
+ readDoubleArray(dataIn: number[]) : void;
+ readDoubleArray(): number[];
+ readBooleanArray(dataIn: boolean[]) : void;
+ readBooleanArray(): boolean[];
+ readCharArray(dataIn: boolean[]) : void;
+ readCharArray(): boolean[];
+ readStringArray(dataIn: string[]) : void;
+ readStringArray(): string[];
+ }
+
+ interface Sequenceable {
+ hasFileDescriptor(): boolean;
+ marshalling(dataOut: MessageParcel): boolean;
+ unmarshalling(dataIn: MessageParcel) : boolean;
+ }
+
+ enum IRemoteObject {
+ /**
+ * Indicates the message code for a Ping operation.
+ */
+ PING_TRANSACTION = ('_' << 24) | ('P' << 16) | ('N' << 8) | 'G',
+
+ /**
+ * Indicates the message code for a dump operation.
+ */
+ DUMP_TRANSACTION = ('_' << 24) | ('D' << 16) | ('M' << 8) | 'P',
+
+ /**
+ * Indicates the message code for a transmission.
+ */
+ INTERFACE_TRANSACTION = ('_' << 24) | ('N' << 16) | ('T' << 8) | 'F',
+
+ /**
+ * Indicates the minimum value of a valid message code.
+ *
+ *
This constant is used to check the validity of an operation.
+ */
+ MIN_TRANSACTION_ID = 0x1,
+
+ /**
+ * Indicates the maximum value of a valid message code.
+ *
+ *
This constant is used to check the validity of an operation.
+ */
+ MAX_TRANSACTION_ID = 0x00FFFFFF,
+ }
+
+ interface IRemoteObject {
+ /**
+ * Queries the description of an interface.
+ *
+ *
A valid {@link IRemoteBroker} object is returned for an interface used by the service provider;
+ * {@code null} is returned for an interface used by the service user,
+ * indicating that the interface is not a local one.
+ *
+ * @param descriptor Indicates a string of the interface descriptor.
+ * @return Returns the {@link IRemoteBroker} object bound to the specified interface descriptor.
+ * @since 1
+ */
+ queryLocalInterface(descriptor: string): IRemoteBroker;
+
+ /**
+ * Sends a {@link MessageParcel} message to the peer process in synchronous or asynchronous mode.
+ *
+ *
If asynchronous mode is set for {@code option}, a response is returned immediately.
+ * If synchronous mode is set for {@code option}, the interface will wait for a response from the peer process
+ * until the request times out. The user must prepare {@code reply} for receiving the execution result
+ * given by the peer process.
+ *
+ * @param code Indicates the message code, which is determined by both sides of the communication.
+ * If the interface is generated by the IDL tool, the message code is automatically generated by IDL.
+ * @param data Indicates the {@link MessageParcel} object sent to the peer process.
+ * @param reply Indicates the {@link MessageParcel} object returned by the peer process.
+ * @param option Indicates the synchronous or asynchronous mode to send messages.
+ * @return Returns {@code true} if the method is called successfully; returns {@code false} otherwise.
+ * @throws RemoteException Throws this exception if the method fails to be called.
+ * @since 1
+ */
+ sendRequest(code: number, data: MessageParcel, reply: MessageParcel, option: MessageOption): boolean;
+
+ /**
+ * Registers a callback used to receive notifications of the death of a remote object.
+ *
+ *
This method is called if the remote object process matching the {@link RemoteProxy} object dies.
+ *
+ * @param recipient Indicates the callback to be registered.
+ * @param flags Indicates the flag of the death notification.
+ * @return Returns {@code true} if the callback is registered successfully; returns {@code false} otherwise.
+ * @since 1
+ */
+ addDeathRecipient(recipient: DeathRecipient, flags: number): boolean;
+
+ /**
+ * Deregisters a callback used to receive notifications of the death of a remote object.
+ *
+ * @param recipient Indicates the callback to be deregistered.
+ * @param flags Indicates the flag of the death notification.
+ * @return Returns {@code true} if the callback is deregistered successfully; returns {@code false} otherwise.
+ * @since 1
+ */
+ removeDeathRecipient(recipient: DeathRecipient, flags: number): boolean;
+
+ /**
+ * Obtains the interface descriptor of an object.
+ *
+ *
The interface descriptor is a character string.
+ *
+ * @return Returns the interface descriptor.
+ * @since 1
+ */
+ getInterfaceDescriptor(): string;
+
+ /**
+ * Checks whether an object is dead.
+ *
+ * @return Returns {@code true} if the object is dead; returns {@code false} otherwise.
+ * @since 1
+ */
+ isObjectDead(): boolean;
+ }
+
+ interface IRemoteBroker {
+ asObject(): IRemoteObject;
+ }
+
+ interface DeathRecipient {
+ onRemoteDied(): void;
+ }
+
+ enum MessageOption {
+ TF_SYNC = 0,
+ TF_ASYNC = 1,
+ TF_ACCEPT_FDS = 0x10,
+ TF_WAIT_TIME = 4,
+ MAX_WAIT_TIME = 3000,
+ }
+
+ interface MessageOption {
+ flags: number;
+ waitTime: number;
+ }
+
+ class RemoteObject implements IRemoteObject {
+ descriptor: string;
+ interface: IRemoteObject;
+
+ /**
+ * Queries a remote object using an interface descriptor.
+ *
+ * @param descriptor Indicates the interface descriptor used to query the remote object.
+ * @return Returns the remote object matching the interface descriptor; returns null
+ * if no such remote object is found.
+ * @since 1
+ */
+ queryLocalInterface(interface: string): IRemoteObject;
+
+ /**
+ * Queries an interface descriptor.
+ *
+ * @return Returns the interface descriptor.
+ * @since 1
+ */
+ getInterfaceDescriptor(): string;
+
+ /**
+ * Sets an entry for receiving requests.
+ *
+ *
This method is implemented by the remote service provider. You need to override this method with
+ * your own service logic when you are using IPC.
+ *
+ * @param code Indicates the service request code sent from the peer end.
+ * @param data Indicates the {@link MessageParcel} object sent from the peer end.
+ * @param reply Indicates the response message object sent from the remote service.
+ * The local service writes the response data to the {@link MessageParcel} object.
+ * @param option Indicates whether the operation is synchronous or asynchronous.
+ * @return Returns {@code true} if the operation succeeds; returns {@code false} otherwise.
+ * @throws RemoteException Throws this exception if a remote service error occurs.
+ * @since 1
+ */
+ onRemoteRequest(code: number, data: MessageParcel, reply: MessageParcel, option: MessageOption): boolean;
+
+ /**
+ * Sends a request to the peer object.
+ *
+ *
If the peer object and {@code RemoteObject} are on the same device, the request is sent by the IPC driver.
+ * If they are on different devices, the request is sent by the socket driver.
+ *
+ * @param code Indicates the message code of the request.
+ * @param data Indicates the {@link MessageParcel} object storing the data to be sent.
+ * @param reply Indicates the {@link MessageParcel} object receiving the response data.
+ * @param option Indicates a synchronous (default) or asynchronous request.
+ * @return Returns {@code true} if the operation succeeds; returns {@code false} otherwise.
+ * @since 1
+ */
+ sendRequest(code: number, data: MessageParcel, reply: MessageParcel, option: MessageOption): boolean;
+
+ /**
+ * Obtains the PID of the {@link RemoteProxy} object.
+ *
+ * @return Returns the PID of the {@link RemoteProxy} object.
+ * @since 1
+ */
+ getCallingPid(): number;
+
+ /**
+ * Obtains the UID of the {@link RemoteProxy} object.
+ *
+ * @return Returns the UID of the {@link RemoteProxy} object.
+ * @since 1
+ */
+ getCallingUid(): number;
+
+ /**
+ * Modifies the description of the current {@code RemoteObject}.
+ *
+ *
This method is used to change the default descriptor specified during the creation of {@code RemoteObject}.
+ *
+ * @param localInterface Indicates the {@code RemoteObject} whose descriptor is to be changed.
+ * @param descriptor Indicates the new descriptor of the {@code RemoteObject}.
+ * @since 1
+ */
+ attachLocalInterface(localInterface: IRemoteBroker, descriptor: string): void;
+ }
+
+ class RemoteProxy implements IRemoteObject {
+ /**
+ * Queries a local interface with a specified descriptor.
+ *
+ * @param descriptor Indicates the descriptor of the interface to query.
+ * @return Returns null by default, indicating a proxy interface.
+ * @since 1
+ */
+ queryLocalInterface(interface: string): IRemoteObject;
+
+ /**
+ * Registers a callback used to receive death notifications of a remote object.
+ *
+ * @param recipient Indicates the callback to be registered.
+ * @param flags Indicates the flag of the death notification. This is a reserved parameter. Set it to {@code 0}.
+ * @return Returns {@code true} if the callback is registered successfully; returns {@code false} otherwise.
+ * @since 1
+ */
+ addDeathRecipient(recipient: DeathRecipient, flags: number): boolean;
+
+ /**
+ * Deregisters a callback used to receive death notifications of a remote object.
+ *
+ * @param recipient Indicates the callback to be deregistered.
+ * @param flags Indicates the flag of the death notification. This is a reserved parameter. Set it to {@code 0}.
+ * @return Returns {@code true} if the callback is deregistered successfully; returns {@code false} otherwise.
+ * @since 1
+ */
+ removeDeathRecipient(recipient: DeathRecipient, flags: number): boolean;
+
+ /**
+ * Queries the interface descriptor of remote object.
+ *
+ * @return Returns the interface descriptor.
+ * @since 1
+ */
+ getInterfaceDescriptor(): string;
+
+ /**
+ * Sends a request to the peer object.
+ *
+ *
If the peer object and {@code RemoteProxy} are on the same device, the request is sent by the IPC driver.
+ * If they are on different devices, the request is sent by the socket driver.
+ *
+ * @param code Indicates the message code of the request.
+ * @param data Indicates the {@link MessageParcel} object storing the data to be sent.
+ * @param reply Indicates the {@link MessageParcel} object receiving the response data.
+ * @param option Indicates a synchronous (default) or asynchronous request.
+ * @return Returns {@code true} if the operation succeeds; returns {@code false} otherwise.
+ * @throws RemoteException Throws this exception if a remote object exception occurs.
+ * @since 1
+ */
+ sendRequest(code: number, data: MessageParcel, reply: MessageParcel, option: MessageOption): boolean;
+
+ /**
+ * Checks whether the {@code RemoteObject} corresponding to a {@code RemoteProxy} is dead.
+ *
+ * @return Returns {@code true} if the {@code RemoteObject} is dead; returns {@code false} otherwise.
+ * @since 1
+ */
+ isObjectDead(): boolean;
+ }
+
+ class IPCSkeleton {
+ /**
+ * Obtains a local {@link IRemoteObject} reference of a registered service.
+ *
+ *
This method is static.
+ *
+ * @return Returns an {@link IRemoteObject} reference of the registered service.
+ * @since 1
+ */
+ static getContextObject(): IRemoteObject;
+
+ /**
+ * Obtains the PID of a proxy.
+ *
+ *
This method is static. The PID is a positive integer during the communication between
+ * the {@link RemoteProxy} object and {@link RemoteObject} object, and resumes to {@code 0}
+ * when the communication ends. If this method is called from the {@link RemoteProxy} object,
+ * {@code 0} is returned; if this method is called from the {@link RemoteObject} object,
+ * the PID of the corresponding {@link RemoteProxy} object is returned.
+ *
+ * @return Returns the PID of the proxy.
+ * @since 1
+ */
+ static getCallingPid(): number;
+
+ /**
+ * Obtains the UID of a proxy.
+ *
+ *
This method is static. The UID is a positive integer during the communication between
+ * the {@link RemoteProxy} object and {@link RemoteObject} object, and resumes to {@code 0}
+ * when the communication ends. If this method is called from the {@link RemoteProxy} object,
+ * {@code 0} is returned; if this method is called from the {@link RemoteObject} object,
+ * the UID of the corresponding {@link RemoteProxy} object is returned.
+ *
+ * @return Returns the UID of the proxy.
+ * @since 1
+ */
+ static getCallingUid(): number;
+
+ /**
+ * Obtains the ID of the device where the peer process resides.
+ *
+ *
This method is static.
+ *
+ * @return Returns the ID of the device where the peer process resides.
+ * @since 1
+ */
+ static getCallingDeviceID(): string;
+
+ /**
+ * Obtains the ID of the local device.
+ *
+ *
This method is static.
+ *
+ * @return Returns the ID of the local device.
+ * @since 1
+ */
+ static getLocalDeviceID(): string;
+
+ /**
+ * Checks whether a call is made on the same device.
+ *
+ *
This method is static.
+ *
+ * @return Returns {@code true} if the call is made on the same device; returns {@code false} otherwise.
+ * @since 1
+ */
+ static isLocalCalling(): boolean;
+
+ /**
+ * Flushes all pending commands from a specified {@link RemoteProxy} to the corresponding {@link RemoteObject}.
+ *
+ *
This method is static. You are advised to call this method before performing any time-sensitive operations.
+ *
+ * @param object Indicates the specified {@link RemoteProxy}.
+ * @return Returns {@code 0} if the operation succeeds; returns an error code if the input object is empty
+ * or {@link RemoteObject}, or the operation fails.
+ * @since 1
+ */
+ static flushCommands(object: IRemoteObject): number;
+
+ /**
+ * Replaces the UID and PID of the remote user with those of the local user.
+ *
+ *
This method is static. It can be used in scenarios like authentication.
+ *
+ * @return Returns a string containing the UID and PID of the remote user.
+ * @since 1
+ */
+ static resetCallingIdentity(): string;
+
+ /**
+ * Restores the UID and PID to those of the remote user.
+ *
+ *
This method is static. It is usually called after {@code resetCallingIdentity} is used
+ * and requires the UID and PID of the remote user returned by {@code resetCallingIdentity}.
+ *
+ * @param identity Indicates the string containing the UID and PID of the remote user,
+ * which is returned by {@code resetCallingIdentity}.
+ * @return Returns {@code true} if the operation succeeds; returns {@code false} otherwise.
+ * @since 1
+ */
+ static setCallingIdentity(identity: string): boolean;
+ }
+}
+
+export default rpc;
diff --git a/interfaces/kits/js/napi/BUILD.gn b/interfaces/kits/js/napi/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..fbca183bbbeddacd2fb9274f0f98c15918882408
--- /dev/null
+++ b/interfaces/kits/js/napi/BUILD.gn
@@ -0,0 +1,64 @@
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+SUBSYSTEM_DIR = "//foundation/communication/ipc"
+
+base_output_path = get_label_info(":rpc_js", "target_out_dir")
+ipc_js_obj_path = base_output_path + "/rpc.o"
+
+gen_js_obj("rpc_js") {
+ input = "//foundation/communication/ipc/interfaces/kits/js/napi/rpc.js"
+ output = ipc_js_obj_path
+}
+
+config("rpc_public_config") {
+ visibility = [ ":*" ]
+ include_dirs = [ "$SUBSYSTEM_DIR/ipc/native/src/napi/include" ]
+}
+
+ohos_shared_library("rpc") {
+ include_dirs = [
+ "$SUBSYSTEM_DIR/utils/include",
+ "//foundation/ace/napi/interfaces/kits",
+ "//utils/system/safwk/native/include",
+ ]
+ public_configs = [ ":rpc_public_config" ]
+
+ sources = [
+ "$SUBSYSTEM_DIR/ipc/native/src/napi/src/napi_message_option.cpp",
+ "$SUBSYSTEM_DIR/ipc/native/src/napi/src/napi_message_parcel.cpp",
+ "$SUBSYSTEM_DIR/ipc/native/src/napi/src/napi_remote_object.cpp",
+ "$SUBSYSTEM_DIR/ipc/native/src/napi/src/napi_rpc_native_module.cpp",
+ ]
+
+ deps = [
+ ":rpc_js",
+ "//foundation/ace/napi:ace_napi",
+ "//third_party/libuv:uv_static",
+ "//utils/native/base:utils",
+ ]
+
+ external_deps = [
+ "hiviewdfx_hilog_native:libhilog",
+ "ipc:ipc_core",
+ "safwk:system_ability_fwk",
+ "samgr_L2:samgr_proxy",
+ ]
+
+ relative_install_dir = "module"
+
+ subsystem_name = "communication"
+ part_name = "ipc_js"
+}
diff --git a/interfaces/kits/js/napi/rpc.js b/interfaces/kits/js/napi/rpc.js
new file mode 100644
index 0000000000000000000000000000000000000000..f49e33e8973377dfe7d144a03f6d60cd2a99c65d
--- /dev/null
+++ b/interfaces/kits/js/napi/rpc.js
@@ -0,0 +1,217 @@
+const rpcSo = requireInternal("rpc");
+
+// 定义异常类型常量
+const EXC_INSECURITY = -1;
+const EXC_ILLEGAL_ARGUMENT = -3;
+const EXC_NULL_POINTER = -4;
+const EXC_ILLEGAL_STATE = -5;
+const EXC_UNSUPPORTED_OPERATION = -7;
+const EXC_INDEX_OUTOF_BOUNDS = -10;
+const EXC_NEGATIVE_ARRAY_SIZE = -11;
+const EXC_ARRAY_STORE = -12;
+const EXC_CLASS_CAST = -13;
+const EXC_PARCEL_CAPACITY_ERROR = -14;
+const EXC_REMOTE_TRANSACTION_FAILED = -200;
+
+let MessageParcel = rpcSo.MessageParcel;
+let IPCSkeleton = rpcSo.IPCSkeleton;
+let RemoteObject = rpcSo.RemoteObject;
+let RemoteProxy = rpcSo.RemoteProxy;
+let MessageOption = rpcSo.MessageOption;
+
+class Exception {
+ message;
+ constructor(msg) {
+ this.message = msg;
+ }
+
+ getMessage() {
+ return this.message;
+ }
+}
+
+class NullPointerException extends Exception {}
+class SecurityException extends Exception {}
+class IllegalArgumentException extends Exception {}
+class IllegalStateException extends Exception {}
+class UnsupportedOperationException extends Exception {}
+class IndexOutOfBoundsException extends Exception {}
+class NegativeArraySizeException extends Exception {}
+class ArrayStoreException extends Exception {}
+class ClassCastException extends Exception {}
+class RemoteException extends Exception {}
+class ParcelException extends Exception {}
+class RuntimeException extends Exception {}
+
+
+// MessageParcel的附加功能
+MessageParcel.prototype.createException = function(code, msg) {
+ switch (code) {
+ case EXC_INSECURITY: {
+ return new SecurityException(msg);
+ }
+ case EXC_ILLEGAL_ARGUMENT: {
+ return new IllegalArgumentException(msg);
+ }
+ case EXC_NULL_POINTER: {
+ return new NullPointerException(msg);
+ }
+ case EXC_ILLEGAL_STATE: {
+ return new IllegalStateException(msg);
+ }
+ case EXC_UNSUPPORTED_OPERATION: {
+ return new UnsupportedOperationException(msg);
+ }
+ case EXC_INDEX_OUTOF_BOUNDS: {
+ return new IndexOutOfBoundsException(msg);
+ }
+ case EXC_NEGATIVE_ARRAY_SIZE: {
+ return new NegativeArraySizeException(msg);
+ }
+ case EXC_ARRAY_STORE: {
+ return new ArrayStoreException(msg);
+ }
+ case EXC_CLASS_CAST: {
+ return new ClassCastException(msg);
+ }
+ case EXC_REMOTE_TRANSACTION_FAILED: {
+ return new RemoteException(msg);
+ }
+ case EXC_PARCEL_CAPACITY_ERROR: {
+ return new ParcelException(msg);
+ }
+ default: {
+ return new RuntimeException("Unknown exception code: " + code + " msg " + msg);
+ }
+ }
+}
+
+MessageParcel.prototype.writeException = function(exception) {
+ let code = 0;
+ if (exception instanceof SecurityException) {
+ code = EXC_INSECURITY;
+ } else if (exception instanceof IllegalArgumentException) {
+ code = EXC_ILLEGAL_ARGUMENT;
+ } else if (exception instanceof NullPointerException) {
+ code = EXC_NULL_POINTER;
+ } else if (exception instanceof IllegalStateException) {
+ code = EXC_ILLEGAL_STATE;
+ } else if (exception instanceof UnsupportedOperationException) {
+ code = EXC_UNSUPPORTED_OPERATION;
+ } else if (exception instanceof IndexOutOfBoundsException) {
+ code = EXC_INDEX_OUTOF_BOUNDS;
+ } else if (exception instanceof NegativeArraySizeException) {
+ code = EXC_NEGATIVE_ARRAY_SIZE;
+ } else if (exception instanceof ArrayStoreException) {
+ code = EXC_ARRAY_STORE;
+ } else if (exception instanceof ClassCastException) {
+ code = EXC_CLASS_CAST;
+ } else if (exception instanceof RemoteException) {
+ code = EXC_REMOTE_TRANSACTION_FAILED;
+ } else if (exception instanceof ParcelException) {
+ code = EXC_PARCEL_CAPACITY_ERROR;
+ } else {
+ code = 0;
+ }
+ // Todo
+ this.writeInt(code);
+ if (code === 0) {
+ if (exception instanceof RuntimeException) {
+ throw new RuntimeException(exception.getMessage());
+ }
+ throw new RuntimeException(exception.getMessage());
+ }
+ // TODO
+ this.writeString(exception.getMessage());
+}
+
+MessageParcel.prototype.writeNoException = function() {
+ this.writeInt(0);
+}
+
+MessageParcel.prototype.readException = function() {
+ let code = this.readInt();
+ if (code === 0) {
+ return;
+ }
+ let msg = this.readString();
+ let exception = this.createException(code, msg);
+ return exception;
+}
+
+MessageParcel.prototype.createRemoteObjectArray = function() {
+ let num = this.readInt();
+ if (num <= 0) {
+ return null;
+ }
+ let list = new Array(num);
+ for (let i = 0; i < num; i++) {
+ list[i] = this.readRemoteObject();
+ }
+ return list;
+}
+
+MessageParcel.prototype.writeRemoteObjectArray = function(objects) {
+ if (objects === null || objects.length <= 0 ) {
+ this.writeInt(-1);
+ return false;
+ }
+
+ let num = objects.length;
+ this.writeInt(num);
+ for (let i = 0; i < num; i ++) {
+ this.writeRemoteObject(objects[i]);
+ }
+ return true;
+}
+
+// 传入的对象是一个数组[]
+MessageParcel.prototype.readRemoteObjectArray = function(objects) {
+ if (objects === null) {
+ return;
+ }
+
+ let num = this.readInt();
+ if (num !== objects.length) {
+ return;
+ }
+ for (let i = 0; i < num; i ++) {
+ objects[i] = this.readRemoteObject();
+ }
+}
+
+// 定义RemoteObject中N_API中不存在的方法
+// proxy实现,stub端不实现
+RemoteObject.prototype.addDeathRecipient = function(recipient, flags) {
+ return false;
+}
+
+// proxy实现,stub端不实现
+RemoteObject.prototype.removeDeathRecipient = function(recipient, flags) {
+ return false;
+}
+
+// proxy实现,stub端不实现
+RemoteObject.prototype.isObjectDead = function() {
+ return false;
+}
+
+export default {
+ MessageParcel: MessageParcel,
+ IPCSkeleton: IPCSkeleton,
+ RemoteObject: RemoteObject,
+ RemoteProxy: RemoteProxy,
+ MessageOption: MessageOption,
+ NullPointerException: NullPointerException,
+ SecurityException: SecurityException,
+ IllegalArgumentException: IllegalArgumentException,
+ IllegalStateException: IllegalStateException,
+ UnsupportedOperationException: UnsupportedOperationException,
+ IndexOutOfBoundsException: IndexOutOfBoundsException,
+ NegativeArraySizeException: NegativeArraySizeException,
+ ArrayStoreException: ArrayStoreException,
+ ClassCastException: ClassCastException,
+ RemoteException: RemoteException,
+ ParcelException: ParcelException,
+ RuntimeException: RuntimeException
+}
\ No newline at end of file
diff --git a/ipc/native/src/napi/include/napi_message_option.h b/ipc/native/src/napi/include/napi_message_option.h
new file mode 100644
index 0000000000000000000000000000000000000000..f03e8e60ee82fb7fcee25cd78d82ba0fef8c8f34
--- /dev/null
+++ b/ipc/native/src/napi/include/napi_message_option.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NAPI_IPC_OHOS_MESSAGE_OPTION_H
+#define NAPI_IPC_OHOS_MESSAGE_OPTION_H
+
+#include "napi/native_api.h"
+#include "napi/native_common.h"
+#include "napi/native_node_api.h"
+#include "message_option.h"
+
+namespace OHOS {
+/*
+ * Get flags field from ohos.rpc.MessageOption.
+ */
+napi_value NAPI_ohos_rpc_message_option_get_flags(napi_env env, napi_callback_info info);
+
+/*
+ * Set flags to ohos.rpc.MessageOption
+ */
+napi_value NAPI_ohos_rpc_message_option_set_flags(napi_env env, napi_callback_info info);
+
+/*
+ * Get wait time field from ohos.rpc.MessageOption.
+ */
+napi_value NAPI_ohos_rpc_message_option_get_waitTime(napi_env env, napi_callback_info info);
+
+/*
+ * Set wait time to ohos.rpc.MessageOption
+ */
+napi_value NAPI_ohos_rpc_message_option_set_waitTime(napi_env env, napi_callback_info info);
+} // namespace OHOS
+#endif // NAPI_IPC_OHOS_MESSAGE_OPTION_H
\ No newline at end of file
diff --git a/ipc/native/src/napi/include/napi_message_parcel.h b/ipc/native/src/napi/include/napi_message_parcel.h
new file mode 100644
index 0000000000000000000000000000000000000000..5275b48122d6a0bf6729c58618cb55de5691ca04
--- /dev/null
+++ b/ipc/native/src/napi/include/napi_message_parcel.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NAPI_IPC_OHOS_MESSAGE_PARCEL_H
+#define NAPI_IPC_OHOS_MESSAGE_PARCEL_H
+
+#include "securec.h"
+#include "napi/native_api.h"
+#include "napi/native_common.h"
+#include "napi/native_node_api.h"
+#include "message_parcel.h"
+#include "ipc_skeleton.h"
+
+namespace OHOS {
+class NAPI_MessageParcel {
+public:
+ NAPI_MessageParcel(napi_env env, napi_value thisVar, MessageParcel *parcel);
+ virtual ~NAPI_MessageParcel();
+ MessageParcel *getMessageParcel();
+ static napi_value Export(napi_env env, napi_value exports);
+ static napi_ref getParcelConsRef();
+private:
+ // Napi methods and properties
+ static napi_value JS_Constructor(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_create(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_reclaim(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeRemoteObject(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readRemoteObject(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeInterfaceToken(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readInterfaceToken(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_getSize(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_getCapacity(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_setSize(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_setCapacity(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_getWritableBytes(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_getReadableBytes(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_getReadPosition(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_getWritePosition(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_rewindWrite(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_rewindRead(napi_env env, napi_callback_info cbinfo);
+
+ static napi_value JS_writeByte(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeShort(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeInt(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeLong(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeFloat(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeDouble(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeBoolean(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeChar(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeStringWithLength(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeString(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeSequenceable(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeByteArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeShortArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeIntArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeLongArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeFloatArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeDoubleArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeBooleanArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeCharArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeStringArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_writeSequenceableArray(napi_env env, napi_callback_info cbinfo);
+
+ static napi_value JS_readByte(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readShort(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readInt(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readLong(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readFloat(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readDouble(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readBoolean(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readChar(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readString(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readSequenceable(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readByteArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readShortArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readIntArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readLongArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readFloatArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readDoubleArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readBooleanArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readCharArray(napi_env env, napi_callback_info cbinfo);
+ static napi_value JS_readStringArray(napi_env env, napi_callback_info cbinfo);
+
+ napi_env env_ = nullptr;
+ MessageParcel *nativeParcel_ = nullptr;
+ size_t maxCapacityToWrite_;
+ bool owner;
+};
+namespace {
+ napi_value g_messageParcelConstructor = nullptr;
+ napi_ref g_messageParcelConsRef = nullptr;
+}
+} // namespace OHOS
+#endif // NAPI_IPC_OHOS_MESSAGE_PARCEL_H
diff --git a/ipc/native/src/napi/include/napi_remote_object.h b/ipc/native/src/napi/include/napi_remote_object.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa95bfa605961dd88fd2be423432a10c9de2b45b
--- /dev/null
+++ b/ipc/native/src/napi/include/napi_remote_object.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NAPI_IPC_OHOS_REMOTE_OBJECT_H
+#define NAPI_IPC_OHOS_REMOTE_OBJECT_H
+
+#include "napi/native_common.h"
+#include "napi/native_node_api.h"
+#include "refbase.h"
+#include "iremote_object.h"
+#include "system_ability_manager_proxy.h"
+#include "iservice_registry.h"
+
+namespace OHOS {
+EXTERN_C_START
+ napi_value NAPIIPCSkeletonExport(napi_env env, napi_value exports);
+ napi_value NAPIRemoteProxyExport(napi_env env, napi_value exports);
+ napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports);
+ napi_value NAPIMessageOptionExport(napi_env env, napi_value exports);
+EXTERN_C_END
+
+ // IPCSkeleton napi methods
+ // test for get ability
+ napi_value N_API_GetLocalAbility(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_getContextObject(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_getCallingPid(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_getCallingUid(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_getCallingDeviceID(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_getLocalDeviceID(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_isLocalCalling(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_flushCommands(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_resetCallingIdentity(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_IPCSkeleton_setCallingIdentity(napi_env env, napi_callback_info info);
+
+ // RemoteObject napi methods
+ napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info);
+
+ // RemoteProxy napi methods
+ napi_value SendRequestPromise(napi_env env, sptr target, uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option);
+
+ napi_value NAPI_RemoteProxy_sendRequest(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_RemoteProxy_addDeathRecipient(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_RemoteProxy_removeDeathRecipient(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_RemoteProxy_getInterfaceDescriptor(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_RemoteProxy_isObjectDead(napi_env env, napi_callback_info info);
+
+ napi_value NAPI_RemoteProxy_getHandle(napi_env env, napi_callback_info info);
+
+ sptr NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object);
+
+ napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr target);
+
+ struct SendRequestParam {
+ sptr target;
+ uint32_t code;
+ MessageParcel& data;
+ MessageParcel& reply;
+ MessageOption& option;
+ napi_async_work asyncWork;
+ napi_deferred deferred;
+ int errCode;
+ };
+} // namespace OHOS
+#endif // NAPI_IPC_OHOS_REMOTE_OBJECT_H
\ No newline at end of file
diff --git a/ipc/native/src/napi/src/napi_message_option.cpp b/ipc/native/src/napi/src/napi_message_option.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..df43fff5da678c21f753ad907870fd705181ade1
--- /dev/null
+++ b/ipc/native/src/napi/src/napi_message_option.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "napi_message_option.h"
+#include "ipc_debug.h"
+#include "log_tags.h"
+
+namespace OHOS {
+/*
+ * Get flags field from ohos.rpc.MessageOption.
+ */
+napi_value NAPI_ohos_rpc_message_option_get_flags(napi_env env, napi_callback_info info)
+{
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
+ NAPI_ASSERT(env, thisVar != nullptr, "failed to get js message option object");
+ MessageOption *option = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&option);
+ NAPI_ASSERT(env, option != nullptr, "failed to get native message option");
+ int flags = option->GetFlags();
+ napi_value result = nullptr;
+ status = napi_create_int32(env, flags, &result);
+ NAPI_ASSERT(env, status == napi_ok, "failed to create int32 value");
+ return result;
+}
+
+/*
+ * Set flags to ohos.rpc.MessageOption
+ */
+napi_value NAPI_ohos_rpc_message_option_set_flags(napi_env env, napi_callback_info info)
+{
+ napi_value thisVar = nullptr;
+ size_t argc;
+ napi_value argv[1] = { 0 };
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, thisVar != nullptr, "failed to get js message option object");
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+ int32_t flags = 0;
+ napi_status status = napi_get_value_int32(env, argv[0], &flags);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get int32 value");
+ MessageOption *option = nullptr;
+ status = napi_unwrap(env, thisVar, (void**)&option);
+ NAPI_ASSERT(env, option != nullptr, "failed to get native message option");
+ option->SetFlags(flags);
+ napi_value result = nullptr;
+ napi_get_undefined(env, &result);
+ return result;
+}
+
+/*
+ * Get wait time field from ohos.rpc.MessageOption.
+ */
+napi_value NAPI_ohos_rpc_message_option_get_waitTime(napi_env env, napi_callback_info info)
+{
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
+ NAPI_ASSERT(env, thisVar != nullptr, "failed to get js message option object");
+ MessageOption *option = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&option);
+ NAPI_ASSERT(env, option != nullptr, "failed to get native message option");
+ int flags = option->GetWaitTime();
+ napi_value result = nullptr;
+ status = napi_create_int32(env, flags, &result);
+ NAPI_ASSERT(env, status == napi_ok, "failed to create int32 value");
+ return result;
+}
+
+/*
+ * Set wait time to ohos.rpc.MessageOption
+ */
+napi_value NAPI_ohos_rpc_message_option_set_waitTime(napi_env env, napi_callback_info info)
+{
+ napi_value thisVar = nullptr;
+ size_t argc;
+ napi_value argv[1] = { 0 };
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, thisVar != nullptr, "failed to get js message option object");
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+ int32_t waittime = 0;
+ napi_status status = napi_get_value_int32(env, argv[0], &waittime);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get int32 value");
+ MessageOption *option = nullptr;
+ status = napi_unwrap(env, thisVar, (void**)&option);
+ NAPI_ASSERT(env, option != nullptr, "failed to get native message option");
+ option->SetFlags(waittime);
+ napi_value result = nullptr;
+ napi_get_undefined(env, &result);
+ return result;
+}
+} // namespace OHOS
\ No newline at end of file
diff --git a/ipc/native/src/napi/src/napi_message_parcel.cpp b/ipc/native/src/napi/src/napi_message_parcel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..76490952e012e3670cad8d3fc5d25922a86063d9
--- /dev/null
+++ b/ipc/native/src/napi/src/napi_message_parcel.cpp
@@ -0,0 +1,1974 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "napi_message_parcel.h"
+#include
+#include
+#include
+#include
+#include "napi_remote_object.h"
+#include "hilog/log.h"
+#include "log_tags.h"
+#include "string_ex.h"
+
+
+namespace OHOS {
+using namespace OHOS::HiviewDFX;
+constexpr size_t MAX_CAPACITY_TO_WRITE = 200 * 1024;
+constexpr size_t BYTE_SIZE_32 = 4;
+constexpr size_t BYTE_SIZE_64 = 8;
+
+static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "napi_messageParcel" };
+#ifndef TITLE
+#define TITLE __PRETTY_FUNCTION__
+#endif
+#define DBINDER_LOGE(fmt, args...) \
+ (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
+#define DBINDER_LOGI(fmt, args...) \
+ (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
+
+#define CHECK_WRITE_CAPACITY(env, lenToWrite, napiParcel) \
+ size_t cap = napiParcel->maxCapacityToWrite_ - napiParcel->nativeParcel_->GetWritePosition(); \
+ if (cap < lenToWrite) { \
+ DBINDER_LOGI("No enough capacity to write"); \
+ napi_throw_range_error(env, nullptr, "No enough capacity to write"); \
+ }
+
+#define REWIND_IF_WRITE_CHECK_FAIL(env, lenToWrite, pos, napiParcel) \
+ size_t cap = napiParcel->maxCapacityToWrite_ - napiParcel->nativeParcel_->GetWritePosition(); \
+ if (cap < lenToWrite) { \
+ DBINDER_LOGI("No enough capacity to write"); \
+ napiParcel->nativeParcel_->RewindWrite(pos); \
+ napi_throw_range_error(env, nullptr, "No enough capacity to write"); \
+ }
+
+#define CHECK_READ_LENGTH(env, arrayLength, typeSize, napiParcel) \
+ size_t remainSize = napiParcel->nativeParcel_->GetDataSize() - napiParcel->nativeParcel_->GetReadPosition(); \
+ if ((arrayLength < 0) || (arrayLength > remainSize) || ((arrayLength * typeSize) > remainSize)) { \
+ DBINDER_LOGI("No enough data to read"); \
+ napi_throw_range_error(env, nullptr, "No enough data to read"); \
+ }
+
+NAPI_MessageParcel::NAPI_MessageParcel(napi_env env, napi_value thisVar, MessageParcel *parcel)
+{
+ DBINDER_LOGI("NAPI_MessageParcel::constructor");
+ env_ = env;
+ maxCapacityToWrite_ = MAX_CAPACITY_TO_WRITE;
+ // do NOT reference js parcel here
+ if (parcel == nullptr) {
+ nativeParcel_ = new MessageParcel();
+ owner = true;
+ } else {
+ nativeParcel_ = parcel;
+ owner = false;
+ }
+}
+
+NAPI_MessageParcel::~NAPI_MessageParcel()
+{
+ DBINDER_LOGI("NAPI_MessageParcel::Destructor");
+ if (owner) {
+ delete nativeParcel_;
+ }
+ nativeParcel_ = nullptr;
+ env_ = nullptr;
+}
+
+MessageParcel *NAPI_MessageParcel::getMessageParcel()
+{
+ return nativeParcel_;
+}
+
+napi_value NAPI_MessageParcel::JS_writeByte(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ int32_t value = 0;
+ napi_get_value_int32(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32, napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteInt8(static_cast(value));
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeShort(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ int32_t value = 0;
+ napi_get_value_int32(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32, napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteInt16(static_cast(value));
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeInt(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ int32_t value = 0;
+ napi_get_value_int32(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32, napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteInt32(value);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeLong(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ int64_t value = 0;
+ napi_get_value_int64(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_64, napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteInt64(value);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeFloat(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ double value = 0;
+ napi_get_value_double(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ // bool result = napiParcel->nativeParcel_->WriteFloat(static_cast(value));
+ CHECK_WRITE_CAPACITY(env, sizeof(double), napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteDouble(value);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeDouble(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ double value = 0;
+ napi_get_value_double(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, sizeof(double), napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteDouble(value);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeBoolean(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_boolean, "type mismatch for parameter 1");
+
+ bool value = 0;
+ napi_get_value_bool(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32, napiParcel);
+ bool result = napiParcel->nativeParcel_->WriteInt8(static_cast(value));
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeChar(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
+
+ size_t bufferSize = 0;
+ size_t strLength = 0;
+ napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
+ DBINDER_LOGI("messageparcel writeChar bufferSize = %{public}d", (int)bufferSize);
+ char buffer[bufferSize + 1];
+ napi_get_value_string_utf8(env, argv[0], buffer, bufferSize + 1, &strLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32, napiParcel);
+ std::string parcelString = buffer;
+ auto value = reinterpret_cast(to_utf16(parcelString).data());
+ bool result = napiParcel->nativeParcel_->WriteUint16(*value);
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeStringWithLength(napi_env env, napi_callback_info info)
+{
+ size_t argc = 2;
+ napi_value argv[2] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
+
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+
+ uint32_t stringLength = 0;
+ napi_get_value_uint32(env, argv[1], &stringLength);
+ // TODO 40960 definition
+ NAPI_ASSERT(env, stringLength < 40960, "string length too large");
+
+ char stringValue[stringLength + 1];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, argv[0], stringValue, stringLength + 1, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == stringLength, "string length wrong");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * stringLength, napiParcel);
+ std::string parcelString = stringValue;
+ bool result = napiParcel->nativeParcel_->WriteString16(to_utf16(parcelString));
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeByteArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isTypedArray;
+ napi_is_typedarray(env, argv[0], &isTypedArray);
+ NAPI_ASSERT(env, isTypedArray == true, "type mismatch for parameter 1");
+
+ napi_typedarray_type typedarrayType;
+ size_t typedarrayLength = 0;
+ void *typedarrayBufferPtr = nullptr;
+ napi_value tmpArrayBuffer = nullptr;
+ size_t byteOffset = 0;
+ napi_get_typedarray_info(env, argv[0], &typedarrayType, &typedarrayLength, &typedarrayBufferPtr,
+ &tmpArrayBuffer, &byteOffset);
+
+ NAPI_ASSERT(env, typedarrayType == napi_int8_array, "array type mismatch for parameter 1");
+ DBINDER_LOGI("messageparcel WriteBuffer typedarrayLength = %{public}d", (int)(typedarrayLength));
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ size_t len = (typedarrayLength / 4) + (typedarrayLength % 4 == 0 ? 0 : 1);
+ DBINDER_LOGI("messageparcel WriteBuffer len = %{public}d", (int)(len));
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * (len + 1), napiParcel);
+ napiParcel->nativeParcel_->WriteUint32(typedarrayLength);
+ bool result = napiParcel->nativeParcel_->WriteBuffer(typedarrayBufferPtr, typedarrayLength);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeShortArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * (arrayLength + 1), napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ int32_t value = 0;
+ napi_get_value_int32(env, element, &value);
+ result = napiParcel->nativeParcel_->WriteInt16(static_cast(value));
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeIntArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * (arrayLength + 1), napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ napi_valuetype valueType;
+ napi_typeof(env, element, &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch element");
+
+ int32_t value = 0;
+ napi_get_value_int32(env, element, &value);
+ result = napiParcel->nativeParcel_->WriteInt32(value);
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeLongArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+ DBINDER_LOGI("messageparcel WriteBuffer typedarrayLength = %{public}d", (int)(arrayLength));
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 + BYTE_SIZE_64 * arrayLength, napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ int64_t value = 0;
+ napi_get_value_int64(env, element, &value);
+ //DBINDER_LOGI("messageparcel WriteBuffer typedarrayLength = %{public}d", (int)(value));
+
+ result = napiParcel->nativeParcel_->WriteInt64(value);
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeFloatArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 + sizeof(double) * arrayLength, napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ double value = 0;
+ napi_get_value_double(env, element, &value);
+
+ // result = napiParcel->nativeParcel_->WriteFloat(static_cast(value));
+ result = napiParcel->nativeParcel_->WriteDouble(value);
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeDoubleArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 + sizeof(double) * arrayLength, napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ double value = 0;
+ napi_get_value_double(env, element, &value);
+
+ result = napiParcel->nativeParcel_->WriteDouble(value);
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeBooleanArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * (arrayLength + 1), napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ bool value = 0;
+ napi_get_value_bool(env, element, &value);
+
+ result = napiParcel->nativeParcel_->WriteInt8(static_cast(value));
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeCharArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * (arrayLength + 1), napiParcel);
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ // uint32_t value = 0;
+ // napi_get_value_uint32(env, element, &value);
+ // DBINDER_LOGI("messageparcel WriteBuffer typedarrayLength = %{public}d", (int)(value));
+ size_t bufferSize = 0;
+ size_t strLength = 0;
+ napi_get_value_string_utf8(env, element, nullptr, 0, &bufferSize);
+ DBINDER_LOGI("messageparcel writeChar bufferSize = %{public}d", (int)bufferSize);
+ char buffer[bufferSize + 1];
+ napi_get_value_string_utf8(env, element, buffer, bufferSize + 1, &strLength);
+ DBINDER_LOGI("messageparcel writeChar strLength = %{public}d", (int)strLength);
+
+ std::string parcelString = buffer;
+ auto value = reinterpret_cast(to_utf16(parcelString).data());
+ result = napiParcel->nativeParcel_->WriteUint16(*value);
+
+ // result = napiParcel->nativeParcel_->WriteUint16(static_cast(value));
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeString(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 2 parameter");
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
+
+ size_t bufferSize = 0;
+ napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
+ NAPI_ASSERT(env, bufferSize < 40960, "string length too large");
+
+ char stringValue[bufferSize + 1];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
+
+ CHECK_WRITE_CAPACITY(env, BYTE_SIZE_32 * bufferSize, napiParcel);
+ std::string parcelString = stringValue;
+ bool result = napiParcel->nativeParcel_->WriteString16(to_utf16(parcelString));
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeStringArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ size_t bufferSize = 0;
+ napi_get_value_string_utf8(env, element, nullptr, 0, &bufferSize);
+ NAPI_ASSERT(env, bufferSize < 40960, "string length too large");
+
+ char stringValue[bufferSize + 1];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, element, stringValue, bufferSize + 1, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
+
+ REWIND_IF_WRITE_CHECK_FAIL(env, BYTE_SIZE_32 * bufferSize, pos, napiParcel);
+ std::string parcelString = stringValue;
+ result = napiParcel->nativeParcel_->WriteString16(to_utf16(parcelString));
+
+ if (!result) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeSequenceable(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteInt32(1);
+ napi_value propKey = nullptr;
+ const char *propKeyStr = "marshalling";
+ napi_create_string_utf8(env, propKeyStr, strlen(propKeyStr), &propKey);
+ napi_value prop = nullptr;
+ napi_get_property(env, argv[0], propKey, &prop);
+
+ napi_value funcArg[1] = { thisVar };
+ napi_value callResult = nullptr;
+ bool result = napi_call_function(env, thisVar, prop, 1, funcArg, &callResult);
+ bool isExceptionPending = false;
+ napi_is_exception_pending(env, &isExceptionPending);
+ if (isExceptionPending) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeSequenceableArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ uint32_t arrayLength = 0;
+ napi_get_array_length(env, argv[0], &arrayLength);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ size_t pos = napiParcel->nativeParcel_->GetWritePosition();
+ napiParcel->nativeParcel_->WriteUint32(arrayLength);
+ bool result = false;
+ for (size_t i = 0; i < arrayLength; i++) {
+ bool hasElement = false;
+ napi_has_element(env, argv[0], i, &hasElement);
+ NAPI_ASSERT(env, hasElement == true, "parameter check error");
+
+ napi_value element = nullptr;
+ napi_get_element(env, argv[0], i, &element);
+
+ napi_value propKey = nullptr;
+ const char* propKeyStr = "marshalling";
+ napi_create_string_utf8(env, propKeyStr, strlen(propKeyStr), &propKey);
+ napi_value prop = nullptr;
+ napi_get_property(env, element, propKey, &prop);
+
+ napi_value funcArg[1] = { thisVar };
+ napi_value callResult = nullptr;
+ result = napi_call_function(env, thisVar, prop, 1, funcArg, &callResult);
+
+ bool isExceptionPending = false;
+ napi_is_exception_pending(env, &isExceptionPending);
+ if (!result || isExceptionPending) {
+ napiParcel->nativeParcel_->RewindWrite(pos);
+ break;
+ }
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readByte(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ int8_t value = napiParcel->nativeParcel_->ReadInt8();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_int32(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readShort(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ int16_t value = napiParcel->nativeParcel_->ReadInt16();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_int32(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readInt(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ int32_t value = napiParcel->nativeParcel_->ReadInt32();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_int32(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readLong(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ int64_t value = napiParcel->nativeParcel_->ReadInt64();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_int64(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readFloat(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ // float value = napiParcel->nativeParcel_->ReadFloat();
+ double value = napiParcel->nativeParcel_->ReadDouble();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_double(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readDouble(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ double value = napiParcel->nativeParcel_->ReadDouble();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_double(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readBoolean(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ int8_t value = napiParcel->nativeParcel_->ReadInt8();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readChar(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ uint16_t value = napiParcel->nativeParcel_->ReadUint16();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readString(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ std::u16string parcelString = napiParcel->nativeParcel_->ReadString16();
+ std::string outString = Str16ToStr8(parcelString.c_str());
+ napi_value napiValue = nullptr;
+ napi_create_string_utf8(env, outString.c_str(), outString.length(), &napiValue);
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_getSize(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ size_t value = napiParcel->nativeParcel_->GetDataSize();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, static_cast(value), &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_getCapacity(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ size_t value = napiParcel->nativeParcel_->GetDataCapacity();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, static_cast(value), &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_setSize(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ uint32_t value = 0;
+ napi_get_value_uint32(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ bool result = napiParcel->nativeParcel_->SetDataSize(static_cast(value));
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_setCapacity(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ uint32_t value = 0;
+ napi_get_value_uint32(env, argv[0], &value);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ bool result = napiParcel->nativeParcel_->SetDataCapacity(static_cast(value));
+ if (result) {
+ napiParcel->maxCapacityToWrite_ = value;
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_getWritableBytes(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ size_t value = napiParcel->nativeParcel_->GetWritableBytes();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, static_cast(value), &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_getReadableBytes(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ size_t value = napiParcel->nativeParcel_->GetReadableBytes();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, static_cast(value), &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_getReadPosition(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ size_t value = napiParcel->nativeParcel_->GetReadPosition();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_rewindRead(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ uint32_t pos = 0;
+ napi_get_value_uint32(env, argv[0], &pos);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ bool result = napiParcel->nativeParcel_->RewindRead(static_cast(pos));
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_getWritePosition(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ size_t value = napiParcel->nativeParcel_->GetWritePosition();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_uint32(env, value, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_rewindWrite(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+
+ uint32_t pos = 0;
+ napi_get_value_uint32(env, argv[0], &pos);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ bool result = napiParcel->nativeParcel_->RewindWrite(static_cast(pos));
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readByteArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ uint32_t arrayBufferLength = napiParcel->nativeParcel_->ReadUint32();
+ NAPI_ASSERT(env, arrayBufferLength < 40960, "byte array length too large");
+ size_t len = (arrayBufferLength / 4) + (arrayBufferLength % 4 == 0 ? 0 : 1);
+ DBINDER_LOGI("messageparcel WriteBuffer typedarrayLength = %{public}d", (int)(len));
+
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, len, BYTE_SIZE_32, napiParcel);
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isTypedArray;
+ napi_is_typedarray(env, argv[0], &isTypedArray);
+ NAPI_ASSERT(env, isTypedArray == true, "type mismatch for parameter 1");
+
+ napi_typedarray_type arrayType;
+ size_t arrayLength = 0;
+ void *arrayBufferPtr = nullptr;
+ napi_value tmpArrayBuffer = nullptr;
+ size_t byteOffset = 0;
+ napi_get_typedarray_info(env, argv[0], &arrayType, &arrayLength, &arrayBufferPtr,
+ &tmpArrayBuffer, &byteOffset);
+ NAPI_ASSERT(env, arrayType == napi_int8_array, "array type mismatch for parameter 1");
+ NAPI_ASSERT(env, arrayLength == arrayBufferLength, "array size mismatch for length");
+
+ const uint8_t *arrayAddr = napiParcel->nativeParcel_->ReadUnpadBuffer(arrayBufferLength);
+ NAPI_ASSERT(env, arrayAddr != nullptr, "buffer is nullptr");
+ errno_t status = memcpy_s(arrayBufferPtr, arrayBufferLength, arrayAddr, arrayBufferLength);
+ NAPI_ASSERT(env, status == EOK, "memcpy_s is failed");
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ CHECK_READ_LENGTH(env, len, BYTE_SIZE_32, napiParcel);
+ napi_value arrayBuffer = nullptr;
+ void *arrayBufferPtr = nullptr;
+ napi_create_arraybuffer(env, arrayBufferLength, &arrayBufferPtr, &arrayBuffer);
+ napi_value typedarray = nullptr;
+ napi_create_typedarray(env, napi_int8_array, arrayBufferLength, arrayBuffer, 0, &typedarray);
+ if (arrayBufferLength == 0) {
+ return typedarray;
+ }
+
+ const uint8_t *arrayAddr = napiParcel->nativeParcel_->ReadUnpadBuffer(arrayBufferLength);
+ NAPI_ASSERT(env, arrayAddr != nullptr, "buffer is nullptr");
+ errno_t status = memcpy_s(arrayBufferPtr, arrayBufferLength, arrayAddr, arrayBufferLength);
+ NAPI_ASSERT(env, status == EOK, "memcpy_s is failed");
+ return typedarray;
+}
+
+napi_value NAPI_MessageParcel::JS_readShortArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int16_t val = napiParcel->nativeParcel_->ReadInt16();
+ napi_value num = nullptr;
+ napi_create_int32(env, val, &num);
+ napi_set_element(env, argv[0], i, num);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int16_t val = napiParcel->nativeParcel_->ReadInt16();
+ napi_value num = nullptr;
+ napi_create_int32(env, val, &num);
+ napi_set_element(env, result, i, num);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readIntArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int32_t val = napiParcel->nativeParcel_->ReadInt32();
+ napi_value num = nullptr;
+ napi_create_int32(env, val, &num);
+ napi_set_element(env, argv[0], i, num);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int32_t val = napiParcel->nativeParcel_->ReadInt32();
+ napi_value num = nullptr;
+ napi_create_int32(env, val, &num);
+ napi_set_element(env, result, i, num);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readLongArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_64, napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int64_t val = napiParcel->nativeParcel_->ReadInt64();
+ napi_value num = nullptr;
+ napi_create_int64(env, val, &num);
+ napi_set_element(env, argv[0], i, num);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_64, napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int64_t val = napiParcel->nativeParcel_->ReadInt64();
+ napi_value num = nullptr;
+ napi_create_int64(env, val, &num);
+ napi_set_element(env, result, i, num);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readFloatArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, sizeof(double), napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ // float val = napiParcel->nativeParcel_->ReadFloat();
+ double val = napiParcel->nativeParcel_->ReadDouble();
+ napi_value num = nullptr;
+ napi_create_double(env, val, &num);
+ napi_set_element(env, argv[0], i, num);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, sizeof(double), napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ // float val = napiParcel->nativeParcel_->ReadFloat();
+ double val = napiParcel->nativeParcel_->ReadDouble();
+ napi_value num = nullptr;
+ napi_create_double(env, val, &num);
+ napi_set_element(env, result, i, num);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readDoubleArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, sizeof(double), napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ double val = napiParcel->nativeParcel_->ReadDouble();
+ napi_value num = nullptr;
+ napi_create_double(env, val, &num);
+ napi_set_element(env, argv[0], i, num);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, sizeof(double), napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ double val = napiParcel->nativeParcel_->ReadDouble();
+ napi_value num = nullptr;
+ napi_create_double(env, val, &num);
+ napi_set_element(env, result, i, num);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readBooleanArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int8_t val = napiParcel->nativeParcel_->ReadInt8();
+ napi_value boolean = nullptr;
+ napi_get_boolean(env, val, &boolean);
+ napi_set_element(env, argv[0], i, boolean);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ int8_t val = napiParcel->nativeParcel_->ReadInt8();
+ napi_value boolean = nullptr;
+ napi_get_boolean(env, val, &boolean);
+ napi_set_element(env, result, i, boolean);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readCharArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ uint16_t val = napiParcel->nativeParcel_->ReadUint16();
+ napi_value num = nullptr;
+ napi_create_uint32(env, val, &num);
+ napi_set_element(env, argv[0], i, num);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ if (arrayLength <= 0) {
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ return result;
+ }
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value result = nullptr;
+ napi_create_array_with_length(env, arrayLength, &result);
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ uint16_t val = napiParcel->nativeParcel_->ReadUint16();
+ napi_value num = nullptr;
+ napi_create_uint32(env, val, &num);
+ napi_set_element(env, result, i, num);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readStringArray(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ int32_t arrayLength = napiParcel->nativeParcel_->ReadInt32();
+ if (argc > 0) {
+ NAPI_ASSERT(env, argc == 1, "type mismatch for parameter 1");
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value argv[1] = {0};
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+
+ bool isArray;
+ napi_is_array(env, argv[0], &isArray);
+ NAPI_ASSERT(env, isArray == true, "type mismatch for parameter 1");
+
+ for (int32_t i = 0; i < arrayLength; i++) {
+ if (napiParcel->nativeParcel_->GetReadableBytes() <= 0) {
+ break;
+ }
+ std::u16string parcelString = napiParcel->nativeParcel_->ReadString16();
+ std::string outString = Str16ToStr8(parcelString.c_str());
+ napi_value val = nullptr;
+ napi_create_string_utf8(env, outString.c_str(), outString.length(), &val);
+ napi_set_element(env, argv[0], i, val);
+ }
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, true, &napiValue));
+ return napiValue;
+ }
+
+ CHECK_READ_LENGTH(env, (size_t)arrayLength, BYTE_SIZE_32, napiParcel)
+ napi_value result = nullptr;
+ napi_create_array(env, &result);
+ for (int32_t i = 0; i < arrayLength; i++) {
+ if (napiParcel->nativeParcel_->GetReadableBytes() <= 0) {
+ break;
+ }
+ std::u16string parcelString = napiParcel->nativeParcel_->ReadString16();
+ std::string outString = Str16ToStr8(parcelString.c_str());
+ napi_value val = nullptr;
+ napi_create_string_utf8(env, outString.c_str(), outString.length(), &val);
+ napi_set_element(env, result, i, val);
+ }
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_readSequenceable(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void **)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ int32_t len = napiParcel->nativeParcel_->ReadInt32();
+ bool result = false;
+ if (len > 0) {
+ napi_value propKey = nullptr;
+ const char* propKeyStr = "unmarshalling";
+ napi_create_string_utf8(env, propKeyStr, strlen(propKeyStr), &propKey);
+ napi_value prop = nullptr;
+ napi_get_property(env, argv[0], propKey, &prop);
+
+ napi_value funcArg[1] = {thisVar};
+ napi_value callResult = nullptr;
+ result = napi_call_function(env, thisVar, prop, 1, funcArg, &callResult);
+ }
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_create(napi_env env, napi_callback_info info)
+{
+ // new native parcel object
+ napi_value constructor = nullptr;
+ napi_status status = napi_get_reference_value(env, g_messageParcelConsRef, &constructor);
+ NAPI_ASSERT(env, constructor != nullptr, "failed to get js MessageParcel constructor");
+ napi_value jsMessageParcel;
+ status = napi_new_instance(env, constructor, 0, nullptr, &jsMessageParcel);
+ NAPI_ASSERT(env, status == napi_ok, "failed to construct js MessageParcel");
+ return jsMessageParcel;
+}
+
+napi_value NAPI_MessageParcel::JS_reclaim(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_remove_wrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ delete napiParcel;
+ // napiParcel->nativeParcel_->FlushBuffer();
+
+ napi_value result = nullptr;
+ napi_get_undefined(env, &result);
+ return result;
+}
+
+napi_value NAPI_MessageParcel::JS_writeRemoteObject(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_value napiValue = nullptr;
+ sptr remoteObject = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
+ if (remoteObject == nullptr) {
+ NAPI_CALL(env, napi_get_boolean(env, false, &napiValue));
+ return napiValue;
+ }
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+ //sptr remoteObject = sptr(reinterpret_cast(value));
+ bool result = napiParcel->nativeParcel_->WriteRemoteObject(remoteObject);
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readRemoteObject(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ sptr value = napiParcel->nativeParcel_->ReadRemoteObject();
+ napi_value napiValue = NAPI_ohos_rpc_CreateJsRemoteObject(env, value);
+ //NAPI_CALL(env, napi_create_external(env, (void*)value.GetRefPtr(), nullptr, nullptr, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_writeInterfaceToken(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter");
+
+ size_t bufferSize = 0;
+ napi_get_value_string_utf8(env, argv[0], nullptr, 0, &bufferSize);
+ NAPI_ASSERT(env, bufferSize < 40960, "string length too large");
+
+ char stringValue[bufferSize + 1];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, argv[0], stringValue, bufferSize + 1, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == bufferSize, "string length wrong");
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT(env, napiParcel != nullptr, "napiParcel is null");
+
+ std::string parcelString = stringValue;
+ bool result = napiParcel->nativeParcel_->WriteInterfaceToken(to_utf16(parcelString));
+
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::JS_readInterfaceToken(napi_env env, napi_callback_info info)
+{
+ size_t argc = 0;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, nullptr, &thisVar, nullptr);
+
+ NAPI_MessageParcel *napiParcel = nullptr;
+ napi_unwrap(env, thisVar, (void**)&napiParcel);
+ NAPI_ASSERT_BASE(env, napiParcel != nullptr, "napiParcel is null", 0);
+
+ std::u16string parcelString = napiParcel->nativeParcel_->ReadInterfaceToken();
+ std::string outString = Str16ToStr8(parcelString.c_str());
+ napi_value napiValue = nullptr;
+ napi_create_string_utf8(env, outString.c_str(), outString.length(), &napiValue);
+ return napiValue;
+}
+
+napi_value NAPI_MessageParcel::Export(napi_env env, napi_value exports)
+{
+ const std::string className = "MessageParcel";
+ napi_property_descriptor properties[] = {
+ DECLARE_NAPI_STATIC_FUNCTION("create", NAPI_MessageParcel::JS_create),
+ DECLARE_NAPI_FUNCTION("reclaim", NAPI_MessageParcel::JS_reclaim),
+ DECLARE_NAPI_FUNCTION("writeByte", NAPI_MessageParcel::JS_writeByte),
+ DECLARE_NAPI_FUNCTION("writeShort", NAPI_MessageParcel::JS_writeShort),
+ DECLARE_NAPI_FUNCTION("writeInt", NAPI_MessageParcel::JS_writeInt),
+ DECLARE_NAPI_FUNCTION("writeLong", NAPI_MessageParcel::JS_writeLong),
+ DECLARE_NAPI_FUNCTION("writeFloat", NAPI_MessageParcel::JS_writeFloat),
+ DECLARE_NAPI_FUNCTION("writeDouble", NAPI_MessageParcel::JS_writeDouble),
+ DECLARE_NAPI_FUNCTION("writeBoolean", NAPI_MessageParcel::JS_writeBoolean),
+ DECLARE_NAPI_FUNCTION("writeChar", NAPI_MessageParcel::JS_writeChar),
+ DECLARE_NAPI_FUNCTION("writeStringWithLength", NAPI_MessageParcel::JS_writeStringWithLength),
+ DECLARE_NAPI_FUNCTION("writeString", NAPI_MessageParcel::JS_writeString),
+ DECLARE_NAPI_FUNCTION("writeByteArray", NAPI_MessageParcel::JS_writeByteArray),
+ DECLARE_NAPI_FUNCTION("readByte", NAPI_MessageParcel::JS_readByte),
+ DECLARE_NAPI_FUNCTION("readShort", NAPI_MessageParcel::JS_readShort),
+ DECLARE_NAPI_FUNCTION("readInt", NAPI_MessageParcel::JS_readInt),
+ DECLARE_NAPI_FUNCTION("readLong", NAPI_MessageParcel::JS_readLong),
+ DECLARE_NAPI_FUNCTION("readFloat", NAPI_MessageParcel::JS_readFloat),
+ DECLARE_NAPI_FUNCTION("readDouble", NAPI_MessageParcel::JS_readDouble),
+ DECLARE_NAPI_FUNCTION("readBoolean", NAPI_MessageParcel::JS_readBoolean),
+ DECLARE_NAPI_FUNCTION("readChar", NAPI_MessageParcel::JS_readChar),
+ DECLARE_NAPI_FUNCTION("readString", NAPI_MessageParcel::JS_readString),
+ DECLARE_NAPI_FUNCTION("writeRemoteObject", NAPI_MessageParcel::JS_writeRemoteObject),
+ DECLARE_NAPI_FUNCTION("readRemoteObject", NAPI_MessageParcel::JS_readRemoteObject),
+ DECLARE_NAPI_FUNCTION("writeInterfaceToken", NAPI_MessageParcel::JS_writeInterfaceToken),
+ DECLARE_NAPI_FUNCTION("readInterfaceToken", NAPI_MessageParcel::JS_readInterfaceToken),
+ DECLARE_NAPI_FUNCTION("getSize", NAPI_MessageParcel::JS_getSize),
+ DECLARE_NAPI_FUNCTION("getCapacity", NAPI_MessageParcel::JS_getCapacity),
+ DECLARE_NAPI_FUNCTION("setSize", NAPI_MessageParcel::JS_setSize),
+ DECLARE_NAPI_FUNCTION("setCapacity", NAPI_MessageParcel::JS_setCapacity),
+ DECLARE_NAPI_FUNCTION("getWritableBytes", NAPI_MessageParcel::JS_getWritableBytes),
+ DECLARE_NAPI_FUNCTION("getReadableBytes", NAPI_MessageParcel::JS_getReadableBytes),
+ DECLARE_NAPI_FUNCTION("getReadPosition", NAPI_MessageParcel::JS_getReadPosition),
+ DECLARE_NAPI_FUNCTION("getWritePosition", NAPI_MessageParcel::JS_getWritePosition),
+ DECLARE_NAPI_FUNCTION("rewindWrite", NAPI_MessageParcel::JS_rewindWrite),
+ DECLARE_NAPI_FUNCTION("rewindRead", NAPI_MessageParcel::JS_rewindRead),
+ DECLARE_NAPI_FUNCTION("writeSequenceable", NAPI_MessageParcel::JS_writeSequenceable),
+ DECLARE_NAPI_FUNCTION("writeShortArray", NAPI_MessageParcel::JS_writeShortArray),
+ DECLARE_NAPI_FUNCTION("writeIntArray", NAPI_MessageParcel::JS_writeIntArray),
+ DECLARE_NAPI_FUNCTION("writeLongArray", NAPI_MessageParcel::JS_writeLongArray),
+ DECLARE_NAPI_FUNCTION("writeFloatArray", NAPI_MessageParcel::JS_writeFloatArray),
+ DECLARE_NAPI_FUNCTION("writeDoubleArray", NAPI_MessageParcel::JS_writeDoubleArray),
+ DECLARE_NAPI_FUNCTION("writeBooleanArray", NAPI_MessageParcel::JS_writeBooleanArray),
+ DECLARE_NAPI_FUNCTION("writeCharArray", NAPI_MessageParcel::JS_writeCharArray),
+ DECLARE_NAPI_FUNCTION("writeStringArray", NAPI_MessageParcel::JS_writeStringArray),
+ DECLARE_NAPI_FUNCTION("writeSequenceableArray", NAPI_MessageParcel::JS_writeSequenceableArray),
+ DECLARE_NAPI_FUNCTION("readSequenceable", NAPI_MessageParcel::JS_readSequenceable),
+ DECLARE_NAPI_FUNCTION("readByteArray", NAPI_MessageParcel::JS_readByteArray),
+ DECLARE_NAPI_FUNCTION("readShortArray", NAPI_MessageParcel::JS_readShortArray),
+ DECLARE_NAPI_FUNCTION("readIntArray", NAPI_MessageParcel::JS_readIntArray),
+ DECLARE_NAPI_FUNCTION("readLongArray", NAPI_MessageParcel::JS_readLongArray),
+ DECLARE_NAPI_FUNCTION("readFloatArray", NAPI_MessageParcel::JS_readFloatArray),
+ DECLARE_NAPI_FUNCTION("readDoubleArray", NAPI_MessageParcel::JS_readDoubleArray),
+ DECLARE_NAPI_FUNCTION("readBooleanArray", NAPI_MessageParcel::JS_readBooleanArray),
+ DECLARE_NAPI_FUNCTION("readCharArray", NAPI_MessageParcel::JS_readCharArray),
+ DECLARE_NAPI_FUNCTION("readStringArray", NAPI_MessageParcel::JS_readStringArray),
+ };
+ napi_define_class(env, className.c_str(), className.length(), JS_Constructor, nullptr,
+ sizeof(properties) / sizeof(properties[0]), properties, &g_messageParcelConstructor);
+ NAPI_ASSERT(env, g_messageParcelConstructor != nullptr, "define js class MessageParcel failed");
+ napi_status status = napi_set_named_property(env, exports, "MessageParcel", g_messageParcelConstructor);
+ NAPI_ASSERT(env, status == napi_ok, "set property MessageParcel failed");
+ status = napi_create_reference(env, g_messageParcelConstructor, 1, &g_messageParcelConsRef);
+ NAPI_ASSERT(env, status == napi_ok, "create ref to js MessageParcel constructor failed");
+ return exports;
+}
+
+napi_value NAPI_MessageParcel::JS_Constructor(napi_env env, napi_callback_info info)
+{
+ napi_value thisVar = nullptr;
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, status == napi_ok, "napi get callback info failed");
+ MessageParcel* parcel = nullptr;
+ if (argv[0] != nullptr) {
+ int64_t tmp = 0;
+ napi_get_value_int64(env, argv[0], &tmp);
+ parcel = reinterpret_cast(tmp);
+ DBINDER_LOGI("parcel addr:%{public}p, %{public}p", parcel, (void*)(tmp));
+ NAPI_ASSERT(env, parcel != nullptr, "parcel is null");
+ }
+ // new native parcel object
+ auto messageParcel = new NAPI_MessageParcel(env, thisVar, parcel);
+ // connect native object to js thisVar
+ status = napi_wrap(
+ env, thisVar, messageParcel,
+ [](napi_env env, void *data, void *hint) {
+ DBINDER_LOGI("NAPI_MessageParcel:%{public}p destructed by js callback", data);
+ delete (reinterpret_cast(data));
+ },
+ nullptr, nullptr);
+ NAPI_ASSERT(env, status == napi_ok, "napi wrap message parcel failed");
+ return thisVar;
+}
+
+napi_ref NAPI_MessageParcel::getParcelConsRef()
+{
+ return g_messageParcelConsRef;
+}
+} // namespace OHOS
diff --git a/ipc/native/src/napi/src/napi_remote_object.cpp b/ipc/native/src/napi/src/napi_remote_object.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..631c3327599ec60131a018d0ca0ed5c546408793
--- /dev/null
+++ b/ipc/native/src/napi/src/napi_remote_object.cpp
@@ -0,0 +1,1405 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "napi_remote_object.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "napi_message_parcel.h"
+#include "napi_message_option.h"
+#include "hilog/log.h"
+#include "log_tags.h"
+#include "ipc_object_stub.h"
+#include "ipc_object_proxy.h"
+#include "ipc_thread_skeleton.h"
+#include "ipc_skeleton.h"
+#include "ipc_types.h"
+#include "string_ex.h"
+//#include "dnetwork_adapter.h"
+
+namespace OHOS {
+static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_IPC, "napi_remoteObject" };
+#ifndef TITLE
+#define TITLE __PRETTY_FUNCTION__
+#endif
+#define DBINDER_LOGE(fmt, args...) \
+ (void)OHOS::HiviewDFX::HiLog::Error(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
+#define DBINDER_LOGI(fmt, args...) \
+ (void)OHOS::HiviewDFX::HiLog::Info(LOG_LABEL, "%{public}s %{public}d: " fmt, TITLE, __LINE__, ##args)
+
+/*
+ * The native DeathRecipient container.
+ * As an recipient of obituary of service death,
+ * and pass the message to js Layer.
+ */
+class NAPIDeathRecipient : public IRemoteObject::DeathRecipient {
+public:
+ explicit NAPIDeathRecipient(napi_env env, napi_value jsRecipient);
+
+ void OnRemoteDied(const wptr &object) override;
+
+ bool Matches(napi_value jsRecipient);
+
+protected:
+ virtual ~NAPIDeathRecipient();
+
+private:
+ std::mutex mutex_;
+ napi_env env_ = nullptr;
+ napi_ref deathRecipientRef_ = nullptr;
+};
+
+NAPIDeathRecipient::NAPIDeathRecipient(napi_env env, napi_value jsDeathRecipient)
+{
+ env_ = env;
+ napi_status status = napi_create_reference(env_, jsDeathRecipient, 1, &deathRecipientRef_);
+ NAPI_ASSERT_RETURN_VOID(env, status == napi_ok, "failed to create ref to js death recipient");
+}
+
+NAPIDeathRecipient::~NAPIDeathRecipient()
+{
+ if (env_ != nullptr) {
+ if (deathRecipientRef_ != nullptr) {
+ napi_status status = napi_delete_reference(env_, deathRecipientRef_);
+ NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js death recipient");
+ deathRecipientRef_ = nullptr;
+ }
+ }
+}
+
+void NAPIDeathRecipient::OnRemoteDied(const wptr &object)
+{
+ DBINDER_LOGI("OnRemoteDied called");
+ if (deathRecipientRef_ == nullptr) {
+ DBINDER_LOGE("js death recipient has already removed");
+ return;
+ }
+ napi_value jsDeathRecipient = nullptr;
+ napi_get_reference_value(env_, deathRecipientRef_, &jsDeathRecipient);
+ NAPI_ASSERT_RETURN_VOID(env_, jsDeathRecipient != nullptr, "failed to get js death recipient");
+ napi_value onRemoteDied = nullptr;
+ napi_get_named_property(env_, jsDeathRecipient, "onRemoteDied", &onRemoteDied);
+ NAPI_ASSERT_RETURN_VOID(env_, onRemoteDied != nullptr, "failed to get property onRemoteDied");
+ napi_value return_val = nullptr;
+ napi_status status = napi_call_function(env_, jsDeathRecipient, onRemoteDied, 0, nullptr, &return_val);
+ NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to call function onRemoteDied");
+
+ std::lock_guard lockGuard(mutex_);
+ napi_delete_reference(env_, deathRecipientRef_);
+ deathRecipientRef_ = nullptr;
+}
+
+bool NAPIDeathRecipient::Matches(napi_value object)
+{
+ bool result = false;
+ if (object != nullptr) {
+ std::lock_guard lockGuard(mutex_);
+ if (deathRecipientRef_ != nullptr) {
+ napi_value jsDeathRecipient = nullptr;
+ napi_get_reference_value(env_, deathRecipientRef_, &jsDeathRecipient);
+ napi_status status = napi_strict_equals(env_, object, jsDeathRecipient, &result);
+ if (status != napi_ok) {
+ DBINDER_LOGI("compares death recipients failed");
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * List of native NAPIDeathRecipient
+ */
+class NAPIDeathRecipientList : public RefBase {
+public:
+ NAPIDeathRecipientList();
+
+ ~NAPIDeathRecipientList();
+
+ bool Add(const sptr &recipient);
+
+ bool Remove(const sptr &recipient);
+
+ sptr Find(napi_value jsRecipient);
+private:
+ std::mutex mutex_;
+ std::set> set_;
+};
+
+NAPIDeathRecipientList::NAPIDeathRecipientList() {}
+
+NAPIDeathRecipientList::~NAPIDeathRecipientList()
+{
+ std::lock_guard lockGuard(mutex_);
+ set_.clear();
+}
+
+bool NAPIDeathRecipientList::Add(const sptr &recipient)
+{
+ std::lock_guard lockGuard(mutex_);
+ auto ret = set_.insert(recipient);
+ return ret.second;
+}
+
+bool NAPIDeathRecipientList::Remove(const sptr &recipient)
+{
+ std::lock_guard lockGuard(mutex_);
+ return (set_.erase(recipient) > 0);
+}
+
+sptr NAPIDeathRecipientList::Find(napi_value jsRecipient)
+{
+ std::lock_guard lockGuard(mutex_);
+ for (auto it = set_.begin(); it != set_.end(); it++) {
+ if ((*it)->Matches(jsRecipient)) {
+ return *it;
+ }
+ }
+ return nullptr;
+}
+
+class NAPIRemoteProxyHolder {
+public:
+ NAPIRemoteProxyHolder();
+ ~NAPIRemoteProxyHolder();
+ sptr list_;
+ sptr object_;
+};
+
+NAPIRemoteProxyHolder::NAPIRemoteProxyHolder() : list_(nullptr), object_(nullptr) {}
+
+NAPIRemoteProxyHolder::~NAPIRemoteProxyHolder()
+{
+ list_ = nullptr;
+ object_ = nullptr;
+}
+
+namespace {
+ napi_value g_remoteStubConstructor = nullptr;
+ napi_ref g_remoteStubConsRef = nullptr;
+ napi_value g_remoteProxyConstructor = nullptr;
+ napi_ref g_remoteProxyConsRef = nullptr;
+ napi_value g_messageOptionConstructor = nullptr;
+ napi_ref g_messageOptionConsRef = nullptr;
+}
+
+napi_value RemoteProxy_JS_Constructor(napi_env env, napi_callback_info info)
+{
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
+ // new napi proxy holder instance
+ auto proxyHolder = new NAPIRemoteProxyHolder();
+ // connect native object to js thisVar
+ napi_status status = napi_wrap(
+ env, thisVar, proxyHolder,
+ [](napi_env env, void *data, void *hint) {
+ DBINDER_LOGI("proxy holder destructed by js callback");
+ delete (reinterpret_cast(data));
+ },
+ nullptr, nullptr);
+ NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteProxy and native holder failed");
+ return thisVar;
+}
+
+EXTERN_C_START
+/*
+ * function for module exports
+ */
+napi_value NAPIRemoteProxyExport(napi_env env, napi_value exports)
+{
+ const std::string className = "RemoteProxy";
+ napi_property_descriptor properties[] = {
+ DECLARE_NAPI_FUNCTION("sendRequest", NAPI_RemoteProxy_sendRequest),
+ DECLARE_NAPI_FUNCTION("addDeathRecipient", NAPI_RemoteProxy_addDeathRecipient),
+ DECLARE_NAPI_FUNCTION("removeDeathRecipient", NAPI_RemoteProxy_removeDeathRecipient),
+ DECLARE_NAPI_FUNCTION("getInterfaceDescriptor", NAPI_RemoteProxy_getInterfaceDescriptor),
+ DECLARE_NAPI_FUNCTION("isObjectDead", NAPI_RemoteProxy_isObjectDead),
+ DECLARE_NAPI_FUNCTION("getHandle", NAPI_RemoteProxy_getHandle),
+ };
+ napi_define_class(env, className.c_str(), className.length(), RemoteProxy_JS_Constructor, nullptr,
+ sizeof(properties) / sizeof(properties[0]), properties, &g_remoteProxyConstructor);
+ NAPI_ASSERT(env, g_remoteProxyConstructor != nullptr, "define js class RemoteProxy failed");
+ napi_status status = napi_set_named_property(env, exports, "RemoteProxy", g_remoteProxyConstructor);
+ NAPI_ASSERT(env, status == napi_ok, "set property RemoteProxy to exports failed");
+ status = napi_create_reference(env, g_remoteProxyConstructor, 1, &g_remoteProxyConsRef);
+ NAPI_ASSERT(env, status == napi_ok, "create ref to js RemoteProxy constructor failed");
+ return exports;
+}
+EXTERN_C_END
+
+/*
+ * The native NAPIRemoteObject act as bridger between js and native.
+ * It received the request from client and pass it js Layer.
+ */
+class NAPIRemoteObject : public IPCObjectStub {
+public:
+ NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor);
+
+ ~NAPIRemoteObject() override;
+
+ bool CheckObjectLegality() const override;
+
+ int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
+
+ napi_ref GetJsObjectRef() const;
+private:
+ napi_env env_ = nullptr;
+ napi_value thisVar_ = nullptr;
+ napi_ref thisVarRef_ = nullptr;
+ struct ThreadLockInfo {
+ std::mutex mutex;
+ std::condition_variable condition;
+ bool ready = false;
+ };
+ struct CallbackParam {
+ napi_env env;
+ napi_ref thisVarRef;
+ uint32_t code;
+ MessageParcel *data;
+ MessageParcel *reply;
+ MessageOption *option;
+ pid_t callingPid;
+ pid_t callingUid;
+ std::string callingDeviceID;
+ std::string localDeviceID;
+ ThreadLockInfo *lockInfo;
+ int result;
+ };
+ void OnJsRemoteRequest(CallbackParam *param);
+};
+
+/*
+ * To ensure a better consistency of the life time of
+ * js RemoteObject and native object, we designed
+ * a container to save the native object.
+ */
+class NAPIRemoteObjectHolder : public RefBase {
+public:
+ explicit NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor);
+ ~NAPIRemoteObjectHolder();
+ sptr Get(napi_value object);
+
+private:
+ std::mutex mutex_;
+ napi_env env_ = nullptr;
+ std::u16string descriptor_;
+ sptr cachedObject_;
+};
+
+NAPIRemoteObjectHolder::NAPIRemoteObjectHolder(napi_env env, const std::u16string &descriptor)
+ : env_(env), descriptor_(descriptor), cachedObject_(nullptr)
+{}
+
+NAPIRemoteObjectHolder::~NAPIRemoteObjectHolder()
+{
+ // free the reference of object.
+ cachedObject_ = nullptr;
+}
+
+sptr NAPIRemoteObjectHolder::Get(napi_value jsRemoteObject)
+{
+ std::lock_guard lockGuard(mutex_);
+ // grab an strong reference to the object,
+ // so it will not be freed util this reference released.
+ sptr remoteObject = nullptr;
+ if (cachedObject_ != nullptr) {
+ remoteObject = cachedObject_;
+ }
+
+ if (remoteObject == nullptr) {
+ remoteObject = new NAPIRemoteObject(env_, jsRemoteObject, descriptor_);
+ cachedObject_ = remoteObject;
+ }
+ return remoteObject;
+}
+
+napi_value RemoteObject_JS_Constructor(napi_env env, napi_callback_info info)
+{
+ // new napi remote object
+ size_t argc = 2;
+ napi_value argv[2] = { 0 };
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
+
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+
+ uint32_t stringLength = 0;
+ napi_get_value_uint32(env, argv[1], &stringLength);
+ NAPI_ASSERT(env, stringLength < 40960, "string length too large");
+
+ char stringValue[stringLength];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, argv[0], stringValue, stringLength, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == stringLength, "string length wrong");
+ std::string descriptor = stringValue;
+
+ auto holder = new NAPIRemoteObjectHolder(env, to_utf16(descriptor));
+ // connect native object to js thisVar
+ napi_status status = napi_wrap(
+ env, thisVar, holder,
+ [](napi_env env, void *data, void *hint) {
+ DBINDER_LOGI("NAPIRemoteObjectHolder destructed by js callback");
+ delete (reinterpret_cast(data));
+ },
+ nullptr, nullptr);
+ NAPI_ASSERT(env, status == napi_ok, "wrap js RemoteObject and native holder failed");
+ return thisVar;
+}
+
+EXTERN_C_START
+/*
+ * function for module exports
+ */
+napi_value NAPIRemoteObjectExport(napi_env env, napi_value exports)
+{
+ const std::string className = "RemoteObject";
+ napi_property_descriptor properties[] = {
+ DECLARE_NAPI_FUNCTION("getCallingPid", NAPI_RemoteObject_getCallingPid),
+ DECLARE_NAPI_FUNCTION("getCallingUid", NAPI_RemoteObject_getCallingUid),
+ };
+ napi_define_class(env, className.c_str(), className.length(), RemoteObject_JS_Constructor, nullptr,
+ sizeof(properties)/sizeof(properties[0]), properties, &g_remoteStubConstructor);
+ NAPI_ASSERT(env, g_remoteStubConstructor != nullptr, "define js class RemoteObject failed");
+ napi_status status = napi_set_named_property(env, exports, "RemoteObject", g_remoteStubConstructor);
+ NAPI_ASSERT(env, status == napi_ok, "set property RemoteObject to exports failed");
+ status = napi_create_reference(env, g_remoteStubConstructor, 1, &g_remoteStubConsRef);
+ NAPI_ASSERT(env, status == napi_ok, "create ref to js RemoteObject constructor failed");
+ return exports;
+}
+EXTERN_C_END
+
+NAPIRemoteObject::NAPIRemoteObject(napi_env env, napi_value thisVar, const std::u16string &descriptor) : IPCObjectStub(descriptor)
+{
+ env_ = env;
+ thisVar_ = thisVar;
+ napi_create_reference(env, thisVar_, 1, &thisVarRef_);
+ NAPI_ASSERT_RETURN_VOID(env, thisVarRef_ != nullptr, "failed to create ref to js RemoteObject");
+}
+
+NAPIRemoteObject::~NAPIRemoteObject()
+{
+ DBINDER_LOGI("NAPIRemoteObject Destructor");
+ if (thisVarRef_ != nullptr) {
+ napi_status status = napi_delete_reference(env_, thisVarRef_);
+ NAPI_ASSERT_RETURN_VOID(env_, status == napi_ok, "failed to delete ref to js RemoteObject");
+ thisVarRef_ = nullptr;
+ }
+}
+
+bool NAPIRemoteObject::CheckObjectLegality() const
+{
+ return true;
+}
+
+napi_ref NAPIRemoteObject::GetJsObjectRef() const
+{
+ return thisVarRef_;
+}
+
+int NAPIRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
+{
+
+ DBINDER_LOGI("enter OnRemoteRequest");
+ if (code == DUMP_TRANSACTION) {
+ DBINDER_LOGE("DUMP_TRANSACTION data size:%zu", data.GetReadableBytes());
+ }
+ pid_t callingPid = IPCSkeleton::GetCallingPid();
+ pid_t callingUid = IPCSkeleton::GetCallingUid();
+ std::string callingDeviceID = IPCSkeleton::GetCallingDeviceID();
+ std::string localDeviceID = IPCSkeleton::GetLocalDeviceID();
+ DBINDER_LOGI("callingPid:%{public}u, callingUid:%{public}u, callingDeviceID:%{public}s, localDeviceId:%{public}s",
+ callingPid, callingUid, callingDeviceID.c_str(), localDeviceID.c_str());
+ std::shared_ptr lockInfo = std::make_shared();
+ CallbackParam* param = new (std::nothrow) CallbackParam{ .env = env_, .thisVarRef = thisVarRef_, .code = code, .data = &data,
+ .reply = &reply, .option = &option, .lockInfo = lockInfo.get(), .callingPid = callingPid, .callingUid = callingUid,
+ .callingDeviceID = callingDeviceID, .localDeviceID = localDeviceID, .result = 0 };
+ OnJsRemoteRequest(param);
+ DBINDER_LOGI("OnJsRemoteRequest done");
+ int ret = param->result;
+ delete param;
+ return ret;
+}
+
+void NAPIRemoteObject::OnJsRemoteRequest(CallbackParam *jsParam)
+{
+ uv_loop_s *loop = nullptr;
+ napi_get_uv_event_loop(env_, &loop);
+
+ uv_work_t *work = new(std::nothrow) uv_work_t;
+ if (work == nullptr) {
+ DBINDER_LOGE("failed to new uv_work_t");
+ // delete jsCb;
+ jsParam->result = -1;
+ return ;
+ }
+ work->data = reinterpret_cast(jsParam);
+ DBINDER_LOGI("start nv queue work loop");
+ uv_queue_work(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) {
+ DBINDER_LOGI("enter thread pool");
+ // Js Thread
+ CallbackParam *param = reinterpret_cast(work->data);
+ napi_value onRemoteRequest = nullptr;
+ napi_value thisVar = nullptr;
+ napi_get_reference_value(param->env, param->thisVarRef, &thisVar);
+ if (thisVar == nullptr) {
+ DBINDER_LOGE("thisVar is null");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ napi_get_named_property(param->env, thisVar, "onRemoteRequest", &onRemoteRequest);
+ if (onRemoteRequest == nullptr) {
+ DBINDER_LOGE("get founction onRemoteRequest failed");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ // create jsCode
+ napi_value jsCode;
+ napi_create_uint32(param->env, param->code, &jsCode);
+
+ // create jsOption
+ napi_value jsOptionConstructor = nullptr;
+ napi_get_reference_value(param->env, g_messageOptionConsRef, &jsOptionConstructor);
+ if (jsOptionConstructor == nullptr) {
+ DBINDER_LOGE("jsOption constructor is null");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ napi_value jsOption;
+ size_t argc = 2;
+ napi_value flags = nullptr;
+ napi_create_int32(param->env, param->option->GetFlags(), &flags);
+ napi_value waittime = nullptr;
+ napi_create_int32(param->env, param->option->GetWaitTime(), &waittime);
+ napi_value argv[2] = { flags, waittime };
+ napi_new_instance(param->env, jsOptionConstructor, argc, argv, &jsOption);
+ if (jsOption == nullptr) {
+ DBINDER_LOGE("new jsOption failed");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+
+ // create message parcel
+ napi_value jsParcelConstructor = nullptr;
+ napi_ref ref = NAPI_MessageParcel::getParcelConsRef();
+ napi_get_reference_value(param->env, ref, &jsParcelConstructor);
+ if (jsParcelConstructor == nullptr) {
+ DBINDER_LOGE("jsParcel constructor is null");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ napi_value jsData;
+ DBINDER_LOGI("native data parcel:%{public}p", param->data);
+ napi_value dataParcel;
+ napi_create_int64(param->env, reinterpret_cast(param->data), &dataParcel);
+ if (dataParcel == nullptr) {
+ DBINDER_LOGE("create js object for data parcel address failed");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ size_t argc3 = 1;
+ napi_value argv3[1] = { dataParcel };
+ napi_new_instance(param->env, jsParcelConstructor, argc3, argv3, &jsData);
+ if (jsData == nullptr) {
+ DBINDER_LOGE("create js data parcel failed");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ DBINDER_LOGI("native reply parcel:%{public}p", param->reply);
+ napi_value jsReply;
+ napi_value replyParcel;
+ napi_create_int64(param->env, reinterpret_cast(param->reply), &replyParcel);
+ if (replyParcel == nullptr) {
+ DBINDER_LOGE("create js object for reply parcel address failed");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ size_t argc4 = 1;
+ napi_value argv4[1] = { replyParcel };
+ napi_new_instance(param->env, jsParcelConstructor, argc4, argv4, &jsReply);
+ if (jsReply == nullptr) {
+ DBINDER_LOGE("create js reply parcel failed");
+ param->result = -1;
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+ return;
+ }
+ // save old calling pid, uid, device id
+ napi_value global;
+ napi_get_global(param->env, &global);
+ napi_value oldPid;
+ napi_get_named_property(param->env, global, "callingPid_", &oldPid);
+ napi_value oldUid;
+ napi_get_named_property(param->env, global, "callingUid_", &oldUid);
+ napi_value oldCallingDeviceID;
+ napi_get_named_property(param->env, global, "callingDeviceID_", &oldCallingDeviceID);
+ napi_value oldLocalDeviceID;
+ napi_get_named_property(param->env, global, "localDeviceID_", &oldLocalDeviceID);
+
+ // set new calling pid, uid, device id
+ napi_value newPid;
+ napi_create_int32(param->env, static_cast(param->callingPid), &newPid);
+ napi_set_named_property(param->env, global, "callingPid_", newPid);
+ napi_value newUid;
+ napi_create_int32(param->env, static_cast(param->callingUid), &newUid);
+ napi_set_named_property(param->env, global, "callingUid_", newUid);
+ napi_value newDeviceID;
+ napi_create_string_utf8(param->env, param->callingDeviceID.c_str(), param->callingDeviceID.length(), &newDeviceID);
+ napi_set_named_property(param->env, global, "callingDeviceID_", newDeviceID);
+ napi_value newLocalDeviceID;
+ napi_create_string_utf8(param->env, param->localDeviceID.c_str(), param->localDeviceID.length(), &newLocalDeviceID);
+ napi_set_named_property(param->env, global, "localDeviceID_", newLocalDeviceID);
+
+ // start to call onRemoteRequest
+ size_t argc2 = 4;
+ napi_value argv2[] = { jsCode, jsData, jsReply, jsOption };
+ napi_value return_val;
+ napi_status ret = napi_call_function(param->env, thisVar, onRemoteRequest, argc2, argv2, &return_val);
+ DBINDER_LOGI("call js onRemoteRequest done");
+ if (ret != napi_ok) {
+ DBINDER_LOGE("OnRemoteRequest got exception");
+ param->result = ERR_UNKNOWN_TRANSACTION;
+ } else {
+ bool result;
+ napi_get_value_bool(param->env, return_val, &result);
+ if (!result) {
+ DBINDER_LOGE("OnRemoteRequest res:%{public}s", result ? "true" : "false");
+ param->result = ERR_UNKNOWN_TRANSACTION;
+ } else {
+ param->result = ERR_NONE;
+ }
+ }
+
+ // reset calling pid, uid, device id
+ napi_set_named_property(param->env, global, "callingPid_", oldPid);
+ napi_set_named_property(param->env, global, "callingUid_", oldUid);
+ napi_set_named_property(param->env, global, "callingDeviceID_", oldCallingDeviceID);
+ napi_set_named_property(param->env, global, "localDeviceID_", oldLocalDeviceID);
+
+ // notify waiting binder thread
+ std::unique_lock lock(param->lockInfo->mutex);
+ param->lockInfo->ready = true;
+ param->lockInfo->condition.notify_all();
+
+ /*if (param->code == SYSPROPS_TRANSACTION) {
+ int result = IPCObjectStub::OnRemoteRequest(param->code, param->data, param->reply, param->option);
+ if (result != ERR_NONE) {
+ DBINDER_LOGE("OnRemoteRequest res:%{public}d", result);
+ param->result = ERR_INVALID_DATA;
+ return;
+ }
+ }*/
+
+ //delete event;
+ //delete work;
+ });
+ std::unique_lock lock(jsParam->lockInfo->mutex);
+ jsParam->lockInfo->condition.wait(lock, [&jsParam] { return jsParam->lockInfo->ready; });
+ //std::this_thread::sleep_for(std::chrono::milliseconds(3000));
+ DBINDER_LOGI("onJsRemoteRequestDone");
+}
+
+NAPIRemoteProxyHolder *NAPI_ohos_rpc_getRemoteProxyHolder(napi_env env, napi_value jsRemoteProxy)
+{
+ NAPIRemoteProxyHolder *proxyHolder = nullptr;
+ napi_unwrap(env, jsRemoteProxy, (void**)&proxyHolder);
+ NAPI_ASSERT(env, proxyHolder != nullptr, "failed to get napi remote proxy holder");
+ return proxyHolder;
+}
+
+napi_value NAPI_ohos_rpc_CreateJsRemoteObject(napi_env env, const sptr target)
+{
+ if (target == nullptr) {
+ DBINDER_LOGE("RemoteObject is null");
+ return nullptr;
+ }
+
+ if (target->CheckObjectLegality()) {
+ DBINDER_LOGI("napi create js remote object");
+ auto object = static_cast(target.GetRefPtr());
+ napi_ref ref = object->GetJsObjectRef();
+ napi_value jsRemoteObject;
+ napi_get_reference_value(env, ref, &jsRemoteObject);
+ NAPI_ASSERT(env, jsRemoteObject != nullptr, "failed to get js RemoteObject");
+ return jsRemoteObject;
+ }
+
+ napi_value constructor = nullptr;
+ napi_status status = napi_get_reference_value(env, g_remoteProxyConsRef, &constructor);
+ NAPI_ASSERT(env, constructor != nullptr, "failed to get js RemoteProxy constructor");
+ napi_value jsRemoteProxy;
+ status = napi_new_instance(env, constructor, 0, nullptr, &jsRemoteProxy);
+ NAPI_ASSERT(env, status == napi_ok, "failed to construct js RemoteProxy");
+ NAPIRemoteProxyHolder *proxyHolder = NAPI_ohos_rpc_getRemoteProxyHolder(env, jsRemoteProxy);
+ proxyHolder->object_ = target;
+ proxyHolder->list_ = new NAPIDeathRecipientList();
+
+ return jsRemoteProxy;
+}
+
+sptr NAPI_ohos_rpc_getNativeRemoteObject(napi_env env, napi_value object)
+{
+ if (object != nullptr) {
+ bool instanceOfStub = false;
+ napi_status status = napi_instanceof(env, object, g_remoteStubConstructor, &instanceOfStub);
+ NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
+ if (instanceOfStub) {
+ NAPIRemoteObjectHolder *holder = nullptr;
+ napi_unwrap(env, object, (void**)&holder);
+ NAPI_ASSERT(env, holder != nullptr, "failed to get napi remote object holder");
+ return holder != nullptr ? holder->Get(object) : nullptr;
+ }
+
+ bool instanceOfProxy = false;
+ status = napi_instanceof(env, object, g_remoteProxyConstructor, &instanceOfProxy);
+ NAPI_ASSERT(env, status == napi_ok, "failed to check js object type");
+ if (instanceOfProxy) {
+ NAPIRemoteProxyHolder *holder = NAPI_ohos_rpc_getRemoteProxyHolder(env, object);
+ return holder != nullptr ? holder->object_ : nullptr;
+ }
+ }
+ return nullptr;
+}
+
+napi_value NAPI_IPCSkeleton_getContextObject(napi_env env, napi_callback_info info)
+{
+ sptr object = IPCSkeleton::GetContextObject();
+ if (object == nullptr) {
+ DBINDER_LOGE("fatal error, could not get registry object");
+ return nullptr;
+ }
+ return NAPI_ohos_rpc_CreateJsRemoteObject(env, object);
+}
+
+napi_value NAPI_IPCSkeleton_getCallingPid(napi_env env, napi_callback_info info)
+{
+ napi_value global;
+ napi_get_global(env, &global);
+ napi_value callingPid;
+ napi_get_named_property(env, global, "callingPid_", &callingPid);
+ return callingPid;
+}
+
+napi_value NAPI_IPCSkeleton_getCallingUid(napi_env env, napi_callback_info info)
+{
+ napi_value global;
+ napi_get_global(env, &global);
+ napi_value callingUid;
+ napi_get_named_property(env, global, "callingUid_", &callingUid);
+ return callingUid;
+}
+
+napi_value NAPI_IPCSkeleton_getCallingDeviceID(napi_env env, napi_callback_info info)
+{
+ napi_value global;
+ napi_get_global(env, &global);
+ napi_value callingDeviceID;
+ napi_get_named_property(env, global, "callingDeviceID_", &callingDeviceID);
+ return callingDeviceID;
+}
+
+napi_value NAPI_IPCSkeleton_getLocalDeviceID(napi_env env, napi_callback_info info)
+{
+ napi_value global;
+ napi_get_global(env, &global);
+ napi_value localDeviceID;
+ napi_get_named_property(env, global, "localDeviceID_", &localDeviceID);
+ return localDeviceID;
+}
+
+napi_value NAPI_IPCSkeleton_isLocalCalling(napi_env env, napi_callback_info info)
+{
+ bool isLocal = IPCSkeleton::IsLocalCalling();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, isLocal, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_IPCSkeleton_flushCommands(napi_env env, napi_callback_info info)
+{
+ size_t argc = 1;
+ napi_value argv[1] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
+
+ sptr target = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
+ int32_t result = IPCSkeleton::FlushCommands(target);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_int32(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_IPCSkeleton_resetCallingIdentity(napi_env env, napi_callback_info info)
+{
+ std::string identity = IPCSkeleton::ResetCallingIdentity();
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_create_string_utf8(env, identity.c_str(), identity.length(), &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_IPCSkeleton_setCallingIdentity(napi_env env, napi_callback_info info)
+{
+ size_t argc = 2;
+ napi_value argv[2] = {0};
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
+
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+
+ uint32_t stringLength = 0;
+ napi_get_value_uint32(env, argv[1], &stringLength);
+ NAPI_ASSERT(env, stringLength < 40960, "string length too large");
+
+ char stringValue[stringLength];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, argv[0], stringValue, stringLength, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == stringLength, "string length wrong");
+ std::string identity = stringValue;
+ bool result = IPCSkeleton::SetCallingIdentity(identity);
+ napi_value napiValue = nullptr;
+ NAPI_CALL(env, napi_get_boolean(env, result, &napiValue));
+ return napiValue;
+}
+
+napi_value NAPI_RemoteObject_getCallingPid(napi_env env, napi_callback_info info)
+{
+ napi_value result;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
+ sptr nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
+ if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
+ IPCObjectStub *target = reinterpret_cast(nativeObject.GetRefPtr());
+ uint32_t pid = target->GetCallingPid();
+ napi_create_uint32(env, pid, &result);
+ return result;
+ }
+ uint32_t pid = getpid();
+ napi_create_uint32(env, pid, &result);
+ return result;
+}
+
+napi_value NAPI_RemoteObject_getCallingUid(napi_env env, napi_callback_info info)
+{
+ napi_value result;
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, 0, nullptr, &thisVar, nullptr);
+ sptr nativeObject = NAPI_ohos_rpc_getNativeRemoteObject(env, thisVar);
+ if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
+ IPCObjectStub *target = reinterpret_cast(nativeObject.GetRefPtr());
+ uint32_t uid = target->GetCallingUid();
+ napi_create_uint32(env, uid, &result);
+ return result;
+ }
+ uint32_t uid = getuid();
+ napi_create_uint32(env, uid, &result);
+ return result;
+}
+
+// This method runs on a worker thread, no access to the JavaScript
+void ExecuteSendRequest(napi_env env, void* data)
+{
+ SendRequestParam* param = reinterpret_cast(data);
+ param->errCode = param->target->SendRequest(param->code, param->data, param->reply, param->option);
+ DBINDER_LOGI("sendRequest done, errCode:%{public}d", param->errCode);
+}
+
+// This method runs on the main thread after 'ExecuteSendRequest' exits
+void SendRequestComplete(napi_env env, napi_status status, void* data)
+{
+ SendRequestParam* param = reinterpret_cast(data);
+ napi_value result = nullptr;
+ napi_create_int32(env, param->errCode, &result);
+ DBINDER_LOGI("sendRequest complete, errCode:%{public}d", param->errCode);
+ if (param->errCode == 0) {
+ napi_resolve_deferred(env, param->deferred, result);
+ } else {
+ napi_reject_deferred(env, param->deferred, result);
+ }
+ napi_delete_async_work(env, param->asyncWork);
+ delete param;
+}
+
+napi_value SendRequestPromise(napi_env env, sptr target, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
+{
+ napi_deferred deferred = nullptr;
+ napi_value promise = nullptr;
+ NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
+ SendRequestParam *sendRquestParam = new SendRequestParam{
+ .target = target,
+ .code = code,
+ .data = data,
+ .reply = reply,
+ .option = option,
+ .deferred = deferred,
+ .errCode = -1,
+ .asyncWork = nullptr
+ };
+ napi_value resourceName = nullptr;
+ NAPI_CALL(env, napi_create_string_utf8(env, __func__, NAPI_AUTO_LENGTH, &resourceName));
+ NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, ExecuteSendRequest, SendRequestComplete,
+ (void*)sendRquestParam, &sendRquestParam->asyncWork));
+ NAPI_CALL(env, napi_queue_async_work(env, sendRquestParam->asyncWork));
+ DBINDER_LOGI("sendRequest and returns promise");
+ return promise;
+
+}
+
+napi_value NAPI_RemoteProxy_sendRequest(napi_env env, napi_callback_info info)
+{
+ DBINDER_LOGI("send request starts");
+ size_t argc = 4;
+ napi_value argv[4] = { 0 };
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 4, "requires 4 parameter");
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 2");
+ napi_typeof(env, argv[2], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 3");
+ napi_typeof(env, argv[3], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 4");
+
+ NAPI_MessageParcel *data = nullptr;
+ napi_status status = napi_unwrap(env, argv[1], (void**)&data);
+ NAPI_ASSERT(env, status == napi_ok, "failed t0 get data message parcel");
+ NAPI_MessageParcel *reply = nullptr;
+ status = napi_unwrap(env, argv[2], (void**)&reply);
+ NAPI_ASSERT(env, status == napi_ok, "failed t0 get reply message parcel");
+ MessageOption *option = nullptr;
+ status = napi_unwrap(env, argv[3], (void**)&option);
+ NAPI_ASSERT(env, option != nullptr, "failed to get message option");
+
+ int32_t code = 0;
+ napi_get_value_int32(env, argv[0], &code);
+
+ NAPIRemoteProxyHolder *proxyHolder = nullptr;
+ status = napi_unwrap(env, thisVar, (void**)&proxyHolder);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
+ if (proxyHolder == nullptr) {
+ DBINDER_LOGE("proxy holder is null");
+ napi_value undefined;
+ napi_get_undefined(env, &undefined);
+ return undefined;
+ }
+
+ sptr target = proxyHolder->object_;
+ if (target == nullptr) {
+ DBINDER_LOGE("Invalid proxy object");
+ napi_value undefined;
+ napi_get_undefined(env, &undefined);
+ return undefined;
+ }
+ return SendRequestPromise(env, target, code, *(data->getMessageParcel()), *(reply->getMessageParcel()), *option);
+}
+
+napi_value NAPI_RemoteProxy_addDeathRecipient(napi_env env, napi_callback_info info)
+{
+ DBINDER_LOGI("add death recipient");
+ size_t argc = 2;
+ napi_value argv[2] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+ int32_t flag = 0;
+ napi_get_value_int32(env, argv[1], &flag);
+
+ napi_value result;
+ if (argv[0] == nullptr) {
+ //JniHelperThrowNullPointerException(env, "the recipient is null");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+
+ NAPIRemoteProxyHolder *proxyHolder = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&proxyHolder);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
+ if (proxyHolder == nullptr) {
+ //JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+ sptr target = proxyHolder->object_;
+ if ((target == nullptr) || !target->IsProxyObject()) {
+ DBINDER_LOGE("could not add recipient from invalid target");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+
+ sptr nativeRecipient = new NAPIDeathRecipient(env, argv[0]);
+ if (target->AddDeathRecipient(nativeRecipient)) {
+ NAPIDeathRecipientList *list = proxyHolder->list_;
+ if (list->Add(nativeRecipient)) {
+ napi_get_boolean(env, true, &result);
+ return result;
+ }
+ }
+ napi_get_boolean(env, false, &result);
+ return result;
+}
+
+napi_value NAPI_RemoteProxy_removeDeathRecipient(napi_env env, napi_callback_info info)
+{
+ DBINDER_LOGI("remove death recipient");
+ size_t argc = 2;
+ napi_value argv[2] = { 0 };
+ napi_value thisVar = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+ napi_value result;
+ if (argv[0] == nullptr) {
+ //JniHelperThrowNullPointerException(env, "the recipient is null");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+ int32_t flag = 0;
+ napi_get_value_int32(env, argv[1], &flag);
+
+ NAPIRemoteProxyHolder *proxyHolder = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&proxyHolder);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
+ if (proxyHolder == nullptr) {
+ //JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+ sptr target = proxyHolder->object_;
+ if ((target == nullptr) || !target->IsProxyObject()) {
+ DBINDER_LOGE("could not remove recipient from invalid target");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+ // list should not be null here, it should be alloc at create proxy object.
+ sptr list = proxyHolder->list_;
+ sptr nativeRecipient = list->Find(argv[0]);
+ if (nativeRecipient == nullptr) {
+ DBINDER_LOGE("recipient not found");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+ target->RemoveDeathRecipient(nativeRecipient);
+ if (list->Remove(nativeRecipient)) {
+ napi_get_boolean(env, true, &result);
+ return result;
+ } else {
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+}
+
+napi_value NAPI_RemoteProxy_getInterfaceDescriptor(napi_env env, napi_callback_info info)
+{
+ DBINDER_LOGI("get inteface descriptor");
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
+ NAPIRemoteProxyHolder *holder = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&holder);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
+ napi_value result;
+ if (holder == nullptr) {
+ //JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
+ napi_create_string_utf8(env, "", 0, &result);
+ return result;
+ }
+ IPCObjectProxy *target = reinterpret_cast(holder->object_.GetRefPtr());
+ if (target == nullptr) {
+ DBINDER_LOGE("Invalid proxy object");
+ napi_create_string_utf8(env, "", 0, &result);
+ return result;
+ }
+ std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
+ napi_create_string_utf8(env, Str16ToStr8(remoteDescriptor).c_str(), NAPI_AUTO_LENGTH, &result);
+ return result;
+}
+
+napi_value NAPI_RemoteProxy_isObjectDead(napi_env env, napi_callback_info info)
+{
+ DBINDER_LOGI("call isObjectDead");
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
+ NAPIRemoteProxyHolder *holder = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&holder);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
+ napi_value result;
+ if (holder == nullptr) {
+ //JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+ IPCObjectProxy *target = reinterpret_cast(holder->object_.GetRefPtr());
+ if (target == nullptr) {
+ DBINDER_LOGE("Invalid proxy object");
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+
+ if (target->IsObjectDead()) {
+ napi_get_boolean(env, true, &result);
+ return result;
+ } else {
+ napi_get_boolean(env, false, &result);
+ return result;
+ }
+}
+
+napi_value NAPI_RemoteProxy_getHandle(napi_env env, napi_callback_info info)
+{
+ DBINDER_LOGI("call get handle");
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, 0, 0, &thisVar, nullptr);
+ NAPIRemoteProxyHolder *holder = nullptr;
+ napi_status status = napi_unwrap(env, thisVar, (void**)&holder);
+ NAPI_ASSERT(env, status == napi_ok, "failed to get proxy holder");
+ napi_value result;
+ if (holder == nullptr) {
+ //JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
+ napi_create_uint32(env, 0, &result);
+ return result;
+ }
+ IPCObjectProxy *target = reinterpret_cast(holder->object_.GetRefPtr());
+ if (target == nullptr) {
+ DBINDER_LOGE("Invalid proxy object");
+ napi_create_uint32(env, 0, &result);
+ return result;
+ }
+ uint32_t handle = target->GetHandle();
+ napi_create_uint32(env, handle, &result);
+ return result;
+}
+
+napi_value NAPIIPCSkeleton_JS_Constructor(napi_env env, napi_callback_info info) {
+ napi_value thisArg = nullptr;
+ void *data = nullptr;
+ napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, &data);
+ napi_value global = nullptr;
+ napi_get_global(env, &global);
+ return thisArg;
+}
+
+// get rpc test proxy
+napi_value N_API_GetLocalAbility(napi_env env, napi_callback_info info) {
+ auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ sptr object = samgrProxy->GetSystemAbility(1108);
+ if (object == nullptr) {
+ DBINDER_LOGE("fatal error, could not get registry object");
+ return nullptr;
+ }
+ return NAPI_ohos_rpc_CreateJsRemoteObject(env, object);
+}
+
+// get remote rpc test proxy
+napi_value N_API_GetRemoteAbility(napi_env env, napi_callback_info info) {
+ size_t argc = 2;
+ napi_value argv[2] = { 0 };
+ napi_value thisVar = nullptr;
+ void* data = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
+ NAPI_ASSERT(env, argc == 2, "requires 2 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_string, "type mismatch for parameter 1");
+
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+
+ uint32_t stringLength = 0;
+ napi_get_value_uint32(env, argv[1], &stringLength);
+ NAPI_ASSERT(env, stringLength < 40960, "string length too large");
+
+ char stringValue[stringLength];
+ size_t jsStringLength = 0;
+ napi_get_value_string_utf8(env, argv[0], stringValue, stringLength, &jsStringLength);
+ NAPI_ASSERT(env, jsStringLength == stringLength, "string length wrong");
+ std::string remoteDeviceId = stringValue;
+ DBINDER_LOGI("RpcTest: device id is %{public}s", remoteDeviceId.c_str());
+ auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ // TODO
+ sptr object = samgrProxy->GetSystemAbility(1108, remoteDeviceId);
+ if (object == nullptr) {
+ DBINDER_LOGE("RpcTest: fatal error, could not get registry object");
+ return nullptr;
+ }
+ return NAPI_ohos_rpc_CreateJsRemoteObject(env, object);
+}
+
+napi_value N_API_AddLocalAbility(napi_env env, napi_callback_info info) {
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
+ sptr stub = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
+ if (stub == nullptr) {
+ DBINDER_LOGE("fatal error, could not get registry object");
+ return nullptr;
+ }
+ auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ int ret = samgrProxy->AddSystemAbility(1108, stub);
+ napi_value result = nullptr;
+ napi_status status;
+ status = napi_create_int32(env, ret, &result);
+ NAPI_ASSERT(env, status == napi_ok, "failed to create int32 value");
+ return result;
+}
+
+//napi_value N_API_GetRemoteNodeBasicInfo(napi_env env, napi_callback_info info) {
+//
+// napi_value emptyStringValue;
+// napi_create_string_utf8(env, "", 0, &emptyStringValue);
+// std::shared_ptr mDnetworkAdapter = Communication::DnetworkAdapter::GetInstance();
+// if (mDnetworkAdapter == nullptr) {
+// DBINDER_LOGE("RpcTest: DnetworkAdapter mDnetworkAdapter is null");
+// return emptyStringValue;
+// }
+// //get remote node list
+// std::list> nodesBasicInfo = mDnetworkAdapter->GetRemoteNodesBasicInfo();
+// if (nodesBasicInfo.size() <= 0) {
+// DBINDER_LOGE("RpcTest: RemoteList is null");
+// return emptyStringValue;
+// }
+// // get first node from list
+// std::shared_ptr nodeBasicInfo = nodesBasicInfo.front();
+// if (nodeBasicInfo == nullptr) {
+// DBINDER_LOGE("RpcTest: nodeBasicInfo is null");
+// return emptyStringValue;
+// }
+//
+// std::string remoteDeviceId = nodeBasicInfo->GetNodeId();
+// napi_value napiValue = nullptr;
+// NAPI_CALL(env, napi_create_string_utf8(env, remoteDeviceId.c_str(), remoteDeviceId.length(), &napiValue));
+// return napiValue;
+//}
+
+//napi_value N_API_GetLocalNodeBasicInfo(napi_env env, napi_callback_info info) {
+//
+// napi_value emptyStringValue;
+// napi_create_string_utf8(env, "", 0, &emptyStringValue);
+// std::shared_ptr mDnetworkAdapter = Communication::DnetworkAdapter::GetInstance();
+// if (mDnetworkAdapter == nullptr) {
+// DBINDER_LOGE("RpcTest: DnetworkAdapter mDnetworkAdapter is null");
+// return emptyStringValue;
+// }
+// //get local node
+// std::shared_ptr nodeInfo = mDnetworkAdapter->GetLocalBasicInfo();
+// if (nodeInfo == nullptr) {
+// DBINDER_LOGE("RpcTest: local node is null");
+// return emptyStringValue;
+// }
+//
+// std::string localDeviceId = nodeInfo->GetNodeId();
+// napi_value napiValue = nullptr;
+// NAPI_CALL(env, napi_create_string_utf8(env, localDeviceId.c_str(), localDeviceId.length(), &napiValue));
+// return napiValue;
+//}
+
+napi_value N_API_AddRemoteAbility(napi_env env, napi_callback_info info) {
+
+ size_t argc = 1;
+ napi_value argv[1] = { 0 };
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
+
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_object, "type mismatch for parameter 1");
+ sptr stub = NAPI_ohos_rpc_getNativeRemoteObject(env, argv[0]);
+ if (stub == nullptr) {
+ DBINDER_LOGE("RpcServer: fatal error, could not registry object");
+ return nullptr;
+ }
+ auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
+ ISystemAbilityManager::SAExtraProp saExtra;
+ saExtra.isDistributed = true;
+ int ret = samgrProxy->AddSystemAbility(1108, stub, saExtra);
+ napi_value result = nullptr;
+ napi_status status;
+ status = napi_create_int32(env, ret, &result);
+ NAPI_ASSERT(env, status == napi_ok, "failed to create int32 value");
+ return result;
+}
+
+EXTERN_C_START
+/*
+ * function for module exports
+ */
+napi_value NAPIIPCSkeletonExport(napi_env env, napi_value exports)
+{
+ DBINDER_LOGI("napi_moudule IPCSkeleton Init start...");
+ napi_property_descriptor desc[] = {
+ DECLARE_NAPI_STATIC_FUNCTION("getContextObject", NAPI_IPCSkeleton_getContextObject),
+ DECLARE_NAPI_STATIC_FUNCTION("getCallingPid", NAPI_IPCSkeleton_getCallingPid),
+ DECLARE_NAPI_STATIC_FUNCTION("getCallingUid", NAPI_IPCSkeleton_getCallingUid),
+ DECLARE_NAPI_STATIC_FUNCTION("getCallingDeviceID", NAPI_IPCSkeleton_getCallingDeviceID),
+ DECLARE_NAPI_STATIC_FUNCTION("getLocalDeviceID", NAPI_IPCSkeleton_getLocalDeviceID),
+ DECLARE_NAPI_STATIC_FUNCTION("isLocalCalling", NAPI_IPCSkeleton_isLocalCalling),
+ DECLARE_NAPI_STATIC_FUNCTION("flushCommands", NAPI_IPCSkeleton_flushCommands),
+ DECLARE_NAPI_STATIC_FUNCTION("resetCallingIdentity", NAPI_IPCSkeleton_resetCallingIdentity),
+ DECLARE_NAPI_STATIC_FUNCTION("setCallingIdentity", NAPI_IPCSkeleton_setCallingIdentity),
+ DECLARE_NAPI_STATIC_FUNCTION("getLocalAbility", N_API_GetLocalAbility),
+ DECLARE_NAPI_STATIC_FUNCTION("addLocalAbility", N_API_AddLocalAbility),
+ //DECLARE_NAPI_STATIC_FUNCTION("getRemoteNodesBasicInfo", N_API_GetRemoteNodeBasicInfo),
+ //DECLARE_NAPI_STATIC_FUNCTION("getLocalNodeBasicInfo", N_API_GetLocalNodeBasicInfo),
+ DECLARE_NAPI_STATIC_FUNCTION("getRemoteAbility", N_API_GetRemoteAbility),
+ DECLARE_NAPI_STATIC_FUNCTION("addRemoteAbility", N_API_AddRemoteAbility),
+ };
+ NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
+ napi_value result = nullptr;
+ napi_define_class(env, "IPCSkeleton", NAPI_AUTO_LENGTH, NAPIIPCSkeleton_JS_Constructor, nullptr,
+ sizeof(desc) / sizeof(desc[0]), desc, &result);
+ napi_status status = napi_set_named_property(env, exports, "IPCSkeleton", result);
+ NAPI_ASSERT(env, status == napi_ok, "create ref to js RemoteObject constructor failed");
+ DBINDER_LOGI("napi_moudule IPCSkeleton Init end...");
+ return exports;
+}
+EXTERN_C_END
+
+
+napi_value NAPIMessageOption_JS_Constructor(napi_env env, napi_callback_info info) {
+ size_t argc = 2;
+ napi_value argv[2] = { 0 };
+ napi_value thisVar = nullptr;
+ napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
+ NAPI_ASSERT(env, argc >= 0, "invalid parameter number");
+ int flags = 0;
+ int waittime = 0;
+ if (argc == 0) {
+ flags = MessageOption::TF_SYNC;
+ waittime = MessageOption::TF_WAIT_TIME;
+ } else if (argc == 1) {
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+ int32_t jsFlags = 0;
+ napi_get_value_int32(env, argv[1], &jsFlags);
+ flags = jsFlags;
+ waittime = MessageOption::TF_WAIT_TIME;
+ } else {
+ napi_valuetype valueType;
+ napi_typeof(env, argv[0], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 1");
+ napi_typeof(env, argv[1], &valueType);
+ NAPI_ASSERT(env, valueType == napi_number, "type mismatch for parameter 2");
+ int32_t jsFlags = 0;
+ napi_get_value_int32(env, argv[0], &jsFlags);
+ int32_t jsWaittime = 0;
+ napi_get_value_int32(env, argv[1], &jsWaittime);
+ flags = jsFlags;
+ waittime = jsWaittime;
+ }
+
+ auto messageOption = new MessageOption(flags, waittime);
+ // connect native message option to js thisVar
+ napi_status status = napi_wrap(
+ env, thisVar, messageOption,
+ [](napi_env env, void *data, void *hint) {
+ DBINDER_LOGI("NAPIMessageOption destructed by js callback");
+ delete (reinterpret_cast(data));
+ },
+ nullptr, nullptr);
+ NAPI_ASSERT(env, status == napi_ok, "wrap js MessageOption and native option failed");
+ return thisVar;
+}
+
+EXTERN_C_START
+/*
+ * function for module exports
+ */
+napi_value NAPIMessageOptionExport(napi_env env, napi_value exports)
+{
+ const std::string className = "MessageOption";
+ napi_property_descriptor properties[] = {
+ DECLARE_NAPI_FUNCTION("getFlags", NAPI_ohos_rpc_message_option_get_flags),
+ DECLARE_NAPI_FUNCTION("setFlags", NAPI_ohos_rpc_message_option_set_flags),
+ DECLARE_NAPI_FUNCTION("getWaitTime", NAPI_ohos_rpc_message_option_get_waitTime),
+ DECLARE_NAPI_FUNCTION("setWaitTime", NAPI_ohos_rpc_message_option_set_waitTime),
+ };
+ napi_define_class(env, className.c_str(), className.length(), NAPIMessageOption_JS_Constructor, nullptr,
+ sizeof(properties) / sizeof(properties[0]), properties, &g_messageOptionConstructor);
+ NAPI_ASSERT(env, g_messageOptionConstructor != nullptr, "define js class MessageOption failed");
+ napi_status status = napi_set_named_property(env, exports, "MessageOption", g_messageOptionConstructor);
+ NAPI_ASSERT(env, status == napi_ok, "set property MessageOption to exports failed");
+ status = napi_create_reference(env, g_messageOptionConstructor, 1, &g_messageOptionConsRef);
+ NAPI_ASSERT(env, status == napi_ok, "create ref to js MessageOption constructor failed");
+ return exports;
+}
+EXTERN_C_END
+
+} // namespace OHOS
diff --git a/ipc/native/src/napi/src/napi_rpc_native_module.cpp b/ipc/native/src/napi/src/napi_rpc_native_module.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..890ef539ff5adf9696b57c4f5a745d1bd14c8184
--- /dev/null
+++ b/ipc/native/src/napi/src/napi_rpc_native_module.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "napi_remote_object.h"
+#include
+#include
+#include
+#include "napi/native_api.h"
+#include "napi/native_node_api.h"
+#include "hilog/log.h"
+#include "log_tags.h"
+#include "napi_message_parcel.h"
+
+extern const char _binary_rpc_js_start[];
+extern const char _binary_rpc_js_end[];
+
+namespace OHOS {
+EXTERN_C_START
+static napi_value RPCExport(napi_env env, napi_value exports) {
+ NAPI_MessageParcel::Export(env, exports);
+ NAPIIPCSkeletonExport(env, exports);
+ NAPIRemoteObjectExport(env, exports);
+ NAPIRemoteProxyExport(env, exports);
+ NAPIMessageOptionExport(env, exports);
+ return exports;
+}
+EXTERN_C_END
+
+extern "C" __attribute__((visibility("default"))) void NAPI_rpc_GetJSCode(const char **buf, int *bufLen)
+{
+ if (buf != nullptr) {
+ *buf = _binary_rpc_js_start;
+ }
+
+ if (bufLen != nullptr) {
+ *bufLen = _binary_rpc_js_end - _binary_rpc_js_start;
+ }
+}
+
+static napi_module RPCModule_ = {
+ .nm_version = 1,
+ .nm_flags = 0,
+ .nm_filename = nullptr,
+ .nm_register_func = RPCExport,
+ .nm_modname = "rpc",
+ .nm_priv = ((void*)0),
+ .reserved = { 0 }
+};
+
+/*
+ * Module register function
+ */
+extern "C" __attribute__((constructor)) void RegisterModule(void)
+{
+ napi_module_register(&RPCModule_);
+}
+} // namesapce OHOS
diff --git a/ohos.build b/ohos.build
index 07b476a44d060b9422816c77997de5e8b129a6ea..5fc6afb0cc15be2507dd0827b4464c6ec79b5005 100755
--- a/ohos.build
+++ b/ohos.build
@@ -68,6 +68,23 @@
"//foundation/communication/ipc/ipc/test:moduletest",
"//foundation/communication/ipc/ipc/native/test:unittest"
]
+ },
+ "ipc_js": {
+ "module_list": [
+ "//foundation/communication/ipc/interfaces/kits/js/napi:rpc"
+ ],
+ "inner_kits": [
+ {
+ "type": "so",
+ "name": "//foundation/communication/ipc/interfaces/kits/js/napi:rpc",
+ "header": {
+ "header_files": [
+ "napi_remote_object.h"
+ ],
+ "header_base": "//foundation/communication/ipc/ipc/native/src/napi/include"
+ }
+ }
+ ]
}
}
}