Line data Source code
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 : #include "src/objects/js-objects.h"
11 : #include "src/objects/struct.h"
12 :
13 : // Has to be the last include (doesn't have include guards):
14 : #include "src/objects/object-macros.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : template <typename T>
20 : class Handle;
21 : class Isolate;
22 : class JSModuleNamespace;
23 : class ModuleDescriptor;
24 : class ModuleInfo;
25 : class ModuleInfoEntry;
26 : class String;
27 : class Zone;
28 :
29 : // The runtime representation of an ECMAScript module.
30 : class Module : public Struct {
31 : public:
32 : NEVER_READ_ONLY_SPACE
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 : static int ImportIndex(int cell_index);
115 : static int ExportIndex(int cell_index);
116 :
117 : // Get the namespace object for [module_request] of [module]. If it doesn't
118 : // exist yet, it is created.
119 : static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate,
120 : Handle<Module> module,
121 : int module_request);
122 :
123 : // Get the namespace object for [module]. If it doesn't exist yet, it is
124 : // created.
125 : static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate,
126 : Handle<Module> module);
127 :
128 : // Layout description.
129 : #define MODULE_FIELDS(V) \
130 : V(kCodeOffset, kTaggedSize) \
131 : V(kExportsOffset, kTaggedSize) \
132 : V(kRegularExportsOffset, kTaggedSize) \
133 : V(kRegularImportsOffset, kTaggedSize) \
134 : V(kHashOffset, kTaggedSize) \
135 : V(kModuleNamespaceOffset, kTaggedSize) \
136 : V(kRequestedModulesOffset, kTaggedSize) \
137 : V(kStatusOffset, kTaggedSize) \
138 : V(kDfsIndexOffset, kTaggedSize) \
139 : V(kDfsAncestorIndexOffset, kTaggedSize) \
140 : V(kExceptionOffset, kTaggedSize) \
141 : V(kScriptOffset, kTaggedSize) \
142 : V(kImportMetaOffset, kTaggedSize) \
143 : /* Total size. */ \
144 : V(kSize, 0)
145 :
146 : DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, MODULE_FIELDS)
147 : #undef MODULE_FIELDS
148 :
149 : private:
150 : friend class Factory;
151 :
152 : DECL_ACCESSORS(exception, Object)
153 :
154 : // TODO(neis): Don't store those in the module object?
155 : DECL_INT_ACCESSORS(dfs_index)
156 : DECL_INT_ACCESSORS(dfs_ancestor_index)
157 :
158 : // Helpers for Instantiate and Evaluate.
159 :
160 : static void CreateExport(Isolate* isolate, Handle<Module> module,
161 : int cell_index, Handle<FixedArray> names);
162 : static void CreateIndirectExport(Isolate* isolate, Handle<Module> module,
163 : Handle<String> name,
164 : Handle<ModuleInfoEntry> entry);
165 :
166 : // The [must_resolve] argument indicates whether or not an exception should be
167 : // thrown in case the module does not provide an export named [name]
168 : // (including when a cycle is detected). An exception is always thrown in the
169 : // case of conflicting star exports.
170 : //
171 : // If [must_resolve] is true, a null result indicates an exception. If
172 : // [must_resolve] is false, a null result may or may not indicate an
173 : // exception (so check manually!).
174 : class ResolveSet;
175 : static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport(
176 : Isolate* isolate, Handle<Module> module, Handle<String> module_specifier,
177 : Handle<String> export_name, MessageLocation loc, bool must_resolve,
178 : ResolveSet* resolve_set);
179 : static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveImport(
180 : Isolate* isolate, Handle<Module> module, Handle<String> name,
181 : int module_request, MessageLocation loc, bool must_resolve,
182 : ResolveSet* resolve_set);
183 :
184 : static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports(
185 : Isolate* isolate, Handle<Module> module, Handle<String> module_specifier,
186 : Handle<String> export_name, MessageLocation loc, bool must_resolve,
187 : ResolveSet* resolve_set);
188 :
189 : static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
190 : Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
191 : v8::Module::ResolveCallback callback);
192 : static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
193 : Isolate* isolate, Handle<Module> module,
194 : ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index, Zone* zone);
195 : static V8_WARN_UNUSED_RESULT bool RunInitializationCode(
196 : Isolate* isolate, Handle<Module> module);
197 :
198 : static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
199 : Isolate* isolate, Handle<Module> module,
200 : ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index);
201 :
202 : static V8_WARN_UNUSED_RESULT bool MaybeTransitionComponent(
203 : Isolate* isolate, Handle<Module> module,
204 : ZoneForwardList<Handle<Module>>* stack, Status new_status);
205 :
206 : // Set module's status back to kUninstantiated and reset other internal state.
207 : // This is used when instantiation fails.
208 : static void Reset(Isolate* isolate, Handle<Module> module);
209 : static void ResetGraph(Isolate* isolate, Handle<Module> module);
210 :
211 : // To set status to kErrored, RecordError should be used.
212 : void SetStatus(Status status);
213 : void RecordError(Isolate* isolate);
214 :
215 : #ifdef DEBUG
216 : // For --trace-module-status.
217 : void PrintStatusTransition(Status new_status);
218 : #endif // DEBUG
219 :
220 627 : OBJECT_CONSTRUCTORS(Module, Struct);
221 : };
222 :
223 : // When importing a module namespace (import * as foo from "bar"), a
224 : // JSModuleNamespace object (representing module "bar") is created and bound to
225 : // the declared variable (foo). A module can have at most one namespace object.
226 : class JSModuleNamespace : public JSObject {
227 : public:
228 : DECL_CAST(JSModuleNamespace)
229 : DECL_PRINTER(JSModuleNamespace)
230 : DECL_VERIFIER(JSModuleNamespace)
231 :
232 : // The actual module whose namespace is being represented.
233 : DECL_ACCESSORS(module, Module)
234 :
235 : // Retrieve the value exported by [module] under the given [name]. If there is
236 : // no such export, return Just(undefined). If the export is uninitialized,
237 : // schedule an exception and return Nothing.
238 : V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate,
239 : Handle<String> name);
240 :
241 : // Return the (constant) property attributes for the referenced property,
242 : // which is assumed to correspond to an export. If the export is
243 : // uninitialized, schedule an exception and return Nothing.
244 : static V8_WARN_UNUSED_RESULT Maybe<PropertyAttributes> GetPropertyAttributes(
245 : LookupIterator* it);
246 :
247 : // In-object fields.
248 : enum {
249 : kToStringTagFieldIndex,
250 : kInObjectFieldCount,
251 : };
252 :
253 : // Layout description.
254 : #define JS_MODULE_NAMESPACE_FIELDS(V) \
255 : V(kModuleOffset, kTaggedSize) \
256 : /* Header size. */ \
257 : V(kHeaderSize, 0) \
258 : V(kInObjectFieldsOffset, kTaggedSize* kInObjectFieldCount) \
259 : /* Total size. */ \
260 : V(kSize, 0)
261 :
262 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
263 : JS_MODULE_NAMESPACE_FIELDS)
264 : #undef JS_MODULE_NAMESPACE_FIELDS
265 :
266 : OBJECT_CONSTRUCTORS(JSModuleNamespace, JSObject);
267 : };
268 :
269 : // ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope.
270 : class ModuleInfo : public FixedArray {
271 : public:
272 : DECL_CAST(ModuleInfo)
273 :
274 : static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone,
275 : ModuleDescriptor* descr);
276 :
277 : inline FixedArray module_requests() const;
278 : inline FixedArray special_exports() const;
279 : inline FixedArray regular_exports() const;
280 : inline FixedArray regular_imports() const;
281 : inline FixedArray namespace_imports() const;
282 : inline FixedArray module_request_positions() const;
283 :
284 : // Accessors for [regular_exports].
285 : int RegularExportCount() const;
286 : String RegularExportLocalName(int i) const;
287 : int RegularExportCellIndex(int i) const;
288 : FixedArray RegularExportExportNames(int i) const;
289 :
290 : #ifdef DEBUG
291 : inline bool Equals(ModuleInfo other) const;
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 : OBJECT_CONSTRUCTORS(ModuleInfo, FixedArray);
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 : // Layout description.
337 : #define MODULE_INFO_FIELDS(V) \
338 : V(kExportNameOffset, kTaggedSize) \
339 : V(kLocalNameOffset, kTaggedSize) \
340 : V(kImportNameOffset, kTaggedSize) \
341 : V(kModuleRequestOffset, kTaggedSize) \
342 : V(kCellIndexOffset, kTaggedSize) \
343 : V(kBegPosOffset, kTaggedSize) \
344 : V(kEndPosOffset, kTaggedSize) \
345 : /* Total size. */ \
346 : V(kSize, 0)
347 :
348 : DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, MODULE_INFO_FIELDS)
349 : #undef MODULE_INFO_FIELDS
350 :
351 : OBJECT_CONSTRUCTORS(ModuleInfoEntry, Struct);
352 : };
353 :
354 : } // namespace internal
355 : } // namespace v8
356 :
357 : #include "src/objects/object-macros-undef.h"
358 :
359 : #endif // V8_OBJECTS_MODULE_H_
|