• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_QUICKJS_QJS_UTILS_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_QUICKJS_QJS_UTILS_H
18 
19 #include <cassert>
20 #include <cstring>
21 #include <stack>
22 #include <vector>
23 
24 #include "frameworks/bridge/js_frontend/js_ace_page.h"
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 #include "third_party/quickjs/cutils.h"
29 #include "third_party/quickjs/quickjs-libc.h"
30 #ifdef __cplusplus
31 }
32 #endif
33 
34 namespace OHOS::Ace::Framework {
35 
36 enum class JsErrorType {
37     JS_CRASH = 0,
38     JS_CALLBACK_ERROR,
39     FIRE_EVENT_ERROR,
40     EVAL_BUFFER_ERROR,
41     READ_OBJECT_ERROR,
42     DESTROY_APP_ERROR,
43     DESTROY_PAGE_ERROR,
44     LOAD_JS_BUNDLE_ERROR,
45     COMPILE_AND_RUN_BUNDLE_ERROR,
46     LOAD_JS_FRAMEWORK_ERROR,
47 };
48 
49 class ScopedString {
50 public:
51     ScopedString(JSContext* ctx, JSValueConst val);
52     ScopedString(JSContext* ctx, JSAtom val);
53     ScopedString(JSValueConst val);
54     ScopedString(JSAtom val);
55     ScopedString(const ScopedString& rhs) = delete;
56     ScopedString& operator=(const ScopedString& rhs) = delete;
57     ScopedString(ScopedString&& rhs) = delete;
58     ScopedString& operator=(ScopedString&& rhs) = delete;
59     ~ScopedString();
60 
61     bool operator==(const char* rhs);
62     bool operator==(const std::string& rhs);
63     bool operator==(const ScopedString& rhs);
64 
65     const char* get() const;
66     std::string str();
67 
68     static std::string Stringify(JSValueConst val);
69     static std::string Stringify(JSContext* ctx, JSValueConst val);
70 
71     operator std::string() const;
72 
73 private:
74     JSContext* context_ = nullptr;
75     const char* stringValue_ = nullptr;
76 };
77 
78 class QJSUtils {
79 public:
80     using FilterFunction = bool (*)(std::string);
81 
82     static JSValue NewStringLen(JSContext* ctx, const char* str, size_t len);
83     static JSValue NewString(JSContext* ctx, const char* str);
84     static JSValue ParseJSON(JSContext* ctx, const char* buf, size_t bufLen, const char* filename = nullptr);
85     static JSValue NewObject(JSContext* ctx);
86     static JSValue Call(JSContext* ctx, JSValueConst funcObj, JSValueConst thisObj, int32_t argc, JSValueConst* argv);
87     static JSValue Eval(JSContext* ctx, const char* input, size_t inputLen, const char* filename, int32_t evalFlags);
88     static JSValue GetPropertyStr(JSContext* ctx, JSValueConst thisObj, const char* prop);
89     static void JsStdDumpErrorAce(JSContext* ctx, JsErrorType errorType = JsErrorType::JS_CRASH, int32_t instanceId = 0,
90         const char* pageUrl = nullptr, const RefPtr<JsAcePage>& page = nullptr);
91     static void ExtractEachInfo(const std::string& tempStack, std::vector<std::string>& res);
92     static void GetPosInfo(const std::string& temp, int32_t start, std::string& line);
93     static std::string GetSourceInfo(const std::string& line, const RefPtr<RevSourceMap>& pageMap,
94         const RefPtr<RevSourceMap>& appMap, bool isAppPage);
95     static void JsDumpMemoryStats(JSContext* ctx);
96     static int32_t JsGetArrayLength(JSContext* ctx, JSValueConst arrayObject);
97 
98     static std::vector<std::string> GetObjectKeys(JSContext* ctx, JSValueConst obj, int flags = JS_GPN_STRING_MASK);
99     static std::vector<std::string> GetObjectKeys(JSValueConst obj, int flags = JS_GPN_STRING_MASK);
100     static std::vector<std::string> GetFilteredObjectKeys(
101         JSContext* ctx, JSValueConst obj, FilterFunction filterFunc, int flags = JS_GPN_STRING_MASK);
102     static bool CheckAndGetJsProperty(JSContext* ctx, JSValueConst jsObj, JSPropertyEnum** pTab, uint32_t* len);
103     static std::string typeAsString(JSValueConst val);
104     static JSValue GetArgvSafe(int idx, int argc, JSValueConst* argv);
105     static void DefineGlobalFunction(JSContext* ctx, JSCFunction jsFunc, const char* name, const int paramNum);
106     static std::string JsDumpSourceFile(const char* stack, const RefPtr<RevSourceMap>& pageMap,
107         const RefPtr<RevSourceMap>& appMap);
108 };
109 
110 /**
111  * @brief A class maintaining a stack of JSContext pointers.
112  *
113  */
114 class QJSContext {
115 public:
116     /**
117      * @brief A class that acquires a JSContext to be retrieved further in a call stack by QJSContext::Current().
118      *
119      * This is used to relieve the QJS embedder of passing JSContext* as an argument.
120      *
121      * @note QJSContext::Scope is thread-safe, but not reentrant.
122      */
123     class Scope {
124     public:
125         Scope(JSContext* ctx);
126         ~Scope();
127 
128         static void* operator new(size_t) = delete;
129         static void* operator new[](size_t) = delete;
130         static void operator delete(void*) = delete;
131         static void operator delete[](void*) = delete;
132         Scope(const Scope&) = delete;
133         void operator=(const Scope&) = delete;
134     };
135 
136     /**
137      * @brief Get the context on the top of the stack
138      *
139      * @return JSContext*
140      */
141     static JSContext* Current();
142 
143     static void* operator new(size_t) = delete;
144     static void* operator new[](size_t) = delete;
145     static void operator delete(void*) = delete;
146     static void operator delete[](void*) = delete;
147     QJSContext(const QJSContext&) = delete;
148     void operator=(const QJSContext&) = delete;
149 
150 private:
151 #if defined(USE_CLANG_COVERAGE) || defined(CLANG_COVERAGE)
152     static std::stack<JSContext*> s_qjsContextStack;
153 #else
154     static thread_local std::stack<JSContext*> s_qjsContextStack;
155 #endif
156 };
157 
158 class QJSHandleScope {
159 public:
160     QJSHandleScope(JSContext* ctx);
161     ~QJSHandleScope();
162 
163     static void* operator new(size_t) = delete;
164     static void* operator new[](size_t) = delete;
165     static void operator delete(void*) = delete;
166     static void operator delete[](void*) = delete;
167 
168 private:
169     friend class QJSUtils;
170     friend class QJSValue;
171 #if defined(USE_CLANG_COVERAGE) || defined(CLANG_COVERAGE)
172     static std::stack<QJSHandleScope*> qjsHandleScopeStack_;
173 #else
174     static thread_local std::stack<QJSHandleScope*> qjsHandleScopeStack_;
175 #endif
176 
177     static QJSHandleScope* GetCurrent();
178     void Push(JSValue val);
179 
180     int32_t scopeId_ = 0;
181     std::vector<JSValueConst> jsValues_;
182     JSContext* context_ = nullptr;
183 };
184 
CheckAndGetJsProperty(JSContext * ctx,JSValueConst fromMap,JSPropertyEnum ** pTab,uint32_t * len)185 inline bool CheckAndGetJsProperty(JSContext* ctx, JSValueConst fromMap, JSPropertyEnum** pTab, uint32_t* len)
186 {
187     if (!JS_IsObject(fromMap)) {
188         return false;
189     }
190 
191     JS_GetOwnPropertyNames(ctx, pTab, len, fromMap, JS_GPN_STRING_MASK);
192     if (*pTab == nullptr) {
193         return false;
194     }
195     return true;
196 }
197 
198 } // namespace OHOS::Ace::Framework
199 
200 #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_QUICKJS_QJS_UTILS_H
201