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 "include/v8-script.h" 9 #include "src/objects/fixed-array.h" 10 #include "src/objects/js-objects.h" 11 #include "src/objects/objects.h" 12 #include "src/objects/struct.h" 13 14 // Has to be the last include (doesn't have include guards): 15 #include "src/objects/object-macros.h" 16 17 namespace v8 { 18 namespace internal { 19 20 template <typename T> 21 class Handle; 22 class Isolate; 23 class JSModuleNamespace; 24 class SourceTextModuleDescriptor; 25 class SourceTextModuleInfo; 26 class SourceTextModuleInfoEntry; 27 class String; 28 class Zone; 29 30 #include "torque-generated/src/objects/module-tq.inc" 31 32 // Module is the base class for ECMAScript module types, roughly corresponding 33 // to Abstract Module Record. 34 // https://tc39.github.io/ecma262/#sec-abstract-module-records 35 class Module : public TorqueGeneratedModule<Module, HeapObject> { 36 public: 37 NEVER_READ_ONLY_SPACE 38 DECL_VERIFIER(Module) 39 DECL_PRINTER(Module) 40 41 enum Status { 42 // Order matters! 43 kUnlinked, 44 kPreLinking, 45 kLinking, 46 kLinked, 47 kEvaluating, 48 kEvaluatingAsync, 49 kEvaluated, 50 kErrored 51 }; 52 53 // The exception in the case {status} is kErrored. 54 Object GetException(); 55 56 // Returns if this module or any transitively requested module is [[Async]], 57 // i.e. has a top-level await. 58 V8_WARN_UNUSED_RESULT bool IsGraphAsync(Isolate* isolate) const; 59 60 // While deprecating v8::ResolveCallback in v8.h we still need to support the 61 // version of the API that uses it, but we can't directly reference the 62 // deprecated version because of the enusing build warnings. So, we declare 63 // this matching typedef for temporary internal use. 64 // TODO(v8:10958) Delete this typedef and all references to it once 65 // v8::ResolveCallback is removed. 66 typedef MaybeLocal<v8::Module> (*DeprecatedResolveCallback)( 67 Local<v8::Context> context, Local<v8::String> specifier, 68 Local<v8::Module> referrer); 69 70 // Implementation of spec operation ModuleDeclarationInstantiation. 71 // Returns false if an exception occurred during instantiation, true 72 // otherwise. (In the case where the callback throws an exception, that 73 // exception is propagated.) 74 static V8_WARN_UNUSED_RESULT bool Instantiate( 75 Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context, 76 v8::Module::ResolveModuleCallback callback, 77 DeprecatedResolveCallback callback_without_import_assertions); 78 79 // Implementation of spec operation ModuleEvaluation. 80 static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate( 81 Isolate* isolate, Handle<Module> module); 82 83 // Get the namespace object for [module]. If it doesn't exist yet, it is 84 // created. 85 static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate, 86 Handle<Module> module); 87 88 using BodyDescriptor = 89 FixedBodyDescriptor<kExportsOffset, kHeaderSize, kHeaderSize>; 90 91 struct Hash; 92 93 protected: 94 friend class Factory; 95 96 // The [must_resolve] argument indicates whether or not an exception should be 97 // thrown in case the module does not provide an export named [name] 98 // (including when a cycle is detected). An exception is always thrown in the 99 // case of conflicting star exports. 100 // 101 // If [must_resolve] is true, a null result indicates an exception. If 102 // [must_resolve] is false, a null result may or may not indicate an 103 // exception (so check manually!). 104 class ResolveSet; 105 static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport( 106 Isolate* isolate, Handle<Module> module, Handle<String> module_specifier, 107 Handle<String> export_name, MessageLocation loc, bool must_resolve, 108 ResolveSet* resolve_set); 109 110 static V8_WARN_UNUSED_RESULT bool PrepareInstantiate( 111 Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context, 112 v8::Module::ResolveModuleCallback callback, 113 DeprecatedResolveCallback callback_without_import_assertions); 114 static V8_WARN_UNUSED_RESULT bool FinishInstantiate( 115 Isolate* isolate, Handle<Module> module, 116 ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index, 117 Zone* zone); 118 119 // Set module's status back to kUnlinked and reset other internal state. 120 // This is used when instantiation fails. 121 static void Reset(Isolate* isolate, Handle<Module> module); 122 static void ResetGraph(Isolate* isolate, Handle<Module> module); 123 124 // To set status to kErrored, RecordError or RecordErrorUsingPendingException 125 // should be used. 126 void SetStatus(Status status); 127 static void RecordErrorUsingPendingException(Isolate* isolate, 128 Handle<Module>); 129 static void RecordError(Isolate* isolate, Handle<Module> module, 130 Handle<Object> error); 131 132 TQ_OBJECT_CONSTRUCTORS(Module) 133 }; 134 135 // When importing a module namespace (import * as foo from "bar"), a 136 // JSModuleNamespace object (representing module "bar") is created and bound to 137 // the declared variable (foo). A module can have at most one namespace object. 138 class JSModuleNamespace 139 : public TorqueGeneratedJSModuleNamespace<JSModuleNamespace, 140 JSSpecialObject> { 141 public: 142 DECL_PRINTER(JSModuleNamespace) 143 144 // Retrieve the value exported by [module] under the given [name]. If there is 145 // no such export, return Just(undefined). If the export is uninitialized, 146 // schedule an exception and return Nothing. 147 V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate, 148 Handle<String> name); 149 150 // Return the (constant) property attributes for the referenced property, 151 // which is assumed to correspond to an export. If the export is 152 // uninitialized, schedule an exception and return Nothing. 153 static V8_WARN_UNUSED_RESULT Maybe<PropertyAttributes> GetPropertyAttributes( 154 LookupIterator* it); 155 156 static V8_WARN_UNUSED_RESULT Maybe<bool> DefineOwnProperty( 157 Isolate* isolate, Handle<JSModuleNamespace> o, Handle<Object> key, 158 PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw); 159 160 // In-object fields. 161 enum { 162 kToStringTagFieldIndex, 163 kInObjectFieldCount, 164 }; 165 166 // We need to include in-object fields 167 // TODO(v8:8944): improve handling of in-object fields 168 static constexpr int kSize = 169 kHeaderSize + (kTaggedSize * kInObjectFieldCount); 170 171 TQ_OBJECT_CONSTRUCTORS(JSModuleNamespace) 172 }; 173 174 class ScriptOrModule 175 : public TorqueGeneratedScriptOrModule<ScriptOrModule, Struct> { 176 public: 177 DECL_PRINTER(ScriptOrModule) 178 179 using BodyDescriptor = StructBodyDescriptor; 180 181 TQ_OBJECT_CONSTRUCTORS(ScriptOrModule) 182 }; 183 184 } // namespace internal 185 } // namespace v8 186 187 #include "src/objects/object-macros-undef.h" 188 189 #endif // V8_OBJECTS_MODULE_H_ 190