1 /*
2 * Copyright (c) 2021 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 "jerryscript_native_buffer.h"
17
18 #include <map>
19
20 #include "utils/log.h"
21
22 // The maximum length for NativaBuffer, default is 2MiB.
23 static constexpr size_t kMaxByteLength = 2097152;
24
25 static std::map<size_t, JerryScriptBufferCallback*> g_freeCallbackStorage;
26
27 struct JerryScriptBufferCallback {
CreateNewInstanceJerryScriptBufferCallback28 static JerryScriptBufferCallback* CreateNewInstance()
29 {
30 return new JerryScriptBufferCallback();
31 }
32
33 NativeEngine* engine = nullptr;
34 NativeFinalize cb = nullptr;
35 void* hint = nullptr;
36 };
37
JerryScriptNativeBuffer(JerryScriptNativeEngine * engine,jerry_value_t value)38 JerryScriptNativeBuffer::JerryScriptNativeBuffer(JerryScriptNativeEngine* engine, jerry_value_t value)
39 : JerryScriptNativeObject(engine, value)
40 {
41 }
42
JerryScriptNativeBuffer(JerryScriptNativeEngine * engine,uint8_t ** value,size_t length)43 JerryScriptNativeBuffer::JerryScriptNativeBuffer(JerryScriptNativeEngine* engine, uint8_t** value, size_t length)
44 : JerryScriptNativeBuffer(engine, CheckAndCreateBuffer(length))
45 {
46 if (length > kMaxByteLength) {
47 *value = nullptr;
48 } else {
49 *value = jerry_get_arraybuffer_pointer(value_);
50 }
51 }
52
JerryScriptNativeBuffer(JerryScriptNativeEngine * engine,uint8_t ** value,size_t length,const uint8_t * data)53 JerryScriptNativeBuffer::JerryScriptNativeBuffer(JerryScriptNativeEngine* engine, uint8_t** value, size_t length,
54 const uint8_t* data) : JerryScriptNativeBuffer(engine, CheckAndCreateBuffer(length))
55 {
56 if (length > kMaxByteLength) {
57 *value = nullptr;
58 return;
59 }
60 if (data != nullptr) {
61 jerry_arraybuffer_write(value_, 0, data, length);
62 }
63 *value = jerry_get_arraybuffer_pointer(value_);
64 }
65
JerryScriptNativeBuffer(JerryScriptNativeEngine * engine,uint8_t * data,size_t length,NativeFinalize callback,void * hint)66 JerryScriptNativeBuffer::JerryScriptNativeBuffer(JerryScriptNativeEngine* engine,
67 uint8_t* data,
68 size_t length,
69 NativeFinalize callback,
70 void* hint)
71 : JerryScriptNativeBuffer(engine, NULL)
72 {
73 if (length > kMaxByteLength) {
74 return;
75 }
76 auto freeCallback = JerryScriptBufferCallback::CreateNewInstance();
77 if (freeCallback != nullptr) {
78 freeCallback->engine = engine_;
79 freeCallback->cb = callback;
80 freeCallback->hint = hint;
81 }
82
83 g_freeCallbackStorage.insert(std::pair<size_t, JerryScriptBufferCallback*>((size_t)data, freeCallback));
84 value_ = jerry_create_arraybuffer_external(length, data, [](void* nativePoint) {
85 auto iter = g_freeCallbackStorage.find((size_t)nativePoint);
86 if (iter != g_freeCallbackStorage.end()) {
87 auto callb = iter->second;
88 if (callb != nullptr && callb->cb != nullptr) {
89 callb->cb(callb->engine, nativePoint, callb->hint);
90 g_freeCallbackStorage.erase(iter);
91 delete callb;
92 callb = NULL;
93 } else {
94 free(nativePoint);
95 nativePoint = nullptr;
96 }
97 } else {
98 free(nativePoint);
99 nativePoint = nullptr;
100 }
101 });
102 }
103
~JerryScriptNativeBuffer()104 JerryScriptNativeBuffer::~JerryScriptNativeBuffer() {}
105
GetInterface(int interfaceId)106 void* JerryScriptNativeBuffer::GetInterface(int interfaceId)
107 {
108 return (NativeBuffer::INTERFACE_ID == interfaceId) ? (NativeBuffer*)this
109 : JerryScriptNativeObject::GetInterface(interfaceId);
110 }
111
GetBuffer()112 void* JerryScriptNativeBuffer::GetBuffer()
113 {
114 return jerry_get_arraybuffer_pointer(value_);
115 }
116
GetLength()117 size_t JerryScriptNativeBuffer::GetLength()
118 {
119 return jerry_get_arraybuffer_byte_length(value_);
120 }
121
CheckAndCreateBuffer(size_t length)122 jerry_value_t JerryScriptNativeBuffer::CheckAndCreateBuffer(size_t length)
123 {
124 jerry_value_t buf = NULL;
125
126 if (length > kMaxByteLength) {
127 HILOG_ERROR("The length(%{public}zu) exceeds the maximum byte length definition(%{public}zu).",
128 length, kMaxByteLength);
129 buf = jerry_create_null();
130 } else {
131 buf = jerry_create_arraybuffer(length);
132 }
133 return buf;
134 }
135