1// Copyright 2019 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_SOURCE_TEXT_MODULE_H_
6#define V8_OBJECTS_SOURCE_TEXT_MODULE_H_
7
8#include "src/objects/module.h"
9#include "src/objects/promise.h"
10#include "src/zone/zone-containers.h"
11#include "torque-generated/bit-fields.h"
12
13// Has to be the last include (doesn't have include guards):
14#include "src/objects/object-macros.h"
15
16namespace v8 {
17namespace internal {
18
19class UnorderedModuleSet;
20class StructBodyDescriptor;
21
22#include "torque-generated/src/objects/source-text-module-tq.inc"
23
24// The runtime representation of an ECMAScript Source Text Module Record.
25// https://tc39.github.io/ecma262/#sec-source-text-module-records
26class SourceTextModule
27    : public TorqueGeneratedSourceTextModule<SourceTextModule, Module> {
28 public:
29  NEVER_READ_ONLY_SPACE
30  DECL_VERIFIER(SourceTextModule)
31  DECL_PRINTER(SourceTextModule)
32
33  // The shared function info in case {status} is not kEvaluating, kEvaluated or
34  // kErrored.
35  SharedFunctionInfo GetSharedFunctionInfo() const;
36
37  Script GetScript() const;
38
39  // Whether or not this module is an async module. Set during module creation
40  // and does not change afterwards.
41  DECL_BOOLEAN_ACCESSORS(async)
42
43  // Get the SourceTextModuleInfo associated with the code.
44  inline SourceTextModuleInfo info() const;
45
46  Cell GetCell(int cell_index);
47  static Handle<Object> LoadVariable(Isolate* isolate,
48                                     Handle<SourceTextModule> module,
49                                     int cell_index);
50  static void StoreVariable(Handle<SourceTextModule> module, int cell_index,
51                            Handle<Object> value);
52
53  static int ImportIndex(int cell_index);
54  static int ExportIndex(int cell_index);
55
56  // Used by builtins to fulfill or reject the promise associated
57  // with async SourceTextModules. Return Nothing if the execution is
58  // terminated.
59  static Maybe<bool> AsyncModuleExecutionFulfilled(
60      Isolate* isolate, Handle<SourceTextModule> module);
61  static void AsyncModuleExecutionRejected(Isolate* isolate,
62                                           Handle<SourceTextModule> module,
63                                           Handle<Object> exception);
64
65  // Get the namespace object for [module_request] of [module].  If it doesn't
66  // exist yet, it is created.
67  static Handle<JSModuleNamespace> GetModuleNamespace(
68      Isolate* isolate, Handle<SourceTextModule> module, int module_request);
69
70  // Get the import.meta object of [module].  If it doesn't exist yet, it is
71  // created and passed to the embedder callback for initialization.
72  V8_EXPORT_PRIVATE static MaybeHandle<JSObject> GetImportMeta(
73      Isolate* isolate, Handle<SourceTextModule> module);
74
75  using BodyDescriptor =
76      SubclassBodyDescriptor<Module::BodyDescriptor,
77                             FixedBodyDescriptor<kCodeOffset, kSize, kSize>>;
78
79  static constexpr unsigned kFirstAsyncEvaluatingOrdinal = 2;
80
81 private:
82  friend class Factory;
83  friend class Module;
84
85  struct AsyncEvaluatingOrdinalCompare;
86  using AsyncParentCompletionSet =
87      ZoneSet<Handle<SourceTextModule>, AsyncEvaluatingOrdinalCompare>;
88
89  // Appends a tuple of module and generator to the async parent modules
90  // ArrayList.
91  inline static void AddAsyncParentModule(Isolate* isolate,
92                                          Handle<SourceTextModule> module,
93                                          Handle<SourceTextModule> parent);
94
95  // Get the non-hole cycle root. Only valid when status >= kEvaluated.
96  inline Handle<SourceTextModule> GetCycleRoot(Isolate* isolate) const;
97
98  // Returns a SourceTextModule, the
99  // ith parent in depth first traversal order of a given async child.
100  inline Handle<SourceTextModule> GetAsyncParentModule(Isolate* isolate,
101                                                       int index);
102
103  // Returns the number of async parent modules for a given async child.
104  inline int AsyncParentModuleCount();
105
106  inline bool IsAsyncEvaluating() const;
107
108  inline bool HasPendingAsyncDependencies();
109  inline void IncrementPendingAsyncDependencies();
110  inline void DecrementPendingAsyncDependencies();
111
112  // Bits for flags.
113  DEFINE_TORQUE_GENERATED_SOURCE_TEXT_MODULE_FLAGS()
114
115  // async_evaluating_ordinal, top_level_capability, pending_async_dependencies,
116  // and async_parent_modules are used exclusively during evaluation of async
117  // modules and the modules which depend on them.
118  //
119  // If >1, this module is async and evaluating or currently evaluating an async
120  // child. The integer is an ordinal for when this module first started async
121  // evaluation and is used for sorting async parent modules when determining
122  // which parent module can start executing after an async evaluation
123  // completes.
124  //
125  // If 1, this module has finished async evaluating.
126  //
127  // If 0, this module is not async or has not been async evaluated.
128  static constexpr unsigned kNotAsyncEvaluated = 0;
129  static constexpr unsigned kAsyncEvaluateDidFinish = 1;
130  STATIC_ASSERT(kNotAsyncEvaluated < kAsyncEvaluateDidFinish);
131  STATIC_ASSERT(kAsyncEvaluateDidFinish < kFirstAsyncEvaluatingOrdinal);
132  STATIC_ASSERT(kMaxModuleAsyncEvaluatingOrdinal ==
133                AsyncEvaluatingOrdinalBits::kMax);
134  DECL_PRIMITIVE_ACCESSORS(async_evaluating_ordinal, unsigned)
135
136  // The parent modules of a given async dependency, use async_parent_modules()
137  // to retrieve the ArrayList representation.
138  DECL_ACCESSORS(async_parent_modules, ArrayList)
139
140  // Helpers for Instantiate and Evaluate.
141  static void CreateExport(Isolate* isolate, Handle<SourceTextModule> module,
142                           int cell_index, Handle<FixedArray> names);
143  static void CreateIndirectExport(Isolate* isolate,
144                                   Handle<SourceTextModule> module,
145                                   Handle<String> name,
146                                   Handle<SourceTextModuleInfoEntry> entry);
147
148  static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport(
149      Isolate* isolate, Handle<SourceTextModule> module,
150      Handle<String> module_specifier, Handle<String> export_name,
151      MessageLocation loc, bool must_resolve, ResolveSet* resolve_set);
152  static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveImport(
153      Isolate* isolate, Handle<SourceTextModule> module, Handle<String> name,
154      int module_request_index, MessageLocation loc, bool must_resolve,
155      ResolveSet* resolve_set);
156
157  static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports(
158      Isolate* isolate, Handle<SourceTextModule> module,
159      Handle<String> module_specifier, Handle<String> export_name,
160      MessageLocation loc, bool must_resolve, ResolveSet* resolve_set);
161
162  static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
163      Isolate* isolate, Handle<SourceTextModule> module,
164      v8::Local<v8::Context> context,
165      v8::Module::ResolveModuleCallback callback,
166      Module::DeprecatedResolveCallback callback_without_import_assertions);
167  static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
168      Isolate* isolate, Handle<SourceTextModule> module,
169      ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index,
170      Zone* zone);
171  static V8_WARN_UNUSED_RESULT bool RunInitializationCode(
172      Isolate* isolate, Handle<SourceTextModule> module);
173
174  static void FetchStarExports(Isolate* isolate,
175                               Handle<SourceTextModule> module, Zone* zone,
176                               UnorderedModuleSet* visited);
177
178  static void GatherAsyncParentCompletions(Isolate* isolate, Zone* zone,
179                                           Handle<SourceTextModule> start,
180                                           AsyncParentCompletionSet* exec_list);
181
182  // Implementation of spec concrete method Evaluate.
183  static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
184      Isolate* isolate, Handle<SourceTextModule> module);
185
186  // Implementation of spec abstract operation InnerModuleEvaluation.
187  static V8_WARN_UNUSED_RESULT MaybeHandle<Object> InnerModuleEvaluation(
188      Isolate* isolate, Handle<SourceTextModule> module,
189      ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index);
190
191  static V8_WARN_UNUSED_RESULT bool MaybeTransitionComponent(
192      Isolate* isolate, Handle<SourceTextModule> module,
193      ZoneForwardList<Handle<SourceTextModule>>* stack, Status new_status);
194
195  // Implementation of spec ExecuteModule is broken up into
196  // InnerExecuteAsyncModule for asynchronous modules and ExecuteModule
197  // for synchronous modules.
198  static V8_WARN_UNUSED_RESULT MaybeHandle<Object> InnerExecuteAsyncModule(
199      Isolate* isolate, Handle<SourceTextModule> module,
200      Handle<JSPromise> capability);
201
202  static V8_WARN_UNUSED_RESULT MaybeHandle<Object> ExecuteModule(
203      Isolate* isolate, Handle<SourceTextModule> module);
204
205  // Implementation of spec ExecuteAsyncModule. Return Nothing if the execution
206  // is been terminated.
207  static V8_WARN_UNUSED_RESULT Maybe<bool> ExecuteAsyncModule(
208      Isolate* isolate, Handle<SourceTextModule> module);
209
210  static void Reset(Isolate* isolate, Handle<SourceTextModule> module);
211
212  TQ_OBJECT_CONSTRUCTORS(SourceTextModule)
213};
214
215// SourceTextModuleInfo is to SourceTextModuleDescriptor what ScopeInfo is to
216// Scope.
217class SourceTextModuleInfo : public FixedArray {
218 public:
219  DECL_CAST(SourceTextModuleInfo)
220
221  template <typename IsolateT>
222  static Handle<SourceTextModuleInfo> New(IsolateT* isolate, Zone* zone,
223                                          SourceTextModuleDescriptor* descr);
224
225  inline FixedArray module_requests() const;
226  inline FixedArray special_exports() const;
227  inline FixedArray regular_exports() const;
228  inline FixedArray regular_imports() const;
229  inline FixedArray namespace_imports() const;
230
231  // Accessors for [regular_exports].
232  int RegularExportCount() const;
233  String RegularExportLocalName(int i) const;
234  int RegularExportCellIndex(int i) const;
235  FixedArray RegularExportExportNames(int i) const;
236
237#ifdef DEBUG
238  inline bool Equals(SourceTextModuleInfo other) const;
239#endif
240
241 private:
242  template <typename Impl>
243  friend class FactoryBase;
244  friend class SourceTextModuleDescriptor;
245  enum {
246    kModuleRequestsIndex,
247    kSpecialExportsIndex,
248    kRegularExportsIndex,
249    kNamespaceImportsIndex,
250    kRegularImportsIndex,
251    kLength
252  };
253  enum {
254    kRegularExportLocalNameOffset,
255    kRegularExportCellIndexOffset,
256    kRegularExportExportNamesOffset,
257    kRegularExportLength
258  };
259
260  OBJECT_CONSTRUCTORS(SourceTextModuleInfo, FixedArray);
261};
262
263class ModuleRequest
264    : public TorqueGeneratedModuleRequest<ModuleRequest, Struct> {
265 public:
266  NEVER_READ_ONLY_SPACE
267  DECL_VERIFIER(ModuleRequest)
268
269  template <typename IsolateT>
270  static Handle<ModuleRequest> New(IsolateT* isolate, Handle<String> specifier,
271                                   Handle<FixedArray> import_assertions,
272                                   int position);
273
274  // The number of entries in the import_assertions FixedArray that are used for
275  // a single assertion.
276  static const size_t kAssertionEntrySize = 3;
277
278  using BodyDescriptor = StructBodyDescriptor;
279
280  TQ_OBJECT_CONSTRUCTORS(ModuleRequest)
281};
282
283class SourceTextModuleInfoEntry
284    : public TorqueGeneratedSourceTextModuleInfoEntry<SourceTextModuleInfoEntry,
285                                                      Struct> {
286 public:
287  DECL_VERIFIER(SourceTextModuleInfoEntry)
288
289  template <typename IsolateT>
290  static Handle<SourceTextModuleInfoEntry> New(
291      IsolateT* isolate, Handle<PrimitiveHeapObject> export_name,
292      Handle<PrimitiveHeapObject> local_name,
293      Handle<PrimitiveHeapObject> import_name, int module_request,
294      int cell_index, int beg_pos, int end_pos);
295
296  using BodyDescriptor = StructBodyDescriptor;
297
298  TQ_OBJECT_CONSTRUCTORS(SourceTextModuleInfoEntry)
299};
300
301}  // namespace internal
302}  // namespace v8
303
304#include "src/objects/object-macros-undef.h"
305
306#endif  // V8_OBJECTS_SOURCE_TEXT_MODULE_H_
307