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   static V8_WARN_UNUSED_RESULT MaybeHandle<Object> EvaluateMaybeAsync(
120       Isolate* isolate, Handle<Module> module);
121 
122   static V8_WARN_UNUSED_RESULT MaybeHandle<Object> InnerEvaluate(
123       Isolate* isolate, Handle<Module> module);
124 
125   // Set module's status back to kUnlinked and reset other internal state.
126   // This is used when instantiation fails.
127   static void Reset(Isolate* isolate, Handle<Module> module);
128   static void ResetGraph(Isolate* isolate, Handle<Module> module);
129 
130   // To set status to kErrored, RecordError or RecordErrorUsingPendingException
131   // should be used.
132   void SetStatus(Status status);
133   static void RecordErrorUsingPendingException(Isolate* isolate,
134                                                Handle<Module>);
135   static void RecordError(Isolate* isolate, Handle<Module> module,
136                           Handle<Object> error);
137 
138   TQ_OBJECT_CONSTRUCTORS(Module)
139 };
140 
141 // When importing a module namespace (import * as foo from "bar"), a
142 // JSModuleNamespace object (representing module "bar") is created and bound to
143 // the declared variable (foo).  A module can have at most one namespace object.
144 class JSModuleNamespace
145     : public TorqueGeneratedJSModuleNamespace<JSModuleNamespace,
146                                               JSSpecialObject> {
147  public:
148   DECL_PRINTER(JSModuleNamespace)
149 
150   // Retrieve the value exported by [module] under the given [name]. If there is
151   // no such export, return Just(undefined). If the export is uninitialized,
152   // schedule an exception and return Nothing.
153   V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate,
154                                                       Handle<String> name);
155 
156   // Return the (constant) property attributes for the referenced property,
157   // which is assumed to correspond to an export. If the export is
158   // uninitialized, schedule an exception and return Nothing.
159   static V8_WARN_UNUSED_RESULT Maybe<PropertyAttributes> GetPropertyAttributes(
160       LookupIterator* it);
161 
162   static V8_WARN_UNUSED_RESULT Maybe<bool> DefineOwnProperty(
163       Isolate* isolate, Handle<JSModuleNamespace> o, Handle<Object> key,
164       PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw);
165 
166   // In-object fields.
167   enum {
168     kToStringTagFieldIndex,
169     kInObjectFieldCount,
170   };
171 
172   // We need to include in-object fields
173   // TODO(v8:8944): improve handling of in-object fields
174   static constexpr int kSize =
175       kHeaderSize + (kTaggedSize * kInObjectFieldCount);
176 
177   TQ_OBJECT_CONSTRUCTORS(JSModuleNamespace)
178 };
179 
180 }  // namespace internal
181 }  // namespace v8
182 
183 #include "src/objects/object-macros-undef.h"
184 
185 #endif  // V8_OBJECTS_MODULE_H_
186