Home | History | Annotate | Download | only in objects
      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, public NeverReadOnlySpaceObject {
     29  public:
     30   using NeverReadOnlySpaceObject::GetHeap;
     31   using NeverReadOnlySpaceObject::GetIsolate;
     32 
     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   // Get the namespace object for [module_request] of [module].  If it doesn't
    115   // exist yet, it is created.
    116   static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate,
    117                                                       Handle<Module> module,
    118                                                       int module_request);
    119 
    120   // Get the namespace object for [module].  If it doesn't exist yet, it is
    121   // created.
    122   static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate,
    123                                                       Handle<Module> module);
    124 
    125   static const int kCodeOffset = HeapObject::kHeaderSize;
    126   static const int kExportsOffset = kCodeOffset + kPointerSize;
    127   static const int kRegularExportsOffset = kExportsOffset + kPointerSize;
    128   static const int kRegularImportsOffset = kRegularExportsOffset + kPointerSize;
    129   static const int kHashOffset = kRegularImportsOffset + kPointerSize;
    130   static const int kModuleNamespaceOffset = kHashOffset + kPointerSize;
    131   static const int kRequestedModulesOffset =
    132       kModuleNamespaceOffset + kPointerSize;
    133   static const int kStatusOffset = kRequestedModulesOffset + kPointerSize;
    134   static const int kDfsIndexOffset = kStatusOffset + kPointerSize;
    135   static const int kDfsAncestorIndexOffset = kDfsIndexOffset + kPointerSize;
    136   static const int kExceptionOffset = kDfsAncestorIndexOffset + kPointerSize;
    137   static const int kScriptOffset = kExceptionOffset + kPointerSize;
    138   static const int kImportMetaOffset = kScriptOffset + kPointerSize;
    139   static const int kSize = kImportMetaOffset + kPointerSize;
    140 
    141  private:
    142   friend class Factory;
    143 
    144   DECL_ACCESSORS(exception, Object)
    145 
    146   // TODO(neis): Don't store those in the module object?
    147   DECL_INT_ACCESSORS(dfs_index)
    148   DECL_INT_ACCESSORS(dfs_ancestor_index)
    149 
    150   // Helpers for Instantiate and Evaluate.
    151 
    152   static void CreateExport(Isolate* isolate, Handle<Module> module,
    153                            int cell_index, Handle<FixedArray> names);
    154   static void CreateIndirectExport(Isolate* isolate, Handle<Module> module,
    155                                    Handle<String> name,
    156                                    Handle<ModuleInfoEntry> entry);
    157 
    158   // The [must_resolve] argument indicates whether or not an exception should be
    159   // thrown in case the module does not provide an export named [name]
    160   // (including when a cycle is detected).  An exception is always thrown in the
    161   // case of conflicting star exports.
    162   //
    163   // If [must_resolve] is true, a null result indicates an exception. If
    164   // [must_resolve] is false, a null result may or may not indicate an
    165   // exception (so check manually!).
    166   class ResolveSet;
    167   static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport(
    168       Isolate* isolate, Handle<Module> module, Handle<String> module_specifier,
    169       Handle<String> export_name, MessageLocation loc, bool must_resolve,
    170       ResolveSet* resolve_set);
    171   static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveImport(
    172       Isolate* isolate, Handle<Module> module, Handle<String> name,
    173       int module_request, MessageLocation loc, bool must_resolve,
    174       ResolveSet* resolve_set);
    175 
    176   static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports(
    177       Isolate* isolate, Handle<Module> module, Handle<String> module_specifier,
    178       Handle<String> export_name, MessageLocation loc, bool must_resolve,
    179       ResolveSet* resolve_set);
    180 
    181   static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
    182       Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
    183       v8::Module::ResolveCallback callback);
    184   static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
    185       Isolate* isolate, Handle<Module> module,
    186       ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index, Zone* zone);
    187   static V8_WARN_UNUSED_RESULT bool RunInitializationCode(
    188       Isolate* isolate, Handle<Module> module);
    189 
    190   static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
    191       Isolate* isolate, Handle<Module> module,
    192       ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index);
    193 
    194   static V8_WARN_UNUSED_RESULT bool MaybeTransitionComponent(
    195       Isolate* isolate, Handle<Module> module,
    196       ZoneForwardList<Handle<Module>>* stack, Status new_status);
    197 
    198   // Set module's status back to kUninstantiated and reset other internal state.
    199   // This is used when instantiation fails.
    200   static void Reset(Isolate* isolate, Handle<Module> module);
    201   static void ResetGraph(Isolate* isolate, Handle<Module> module);
    202 
    203   // To set status to kErrored, RecordError should be used.
    204   void SetStatus(Status status);
    205   void RecordError(Isolate* isolate);
    206 
    207 #ifdef DEBUG
    208   // For --trace-module-status.
    209   void PrintStatusTransition(Status new_status);
    210 #endif  // DEBUG
    211 
    212   DISALLOW_IMPLICIT_CONSTRUCTORS(Module);
    213 };
    214 
    215 // When importing a module namespace (import * as foo from "bar"), a
    216 // JSModuleNamespace object (representing module "bar") is created and bound to
    217 // the declared variable (foo).  A module can have at most one namespace object.
    218 class JSModuleNamespace : public JSObject {
    219  public:
    220   DECL_CAST(JSModuleNamespace)
    221   DECL_PRINTER(JSModuleNamespace)
    222   DECL_VERIFIER(JSModuleNamespace)
    223 
    224   // The actual module whose namespace is being represented.
    225   DECL_ACCESSORS(module, Module)
    226 
    227   // Retrieve the value exported by [module] under the given [name]. If there is
    228   // no such export, return Just(undefined). If the export is uninitialized,
    229   // schedule an exception and return Nothing.
    230   V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate,
    231                                                       Handle<String> name);
    232 
    233   // Return the (constant) property attributes for the referenced property,
    234   // which is assumed to correspond to an export. If the export is
    235   // uninitialized, schedule an exception and return Nothing.
    236   static V8_WARN_UNUSED_RESULT Maybe<PropertyAttributes> GetPropertyAttributes(
    237       LookupIterator* it);
    238 
    239   // In-object fields.
    240   enum {
    241     kToStringTagFieldIndex,
    242     kInObjectFieldCount,
    243   };
    244 
    245   static const int kModuleOffset = JSObject::kHeaderSize;
    246   static const int kHeaderSize = kModuleOffset + kPointerSize;
    247 
    248   static const int kSize = kHeaderSize + kPointerSize * kInObjectFieldCount;
    249 
    250  private:
    251   DISALLOW_IMPLICIT_CONSTRUCTORS(JSModuleNamespace);
    252 };
    253 
    254 // ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope.
    255 class ModuleInfo : public FixedArray {
    256  public:
    257   DECL_CAST(ModuleInfo)
    258 
    259   static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone,
    260                                 ModuleDescriptor* descr);
    261 
    262   inline FixedArray* module_requests() const;
    263   inline FixedArray* special_exports() const;
    264   inline FixedArray* regular_exports() const;
    265   inline FixedArray* regular_imports() const;
    266   inline FixedArray* namespace_imports() const;
    267   inline FixedArray* module_request_positions() const;
    268 
    269   // Accessors for [regular_exports].
    270   int RegularExportCount() const;
    271   String* RegularExportLocalName(int i) const;
    272   int RegularExportCellIndex(int i) const;
    273   FixedArray* RegularExportExportNames(int i) const;
    274 
    275 #ifdef DEBUG
    276   inline bool Equals(ModuleInfo* other) const;
    277 #endif
    278 
    279  private:
    280   friend class Factory;
    281   friend class ModuleDescriptor;
    282   enum {
    283     kModuleRequestsIndex,
    284     kSpecialExportsIndex,
    285     kRegularExportsIndex,
    286     kNamespaceImportsIndex,
    287     kRegularImportsIndex,
    288     kModuleRequestPositionsIndex,
    289     kLength
    290   };
    291   enum {
    292     kRegularExportLocalNameOffset,
    293     kRegularExportCellIndexOffset,
    294     kRegularExportExportNamesOffset,
    295     kRegularExportLength
    296   };
    297   DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfo);
    298 };
    299 
    300 class ModuleInfoEntry : public Struct {
    301  public:
    302   DECL_CAST(ModuleInfoEntry)
    303   DECL_PRINTER(ModuleInfoEntry)
    304   DECL_VERIFIER(ModuleInfoEntry)
    305 
    306   DECL_ACCESSORS(export_name, Object)
    307   DECL_ACCESSORS(local_name, Object)
    308   DECL_ACCESSORS(import_name, Object)
    309   DECL_INT_ACCESSORS(module_request)
    310   DECL_INT_ACCESSORS(cell_index)
    311   DECL_INT_ACCESSORS(beg_pos)
    312   DECL_INT_ACCESSORS(end_pos)
    313 
    314   static Handle<ModuleInfoEntry> New(Isolate* isolate,
    315                                      Handle<Object> export_name,
    316                                      Handle<Object> local_name,
    317                                      Handle<Object> import_name,
    318                                      int module_request, int cell_index,
    319                                      int beg_pos, int end_pos);
    320 
    321   static const int kExportNameOffset = HeapObject::kHeaderSize;
    322   static const int kLocalNameOffset = kExportNameOffset + kPointerSize;
    323   static const int kImportNameOffset = kLocalNameOffset + kPointerSize;
    324   static const int kModuleRequestOffset = kImportNameOffset + kPointerSize;
    325   static const int kCellIndexOffset = kModuleRequestOffset + kPointerSize;
    326   static const int kBegPosOffset = kCellIndexOffset + kPointerSize;
    327   static const int kEndPosOffset = kBegPosOffset + kPointerSize;
    328   static const int kSize = kEndPosOffset + kPointerSize;
    329 
    330  private:
    331   DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfoEntry);
    332 };
    333 
    334 }  // namespace internal
    335 }  // namespace v8
    336 
    337 #include "src/objects/object-macros-undef.h"
    338 
    339 #endif  // V8_OBJECTS_MODULE_H_
    340