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> ¤tModule, 204 const JSHandle<SourceTextModule> &requiredModule); 205 static void InstantiateNativeModule(JSThread *thread, JSHandle<SourceTextModule> ¤tModule, 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> ¤tModule, 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