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