1 /*
2 * Copyright (c) 2021-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 "jsnapi_helper.h"
17
18 #include <array>
19 #include <cstdint>
20 #include <fcntl.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "ecmascript/base/builtins_base.h"
25 #include "ecmascript/base/json_parser.h"
26 #include "ecmascript/base/json_stringifier.h"
27 #include "ecmascript/base/path_helper.h"
28 #include "ecmascript/base/string_helper.h"
29 #include "ecmascript/base/typed_array_helper-inl.h"
30 #include "ecmascript/builtins/builtins_object.h"
31 #include "ecmascript/builtins/builtins_string.h"
32 #include "ecmascript/builtins/builtins_typedarray.h"
33 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
34 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
35 #endif
36 #include "ecmascript/byte_array.h"
37 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
38 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
39 #include "ecmascript/debugger/js_debugger_manager.h"
40 #include "ecmascript/ecma_context.h"
41 #include "ecmascript/ecma_global_storage.h"
42 #include "ecmascript/ecma_runtime_call_info.h"
43 #include "ecmascript/ecma_string.h"
44 #include "ecmascript/ecma_vm.h"
45 #include "ecmascript/global_env.h"
46 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
47 #include "ecmascript/interpreter/frame_handler.h"
48 #include "ecmascript/jobs/micro_job_queue.h"
49 #include "ecmascript/js_array.h"
50 #include "ecmascript/js_arraybuffer.h"
51 #include "ecmascript/js_dataview.h"
52 #include "ecmascript/js_file_path.h"
53 #include "ecmascript/js_function.h"
54 #include "ecmascript/js_generator_object.h"
55 #include "ecmascript/js_iterator.h"
56 #include "ecmascript/js_map.h"
57 #include "ecmascript/js_map_iterator.h"
58 #include "ecmascript/js_primitive_ref.h"
59 #include "ecmascript/js_promise.h"
60 #include "ecmascript/js_regexp.h"
61 #include "ecmascript/js_runtime_options.h"
62 #include "ecmascript/js_serializer.h"
63 #include "ecmascript/js_set.h"
64 #include "ecmascript/js_set_iterator.h"
65 #include "ecmascript/js_tagged_number.h"
66 #include "ecmascript/js_thread.h"
67 #include "ecmascript/js_typed_array.h"
68 #include "ecmascript/jspandafile/debug_info_extractor.h"
69 #include "ecmascript/jspandafile/js_pandafile_executor.h"
70 #include "ecmascript/jspandafile/js_pandafile_manager.h"
71 #include "ecmascript/linked_hash_table.h"
72 #include "ecmascript/log.h"
73 #include "ecmascript/mem/mem.h"
74 #include "ecmascript/mem/mem_map_allocator.h"
75 #include "ecmascript/mem/region.h"
76 #include "ecmascript/module/js_module_manager.h"
77 #include "ecmascript/module/js_module_source_text.h"
78 #include "ecmascript/module/module_path_helper.h"
79 #include "ecmascript/object_factory.h"
80 #include "ecmascript/patch/quick_fix_manager.h"
81 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
82 #include "ecmascript/platform/file.h"
83 #include "ecmascript/regexp/regexp_parser.h"
84 #include "ecmascript/tagged_array.h"
85 #include "ecmascript/js_weak_container.h"
86 #ifdef ARK_SUPPORT_INTL
87 #include "ecmascript/js_bigint.h"
88 #include "ecmascript/js_collator.h"
89 #include "ecmascript/js_date_time_format.h"
90 #include "ecmascript/js_number_format.h"
91 #endif
92
93 #include "ohos/init_data.h"
94
95 #include "ecmascript/platform/mutex.h"
96 #include "ecmascript/platform/log.h"
97
98 #if defined(ECMASCRIPT_SUPPORT_DEBUGGER) && defined(PANDA_TARGET_IOS)
99 namespace OHOS::ArkCompiler::Toolchain {
100 using DebuggerPostTask = std::function<void(std::function<void()> &&)>;
101 extern "C" {
102 bool StartDebug(const std::string& componentName, void* vm, bool isDebugMode, int32_t instanceId,
103 const DebuggerPostTask& debuggerPostTask, int port);
104 void StopDebug(const std::string& componentName);
105 void WaitForDebugger(void* vm);
106 }
107 } // namespace OHOS::ArkCompiler::Toolchain
108 const std::string DEBUGGER_NAME = "PandaDebugger";
109 #endif
110
111 namespace panda {
112 using ecmascript::ECMAObject;
113 using ecmascript::EcmaString;
114 using ecmascript::EcmaStringAccessor;
115 using ecmascript::ErrorType;
116 using ecmascript::FastRuntimeStub;
117 using ecmascript::GlobalEnv;
118 using ecmascript::GlobalEnvConstants;
119 using ecmascript::EcmaRuntimeCallInfo;
120 using ecmascript::JSArray;
121 using ecmascript::JSArrayBuffer;
122 using ecmascript::JSDataView;
123 using ecmascript::ByteArray;
124 using ecmascript::JSDate;
125 using ecmascript::JSFunction;
126 using ecmascript::JSFunctionBase;
127 using ecmascript::JSHClass;
128 using ecmascript::JSMap;
129 using ecmascript::Method;
130 using ecmascript::JSNativePointer;
131 using ecmascript::JSObject;
132 using ecmascript::JSPandaFile;
133 using ecmascript::JSPandaFileManager;
134 using ecmascript::JSPrimitiveRef;
135 using ecmascript::JSPromise;
136 using ecmascript::JSRegExp;
137 using ecmascript::JSSerializer;
138 using ecmascript::JSSet;
139 using ecmascript::JSSymbol;
140 using ecmascript::JSTaggedNumber;
141 using ecmascript::JSTaggedType;
142 using ecmascript::JSTaggedValue;
143 using ecmascript::JSThread;
144 using ecmascript::LinkedHashMap;
145 using ecmascript::LinkedHashSet;
146 using ecmascript::ObjectFactory;
147 using ecmascript::PromiseCapability;
148 using ecmascript::PropertyDescriptor;
149 using ecmascript::OperationResult;
150 using ecmascript::Region;
151 using ecmascript::TaggedArray;
152 using ecmascript::JSTypedArray;
153 using ecmascript::base::BuiltinsBase;
154 using ecmascript::builtins::BuiltinsObject;
155 using ecmascript::base::Utf8JsonParser;
156 using ecmascript::base::Utf16JsonParser;
157 using ecmascript::base::JsonStringifier;
158 using ecmascript::base::StringHelper;
159 using ecmascript::base::TypedArrayHelper;
160 using ecmascript::job::MicroJobQueue;
161 using ecmascript::job::QueueType;
162 using ecmascript::JSRuntimeOptions;
163 using ecmascript::BigInt;
164 using ecmascript::MemMapAllocator;
165 using ecmascript::Mutex;
166 using ecmascript::LockHolder;
167 using ecmascript::JSMapIterator;
168 using ecmascript::JSSetIterator;
169 using ecmascript::IterationKind;
170 using ecmascript::JSGeneratorState;
171 using ecmascript::JSIterator;
172 using ecmascript::JSGeneratorFunction;
173 using ecmascript::JSGeneratorObject;
174 using ecmascript::GeneratorContext;
175 using ecmascript::JSProxy;
176 #ifdef ARK_SUPPORT_INTL
177 using ecmascript::JSCollator;
178 using ecmascript::JSDateTimeFormat;
179 using ecmascript::JSNumberFormat;
180 #endif
181 using ecmascript::RegExpParser;
182 using ecmascript::DebugInfoExtractor;
183 using ecmascript::PatchErrorCode;
184 using ecmascript::base::NumberHelper;
185 using ecmascript::Log;
186 using ecmascript::EcmaContext;
187 using ecmascript::JSWeakMap;
188 using ecmascript::JSWeakSet;
189 template<typename T>
190 using JSHandle = ecmascript::JSHandle<T>;
191
192 template<typename T>
193 using JSMutableHandle = ecmascript::JSMutableHandle<T>;
194
195 using PathHelper = ecmascript::base::PathHelper;
196 using ModulePathHelper = ecmascript::ModulePathHelper;
197
198 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
199 #define TYPED_ARRAY_NEW(Type) \
200 Local<Type##Ref> Type##Ref::New( \
201 const EcmaVM *vm, Local<ArrayBufferRef> buffer, int32_t byteOffset, int32_t length) \
202 { \
203 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm)); \
204 JSHandle<GlobalEnv> env = vm->GetGlobalEnv(); \
205 \
206 JSHandle<JSTaggedValue> func = env->Get##Type##Function(); \
207 JSHandle<JSArrayBuffer> arrayBuffer(JSNApiHelper::ToJSHandle(buffer)); \
208 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); \
209 const uint32_t argsLength = 3; \
210 EcmaRuntimeCallInfo *info = \
211 ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, func, argsLength); \
212 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); \
213 info->SetCallArg(arrayBuffer.GetTaggedValue(), JSTaggedValue(byteOffset), JSTaggedValue(length)); \
214 JSTaggedValue result = JSFunction::Construct(info); \
215 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm)); \
216 JSHandle<JSTaggedValue> resultHandle(thread, result); \
217 return JSNApiHelper::ToLocal<Type##Ref>(resultHandle); \
218 }
219
TYPED_ARRAY_ALL(TYPED_ARRAY_NEW)220 TYPED_ARRAY_ALL(TYPED_ARRAY_NEW)
221
222 #undef TYPED_ARRAY_NEW
223
224 // ---------------------------------- JSON ------------------------------------------
225 Local<JSValueRef> JSON::Parse(const EcmaVM *vm, Local<StringRef> string)
226 {
227 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
228 auto ecmaStr = EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject());
229 JSHandle<JSTaggedValue> result;
230 if (EcmaStringAccessor(ecmaStr).IsUtf8()) {
231 Utf8JsonParser parser(thread);
232 result = parser.Parse(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
233 } else {
234 Utf16JsonParser parser(thread);
235 result = parser.Parse(EcmaString::Cast(JSNApiHelper::ToJSTaggedValue(*string).GetTaggedObject()));
236 }
237 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
238 return JSNApiHelper::ToLocal<JSValueRef>(result);
239 }
240
Stringify(const EcmaVM * vm,Local<JSValueRef> json)241 Local<JSValueRef> JSON::Stringify(const EcmaVM *vm, Local<JSValueRef> json)
242 {
243 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
244 auto constants = thread->GlobalConstants();
245 JsonStringifier stringifier(thread);
246 JSHandle<JSTaggedValue> str = stringifier.Stringify(
247 JSNApiHelper::ToJSHandle(json), constants->GetHandledUndefined(), constants->GetHandledUndefined());
248 RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
249 return JSNApiHelper::ToLocal<JSValueRef>(str);
250 }
251
GetOriginalSource(const EcmaVM * vm)252 Local<StringRef> RegExpRef::GetOriginalSource(const EcmaVM *vm)
253 {
254 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
255 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
256 LOG_IF_SPECIAL(regExp, FATAL);
257 JSTaggedValue source = regExp->GetOriginalSource();
258 if (!source.IsString()) {
259 auto constants = thread->GlobalConstants();
260 return JSNApiHelper::ToLocal<StringRef>(constants->GetHandledEmptyString());
261 }
262 JSHandle<JSTaggedValue> sourceHandle(thread, source);
263 return JSNApiHelper::ToLocal<StringRef>(sourceHandle);
264 }
265
GetOriginalFlags()266 std::string RegExpRef::GetOriginalFlags()
267 {
268 DCHECK_SPECIAL_VALUE_WITH_RETURN(this, "");
269 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
270 JSTaggedValue regExpFlags = regExp->GetOriginalFlags();
271 uint32_t regExpFlagsInt = static_cast<uint32_t>(regExpFlags.GetInt());
272 std::string strFlags = "";
273 if (regExpFlagsInt & RegExpParser::FLAG_GLOBAL) {
274 strFlags += "g";
275 }
276 if (regExpFlagsInt & RegExpParser::FLAG_IGNORECASE) {
277 strFlags += "i";
278 }
279 if (regExpFlagsInt & RegExpParser::FLAG_MULTILINE) {
280 strFlags += "m";
281 }
282 if (regExpFlagsInt & RegExpParser::FLAG_DOTALL) {
283 strFlags += "s";
284 }
285 if (regExpFlagsInt & RegExpParser::FLAG_UTF16) {
286 strFlags += "u";
287 }
288 if (regExpFlagsInt & RegExpParser::FLAG_STICKY) {
289 strFlags += "y";
290 }
291 std::sort(strFlags.begin(), strFlags.end());
292 return strFlags;
293 }
294
IsGlobal(const EcmaVM * vm)295 Local<JSValueRef> RegExpRef::IsGlobal(const EcmaVM *vm)
296 {
297 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
298 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
299 LOG_IF_SPECIAL(regExp, FATAL);
300 JSTaggedValue flags = regExp->GetOriginalFlags();
301 bool result = flags.GetInt() & RegExpParser::FLAG_GLOBAL;
302 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
303 return jsValue;
304 }
305
IsIgnoreCase(const EcmaVM * vm)306 Local<JSValueRef> RegExpRef::IsIgnoreCase(const EcmaVM *vm)
307 {
308 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
309 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
310 LOG_IF_SPECIAL(regExp, FATAL);
311 JSTaggedValue flags = regExp->GetOriginalFlags();
312 bool result = flags.GetInt() & RegExpParser::FLAG_IGNORECASE;
313 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
314 return jsValue;
315 }
316
IsMultiline(const EcmaVM * vm)317 Local<JSValueRef> RegExpRef::IsMultiline(const EcmaVM *vm)
318 {
319 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
320 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
321 LOG_IF_SPECIAL(regExp, FATAL);
322 JSTaggedValue flags = regExp->GetOriginalFlags();
323 bool result = flags.GetInt() & RegExpParser::FLAG_MULTILINE;
324 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
325 return jsValue;
326 }
327
IsDotAll(const EcmaVM * vm)328 Local<JSValueRef> RegExpRef::IsDotAll(const EcmaVM *vm)
329 {
330 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
331 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
332 LOG_IF_SPECIAL(regExp, FATAL);
333 JSTaggedValue flags = regExp->GetOriginalFlags();
334 bool result = flags.GetInt() & RegExpParser::FLAG_DOTALL;
335 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
336 return jsValue;
337 }
338
IsUtf16(const EcmaVM * vm)339 Local<JSValueRef> RegExpRef::IsUtf16(const EcmaVM *vm)
340 {
341 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
342 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
343 LOG_IF_SPECIAL(regExp, FATAL);
344 JSTaggedValue flags = regExp->GetOriginalFlags();
345 bool result = flags.GetInt() & RegExpParser::FLAG_UTF16;
346 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
347 return jsValue;
348 }
349
IsStick(const EcmaVM * vm)350 Local<JSValueRef> RegExpRef::IsStick(const EcmaVM *vm)
351 {
352 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
353 JSHandle<JSRegExp> regExp(JSNApiHelper::ToJSHandle(this));
354 LOG_IF_SPECIAL(regExp, FATAL);
355 JSTaggedValue flags = regExp->GetOriginalFlags();
356 bool result = flags.GetInt() & RegExpParser::FLAG_STICKY;
357 Local<JSValueRef> jsValue = BooleanRef::New(vm, result);
358 return jsValue;
359 }
360
IsGenerator()361 bool GeneratorFunctionRef::IsGenerator()
362 {
363 // Omit exception check because ark calls here may not
364 // cause side effect even pending exception exists.
365 return IsGeneratorFunction();
366 }
367
GetGeneratorState(const EcmaVM * vm)368 Local<JSValueRef> GeneratorObjectRef::GetGeneratorState(const EcmaVM *vm)
369 {
370 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
371 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this));
372 LOG_IF_SPECIAL(jsGenerator, FATAL);
373 if (jsGenerator->GetGeneratorState() == JSGeneratorState::COMPLETED) {
374 return StringRef::NewFromUtf8(vm, "closed");
375 }
376 return StringRef::NewFromUtf8(vm, "suspended");
377 }
378
GetGeneratorFunction(const EcmaVM * vm)379 Local<JSValueRef> GeneratorObjectRef::GetGeneratorFunction(const EcmaVM *vm)
380 {
381 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
382 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this));
383 LOG_IF_SPECIAL(jsGenerator, FATAL);
384 JSHandle<GeneratorContext> generatorContext(thread, jsGenerator->GetGeneratorContext());
385 JSTaggedValue jsTagValue = generatorContext->GetMethod();
386 return JSNApiHelper::ToLocal<GeneratorFunctionRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
387 }
388
GetGeneratorReceiver(const EcmaVM * vm)389 Local<JSValueRef> GeneratorObjectRef::GetGeneratorReceiver(const EcmaVM *vm)
390 {
391 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
392 JSHandle<JSGeneratorObject> jsGenerator(JSNApiHelper::ToJSHandle(this));
393 LOG_IF_SPECIAL(jsGenerator, FATAL);
394 JSHandle<GeneratorContext> generatorContext(thread, jsGenerator->GetGeneratorContext());
395 JSTaggedValue jsTagValue = generatorContext->GetAcc();
396 return JSNApiHelper::ToLocal<GeneratorObjectRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
397 }
398
GetCompareFunction(const EcmaVM * vm)399 Local<JSValueRef> CollatorRef::GetCompareFunction(const EcmaVM *vm)
400 {
401 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
402 #ifdef ARK_SUPPORT_INTL
403 JSHandle<JSCollator> jsCollator(JSNApiHelper::ToJSHandle(this));
404 LOG_IF_SPECIAL(jsCollator, FATAL);
405 JSTaggedValue jsTagValue = jsCollator->GetBoundCompare();
406 return JSNApiHelper::ToLocal<CollatorRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
407 #else
408 LOG_ECMA(ERROR) << "Not support arkcompiler intl";
409 return JSNApiHelper::ToLocal<CollatorRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
410 #endif
411 }
412
GetFormatFunction(const EcmaVM * vm)413 Local<JSValueRef> DataTimeFormatRef::GetFormatFunction(const EcmaVM *vm)
414 {
415 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
416 #ifdef ARK_SUPPORT_INTL
417 JSHandle<JSDateTimeFormat> jsDateTimeFormat(JSNApiHelper::ToJSHandle(this));
418 LOG_IF_SPECIAL(jsDateTimeFormat, FATAL);
419 JSTaggedValue jsTagValue = jsDateTimeFormat->GetBoundFormat();
420 return JSNApiHelper::ToLocal<DataTimeFormatRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
421 #else
422 LOG_ECMA(ERROR) << "Not support arkcompiler intl";
423 return JSNApiHelper::ToLocal<DataTimeFormatRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
424 #endif
425 }
426
GetFormatFunction(const EcmaVM * vm)427 Local<JSValueRef> NumberFormatRef::GetFormatFunction(const EcmaVM *vm)
428 {
429 CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
430 #ifdef ARK_SUPPORT_INTL
431 JSHandle<JSNumberFormat> jsNumberFormat(JSNApiHelper::ToJSHandle(this));
432 LOG_IF_SPECIAL(jsNumberFormat, FATAL);
433 JSTaggedValue jsTagValue = jsNumberFormat->GetBoundFormat();
434 return JSNApiHelper::ToLocal<NumberFormatRef>(JSHandle<JSTaggedValue>(thread, jsTagValue));
435 #else
436 LOG_ECMA(ERROR) << "Not support arkcompiler intl";
437 return JSNApiHelper::ToLocal<NumberFormatRef>(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
438 #endif
439 }
440
441 // ----------------------------------- FunctionCallback ---------------------------------
RegisterCallback(ecmascript::EcmaRuntimeCallInfo * ecmaRuntimeCallInfo)442 JSTaggedValue Callback::RegisterCallback(ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo)
443 {
444 // Constructor
445 JSThread *thread = ecmaRuntimeCallInfo->GetThread();
446 JSHandle<JSTaggedValue> constructor = BuiltinsBase::GetConstructor(ecmaRuntimeCallInfo);
447 if (!constructor->IsJSFunction()) {
448 return JSTaggedValue::False();
449 }
450 [[maybe_unused]] LocalScope scope(thread->GetEcmaVM());
451 JSHandle<JSFunction> function(constructor);
452 JSTaggedValue extraInfoValue = function->GetFunctionExtraInfo();
453 if (!extraInfoValue.IsJSNativePointer()) {
454 return JSTaggedValue::False();
455 }
456 JSHandle<JSNativePointer> extraInfo(thread, extraInfoValue);
457 // callBack
458 FunctionCallback nativeFunc = reinterpret_cast<FunctionCallback>(extraInfo->GetExternalPointer());
459
460 JsiRuntimeCallInfo *jsiRuntimeCallInfo = reinterpret_cast<JsiRuntimeCallInfo *>(ecmaRuntimeCallInfo);
461 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
462 bool getStackBeforeCallNapiSuccess = false;
463 if (thread->GetIsProfiling() && function->IsCallNapi()) {
464 getStackBeforeCallNapiSuccess = thread->GetEcmaVM()->GetProfiler()->GetStackBeforeCallNapi(thread);
465 }
466 #endif
467 Local<JSValueRef> result = nativeFunc(jsiRuntimeCallInfo);
468 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
469 if (thread->GetIsProfiling() && function->IsCallNapi() && getStackBeforeCallNapiSuccess) {
470 thread->GetEcmaVM()->GetProfiler()->GetStackAfterCallNapi(thread);
471 }
472 #endif
473 return JSNApiHelper::ToJSHandle(result).GetTaggedValue();
474 }
475 } // namespace panda
476