1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ark_native_buffer.h"
17 #include "ark_native_array_buffer.h"
18 #include <memory>
19 #include <securec.h>
20
21 #include "utils/log.h"
22
23 using panda::BufferRef;
24 using panda::JSValueRef;
25 // The maximum length for NativaBuffer, default is 2MiB.
26 static constexpr size_t K_MAX_BYTE_LENGTH = 2097152;
27 static constexpr size_t ONE_MIB_BYTE_SIZE = 1048576;
28
ArkNativeBuffer(ArkNativeEngine * engine,Local<JSValueRef> value)29 ArkNativeBuffer::ArkNativeBuffer(ArkNativeEngine* engine, Local<JSValueRef> value)
30 : ArkNativeObject(engine, value)
31 {
32 }
33
ArkNativeBuffer(ArkNativeEngine * engine,uint8_t ** value,size_t length)34 ArkNativeBuffer::ArkNativeBuffer(ArkNativeEngine* engine, uint8_t** value, size_t length)
35 : ArkNativeBuffer(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
36 {
37 if (!value) {
38 HILOG_ERROR("value is empty");
39 return;
40 }
41
42 if (length > K_MAX_BYTE_LENGTH) {
43 HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
44 static_cast<float>(length) / static_cast<float>(ONE_MIB_BYTE_SIZE),
45 static_cast<float>(K_MAX_BYTE_LENGTH) / static_cast<float>(ONE_MIB_BYTE_SIZE));
46 *value = nullptr;
47 return;
48 }
49
50 auto vm = engine->GetEcmaVm();
51 LocalScope scope(vm);
52 value_ = Global<BufferRef>(vm, BufferRef::New(vm, length));
53 Global<BufferRef> obj = value_;
54 *value = reinterpret_cast<uint8_t*>(obj->GetBuffer());
55 }
56
ArkNativeBuffer(ArkNativeEngine * engine,uint8_t ** value,size_t length,const uint8_t * data)57 ArkNativeBuffer::ArkNativeBuffer(ArkNativeEngine* engine, uint8_t** value, size_t length, const uint8_t* data)
58 : ArkNativeBuffer(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
59 {
60 if (!value) {
61 HILOG_ERROR("value is empty");
62 return;
63 }
64
65 if (length > K_MAX_BYTE_LENGTH) {
66 HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
67 static_cast<float>(length) / static_cast<float>(ONE_MIB_BYTE_SIZE),
68 static_cast<float>(K_MAX_BYTE_LENGTH) / static_cast<float>(ONE_MIB_BYTE_SIZE));
69 *value = nullptr;
70 return;
71 }
72
73 auto vm = engine->GetEcmaVm();
74 LocalScope scope(vm);
75 value_ = Global<BufferRef>(vm, BufferRef::New(vm, length));
76 Global<BufferRef> obj = value_;
77 *value = reinterpret_cast<uint8_t*>(obj->GetBuffer());
78 if (memcpy_s(*value, length, data, length) != EOK) {
79 HILOG_ERROR("memcpy_s failed");
80 }
81 }
82
ArkNativeBuffer(ArkNativeEngine * engine,uint8_t * value,size_t length,NativeFinalize cb,void * hint)83 ArkNativeBuffer::ArkNativeBuffer(ArkNativeEngine* engine,
84 uint8_t* value,
85 size_t length,
86 NativeFinalize cb,
87 void* hint)
88 : ArkNativeBuffer(engine, JSValueRef::Undefined(engine->GetEcmaVm()))
89 {
90 if (!value) {
91 HILOG_ERROR("value is empty");
92 return;
93 }
94
95 if (length > K_MAX_BYTE_LENGTH) {
96 HILOG_ERROR("Creat failed, current size: %{public}2f MiB, limit size: %{public}2f MiB",
97 static_cast<float>(length) / static_cast<float>(ONE_MIB_BYTE_SIZE),
98 static_cast<float>(K_MAX_BYTE_LENGTH) / static_cast<float>(ONE_MIB_BYTE_SIZE));
99 value = nullptr;
100 return;
101 }
102
103 auto vm = engine->GetEcmaVm();
104 LocalScope scope(vm);
105
106 std::unique_ptr<NativeObjectInfo> cbinfo(NativeObjectInfo::CreateNewInstance());
107 if (!cbinfo) {
108 HILOG_ERROR("cbinfo is nullptr");
109 return;
110 }
111 cbinfo->engine = engine_;
112 cbinfo->callback = cb;
113 cbinfo->hint = hint;
114
115 Local<BufferRef> object = BufferRef::New(vm, value, length,
116 [](void* data, void* info) {
117 auto externalInfo = reinterpret_cast<NativeObjectInfo*>(info);
118 auto engine = externalInfo->engine;
119 auto callback = externalInfo->callback;
120 auto hint = externalInfo->hint;
121 if (callback != nullptr) {
122 callback(engine, data, hint);
123 }
124 delete externalInfo;
125 },
126 cbinfo.get());
127
128 value_ = Global<BufferRef>(vm, object);
129 cbinfo.release();
130 }
131
~ArkNativeBuffer()132 ArkNativeBuffer::~ArkNativeBuffer() {}
133
GetInterface(int interfaceId)134 void* ArkNativeBuffer::GetInterface(int interfaceId)
135 {
136 return (NativeBuffer::INTERFACE_ID == interfaceId) ? (NativeBuffer*)this
137 : ArkNativeObject::GetInterface(interfaceId);
138 }
139
GetBuffer()140 void* ArkNativeBuffer::GetBuffer()
141 {
142 auto vm = engine_->GetEcmaVm();
143 LocalScope scope(vm);
144 Global<BufferRef> v = value_;
145 return v->GetBuffer();
146 }
147
GetLength()148 size_t ArkNativeBuffer::GetLength()
149 {
150 auto vm = engine_->GetEcmaVm();
151 LocalScope scope(vm);
152 Global<BufferRef> v = value_;
153 return v->ByteLength(vm);
154 }
155
IsBuffer()156 bool ArkNativeBuffer::IsBuffer()
157 {
158 return true;
159 }
160
IsArrayBuffer()161 bool ArkNativeBuffer::IsArrayBuffer()
162 {
163 return false;
164 }