• 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 ECMASCRIPT_MODULE_JS_MODULE_SOURCE_TEXT_H
17 #define ECMASCRIPT_MODULE_JS_MODULE_SOURCE_TEXT_H
18 
19 #include "ecmascript/base/string_helper.h"
20 #include "ecmascript/mem/c_containers.h"
21 #include "ecmascript/module/js_module_record.h"
22 #include "ecmascript/module/js_module_entry.h"
23 #include "ecmascript/tagged_array.h"
24 
25 namespace panda::ecmascript {
26 enum class ModuleStatus : uint8_t {
27     UNINSTANTIATED = 0x01,
28     INSTANTIATING,
29     INSTANTIATED,
30     EVALUATING,
31     EVALUATING_ASYNC,
32     EVALUATED
33 };
34 
35 enum class ModuleTypes : uint8_t {
36     ECMA_MODULE = 0x01,
37     CJS_MODULE,
38     JSON_MODULE,
39     NATIVE_MODULE,
40     OHOS_MODULE,
41     APP_MODULE,
42     INTERNAL_MODULE,
43     UNKNOWN
44 };
45 
46 enum class LoadingTypes : uint8_t {
47     STABLE_MODULE = 0x01,
48     DYNAMITC_MODULE,
49     OTHERS
50 };
51 
52 class SourceTextModule final : public ModuleRecord {
53 public:
54     static constexpr int UNDEFINED_INDEX = -1;
55     static constexpr int MODULE_ERROR = 1;
56     static constexpr size_t DEFAULT_DICTIONART_CAPACITY = 2;
57     static constexpr size_t DEFAULT_ARRAY_CAPACITY = 2;
58     static constexpr uint8_t DEREGISTER_MODULE_TAG = 1;
59     static constexpr uint32_t FIRST_ASYNC_EVALUATING_ORDINAL = 2;
60     static constexpr uint32_t NOT_ASYNC_EVALUATED = 0;
61     static constexpr uint32_t ASYNC_EVALUATE_DID_FINISH = 1;
62     struct AsyncEvaluatingOrdinalCompare {
operatorAsyncEvaluatingOrdinalCompare63         bool operator()(const JSHandle<SourceTextModule> &lhs, const JSHandle<SourceTextModule> &rhs) const
64         {
65             return lhs->GetAsyncEvaluatingOrdinal() < rhs->GetAsyncEvaluatingOrdinal();
66         }
67     };
68     using AsyncParentCompletionSet =
69       CSet<JSHandle<SourceTextModule>, AsyncEvaluatingOrdinalCompare>;
70 
71     CAST_CHECK(SourceTextModule, IsSourceTextModule);
72 
73     // 15.2.1.17 Runtime Semantics: HostResolveImportedModule ( referencingModule, specifier )
74     static JSHandle<JSTaggedValue> HostResolveImportedModule(JSThread *thread,
75                                                              const JSHandle<SourceTextModule> &module,
76                                                              const JSHandle<JSTaggedValue> &moduleRequest);
77     static JSHandle<JSTaggedValue> HostResolveImportedModuleWithMerge(JSThread *thread,
78                                                                       const JSHandle<SourceTextModule> &module,
79                                                                       const JSHandle<JSTaggedValue> &moduleRequest);
80 
81     // 15.2.1.16.2 GetExportedNames(exportStarSet)
82     static CVector<std::string> GetExportedNames(JSThread *thread, const JSHandle<SourceTextModule> &module,
83                                                  const JSHandle<TaggedArray> &exportStarSet);
84 
85     // 15.2.1.16.3 ResolveExport(exportName, resolveVector)
86     static JSHandle<JSTaggedValue> ResolveExport(JSThread *thread, const JSHandle<SourceTextModule> &module,
87         const JSHandle<JSTaggedValue> &exportName,
88         CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> &resolveVector);
89     static JSHandle<JSTaggedValue> ResolveExportObject(JSThread *thread, const JSHandle<SourceTextModule> &module,
90                                                        const JSHandle<JSTaggedValue> &exportObject,
91                                                        const JSHandle<JSTaggedValue> &exportName);
92     // 15.2.1.16.4.1 InnerModuleInstantiation ( module, stack, index )
93     static int InnerModuleInstantiation(JSThread *thread,
94         const JSHandle<ModuleRecord> &moduleRecord, CVector<JSHandle<SourceTextModule>> &stack,
95         int index, bool excuteFromJob = false);
96 
97     // 15.2.1.16.4.2 ModuleDeclarationEnvironmentSetup ( module )
98     static void ModuleDeclarationEnvironmentSetup(JSThread *thread, const JSHandle<SourceTextModule> &module);
99     static void ModuleDeclarationArrayEnvironmentSetup(JSThread *thread, const JSHandle<SourceTextModule> &module);
100 
101     // 15.2.1.16.5.1 InnerModuleEvaluation ( module, stack, index )
102     static int InnerModuleEvaluation(JSThread *thread, const JSHandle<ModuleRecord> &moduleRecord,
103         CVector<JSHandle<SourceTextModule>> &stack, int index, const void *buffer = nullptr,
104         size_t size = 0, bool excuteFromJob = false);
105 
106     // 15.2.1.16.5.2 ModuleExecution ( module )
107     static Expected<JSTaggedValue, bool> ModuleExecution(JSThread *thread, const JSHandle<SourceTextModule> &module,
108                                  const void *buffer = nullptr, size_t size = 0, bool excuteFromJob = false);
109 
110     // 16.2.1.5.3.2 ExecuteAsyncModule ( module )
111     static void ExecuteAsyncModule(JSThread *thread, const JSHandle<SourceTextModule> &module,
112                                    const void *buffer = nullptr, size_t size = 0, bool excuteFromJob = false);
113 
114     // 16.2.1.5.3.3 GatherAvailableAncestors ( module, execList )
115     static void GatherAvailableAncestors(JSThread *thread, const JSHandle<SourceTextModule> &module,
116                                          AsyncParentCompletionSet &execList);
117 
118     // 16.2.1.5.3.4 AsyncModuleExecutionFulfilled ( module )
119     static void AsyncModuleExecutionFulfilled(JSThread *thread, const JSHandle<SourceTextModule> &module);
120 
121     // 16.2.1.5.3.5 AsyncModuleExecutionRejected ( module, error )
122     static void AsyncModuleExecutionRejected(JSThread *thread, const JSHandle<SourceTextModule> &module,
123                                              JSTaggedValue error);
124 
125     static JSTaggedValue AsyncModuleFulfilledFunc(EcmaRuntimeCallInfo *argv);
126     static JSTaggedValue AsyncModuleRejectedFunc(EcmaRuntimeCallInfo *argv);
127     static void AddAsyncParentModule(JSThread *thread, JSHandle<SourceTextModule> &module,
128                                      JSHandle<SourceTextModule> &parent);
129     // 15.2.1.18 Runtime Semantics: GetModuleNamespace ( module )
130     static JSHandle<JSTaggedValue> GetModuleNamespace(JSThread *thread, const JSHandle<SourceTextModule> &module);
131 
132     static void AddImportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
133                                const JSHandle<ImportEntry> &importEntry, size_t idx, uint32_t len);
134     static void AddLocalExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
135                                     const JSHandle<LocalExportEntry> &exportEntry, size_t idx, uint32_t len);
136     static void AddIndirectExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
137                                        const JSHandle<IndirectExportEntry> &exportEntry, size_t idx, uint32_t len);
138     static void AddStarExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
139                                    const JSHandle<StarExportEntry> &exportEntry, size_t idx, uint32_t len);
140     static std::pair<bool, ModuleTypes> CheckNativeModule(const CString &moduleRequestName);
141     static Local<JSValueRef> GetRequireNativeModuleFunc(EcmaVM *vm, ModuleTypes moduleType);
142     static void MakeAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments, const CString &moduleName);
143     static void MakeInternalArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
144                                  const CString &moduleRequestName);
145     static bool LoadNativeModule(JSThread *thread, JSHandle<SourceTextModule> &requiredModule,
146                                  ModuleTypes moduleType);
IsNativeModule(ModuleTypes moduleType)147     inline static bool IsNativeModule(ModuleTypes moduleType)
148     {
149         return moduleType == ModuleTypes::OHOS_MODULE ||
150                moduleType == ModuleTypes::APP_MODULE ||
151                moduleType == ModuleTypes::NATIVE_MODULE ||
152                moduleType == ModuleTypes::INTERNAL_MODULE;
153     }
154 
155     static constexpr size_t SOURCE_TEXT_MODULE_OFFSET = ModuleRecord::SIZE;
156     ACCESSORS(Environment, SOURCE_TEXT_MODULE_OFFSET, NAMESPACE_OFFSET);
157     ACCESSORS(Namespace, NAMESPACE_OFFSET, ECMA_MODULE_FILENAME);
158     ACCESSORS(EcmaModuleFilename, ECMA_MODULE_FILENAME, ECMA_MODULE_RECORDNAME);
159     ACCESSORS(EcmaModuleRecordName, ECMA_MODULE_RECORDNAME, REQUESTED_MODULES_OFFSET);
160     ACCESSORS(RequestedModules, REQUESTED_MODULES_OFFSET, IMPORT_ENTRIES_OFFSET);
161     ACCESSORS(ImportEntries, IMPORT_ENTRIES_OFFSET, LOCAL_EXPORT_ENTTRIES_OFFSET);
162     ACCESSORS(LocalExportEntries, LOCAL_EXPORT_ENTTRIES_OFFSET, INDIRECT_EXPORT_ENTTRIES_OFFSET);
163     ACCESSORS(IndirectExportEntries, INDIRECT_EXPORT_ENTTRIES_OFFSET, START_EXPORT_ENTTRIES_OFFSET);
164     ACCESSORS(StarExportEntries, START_EXPORT_ENTTRIES_OFFSET, NAME_DICTIONARY_OFFSET);
165     ACCESSORS(NameDictionary, NAME_DICTIONARY_OFFSET, CYCLE_ROOT_OFFSET);
166     ACCESSORS(CycleRoot, CYCLE_ROOT_OFFSET, TOP_LEVEL_CAPABILITY_OFFSET);
167     ACCESSORS(TopLevelCapability, TOP_LEVEL_CAPABILITY_OFFSET, ASYNC_PARENT_MODULES_OFFSET);
168     ACCESSORS(AsyncParentModules, ASYNC_PARENT_MODULES_OFFSET, EVALUATION_ERROR_OFFSET);
169     ACCESSORS_PRIMITIVE_FIELD(EvaluationError, int32_t, EVALUATION_ERROR_OFFSET, DFS_ANCESTOR_INDEX_OFFSET);
170     ACCESSORS_PRIMITIVE_FIELD(DFSAncestorIndex, int32_t, DFS_ANCESTOR_INDEX_OFFSET, DFS_INDEX_OFFSET);
171     ACCESSORS_PRIMITIVE_FIELD(DFSIndex, int32_t, DFS_INDEX_OFFSET, ASYNC_EVALUATION_OFFSET);
172     ACCESSORS_PRIMITIVE_FIELD(AsyncEvaluatingOrdinal, uint32_t, ASYNC_EVALUATION_OFFSET, PENDING_DEPENDENCIES_OFFSET);
173     ACCESSORS_PRIMITIVE_FIELD(PendingAsyncDependencies, int32_t, PENDING_DEPENDENCIES_OFFSET, BIT_FIELD_OFFSET);
174     ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
175 
176     DEFINE_ALIGN_SIZE(LAST_OFFSET);
177 
178     // define BitField
179     static constexpr size_t STATUS_BITS = 3;
180     static constexpr size_t MODULE_TYPE_BITS = 4;
181     static constexpr size_t IS_NEW_BC_VERSION_BITS = 1;
182     static constexpr size_t HASTLA_BITS = 1;
183     static constexpr size_t LOADING_TYPE_BITS = 3;
184     static constexpr uint16_t REGISTER_COUNTS = 16;
185 
186     FIRST_BIT_FIELD(BitField, Status, ModuleStatus, STATUS_BITS)
187     NEXT_BIT_FIELD(BitField, Types, ModuleTypes, MODULE_TYPE_BITS, Status)
188     NEXT_BIT_FIELD(BitField, IsNewBcVersion, bool, IS_NEW_BC_VERSION_BITS, Types)
189     NEXT_BIT_FIELD(BitField, HasTLA, bool, HASTLA_BITS, IsNewBcVersion)
190     NEXT_BIT_FIELD(BitField, LoadingTypes, LoadingTypes, LOADING_TYPE_BITS, HasTLA)
191     NEXT_BIT_FIELD(BitField, RegisterCounts, uint16_t, REGISTER_COUNTS, LoadingTypes)
192 
193     DECL_DUMP()
194     DECL_VISIT_OBJECT(SOURCE_TEXT_MODULE_OFFSET, EVALUATION_ERROR_OFFSET)
195 
196     // 15.2.1.16.5 Evaluate()
197     static JSTaggedValue Evaluate(JSThread *thread, const JSHandle<SourceTextModule> &module,
198                          const void *buffer = nullptr, size_t size = 0, bool excuteFromJob = false);
199 
200     // 15.2.1.16.4 Instantiate()
201     static int Instantiate(JSThread *thread, const JSHandle<JSTaggedValue> &moduleHdl,
202         bool excuteFromJob = false);
203     static void InstantiateCJS(JSThread *thread, const JSHandle<SourceTextModule> &currentModule,
204                                const JSHandle<SourceTextModule> &requiredModule);
205     static void InstantiateNativeModule(JSThread *thread, JSHandle<SourceTextModule> &currentModule,
206                                         JSHandle<SourceTextModule> &requiredModule,
207                                         const JSHandle<JSTaggedValue> &moduleRequest,
208                                         ModuleTypes moduleType);
209 
210     JSTaggedValue GetModuleValue(JSThread *thread, int32_t index, bool isThrow);
211     void StoreModuleValue(JSThread *thread, int32_t index, const JSHandle<JSTaggedValue> &value);
212 
213     JSTaggedValue GetModuleValue(JSThread *thread, JSTaggedValue key, bool isThrow);
214     void StoreModuleValue(JSThread *thread, const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
215 
216     JSTaggedValue GetNativeModuleValue(JSThread *thread, JSHandle<ResolvedBinding> &binding);
217     JSTaggedValue GetNativeModuleValue(JSThread *thread, JSHandle<ResolvedIndexBinding> &binding);
218 
219     static JSHandle<JSTaggedValue> ResolveIndirectExport(JSThread *thread, const JSHandle<JSTaggedValue> &exportEntry,
220                                                          const JSHandle<JSTaggedValue> &exportName,
221                                                          const JSHandle<SourceTextModule> &module,
222                                                          CVector<std::pair<JSHandle<SourceTextModule>,
223                                                          JSHandle<JSTaggedValue>>> &resolveVector);
224     static JSTaggedValue GetModuleName(JSTaggedValue currentModule);
225 
226     static bool IsDynamicModule(LoadingTypes types);
227 
228     // taskpool
229     static std::optional<std::set<uint32_t>> GetConcurrentRequestedModules(const JSHandle<Method> &method);
230     static int EvaluateForConcurrent(JSThread *thread, const JSHandle<SourceTextModule> &module,
231                                      const JSHandle<Method> &method);
232     static int ModuleEvaluation(JSThread *thread, const JSHandle<ModuleRecord> &moduleRecord,
233                                 int index, const JSHandle<Method> &method);
234 
235 private:
236     static void SetExportName(JSThread *thread,
237                               const JSHandle<JSTaggedValue> &moduleRequest, const JSHandle<SourceTextModule> &module,
238                               CVector<std::string> &exportedNames, JSHandle<TaggedArray> &newExportStarSet);
239     static JSHandle<JSTaggedValue> GetStarResolution(JSThread *thread, const JSHandle<JSTaggedValue> &exportName,
240                                                      const JSHandle<JSTaggedValue> &moduleRequest,
241                                                      const JSHandle<SourceTextModule> &module,
242                                                      JSMutableHandle<JSTaggedValue> &starResolution,
243                                                      CVector<std::pair<JSHandle<SourceTextModule>,
244                                                      JSHandle<JSTaggedValue>>> &resolveVector);
245     template <typename T>
246     static void AddExportName(JSThread *thread, const JSTaggedValue &exportEntry, CVector<std::string> &exportedNames);
247     static JSHandle<JSTaggedValue> ResolveLocalExport(JSThread *thread, const JSHandle<JSTaggedValue> &exportEntry,
248                                                       const JSHandle<JSTaggedValue> &exportName,
249                                                       const JSHandle<SourceTextModule> &module);
250     static JSHandle<JSTaggedValue> ResolveElementOfObject(JSThread *thread,
251                                                          const JSHandle<JSHClass> &hclass,
252                                                          const JSHandle<JSTaggedValue> &exportName,
253                                                          const JSHandle<SourceTextModule> &module);
254     static bool CheckCircularImport(const JSHandle<SourceTextModule> &module,
255         const JSHandle<JSTaggedValue> &exportName,
256         CVector<std::pair<JSHandle<SourceTextModule>, JSHandle<JSTaggedValue>>> &resolveVector);
257     static void InitializeEnvironment(JSThread *thread, const JSHandle<SourceTextModule> &currentModule,
258         JSHandle<JSTaggedValue> &moduleName, JSHandle<JSTaggedValue> &exports, bool isBundle);
259 
260     static void CheckResolvedBinding(JSThread *thread, const JSHandle<SourceTextModule> &module);
261     static void CheckResolvedIndexBinding(JSThread *thread, const JSHandle<SourceTextModule> &module);
262     static JSTaggedValue FindByExport(const JSTaggedValue &exportEntriesTv, const JSTaggedValue &key,
263                                       const JSTaggedValue &dictionary);
264     static JSHandle<SourceTextModule> GetModuleFromBinding(JSThread *thread, const JSTaggedValue &JSTaggedValue);
265     static void DFSModuleInstantiation(JSHandle<SourceTextModule> &module,
266                                        CVector<JSHandle<SourceTextModule>> &stack);
267     static std::optional<int> HandleInnerModuleInstantiation(JSThread *thread,
268                                                              JSHandle<SourceTextModule> &module,
269                                                              JSMutableHandle<JSTaggedValue> &required,
270                                                              CVector<JSHandle<SourceTextModule>> &stack,
271                                                              int &index, bool excuteFromJob);
272     static int HandleInstantiateException(JSHandle<SourceTextModule> &module,
273                                           const CVector<JSHandle<SourceTextModule>> &stack, int result);
274     static void HandleEvaluateResult(JSThread *thread, JSHandle<SourceTextModule> &module,
275                                      JSHandle<PromiseCapability> &capability,
276                                      const CVector<JSHandle<SourceTextModule>> &stack, int result);
277     static void HandleConcurrentEvaluateResult(JSThread *thread, JSHandle<SourceTextModule> &module,
278                                      const CVector<JSHandle<SourceTextModule>> &stack, int result);
279     bool IsAsyncEvaluating();
280 };
281 
282 class ResolvedBinding final : public Record {
283 public:
284     CAST_CHECK(ResolvedBinding, IsResolvedBinding);
285 
286     static constexpr size_t MODULE_OFFSET = Record::SIZE;
287     ACCESSORS(Module, MODULE_OFFSET, BINDING_NAME_OFFSET);
288     ACCESSORS(BindingName, BINDING_NAME_OFFSET, SIZE);
289 
290     DECL_DUMP()
291     DECL_VISIT_OBJECT(MODULE_OFFSET, SIZE)
292 };
293 class ResolvedIndexBinding final : public Record {
294 public:
295     CAST_CHECK(ResolvedIndexBinding, IsResolvedIndexBinding);
296 
297     static constexpr size_t MODULE_OFFSET = Record::SIZE;
298     ACCESSORS(Module, MODULE_OFFSET, INDEX_OFFSET);
299     ACCESSORS_PRIMITIVE_FIELD(Index, int32_t, INDEX_OFFSET, END_OFFSET);
300     DEFINE_ALIGN_SIZE(END_OFFSET);
301 
302     DECL_DUMP()
303     DECL_VISIT_OBJECT(MODULE_OFFSET, INDEX_OFFSET)
304 };
305 }  // namespace panda::ecmascript
306 #endif  // ECMASCRIPT_MODULE_JS_MODULE_SOURCE_TEXT_H
307