ModuleBuilder.h (4689B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_ModuleBuilder_h 8 #define vm_ModuleBuilder_h 9 10 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS 11 12 #include "jstypes.h" // JS_PUBLIC_API 13 #include "frontend/EitherParser.h" // js::frontend::EitherParser 14 #include "frontend/ParserAtom.h" // js::frontend::TaggedParserAtomIndex 15 #include "frontend/Stencil.h" // js::frontend::StencilModuleEntry 16 #include "frontend/TaggedParserAtomIndexHasher.h" // frontend::TaggedParserAtomIndexHasher 17 #include "js/GCVector.h" // JS::GCVector 18 #include "js/HashTable.h" 19 20 struct JS_PUBLIC_API JSContext; 21 class JS_PUBLIC_API JSAtom; 22 23 namespace js { 24 25 namespace frontend { 26 27 class BinaryNode; 28 class ListNode; 29 class ParseNode; 30 31 } // namespace frontend 32 33 // Process a module's parse tree to collate the import and export data used when 34 // creating a ModuleObject. 35 class MOZ_STACK_CLASS ModuleBuilder { 36 explicit ModuleBuilder(FrontendContext* fc, 37 const frontend::EitherParser& eitherParser); 38 39 public: 40 template <class Parser> 41 explicit ModuleBuilder(FrontendContext* fc, Parser* parser) 42 : ModuleBuilder(fc, frontend::EitherParser(parser)) {} 43 44 bool processImport(frontend::BinaryNode* importNode); 45 bool processExport(frontend::ParseNode* exportNode); 46 bool processExportFrom(frontend::BinaryNode* exportNode); 47 48 enum class NoteExportedNameResult { 49 OutOfMemory, 50 Success, 51 AlreadyDeclared, 52 }; 53 54 NoteExportedNameResult noteExportedName(frontend::TaggedParserAtomIndex name); 55 56 bool buildTables(frontend::StencilModuleMetadata& metadata); 57 58 // During BytecodeEmitter we note top-level functions, and afterwards we must 59 // call finishFunctionDecls on the list. 60 bool noteFunctionDeclaration(FrontendContext* fc, uint32_t funIndex); 61 void finishFunctionDecls(frontend::StencilModuleMetadata& metadata); 62 63 void noteAsync(frontend::StencilModuleMetadata& metadata); 64 65 private: 66 using MaybeModuleRequestIndex = frontend::MaybeModuleRequestIndex; 67 using ModuleRequestVector = frontend::StencilModuleMetadata::RequestVector; 68 using RequestedModuleVector = frontend::StencilModuleMetadata::EntryVector; 69 70 using AtomSet = HashSet<frontend::TaggedParserAtomIndex, 71 frontend::TaggedParserAtomIndexHasher>; 72 using ModuleRequestMap = 73 HashMap<frontend::StencilModuleRequest, uint32_t, 74 frontend::StencilModuleRequestHasher, js::SystemAllocPolicy>; 75 using RequestedModuleSet = HashSet<uint32_t, DefaultHasher<uint32_t>>; 76 using ExportEntryVector = Vector<frontend::StencilModuleEntry>; 77 using ImportEntryMap = 78 HashMap<frontend::TaggedParserAtomIndex, frontend::StencilModuleEntry, 79 frontend::TaggedParserAtomIndexHasher>; 80 81 FrontendContext* fc_; 82 frontend::EitherParser eitherParser_; 83 84 // These are populated while parsing. 85 ModuleRequestVector moduleRequests_; 86 ModuleRequestMap moduleRequestIndexes_; 87 // The set contains the ModuleRequestIndexes in requestedModules_. 88 RequestedModuleSet requestedModuleIndexes_; 89 RequestedModuleVector requestedModules_; 90 ImportEntryMap importEntries_; 91 ExportEntryVector exportEntries_; 92 AtomSet exportNames_; 93 94 // These are populated while emitting bytecode. 95 FunctionDeclarationVector functionDecls_; 96 97 frontend::StencilModuleEntry* importEntryFor( 98 frontend::TaggedParserAtomIndex localName) const; 99 100 bool processExportBinding(frontend::ParseNode* binding); 101 bool processExportArrayBinding(frontend::ListNode* array); 102 bool processExportObjectBinding(frontend::ListNode* obj); 103 104 MaybeModuleRequestIndex appendModuleRequest( 105 frontend::TaggedParserAtomIndex specifier, 106 frontend::ListNode* attributeList); 107 108 bool appendExportEntry(frontend::TaggedParserAtomIndex exportName, 109 frontend::TaggedParserAtomIndex localName, 110 frontend::ParseNode* node = nullptr); 111 112 bool maybeAppendRequestedModule(MaybeModuleRequestIndex moduleRequest, 113 frontend::ParseNode* node); 114 115 void markUsedByStencil(frontend::TaggedParserAtomIndex name); 116 117 [[nodiscard]] bool processAttributes(frontend::StencilModuleRequest& request, 118 frontend::ListNode* attributeList); 119 120 [[nodiscard]] bool isAttributeSupported(frontend::TaggedParserAtomIndex key); 121 }; 122 123 } // namespace js 124 125 #endif // vm_ModuleBuilder_h