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 "builtin/ModuleObject.h" // js::{{Im,Ex}portEntry,Requested{Module,}}Object 14 #include "frontend/EitherParser.h" // js::frontend::EitherParser 15 #include "frontend/ParserAtom.h" // js::frontend::TaggedParserAtomIndex 16 #include "frontend/Stencil.h" // js::frontend::StencilModuleEntry 17 #include "frontend/TaggedParserAtomIndexHasher.h" // frontend::TaggedParserAtomIndexHasher 18 #include "js/GCHashTable.h" // JS::GCHash{Map,Set} 19 #include "js/GCVector.h" // JS::GCVector 20 #include "js/RootingAPI.h" // JS::{Handle,Rooted} 21 #include "vm/AtomsTable.h" // js::AtomSet 22 23 struct JS_PUBLIC_API JSContext; 24 class JS_PUBLIC_API JSAtom; 25 26 namespace js { 27 28 namespace frontend { 29 30 class BinaryNode; 31 class ListNode; 32 class ParseNode; 33 34 } // namespace frontend 35 36 // Process a module's parse tree to collate the import and export data used when 37 // creating a ModuleObject. 38 class MOZ_STACK_CLASS ModuleBuilder { 39 explicit ModuleBuilder(JSContext* cx, 40 const frontend::EitherParser& eitherParser); 41 42 public: 43 template <class Parser> ModuleBuilder(JSContext * cx,Parser * parser)44 explicit ModuleBuilder(JSContext* cx, Parser* parser) 45 : ModuleBuilder(cx, frontend::EitherParser(parser)) {} 46 47 bool processImport(frontend::BinaryNode* importNode); 48 bool processExport(frontend::ParseNode* exportNode); 49 bool processExportFrom(frontend::BinaryNode* exportNode); 50 51 bool hasExportedName(frontend::TaggedParserAtomIndex name) const; 52 53 bool buildTables(frontend::StencilModuleMetadata& metadata); 54 55 // During BytecodeEmitter we note top-level functions, and afterwards we must 56 // call finishFunctionDecls on the list. 57 bool noteFunctionDeclaration(JSContext* cx, uint32_t funIndex); 58 void finishFunctionDecls(frontend::StencilModuleMetadata& metadata); 59 60 void noteAsync(frontend::StencilModuleMetadata& metadata); 61 62 private: 63 using RequestedModuleVector = 64 Vector<frontend::StencilModuleEntry, 0, js::SystemAllocPolicy>; 65 66 using AtomSet = HashSet<frontend::TaggedParserAtomIndex, 67 frontend::TaggedParserAtomIndexHasher>; 68 using ExportEntryVector = Vector<frontend::StencilModuleEntry>; 69 using ImportEntryMap = 70 HashMap<frontend::TaggedParserAtomIndex, frontend::StencilModuleEntry, 71 frontend::TaggedParserAtomIndexHasher>; 72 73 JSContext* cx_; 74 frontend::EitherParser eitherParser_; 75 76 // These are populated while parsing. 77 AtomSet requestedModuleSpecifiers_; 78 RequestedModuleVector requestedModules_; 79 ImportEntryMap importEntries_; 80 ExportEntryVector exportEntries_; 81 AtomSet exportNames_; 82 83 // These are populated while emitting bytecode. 84 frontend::FunctionDeclarationVector functionDecls_; 85 86 frontend::StencilModuleEntry* importEntryFor( 87 frontend::TaggedParserAtomIndex localName) const; 88 89 bool processExportBinding(frontend::ParseNode* pn); 90 bool processExportArrayBinding(frontend::ListNode* array); 91 bool processExportObjectBinding(frontend::ListNode* obj); 92 93 bool appendExportEntry(frontend::TaggedParserAtomIndex exportName, 94 frontend::TaggedParserAtomIndex localName, 95 frontend::ParseNode* node = nullptr); 96 97 bool maybeAppendRequestedModule(frontend::TaggedParserAtomIndex specifier, 98 frontend::ParseNode* node); 99 100 void markUsedByStencil(frontend::TaggedParserAtomIndex name); 101 }; 102 103 template <typename T> 104 ArrayObject* CreateArray(JSContext* cx, 105 const JS::Rooted<JS::GCVector<T>>& vector); 106 107 } // namespace js 108 109 #endif // vm_ModuleBuilder_h 110