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_MANAGER_H
17 #define ECMASCRIPT_MODULE_JS_MODULE_MANAGER_H
18 
19 #include "ecmascript/js_tagged_value-inl.h"
20 #include "ecmascript/jspandafile/js_pandafile.h"
21 #include "ecmascript/module/js_module_source_text.h"
22 #include "ecmascript/napi/jsnapi_helper.h"
23 #include "ecmascript/tagged_dictionary.h"
24 
25 namespace panda::ecmascript {
26 enum class ModuleExecuteMode {
27     ExecuteZipMode,
28     ExecuteBufferMode
29 };
30 class ModuleManager {
31 public:
32     explicit ModuleManager(EcmaVM *vm);
~ModuleManager()33     ~ModuleManager()
34     {
35         InstantiatingSModuleList_.clear();
36         resolvedModules_.clear();
37     }
38 
39     JSTaggedValue GetModuleValueInner(int32_t index);
40     JSTaggedValue GetModuleValueInner(int32_t index, JSTaggedValue jsFunc);
41     JSTaggedValue GetModuleValueInner(int32_t index, JSHandle<JSTaggedValue> currentModule);
42     JSTaggedValue GetModuleValueOutter(int32_t index);
43     JSTaggedValue GetModuleValueOutter(int32_t index, JSTaggedValue jsFunc);
44     JSTaggedValue GetModuleValueOutter(int32_t index, JSHandle<JSTaggedValue> currentModule);
45     JSTaggedValue GetLazyModuleValueOutter(int32_t index, JSTaggedValue jsFunc);
46     void StoreModuleValue(int32_t index, JSTaggedValue value);
47     void StoreModuleValue(int32_t index, JSTaggedValue value, JSTaggedValue jsFunc);
48     JSTaggedValue GetModuleNamespace(int32_t index);
49     JSTaggedValue GetModuleNamespace(int32_t index, JSTaggedValue currentFunc);
50     JSTaggedValue GetModuleNamespaceInternal(int32_t index, JSTaggedValue currentModule);
51 
52     // deprecated begin
53     JSTaggedValue GetModuleValueInner(JSTaggedValue key);
54     JSTaggedValue GetModuleValueInner(JSTaggedValue key, JSTaggedValue jsFunc);
55     JSTaggedValue GetModuleValueOutter(JSTaggedValue key);
56     JSTaggedValue GetModuleValueOutter(JSTaggedValue key, JSTaggedValue jsFunc);
57     void StoreModuleValue(JSTaggedValue key, JSTaggedValue value);
58     void StoreModuleValue(JSTaggedValue key, JSTaggedValue value, JSTaggedValue jsFunc);
59     JSTaggedValue GetModuleNamespace(JSTaggedValue localName);
60     JSTaggedValue GetModuleNamespace(JSTaggedValue localName, JSTaggedValue currentFunc);
61     JSTaggedValue GetModuleNamespaceInternal(JSTaggedValue localName, JSTaggedValue currentModule);
62     // deprecated end
63 
64     JSHandle<SourceTextModule> GetImportedModule(const CString &referencing);
65     JSHandle<SourceTextModule> PUBLIC_API HostGetImportedModule(const CString &referencing);
66     JSTaggedValue HostGetImportedModule(void *src);
67     bool IsLocalModuleLoaded(const CString& referencing);
68     bool IsSharedModuleLoaded(const CString &referencing);
69     bool IsModuleLoaded(const CString &referencing);
70 
71     bool IsEvaluatedModule(const CString &referencing);
72     bool IsInstantiatedModule(const CString &referencing);
73     bool IsLocalModuleInstantiated(const CString &referencing);
74 
75     JSHandle<JSTaggedValue> ResolveNativeModule(const CString &moduleRequest, const CString &baseFileName,
76         ModuleTypes moduleType);
77     JSHandle<JSTaggedValue> HostResolveImportedModule(const void *buffer, size_t size, const CString &filename);
78     JSHandle<JSTaggedValue> HostResolveImportedModule(const CString &referencingModule,
79         bool executeFromJob = false);
80     JSHandle<JSTaggedValue> PUBLIC_API HostResolveImportedModuleWithMerge(const CString &referencingModule,
81         const CString &recordName, bool executeFromJob = false);
82     JSHandle<JSTaggedValue> PUBLIC_API HostResolveImportedModuleWithMergeForHotReload(const CString &referencingModule,
83         const CString &recordName, bool executeFromJob = false);
84     JSHandle<JSTaggedValue> HostResolveImportedModule(const JSPandaFile *jsPandaFile, const CString &filename);
85 
86     JSHandle<JSTaggedValue> LoadNativeModule(JSThread *thread, const CString &key);
87 
88     JSHandle<JSTaggedValue> ExecuteNativeModuleMayThrowError(JSThread *thread, const CString &recordName);
89 
90     JSHandle<JSTaggedValue> ExecuteNativeModule(JSThread *thread, const CString &recordName);
91 
92     JSHandle<JSTaggedValue> ExecuteJsonModule(JSThread *thread, const CString &recordName,
93                                               const CString &filename, const JSPandaFile *jsPandaFile);
94     JSHandle<JSTaggedValue> ExecuteCjsModule(JSThread *thread, const CString &recordName,
95                                              const JSPandaFile *jsPandaFile);
96     JSHandle<JSTaggedValue> GetModuleNameSpaceFromFile(
97         JSThread *thread, const CString &recordNameStr, const CString &baseFileName);
98 
99     JSTaggedValue GetCurrentModule();
100     JSHandle<JSTaggedValue> GenerateSendableFuncModule(const JSHandle<JSTaggedValue> &module);
101 
102     JSHandle<JSTaggedValue> TryGetImportedModule(const CString& referencing);
103     void Iterate(const RootVisitor &v);
104 
GetExecuteMode() const105     ModuleExecuteMode GetExecuteMode() const
106     {
107         return isExecuteBuffer_.load(std::memory_order_acquire);
108     }
SetExecuteMode(ModuleExecuteMode mode)109     void SetExecuteMode(ModuleExecuteMode mode)
110     {
111         isExecuteBuffer_.store(mode, std::memory_order_release);
112     }
113 
114     static CString PUBLIC_API GetRecordName(JSTaggedValue module);
115     static int GetExportObjectIndex(EcmaVM *vm, JSHandle<SourceTextModule> ecmaModule, const CString &key);
116 
NextModuleAsyncEvaluatingOrdinal()117     uint32_t NextModuleAsyncEvaluatingOrdinal()
118     {
119         uint32_t ordinal = nextModuleAsyncEvaluatingOrdinal_++;
120         return ordinal;
121     }
AddResolveImportedModule(const CString &recordName, JSTaggedValue module)122     inline void AddResolveImportedModule(const CString &recordName, JSTaggedValue module)
123     {
124         resolvedModules_.emplace(recordName, module);
125     }
126 
UpdateResolveImportedModule(const CString &recordName, JSTaggedValue module)127     inline void UpdateResolveImportedModule(const CString &recordName, JSTaggedValue module)
128     {
129         resolvedModules_[recordName] = module;
130     }
131 
NativeObjDestory()132     void NativeObjDestory()
133     {
134         for (auto it = resolvedModules_.begin(); it != resolvedModules_.end(); it++) {
135             CString key = it->first;
136             ASSERT(!key.empty());
137             JSTaggedValue module = it->second;
138             SourceTextModule::Cast(module)->DestoryLazyImportArray();
139             SourceTextModule::Cast(module)->DestoryEcmaModuleFilenameString();
140             SourceTextModule::Cast(module)->DestoryEcmaModuleRecordNameString();
141         }
142     }
143 
144 private:
145     NO_COPY_SEMANTIC(ModuleManager);
146     NO_MOVE_SEMANTIC(ModuleManager);
147 
148     JSTaggedValue GetModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule);
149     void StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
150                                   int32_t index, JSTaggedValue value);
151 
152     JSTaggedValue GetLazyModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule);
153 
154     // deprecated begin
155     JSTaggedValue GetModuleValueOutterInternal(JSTaggedValue key, JSTaggedValue currentModule);
156     void StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
157                                   JSTaggedValue key, JSTaggedValue value);
158     // deprecated end
159 
160     JSHandle<JSTaggedValue> ResolveModule(JSThread *thread, const JSPandaFile *jsPandaFile,
161         bool executeFromJob = false);
162 
163     JSHandle<JSTaggedValue> ResolveModuleWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile,
164         const CString &recordName, bool executeFromJob = false);
165 
166     JSHandle<JSTaggedValue> CommonResolveImportedModuleWithMerge(const CString &moduleFileName,
167         const CString &recordName, bool executeFromJob = false);
168 
169     void AddToInstantiatingSModuleList(const CString &record);
170 
171     CVector<CString> GetInstantiatingSModuleList();
172 
173     void ClearInstantiatingSModuleList();
174 
175     void RemoveModuleFromCache(const CString &recordName);
176 
177     void RemoveModuleNameFromList(const CString &recordName);
178 
179     static constexpr uint32_t DEAULT_DICTIONART_CAPACITY = 4;
180 
181     uint32_t nextModuleAsyncEvaluatingOrdinal_{SourceTextModule::FIRST_ASYNC_EVALUATING_ORDINAL};
182 
183     EcmaVM *vm_ {nullptr};
184     CUnorderedMap<CString, JSTaggedValue> resolvedModules_;
185     std::atomic<ModuleExecuteMode> isExecuteBuffer_ {ModuleExecuteMode::ExecuteZipMode};
186     CVector<CString> InstantiatingSModuleList_;
187 
188     friend class EcmaVM;
189     friend class PatchLoader;
190     friend class ModuleDeregister;
191     friend class SharedModuleManager;
192 };
193 } // namespace panda::ecmascript
194 #endif // ECMASCRIPT_MODULE_JS_MODULE_MANAGER_H
195