1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_MODULE_H_ 6 #define V8_OBJECTS_MODULE_H_ 7 8 #include "src/objects.h" 9 #include "src/objects/fixed-array.h" 10 11 // Has to be the last include (doesn't have include guards): 12 #include "src/objects/object-macros.h" 13 14 namespace v8 { 15 namespace internal { 16 17 template <typename T> 18 class Handle; 19 class Isolate; 20 class JSModuleNamespace; 21 class ModuleDescriptor; 22 class ModuleInfo; 23 class ModuleInfoEntry; 24 class String; 25 class Zone; 26 27 // The runtime representation of an ECMAScript module. 28 class Module : public Struct, public NeverReadOnlySpaceObject { 29 public: 30 using NeverReadOnlySpaceObject::GetHeap; 31 using NeverReadOnlySpaceObject::GetIsolate; 32 33 DECL_CAST(Module) 34 DECL_VERIFIER(Module) 35 DECL_PRINTER(Module) 36 37 // The code representing this module, or an abstraction thereof. 38 // This is either a SharedFunctionInfo, a JSFunction, a JSGeneratorObject, or 39 // a ModuleInfo, depending on the state (status) the module is in. See 40 // Module::ModuleVerify() for the precise invariant. 41 DECL_ACCESSORS(code, Object) 42 43 // Arrays of cells corresponding to regular exports and regular imports. 44 // A cell's position in the array is determined by the cell index of the 45 // associated module entry (which coincides with the variable index of the 46 // associated variable). 47 DECL_ACCESSORS(regular_exports, FixedArray) 48 DECL_ACCESSORS(regular_imports, FixedArray) 49 50 // The complete export table, mapping an export name to its cell. 51 // TODO(neis): We may want to remove the regular exports from the table. 52 DECL_ACCESSORS(exports, ObjectHashTable) 53 54 // Hash for this object (a random non-zero Smi). 55 DECL_INT_ACCESSORS(hash) 56 57 // Status. 58 DECL_INT_ACCESSORS(status) 59 enum Status { 60 // Order matters! 61 kUninstantiated, 62 kPreInstantiating, 63 kInstantiating, 64 kInstantiated, 65 kEvaluating, 66 kEvaluated, 67 kErrored 68 }; 69 70 // The exception in the case {status} is kErrored. 71 Object* GetException(); 72 73 // The shared function info in case {status} is not kEvaluating, kEvaluated or 74 // kErrored. 75 SharedFunctionInfo* GetSharedFunctionInfo() const; 76 77 // The namespace object (or undefined). 78 DECL_ACCESSORS(module_namespace, HeapObject) 79 80 // Modules imported or re-exported by this module. 81 // Corresponds 1-to-1 to the module specifier strings in 82 // ModuleInfo::module_requests. 83 DECL_ACCESSORS(requested_modules, FixedArray) 84 85 // [script]: Script from which the module originates. 86 DECL_ACCESSORS(script, Script) 87 88 // The value of import.meta inside of this module. 89 // Lazily initialized on first access. It's the hole before first access and 90 // a JSObject afterwards. 91 DECL_ACCESSORS(import_meta, Object) 92 93 // Get the ModuleInfo associated with the code. 94 inline ModuleInfo* info() const; 95 96 // Implementation of spec operation ModuleDeclarationInstantiation. 97 // Returns false if an exception occurred during instantiation, true 98 // otherwise. (In the case where the callback throws an exception, that 99 // exception is propagated.) 100 static V8_WARN_UNUSED_RESULT bool Instantiate( 101 Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context, 102 v8::Module::ResolveCallback callback); 103 104 // Implementation of spec operation ModuleEvaluation. 105 static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate( 106 Isolate* isolate, Handle<Module> module); 107 108 Cell* GetCell(int cell_index); 109 static Handle<Object> LoadVariable(Isolate* isolate, Handle<Module> module, 110 int cell_index); 111 static void StoreVariable(Handle<Module> module, int cell_index, 112 Handle<Object> value); 113 114 // Get the namespace object for [module_request] of [module]. If it doesn't 115 // exist yet, it is created. 116 static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate, 117 Handle<Module> module, 118 int module_request); 119 120 // Get the namespace object for [module]. If it doesn't exist yet, it is 121 // created. 122 static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate, 123 Handle<Module> module); 124 125 static const int kCodeOffset = HeapObject::kHeaderSize; 126 static const int kExportsOffset = kCodeOffset + kPointerSize; 127 static const int kRegularExportsOffset = kExportsOffset + kPointerSize; 128 static const int kRegularImportsOffset = kRegularExportsOffset + kPointerSize; 129 static const int kHashOffset = kRegularImportsOffset + kPointerSize; 130 static const int kModuleNamespaceOffset = kHashOffset + kPointerSize; 131 static const int kRequestedModulesOffset = 132 kModuleNamespaceOffset + kPointerSize; 133 static const int kStatusOffset = kRequestedModulesOffset + kPointerSize; 134 static const int kDfsIndexOffset = kStatusOffset + kPointerSize; 135 static const int kDfsAncestorIndexOffset = kDfsIndexOffset + kPointerSize; 136 static const int kExceptionOffset = kDfsAncestorIndexOffset + kPointerSize; 137 static const int kScriptOffset = kExceptionOffset + kPointerSize; 138 static const int kImportMetaOffset = kScriptOffset + kPointerSize; 139 static const int kSize = kImportMetaOffset + kPointerSize; 140 141 private: 142 friend class Factory; 143 144 DECL_ACCESSORS(exception, Object) 145 146 // TODO(neis): Don't store those in the module object? 147 DECL_INT_ACCESSORS(dfs_index) 148 DECL_INT_ACCESSORS(dfs_ancestor_index) 149 150 // Helpers for Instantiate and Evaluate. 151 152 static void CreateExport(Isolate* isolate, Handle<Module> module, 153 int cell_index, Handle<FixedArray> names); 154 static void CreateIndirectExport(Isolate* isolate, Handle<Module> module, 155 Handle<String> name, 156 Handle<ModuleInfoEntry> entry); 157 158 // The [must_resolve] argument indicates whether or not an exception should be 159 // thrown in case the module does not provide an export named [name] 160 // (including when a cycle is detected). An exception is always thrown in the 161 // case of conflicting star exports. 162 // 163 // If [must_resolve] is true, a null result indicates an exception. If 164 // [must_resolve] is false, a null result may or may not indicate an 165 // exception (so check manually!). 166 class ResolveSet; 167 static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport( 168 Isolate* isolate, Handle<Module> module, Handle<String> module_specifier, 169 Handle<String> export_name, MessageLocation loc, bool must_resolve, 170 ResolveSet* resolve_set); 171 static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveImport( 172 Isolate* isolate, Handle<Module> module, Handle<String> name, 173 int module_request, MessageLocation loc, bool must_resolve, 174 ResolveSet* resolve_set); 175 176 static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports( 177 Isolate* isolate, Handle<Module> module, Handle<String> module_specifier, 178 Handle<String> export_name, MessageLocation loc, bool must_resolve, 179 ResolveSet* resolve_set); 180 181 static V8_WARN_UNUSED_RESULT bool PrepareInstantiate( 182 Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context, 183 v8::Module::ResolveCallback callback); 184 static V8_WARN_UNUSED_RESULT bool FinishInstantiate( 185 Isolate* isolate, Handle<Module> module, 186 ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index, Zone* zone); 187 static V8_WARN_UNUSED_RESULT bool RunInitializationCode( 188 Isolate* isolate, Handle<Module> module); 189 190 static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate( 191 Isolate* isolate, Handle<Module> module, 192 ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index); 193 194 static V8_WARN_UNUSED_RESULT bool MaybeTransitionComponent( 195 Isolate* isolate, Handle<Module> module, 196 ZoneForwardList<Handle<Module>>* stack, Status new_status); 197 198 // Set module's status back to kUninstantiated and reset other internal state. 199 // This is used when instantiation fails. 200 static void Reset(Isolate* isolate, Handle<Module> module); 201 static void ResetGraph(Isolate* isolate, Handle<Module> module); 202 203 // To set status to kErrored, RecordError should be used. 204 void SetStatus(Status status); 205 void RecordError(Isolate* isolate); 206 207 #ifdef DEBUG 208 // For --trace-module-status. 209 void PrintStatusTransition(Status new_status); 210 #endif // DEBUG 211 212 DISALLOW_IMPLICIT_CONSTRUCTORS(Module); 213 }; 214 215 // When importing a module namespace (import * as foo from "bar"), a 216 // JSModuleNamespace object (representing module "bar") is created and bound to 217 // the declared variable (foo). A module can have at most one namespace object. 218 class JSModuleNamespace : public JSObject { 219 public: 220 DECL_CAST(JSModuleNamespace) 221 DECL_PRINTER(JSModuleNamespace) 222 DECL_VERIFIER(JSModuleNamespace) 223 224 // The actual module whose namespace is being represented. 225 DECL_ACCESSORS(module, Module) 226 227 // Retrieve the value exported by [module] under the given [name]. If there is 228 // no such export, return Just(undefined). If the export is uninitialized, 229 // schedule an exception and return Nothing. 230 V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate, 231 Handle<String> name); 232 233 // Return the (constant) property attributes for the referenced property, 234 // which is assumed to correspond to an export. If the export is 235 // uninitialized, schedule an exception and return Nothing. 236 static V8_WARN_UNUSED_RESULT Maybe<PropertyAttributes> GetPropertyAttributes( 237 LookupIterator* it); 238 239 // In-object fields. 240 enum { 241 kToStringTagFieldIndex, 242 kInObjectFieldCount, 243 }; 244 245 static const int kModuleOffset = JSObject::kHeaderSize; 246 static const int kHeaderSize = kModuleOffset + kPointerSize; 247 248 static const int kSize = kHeaderSize + kPointerSize * kInObjectFieldCount; 249 250 private: 251 DISALLOW_IMPLICIT_CONSTRUCTORS(JSModuleNamespace); 252 }; 253 254 // ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope. 255 class ModuleInfo : public FixedArray { 256 public: 257 DECL_CAST(ModuleInfo) 258 259 static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone, 260 ModuleDescriptor* descr); 261 262 inline FixedArray* module_requests() const; 263 inline FixedArray* special_exports() const; 264 inline FixedArray* regular_exports() const; 265 inline FixedArray* regular_imports() const; 266 inline FixedArray* namespace_imports() const; 267 inline FixedArray* module_request_positions() const; 268 269 // Accessors for [regular_exports]. 270 int RegularExportCount() const; 271 String* RegularExportLocalName(int i) const; 272 int RegularExportCellIndex(int i) const; 273 FixedArray* RegularExportExportNames(int i) const; 274 275 #ifdef DEBUG 276 inline bool Equals(ModuleInfo* other) const; 277 #endif 278 279 private: 280 friend class Factory; 281 friend class ModuleDescriptor; 282 enum { 283 kModuleRequestsIndex, 284 kSpecialExportsIndex, 285 kRegularExportsIndex, 286 kNamespaceImportsIndex, 287 kRegularImportsIndex, 288 kModuleRequestPositionsIndex, 289 kLength 290 }; 291 enum { 292 kRegularExportLocalNameOffset, 293 kRegularExportCellIndexOffset, 294 kRegularExportExportNamesOffset, 295 kRegularExportLength 296 }; 297 DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfo); 298 }; 299 300 class ModuleInfoEntry : public Struct { 301 public: 302 DECL_CAST(ModuleInfoEntry) 303 DECL_PRINTER(ModuleInfoEntry) 304 DECL_VERIFIER(ModuleInfoEntry) 305 306 DECL_ACCESSORS(export_name, Object) 307 DECL_ACCESSORS(local_name, Object) 308 DECL_ACCESSORS(import_name, Object) 309 DECL_INT_ACCESSORS(module_request) 310 DECL_INT_ACCESSORS(cell_index) 311 DECL_INT_ACCESSORS(beg_pos) 312 DECL_INT_ACCESSORS(end_pos) 313 314 static Handle<ModuleInfoEntry> New(Isolate* isolate, 315 Handle<Object> export_name, 316 Handle<Object> local_name, 317 Handle<Object> import_name, 318 int module_request, int cell_index, 319 int beg_pos, int end_pos); 320 321 static const int kExportNameOffset = HeapObject::kHeaderSize; 322 static const int kLocalNameOffset = kExportNameOffset + kPointerSize; 323 static const int kImportNameOffset = kLocalNameOffset + kPointerSize; 324 static const int kModuleRequestOffset = kImportNameOffset + kPointerSize; 325 static const int kCellIndexOffset = kModuleRequestOffset + kPointerSize; 326 static const int kBegPosOffset = kCellIndexOffset + kPointerSize; 327 static const int kEndPosOffset = kBegPosOffset + kPointerSize; 328 static const int kSize = kEndPosOffset + kPointerSize; 329 330 private: 331 DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfoEntry); 332 }; 333 334 } // namespace internal 335 } // namespace v8 336 337 #include "src/objects/object-macros-undef.h" 338 339 #endif // V8_OBJECTS_MODULE_H_ 340