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_engine.h"
17
18 #include "jerryscript-ext/handler.h"
19 #include "jerryscript_native_deferred.h"
20 #include "jerryscript_native_reference.h"
21
22 #include "native_value/jerryscript_native_array.h"
23 #include "native_value/jerryscript_native_array_buffer.h"
24 #include "native_value/jerryscript_native_big_int.h"
25 #include "native_value/jerryscript_native_boolean.h"
26 #include "native_value/jerryscript_native_buffer.h"
27 #include "native_value/jerryscript_native_data_view.h"
28 #include "native_value/jerryscript_native_date.h"
29 #include "native_value/jerryscript_native_external.h"
30 #include "native_value/jerryscript_native_function.h"
31 #include "native_value/jerryscript_native_number.h"
32 #include "native_value/jerryscript_native_object.h"
33 #include "native_value/jerryscript_native_string.h"
34 #include "native_value/jerryscript_native_typed_array.h"
35 #include "utils/log.h"
36
JerryScriptNativeEngine(void * jsEngine)37 JerryScriptNativeEngine::JerryScriptNativeEngine(void* jsEngine) : NativeEngine(jsEngine)
38 {
39 HILOG_INFO("JerryScriptNativeEngine::JerryScriptNativeEngine begin");
40 jerry_add_external();
41 jerry_value_t global = jerry_get_global_object();
42 jerry_value_t require = jerry_create_external_function([](const jerry_value_t function, const jerry_value_t thisVal,
43 const jerry_value_t args[],
44 const jerry_length_t argc) -> jerry_value_t {
45 JerryScriptNativeEngine* that = nullptr;
46 jerry_get_object_native_pointer(function, (void**)&that, nullptr);
47 jerry_value_t result = jerry_create_undefined();
48
49 if (!(argc >= 1 && jerry_value_is_string(args[0]))) {
50 return result;
51 }
52
53 jerry_size_t moduleNameSize = jerry_get_utf8_string_size(args[0]);
54
55 if (moduleNameSize == 0) {
56 return result;
57 }
58
59 char* moduleName = new char[moduleNameSize + 1] { 0 };
60 uint32_t moduleNameLength = jerry_string_to_char_buffer(args[0], (jerry_char_t*)moduleName, moduleNameSize + 1);
61 moduleName[moduleNameLength] = '\0';
62 NativeModule* module = that->GetModuleManager()->LoadNativeModule(moduleName, nullptr, false);
63
64 if (module != nullptr) {
65 NativeValue* value = that->CreateObject();
66 module->registerCallback(that, value);
67 result = jerry_acquire_value(*value);
68 }
69 return result;
70 });
71 jerry_set_object_native_pointer(require, this, nullptr);
72 jerryx_set_property_str(global, "requireNapi", require);
73
74 jerry_release_value(require);
75 jerry_release_value(global);
76 HILOG_INFO("JerryScriptNativeEngine::JerryScriptNativeEngine end");
77 Init();
78 }
79
~JerryScriptNativeEngine()80 JerryScriptNativeEngine::~JerryScriptNativeEngine()
81 {
82 Deinit();
83 }
84
Loop(LoopMode mode,bool needSync)85 void JerryScriptNativeEngine::Loop(LoopMode mode, bool needSync)
86 {
87 NativeEngine::Loop(mode, needSync);
88 jerry_value_t retVal = jerry_run_all_enqueued_jobs();
89 jerry_release_value(retVal);
90 }
91
GetGlobal()92 NativeValue* JerryScriptNativeEngine::GetGlobal()
93 {
94 return new JerryScriptNativeObject(this, jerry_get_global_object());
95 }
96
CreateNull()97 NativeValue* JerryScriptNativeEngine::CreateNull()
98 {
99 return new JerryScriptNativeValue(this, jerry_create_null());
100 }
101
CreateUndefined()102 NativeValue* JerryScriptNativeEngine::CreateUndefined()
103 {
104 return new JerryScriptNativeValue(this, jerry_create_undefined());
105 }
106
CreateBoolean(bool value)107 NativeValue* JerryScriptNativeEngine::CreateBoolean(bool value)
108 {
109 return new JerryScriptNativeBoolean(this, value);
110 }
111
CreateNumber(int32_t value)112 NativeValue* JerryScriptNativeEngine::CreateNumber(int32_t value)
113 {
114 return new JerryScriptNativeNumber(this, (double)value);
115 }
116
CreateNumber(uint32_t value)117 NativeValue* JerryScriptNativeEngine::CreateNumber(uint32_t value)
118 {
119 return new JerryScriptNativeNumber(this, (double)value);
120 }
121
CreateNumber(int64_t value)122 NativeValue* JerryScriptNativeEngine::CreateNumber(int64_t value)
123 {
124 return new JerryScriptNativeNumber(this, (double)value);
125 }
126
CreateNumber(double value)127 NativeValue* JerryScriptNativeEngine::CreateNumber(double value)
128 {
129 return new JerryScriptNativeNumber(this, (double)value);
130 }
131
CreateString(const char * value,size_t length)132 NativeValue* JerryScriptNativeEngine::CreateString(const char* value, size_t length)
133 {
134 return new JerryScriptNativeString(this, value, length);
135 }
136
CreateSymbol(NativeValue * value)137 NativeValue* JerryScriptNativeEngine::CreateSymbol(NativeValue* value)
138 {
139 return new JerryScriptNativeValue(this, jerry_create_symbol(*value));
140 }
141
CreateExternal(void * value,NativeFinalize callback,void * hint)142 NativeValue* JerryScriptNativeEngine::CreateExternal(void* value, NativeFinalize callback, void* hint)
143 {
144 return new JerryScriptNativeExternal(this, value, callback, hint);
145 }
146
CreateObject()147 NativeValue* JerryScriptNativeEngine::CreateObject()
148 {
149 return new JerryScriptNativeObject(this);
150 }
151
CreateFunction(const char * name,size_t length,NativeCallback cb,void * value)152 NativeValue* JerryScriptNativeEngine::CreateFunction(const char* name, size_t length, NativeCallback cb, void* value)
153 {
154 return new JerryScriptNativeFunction(this, name, cb, value);
155 }
156
CreateArray(size_t length)157 NativeValue* JerryScriptNativeEngine::CreateArray(size_t length)
158 {
159 return new JerryScriptNativeArray(this, (int)length);
160 }
161
CreateArrayBuffer(void ** value,size_t length)162 NativeValue* JerryScriptNativeEngine::CreateArrayBuffer(void** value, size_t length)
163 {
164 return new JerryScriptNativeArrayBuffer(this, value, length);
165 }
166
CreateArrayBufferExternal(void * value,size_t length,NativeFinalize cb,void * hint)167 NativeValue* JerryScriptNativeEngine::CreateArrayBufferExternal(
168 void* value, size_t length, NativeFinalize cb, void* hint)
169 {
170 return new JerryScriptNativeArrayBuffer(this, (unsigned char*)value, length, cb, hint);
171 }
172
CreateBuffer(void ** value,size_t length)173 NativeValue* JerryScriptNativeEngine::CreateBuffer(void** value, size_t length)
174 {
175 return new JerryScriptNativeBuffer(this, (uint8_t**)value, length);
176 }
177
CreateBufferCopy(void ** value,size_t length,const void * data)178 NativeValue* JerryScriptNativeEngine::CreateBufferCopy(void** value, size_t length, const void* data)
179 {
180 return new JerryScriptNativeBuffer(this, (uint8_t**)value, length, (uint8_t*)data);
181 }
182
CreateBufferExternal(void * value,size_t length,NativeFinalize cb,void * hint)183 NativeValue* JerryScriptNativeEngine::CreateBufferExternal(void* value, size_t length, NativeFinalize cb, void* hint)
184 {
185 return new JerryScriptNativeBuffer(this, (uint8_t*)value, length, cb, hint);
186 }
187
CreateTypedArray(NativeTypedArrayType type,NativeValue * value,size_t length,size_t offset)188 NativeValue* JerryScriptNativeEngine::CreateTypedArray(
189 NativeTypedArrayType type, NativeValue* value, size_t length, size_t offset)
190 {
191 return new JerryScriptNativeTypedArray(this, type, value, length, offset);
192 }
193
CreateDataView(NativeValue * value,size_t length,size_t offset)194 NativeValue* JerryScriptNativeEngine::CreateDataView(NativeValue* value, size_t length, size_t offset)
195 {
196 return new JerryScriptNativeDataView(this, value, length, offset);
197 }
198
CreatePromise(NativeDeferred ** deferred)199 NativeValue* JerryScriptNativeEngine::CreatePromise(NativeDeferred** deferred)
200 {
201 jerry_value_t promise = jerry_create_promise();
202 *deferred = new JerryScriptNativeDeferred(promise);
203 return new JerryScriptNativeValue(this, promise);
204 }
205
CreateError(NativeValue * code,NativeValue * message)206 NativeValue* JerryScriptNativeEngine::CreateError(NativeValue* code, NativeValue* message)
207 {
208 jerry_value_t jerror = 0;
209
210 jerror = jerry_create_error_sz(JERRY_ERROR_COMMON, nullptr, 0);
211 jerror = jerry_get_value_from_error(jerror, true);
212
213 if (message) {
214 jerry_value_t jreturn = jerryx_set_property_str(jerror, "message", *message);
215 jerry_release_value(jreturn);
216 }
217 if (code) {
218 jerry_value_t jreturn = jerryx_set_property_str(jerror, "code", *code);
219 jerry_release_value(jreturn);
220 }
221 jerror = jerry_create_error_from_value(jerror, true);
222
223 return new JerryScriptNativeObject(this, jerror);
224 }
225
CallFunction(NativeValue * thisVar,NativeValue * function,NativeValue * const * argv,size_t argc)226 NativeValue* JerryScriptNativeEngine::CallFunction(
227 NativeValue* thisVar, NativeValue* function, NativeValue* const* argv, size_t argc)
228 {
229 jerry_value_t* args = nullptr;
230 if (argc > 0) {
231 args = new jerry_value_t[argc];
232 for (size_t i = 0; i < argc; i++) {
233 if (argv[i] == nullptr) {
234 args[i] = jerry_create_undefined();
235 } else {
236 args[i] = *argv[i];
237 }
238 }
239 }
240 NativeScope* scope = scopeManager_->Open();
241 jerry_value_t result = jerry_call_function(*function, thisVar ? *thisVar : 0, (const jerry_value_t*)args, argc);
242 scopeManager_->Close(scope);
243 if (args != nullptr) {
244 delete[] args;
245 }
246
247 if (jerry_value_is_error(result)) {
248 jerry_value_t errorObj = jerry_get_value_from_error(result, true);
249 jerry_value_t propName = jerry_create_string_from_utf8((const jerry_char_t*)"message");
250 jerry_property_descriptor_t propDescriptor = { 0 };
251 jerry_get_own_property_descriptor(errorObj, propName, &propDescriptor);
252 jerry_value_t setResult = jerry_set_property(errorObj, propName, propDescriptor.value);
253 jerry_release_value(propName);
254 jerry_release_value(setResult);
255 Throw(JerryValueToNativeValue(this, errorObj));
256 return JerryValueToNativeValue(this, jerry_create_undefined());
257 } else {
258 return JerryValueToNativeValue(this, result);
259 }
260 }
261
RunScript(NativeValue * script)262 NativeValue* JerryScriptNativeEngine::RunScript(NativeValue* script)
263 {
264 NativeString* pscript = (NativeString*)script->GetInterface(NativeString::INTERFACE_ID);
265
266 size_t length = pscript->GetLength();
267 if (length == 0) {
268 return nullptr;
269 }
270 char* strScript = new char[length] { 0 };
271 pscript->GetCString(strScript, length, &length);
272 jerry_value_t result = jerry_eval((const unsigned char*)strScript, pscript->GetLength(), JERRY_PARSE_NO_OPTS);
273 if (jerry_value_is_error(result)) {
274 result = jerry_get_value_from_error(result, true);
275 }
276 delete[] strScript;
277 return JerryValueToNativeValue(this, result);
278 }
279
RunBufferScript(std::vector<uint8_t> & buffer)280 NativeValue* JerryScriptNativeEngine::RunBufferScript(std::vector<uint8_t>& buffer)
281 {
282 return nullptr;
283 }
284
RunActor(std::vector<uint8_t> & buffer,const char * descriptor)285 NativeValue* JerryScriptNativeEngine::RunActor(std::vector<uint8_t>& buffer, const char *descriptor)
286 {
287 return RunBufferScript(buffer);
288 }
289
DefineClass(const char * name,NativeCallback callback,void * data,const NativePropertyDescriptor * properties,size_t length)290 NativeValue* JerryScriptNativeEngine::DefineClass(
291 const char* name, NativeCallback callback, void* data, const NativePropertyDescriptor* properties, size_t length)
292 {
293 auto classConstructor = new JerryScriptNativeFunction(this, name, callback, data);
294 auto classProto = new JerryScriptNativeObject(this);
295
296 jerryx_set_property_str(*classConstructor, "prototype", *classProto);
297
298 for (size_t i = 0; i < length; ++i) {
299 if (properties[i].attributes & NATIVE_STATIC) {
300 classConstructor->DefineProperty(properties[i]);
301 } else {
302 classProto->DefineProperty(properties[i]);
303 }
304 }
305 return classConstructor;
306 }
307
CreateInstance(NativeValue * constructor,NativeValue * const * argv,size_t argc)308 NativeValue* JerryScriptNativeEngine::CreateInstance(NativeValue* constructor, NativeValue* const* argv, size_t argc)
309 {
310 return JerryValueToNativeValue(this, jerry_construct_object(*constructor, (const jerry_value_t*)argv, argc));
311 }
312
CreateReference(NativeValue * value,uint32_t initialRefcount,NativeFinalize callback,void * data,void * hint)313 NativeReference* JerryScriptNativeEngine::CreateReference(NativeValue* value, uint32_t initialRefcount,
314 NativeFinalize callback, void* data, void* hint)
315 {
316 return new JerryScriptNativeReference(this, value, initialRefcount, callback, data, hint);
317 }
318
Throw(NativeValue * error)319 bool JerryScriptNativeEngine::Throw(NativeValue* error)
320 {
321 this->lastException_ = error;
322 return true;
323 }
324
Throw(NativeErrorType type,const char * code,const char * message)325 bool JerryScriptNativeEngine::Throw(NativeErrorType type, const char* code, const char* message)
326 {
327 jerry_value_t jerror = 0;
328 jerry_error_t jtype;
329 switch (type) {
330 case NATIVE_COMMON_ERROR:
331 jtype = JERRY_ERROR_COMMON;
332 break;
333 case NATIVE_TYPE_ERROR:
334 jtype = JERRY_ERROR_TYPE;
335 break;
336 case NATIVE_RANGE_ERROR:
337 jtype = JERRY_ERROR_RANGE;
338 break;
339 default:
340 return false;
341 }
342 jerror = jerry_create_error(jtype, (const unsigned char*)message);
343 jerror = jerry_get_value_from_error(jerror, true);
344 if (code) {
345 jerry_value_t jcode = jerry_create_string_from_utf8((const unsigned char*)code);
346 jerryx_set_property_str(jerror, "code", jcode);
347 }
348 jerror = jerry_create_error_from_value(jerror, true);
349 this->lastException_ = new JerryScriptNativeObject(this, jerror);
350 return true;
351 }
352
CreateRuntime()353 void* JerryScriptNativeEngine::CreateRuntime()
354 {
355 return nullptr;
356 }
357
Serialize(NativeEngine * context,NativeValue * value,NativeValue * transfer)358 NativeValue* JerryScriptNativeEngine::Serialize(NativeEngine* context, NativeValue* value,
359 NativeValue* transfer)
360 {
361 return nullptr;
362 }
363
Deserialize(NativeEngine * context,NativeValue * recorder)364 NativeValue* JerryScriptNativeEngine::Deserialize(NativeEngine* context, NativeValue* recorder)
365 {
366 return nullptr;
367 }
368
GetExceptionForWorker() const369 ExceptionInfo* JerryScriptNativeEngine::GetExceptionForWorker() const
370 {
371 return nullptr;
372 }
373
LoadModule(NativeValue * str,const std::string & fileName)374 NativeValue* JerryScriptNativeEngine::LoadModule(NativeValue* str, const std::string& fileName)
375 {
376 return nullptr;
377 }
378
JerryValueToNativeValue(JerryScriptNativeEngine * engine,jerry_value_t value)379 NativeValue* JerryScriptNativeEngine::JerryValueToNativeValue(JerryScriptNativeEngine* engine, jerry_value_t value)
380 {
381 NativeValue* result = nullptr;
382 switch (jerry_value_get_type(value)) {
383 case JERRY_TYPE_NONE:
384 result = new JerryScriptNativeValue(engine, value);
385 break;
386 case JERRY_TYPE_UNDEFINED:
387 result = new JerryScriptNativeValue(engine, value);
388 break;
389 case JERRY_TYPE_NULL:
390 result = new JerryScriptNativeValue(engine, value);
391 break;
392 case JERRY_TYPE_BOOLEAN:
393 result = new JerryScriptNativeBoolean(engine, value);
394 break;
395 case JERRY_TYPE_NUMBER:
396 result = new JerryScriptNativeNumber(engine, value);
397 break;
398 case JERRY_TYPE_STRING:
399 result = new JerryScriptNativeString(engine, value);
400 break;
401 case JERRY_TYPE_OBJECT:
402 if (jerry_value_is_array(value)) {
403 result = new JerryScriptNativeArray(engine, value);
404 } else if (jerry_value_is_arraybuffer(value)) {
405 result = new JerryScriptNativeArrayBuffer(engine, value);
406 } else if (jerry_value_is_dataview(value)) {
407 result = new JerryScriptNativeDataView(engine, value);
408 } else if (jerry_value_is_typedarray(value)) {
409 result = new JerryScriptNativeTypedArray(engine, value);
410 } else if (jerry_value_is_external(value)) {
411 result = new JerryScriptNativeExternal(engine, value);
412 } else if (jerry_is_date(value)) {
413 result = new JerryScriptNativeDate(engine, value);
414 } else {
415 result = new JerryScriptNativeObject(engine, value);
416 }
417 break;
418 case JERRY_TYPE_FUNCTION:
419 result = new JerryScriptNativeFunction(engine, value);
420 break;
421 case JERRY_TYPE_ERROR:
422 result = new JerryScriptNativeObject(engine, value);
423 break;
424 case JERRY_TYPE_SYMBOL:
425 result = new JerryScriptNativeValue(engine, value);
426 break;
427 case JERRY_TYPE_BIGINT:
428 #if JERRY_API_MINOR_VERSION > 3
429 result = new JerryScriptNativeBigInt(engine, value);
430 break;
431 #endif
432 default:;
433 }
434 return result;
435 }
436
ValueToNativeValue(JSValueWrapper & value)437 NativeValue* JerryScriptNativeEngine::ValueToNativeValue(JSValueWrapper& value)
438 {
439 jerry_value_t jerryValue = value;
440 return JerryValueToNativeValue(this, jerryValue);
441 }
442
TriggerFatalException(NativeValue * error)443 bool JerryScriptNativeEngine::TriggerFatalException(NativeValue* error)
444 {
445
446 return false;
447 }
448
AdjustExternalMemory(int64_t ChangeInBytes,int64_t * AdjustedValue)449 bool JerryScriptNativeEngine::AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue)
450 {
451 HILOG_INFO("L1: napi_adjust_external_memory not supported!");
452 return true;
453 }
454
CreateDate(double time)455 NativeValue* JerryScriptNativeEngine::CreateDate(double time)
456 {
457 jerry_value_t value = jerry_strict_date(time);
458 return JerryValueToNativeValue(this, value);
459 }
460
SetPromiseRejectCallback(NativeReference * rejectCallbackRef,NativeReference * checkCallbackRef)461 void JerryScriptNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRef,
462 NativeReference* checkCallbackRef) {}
463
464
CreateBigWords(int sign_bit,size_t word_count,const uint64_t * words)465 NativeValue* JerryScriptNativeEngine::CreateBigWords(int sign_bit, size_t word_count, const uint64_t* words)
466 {
467 #if JERRY_API_MINOR_VERSION > 3 // jerryscript2.3: 3, jerryscript2.4: 4
468 constexpr int bigintMod = 2;
469 bool sign = false;
470 if ((sign_bit % bigintMod) == 1) {
471 sign = true;
472 }
473 uint32_t size = (uint32_t)word_count;
474
475 jerry_value_t jerryValue = jerry_create_bigint(words, size, sign);
476
477 return new JerryScriptNativeBigInt(this, jerryValue);
478 #else
479 return nullptr;
480 #endif
481 }
482
CreateBigInt(int64_t value)483 NativeValue* JerryScriptNativeEngine::CreateBigInt(int64_t value)
484 {
485 return new JerryScriptNativeBigInt(this, value);
486 }
487
CreateBigInt(uint64_t value)488 NativeValue* JerryScriptNativeEngine::CreateBigInt(uint64_t value)
489 {
490 #if JERRY_API_MINOR_VERSION > 3 // jerryscript2.3: 3, jerryscript2.4: 4
491 return new JerryScriptNativeBigInt(this, value, true);
492 #else
493 return nullptr;
494 #endif
495 }
496
CreateString16(const char16_t * value,size_t length)497 NativeValue* JerryScriptNativeEngine::CreateString16(const char16_t* value, size_t length)
498 {
499 #if JERRY_API_MINOR_VERSION > 3 // jerryscript2.3: 3, jerryscript2.4: 4
500 return new JerryScriptNativeString(this, value, length);
501 #else
502 return nullptr;
503 #endif
504 }
505