tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ModuleObject.h (21031B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef builtin_ModuleObject_h
      8 #define builtin_ModuleObject_h
      9 
     10 #include "mozilla/HashTable.h"  // mozilla::{HashMap, DefaultHasher}
     11 #include "mozilla/Maybe.h"      // mozilla::Maybe
     12 #include "mozilla/Span.h"
     13 
     14 #include <cstdint>   // UINT32_MAX
     15 #include <stddef.h>  // size_t
     16 #include <stdint.h>  // int32_t, uint32_t
     17 
     18 #include "gc/Barrier.h"        // HeapPtr
     19 #include "gc/ZoneAllocator.h"  // CellAllocPolicy
     20 #include "js/Class.h"          // JSClass, ObjectOpResult
     21 #include "js/ColumnNumber.h"   // JS::ColumnNumberOneOrigin
     22 #include "js/GCVector.h"
     23 #include "js/Id.h"  // jsid
     24 #include "js/Modules.h"
     25 #include "js/Proxy.h"       // BaseProxyHandler
     26 #include "js/RootingAPI.h"  // Rooted, Handle, MutableHandle
     27 #include "js/TypeDecls.h"  // HandleValue, HandleId, HandleObject, HandleScript, MutableHandleValue, MutableHandleIdVector, MutableHandleObject
     28 #include "js/UniquePtr.h"  // UniquePtr
     29 #include "vm/JSObject.h"   // JSObject
     30 #include "vm/NativeObject.h"   // NativeObject
     31 #include "vm/ProxyObject.h"    // ProxyObject
     32 #include "vm/SharedStencil.h"  // FunctionDeclarationVector
     33 
     34 class JSAtom;
     35 class JSScript;
     36 class JSTracer;
     37 
     38 namespace JS {
     39 class PropertyDescriptor;
     40 class Value;
     41 }  // namespace JS
     42 
     43 namespace js {
     44 
     45 class ArrayObject;
     46 class CyclicModuleFields;
     47 class SyntheticModuleFields;
     48 class ListObject;
     49 class ModuleEnvironmentObject;
     50 class ModuleObject;
     51 class PromiseObject;
     52 class ScriptSourceObject;
     53 
     54 class ImportAttribute {
     55  const HeapPtr<JSAtom*> key_;
     56  const HeapPtr<JSString*> value_;
     57 
     58 public:
     59  ImportAttribute(Handle<JSAtom*> key, Handle<JSString*> value);
     60 
     61  JSAtom* key() const { return key_; }
     62  JSString* value() const { return value_; }
     63 
     64  void trace(JSTracer* trc);
     65 };
     66 
     67 using ImportAttributeVector = GCVector<ImportAttribute, 0, SystemAllocPolicy>;
     68 
     69 enum class ImportPhase : uint8_t { Evaluation, Limit };
     70 
     71 class ModuleRequestObject : public NativeObject {
     72 public:
     73  enum {
     74    SpecifierSlot = 0,
     75    FirstUnsupportedAttributeKeySlot,
     76    ModuleTypeSlot,
     77    PhaseSlot,
     78    SlotCount
     79  };
     80 
     81  static const JSClass class_;
     82  static bool isInstance(HandleValue value);
     83  [[nodiscard]] static ModuleRequestObject* create(
     84      JSContext* cx, Handle<JSAtom*> specifier,
     85      Handle<ImportAttributeVector> maybeAttributes,
     86      ImportPhase phase = ImportPhase::Evaluation);
     87  [[nodiscard]] static ModuleRequestObject* create(
     88      JSContext* cx, Handle<JSAtom*> specifier, JS::ModuleType moduleType,
     89      ImportPhase phase = ImportPhase::Evaluation);
     90 
     91  JSAtom* specifier() const;
     92  JS::ModuleType moduleType() const;
     93  ImportPhase phase() const;
     94 
     95  // We process import attributes earlier in the process, but according to the
     96  // spec, we should error during module evaluation if we encounter an
     97  // unsupported attribute. We want to generate a nice error message, so we need
     98  // to keep track of the first unsupported key we encounter.
     99  void setFirstUnsupportedAttributeKey(Handle<JSAtom*> key);
    100  bool hasFirstUnsupportedAttributeKey() const;
    101  JSAtom* getFirstUnsupportedAttributeKey() const;
    102 };
    103 
    104 using ModuleRequestVector =
    105    GCVector<HeapPtr<ModuleRequestObject*>, 0, SystemAllocPolicy>;
    106 
    107 class ImportEntry {
    108  const HeapPtr<ModuleRequestObject*> moduleRequest_;
    109  const HeapPtr<JSAtom*> importName_;
    110  const HeapPtr<JSAtom*> localName_;
    111 
    112  // Line number (1-origin).
    113  const uint32_t lineNumber_;
    114 
    115  // Column number in UTF-16 code units.
    116  const JS::ColumnNumberOneOrigin columnNumber_;
    117 
    118 public:
    119  ImportEntry(Handle<ModuleRequestObject*> moduleRequest,
    120              Handle<JSAtom*> maybeImportName, Handle<JSAtom*> localName,
    121              uint32_t lineNumber, JS::ColumnNumberOneOrigin columnNumber);
    122 
    123  ModuleRequestObject* moduleRequest() const { return moduleRequest_; }
    124  JSAtom* importName() const { return importName_; }
    125  JSAtom* localName() const { return localName_; }
    126  uint32_t lineNumber() const { return lineNumber_; }
    127  JS::ColumnNumberOneOrigin columnNumber() const { return columnNumber_; }
    128 
    129  void trace(JSTracer* trc);
    130 };
    131 
    132 using ImportEntryVector = GCVector<ImportEntry, 0, SystemAllocPolicy>;
    133 
    134 class ExportEntry {
    135  const HeapPtr<JSAtom*> exportName_;
    136  const HeapPtr<ModuleRequestObject*> moduleRequest_;
    137  const HeapPtr<JSAtom*> importName_;
    138  const HeapPtr<JSAtom*> localName_;
    139 
    140  // Line number (1-origin).
    141  const uint32_t lineNumber_;
    142 
    143  // Column number in UTF-16 code units.
    144  const JS::ColumnNumberOneOrigin columnNumber_;
    145 
    146 public:
    147  ExportEntry(Handle<JSAtom*> maybeExportName,
    148              Handle<ModuleRequestObject*> maybeModuleRequest,
    149              Handle<JSAtom*> maybeImportName, Handle<JSAtom*> maybeLocalName,
    150              uint32_t lineNumber, JS::ColumnNumberOneOrigin columnNumber);
    151  JSAtom* exportName() const { return exportName_; }
    152  ModuleRequestObject* moduleRequest() const { return moduleRequest_; }
    153  JSAtom* importName() const { return importName_; }
    154  JSAtom* localName() const { return localName_; }
    155  uint32_t lineNumber() const { return lineNumber_; }
    156  JS::ColumnNumberOneOrigin columnNumber() const { return columnNumber_; }
    157 
    158  void trace(JSTracer* trc);
    159 };
    160 
    161 using ExportEntryVector = GCVector<ExportEntry, 0, SystemAllocPolicy>;
    162 
    163 class RequestedModule {
    164  const HeapPtr<ModuleRequestObject*> moduleRequest_;
    165 
    166  // Line number (1-origin).
    167  const uint32_t lineNumber_;
    168 
    169  // Column number in UTF-16 code units.
    170  const JS::ColumnNumberOneOrigin columnNumber_;
    171 
    172 public:
    173  RequestedModule(Handle<ModuleRequestObject*> moduleRequest,
    174                  uint32_t lineNumber, JS::ColumnNumberOneOrigin columnNumber);
    175  ModuleRequestObject* moduleRequest() const { return moduleRequest_; }
    176  uint32_t lineNumber() const { return lineNumber_; }
    177  JS::ColumnNumberOneOrigin columnNumber() const { return columnNumber_; }
    178 
    179  void trace(JSTracer* trc);
    180 };
    181 
    182 using RequestedModuleVector = GCVector<RequestedModule, 0, SystemAllocPolicy>;
    183 
    184 class ResolvedBindingObject : public NativeObject {
    185 public:
    186  enum { ModuleSlot = 0, BindingNameSlot, SlotCount };
    187 
    188  static const JSClass class_;
    189  static bool isInstance(HandleValue value);
    190  static ResolvedBindingObject* create(JSContext* cx,
    191                                       Handle<ModuleObject*> module,
    192                                       Handle<JSAtom*> bindingName);
    193  ModuleObject* module() const;
    194  JSAtom* bindingName() const;
    195 };
    196 
    197 class IndirectBindingMap {
    198 public:
    199  void trace(JSTracer* trc);
    200 
    201  bool put(JSContext* cx, HandleId name,
    202           Handle<ModuleEnvironmentObject*> environment, HandleId targetName);
    203 
    204  size_t count() const { return map_ ? map_->count() : 0; }
    205 
    206  bool has(jsid name) const { return map_ ? map_->has(name) : false; }
    207 
    208  bool lookup(jsid name, ModuleEnvironmentObject** envOut,
    209              mozilla::Maybe<PropertyInfo>* propOut) const;
    210 
    211  template <typename Func>
    212  void forEachExportedName(Func func) const {
    213    if (!map_) {
    214      return;
    215    }
    216 
    217    for (auto r = map_->all(); !r.empty(); r.popFront()) {
    218      func(r.front().key());
    219    }
    220  }
    221 
    222 private:
    223  struct Binding {
    224    Binding(ModuleEnvironmentObject* environment, jsid targetName,
    225            PropertyInfo prop);
    226    HeapPtr<ModuleEnvironmentObject*> environment;
    227 #ifdef DEBUG
    228    HeapPtr<jsid> targetName;
    229 #endif
    230    PropertyInfo prop;
    231  };
    232 
    233  using Map = mozilla::HashMap<PreBarriered<jsid>, Binding,
    234                               mozilla::DefaultHasher<PreBarriered<jsid>>,
    235                               CellAllocPolicy>;
    236 
    237  mozilla::Maybe<Map> map_;
    238 };
    239 
    240 // Vector of atoms representing the names exported from a module namespace.
    241 //
    242 // This is used both on the stack and in the heap.
    243 using ExportNameVector = GCVector<HeapPtr<JSAtom*>, 0, SystemAllocPolicy>;
    244 
    245 class ModuleNamespaceObject : public ProxyObject {
    246 public:
    247  enum ModuleNamespaceSlot { ExportsSlot = 0, BindingsSlot };
    248 
    249  static bool isInstance(HandleValue value);
    250  static ModuleNamespaceObject* create(
    251      JSContext* cx, Handle<ModuleObject*> module,
    252      MutableHandle<UniquePtr<ExportNameVector>> exports,
    253      MutableHandle<UniquePtr<IndirectBindingMap>> bindings);
    254 
    255  ModuleObject& module();
    256  const ExportNameVector& exports() const;
    257  IndirectBindingMap& bindings();
    258 
    259  bool addBinding(JSContext* cx, Handle<JSAtom*> exportedName,
    260                  Handle<ModuleObject*> targetModule,
    261                  Handle<JSAtom*> targetName);
    262 
    263 private:
    264  struct ProxyHandler : public BaseProxyHandler {
    265    constexpr ProxyHandler() : BaseProxyHandler(&family, false) {}
    266 
    267    bool getOwnPropertyDescriptor(
    268        JSContext* cx, HandleObject proxy, HandleId id,
    269        MutableHandle<mozilla::Maybe<PropertyDescriptor>> desc) const override;
    270    bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
    271                        Handle<PropertyDescriptor> desc,
    272                        ObjectOpResult& result) const override;
    273    bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
    274                         MutableHandleIdVector props) const override;
    275    bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
    276                 ObjectOpResult& result) const override;
    277    bool getPrototype(JSContext* cx, HandleObject proxy,
    278                      MutableHandleObject protop) const override;
    279    bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
    280                      ObjectOpResult& result) const override;
    281    bool getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy,
    282                                bool* isOrdinary,
    283                                MutableHandleObject protop) const override;
    284    bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
    285                               bool* succeeded) const override;
    286 
    287    bool preventExtensions(JSContext* cx, HandleObject proxy,
    288                           ObjectOpResult& result) const override;
    289    bool isExtensible(JSContext* cx, HandleObject proxy,
    290                      bool* extensible) const override;
    291    bool has(JSContext* cx, HandleObject proxy, HandleId id,
    292             bool* bp) const override;
    293    bool get(JSContext* cx, HandleObject proxy, HandleValue receiver,
    294             HandleId id, MutableHandleValue vp) const override;
    295    bool set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v,
    296             HandleValue receiver, ObjectOpResult& result) const override;
    297 
    298    void trace(JSTracer* trc, JSObject* proxy) const override;
    299    void finalize(JS::GCContext* gcx, JSObject* proxy) const override;
    300 
    301    static const char family;
    302  };
    303 
    304  bool hasBindings() const;
    305  bool hasExports() const;
    306 
    307  ExportNameVector& mutableExports();
    308 
    309 public:
    310  static const ProxyHandler proxyHandler;
    311 };
    312 
    313 // Value types of [[Status]] in a Cyclic Module Record
    314 // https://tc39.es/ecma262/#table-cyclic-module-fields
    315 enum class ModuleStatus : int8_t {
    316  New,
    317  Unlinked,
    318  Linking,
    319  Linked,
    320  Evaluating,
    321  EvaluatingAsync,
    322  Evaluated,
    323 
    324  // Sub-state of Evaluated with error value set.
    325  //
    326  // This is not returned from ModuleObject::status(); use hadEvaluationError()
    327  // to check this.
    328  Evaluated_Error
    329 };
    330 
    331 // Special values for CyclicModuleFields' asyncEvaluationOrderSlot field,
    332 // which represents the AsyncEvaluationOrder field of cyclic module records.
    333 //
    334 // AsyncEvaluationOrder can have three states:
    335 //  - a positive integer, represented by values <=
    336 //    ASYNC_EVALUATING_POST_ORDER_MAX_VALUE
    337 //  - ~unset~, represented by ASYNC_EVALUATING_POST_ORDER_UNSET
    338 //  - ~done~, represented by ASYNC_EVALUATING_POST_ORDER_DONE
    339 //
    340 // See https://tc39.es/ecma262/#sec-cyclic-module-records for field defintion.
    341 // See https://tc39.es/ecma262/#sec-async-module-execution-fulfilled for sort
    342 // requirement.
    343 
    344 // Value that the field is initially set to.
    345 constexpr uint32_t ASYNC_EVALUATING_POST_ORDER_UNSET = UINT32_MAX;
    346 
    347 // Value that the field is set to after being cleared.
    348 constexpr uint32_t ASYNC_EVALUATING_POST_ORDER_DONE = UINT32_MAX - 1;
    349 
    350 constexpr uint32_t ASYNC_EVALUATING_POST_ORDER_MAX_VALUE = UINT32_MAX - 2;
    351 
    352 class AsyncEvaluationOrder {
    353 private:
    354  uint32_t value = ASYNC_EVALUATING_POST_ORDER_UNSET;
    355 
    356 public:
    357  bool isUnset() const;
    358  bool isInteger() const;
    359  bool isDone() const;
    360 
    361  uint32_t get() const;
    362 
    363  void set(JSRuntime* rt);
    364  void setDone(JSRuntime* rt);
    365 };
    366 
    367 // The map used by [[LoadedModules]] in Realm Record Fields, Script Record
    368 // Fields, and additional fields of Cyclic Module Records.
    369 // https://tc39.es/ecma262/#table-realm-record-fields
    370 // https://tc39.es/ecma262/#table-script-records
    371 // https://tc39.es/ecma262/#table-cyclic-module-fields
    372 //
    373 // For Import attributes proposal, this map maps from ModuleRequest records to
    374 // Module records.
    375 // https://tc39.es/proposal-import-attributes/#sec-cyclic-module-records
    376 //
    377 // TODO:
    378 // Bug 1968874 : Implement [[LoadedModules]] in Realm Records and Script Records
    379 using LoadedModuleMap =
    380    GCHashMap<HeapPtr<JSObject*>, HeapPtr<ModuleObject*>,
    381              StableCellHasher<HeapPtr<JSObject*>>, SystemAllocPolicy>;
    382 
    383 // Currently, the ModuleObject class is used to represent both the Source Text
    384 // Module Record and the Synthetic Module Record. Ideally, this is something
    385 // that should be refactored to follow the same hierarchy as in the spec.
    386 // TODO: See Bug 1880519.
    387 class ModuleObject : public NativeObject {
    388 public:
    389  // Module fields including those for AbstractModuleRecords described by:
    390  // https://tc39.es/ecma262/#sec-abstract-module-records
    391  enum ModuleSlot {
    392    ScriptSlot = 0,
    393    EnvironmentSlot,
    394    NamespaceSlot,
    395    CyclicModuleFieldsSlot,
    396    // `SyntheticModuleFields` if a synthetic module. Otherwise `undefined`.
    397    SyntheticModuleFieldsSlot,
    398    SlotCount
    399  };
    400 
    401  static const JSClass class_;
    402 
    403  static bool isInstance(HandleValue value);
    404 
    405  static ModuleObject* create(JSContext* cx);
    406 
    407  static ModuleObject* createSynthetic(
    408      JSContext* cx, MutableHandle<ExportNameVector> exportNames);
    409 
    410  // Initialize the slots on this object that are dependent on the script.
    411  void initScriptSlots(HandleScript script);
    412 
    413  void setInitialEnvironment(
    414      Handle<ModuleEnvironmentObject*> initialEnvironment);
    415 
    416  void initFunctionDeclarations(UniquePtr<FunctionDeclarationVector> decls);
    417  void initImportExportData(
    418      MutableHandle<RequestedModuleVector> requestedModules,
    419      MutableHandle<ImportEntryVector> importEntries,
    420      MutableHandle<ExportEntryVector> exportEntries, uint32_t localExportCount,
    421      uint32_t indirectExportCount, uint32_t starExportCount);
    422  static bool Freeze(JSContext* cx, Handle<ModuleObject*> self);
    423 #ifdef DEBUG
    424  static bool AssertFrozen(JSContext* cx, Handle<ModuleObject*> self);
    425 #endif
    426 
    427  JSScript* maybeScript() const;
    428  JSScript* script() const;
    429  const char* filename() const;
    430  ModuleEnvironmentObject& initialEnvironment() const;
    431  ModuleEnvironmentObject* environment() const;
    432  ModuleNamespaceObject* namespace_();
    433  ModuleStatus status() const;
    434  mozilla::Maybe<uint32_t> maybeDfsAncestorIndex() const;
    435  uint32_t dfsAncestorIndex() const;
    436  bool hadEvaluationError() const;
    437  Value maybeEvaluationError() const;
    438  Value evaluationError() const;
    439  JSObject* metaObject() const;
    440  ScriptSourceObject* scriptSourceObject() const;
    441  mozilla::Span<const RequestedModule> requestedModules() const;
    442  mozilla::Span<const ImportEntry> importEntries() const;
    443  mozilla::Span<const ExportEntry> localExportEntries() const;
    444  mozilla::Span<const ExportEntry> indirectExportEntries() const;
    445  mozilla::Span<const ExportEntry> starExportEntries() const;
    446  const ExportNameVector& syntheticExportNames() const;
    447 
    448  IndirectBindingMap& importBindings();
    449 
    450  void setStatus(ModuleStatus newStatus);
    451  void setDfsAncestorIndex(uint32_t index);
    452  void clearDfsAncestorIndex();
    453 
    454  static PromiseObject* createTopLevelCapability(JSContext* cx,
    455                                                 Handle<ModuleObject*> module);
    456  bool hasTopLevelAwait() const;
    457  void setEvaluationError(HandleValue newValue);
    458  void setPendingAsyncDependencies(uint32_t newValue);
    459  void setInitialTopLevelCapability(Handle<PromiseObject*> capability);
    460  bool hasTopLevelCapability() const;
    461  PromiseObject* maybeTopLevelCapability() const;
    462  PromiseObject* topLevelCapability() const;
    463  ListObject* asyncParentModules() const;
    464  mozilla::Maybe<uint32_t> maybePendingAsyncDependencies() const;
    465  uint32_t pendingAsyncDependencies() const;
    466  AsyncEvaluationOrder& asyncEvaluationOrder();
    467  AsyncEvaluationOrder const& asyncEvaluationOrder() const;
    468  void setCycleRoot(ModuleObject* cycleRoot);
    469  ModuleObject* getCycleRoot() const;
    470  bool hasCyclicModuleFields() const;
    471  bool hasSyntheticModuleFields() const;
    472  LoadedModuleMap& loadedModules();
    473  const LoadedModuleMap& loadedModules() const;
    474 
    475  static void onTopLevelEvaluationFinished(ModuleObject* module);
    476 
    477  static bool appendAsyncParentModule(JSContext* cx, Handle<ModuleObject*> self,
    478                                      Handle<ModuleObject*> parent);
    479 
    480  [[nodiscard]] static bool topLevelCapabilityResolve(
    481      JSContext* cx, Handle<ModuleObject*> module);
    482  [[nodiscard]] static bool topLevelCapabilityReject(
    483      JSContext* cx, Handle<ModuleObject*> module, HandleValue error);
    484 
    485  void setMetaObject(JSObject* obj);
    486 
    487  static bool instantiateFunctionDeclarations(JSContext* cx,
    488                                              Handle<ModuleObject*> self);
    489 
    490  static bool execute(JSContext* cx, Handle<ModuleObject*> self);
    491 
    492  static ModuleNamespaceObject* createNamespace(
    493      JSContext* cx, Handle<ModuleObject*> self,
    494      MutableHandle<UniquePtr<ExportNameVector>> exports);
    495 
    496  static bool createEnvironment(JSContext* cx, Handle<ModuleObject*> self);
    497  static bool createSyntheticEnvironment(JSContext* cx,
    498                                         Handle<ModuleObject*> self,
    499                                         JS::HandleVector<Value> values);
    500 
    501  void initAsyncSlots(JSContext* cx, bool hasTopLevelAwait,
    502                      Handle<ListObject*> asyncParentModules);
    503 
    504 private:
    505  static const JSClassOps classOps_;
    506 
    507  static void trace(JSTracer* trc, JSObject* obj);
    508  static void finalize(JS::GCContext* gcx, JSObject* obj);
    509 
    510  CyclicModuleFields* cyclicModuleFields();
    511  const CyclicModuleFields* cyclicModuleFields() const;
    512 
    513  SyntheticModuleFields* syntheticModuleFields();
    514  const SyntheticModuleFields* syntheticModuleFields() const;
    515 };
    516 
    517 using VisitedModuleSet =
    518    GCHashSet<HeapPtr<ModuleObject*>, DefaultHasher<HeapPtr<ModuleObject*>>,
    519              SystemAllocPolicy>;
    520 
    521 // The fields of a GraphLoadingState Record, as described in:
    522 // https://tc39.es/ecma262/#graphloadingstate-record
    523 struct GraphLoadingStateRecord {
    524  GraphLoadingStateRecord() = default;
    525  GraphLoadingStateRecord(JS::LoadModuleResolvedCallback resolved,
    526                          JS::LoadModuleRejectedCallback rejected);
    527 
    528  void trace(JSTracer* trc);
    529 
    530  // [[Visited]] : a List of Cyclic Module Records
    531  VisitedModuleSet visited;
    532 
    533  JS::LoadModuleResolvedCallback resolved;
    534  JS::LoadModuleRejectedCallback rejected;
    535 };
    536 
    537 class GraphLoadingStateRecordObject : public NativeObject {
    538 public:
    539  enum {
    540    StateSlot = 0,
    541    PromiseSlot,
    542    IsLoadingSlot,
    543    PendingModulesCountSlot,
    544    HostDefinedSlot,
    545    SlotCount
    546  };
    547 
    548  static const JSClass class_;
    549  static const JSClassOps classOps_;
    550 
    551  [[nodiscard]] static GraphLoadingStateRecordObject* create(
    552      JSContext* cx, bool isLoading, uint32_t pendingModulesCount,
    553      JS::LoadModuleResolvedCallback resolved,
    554      JS::LoadModuleRejectedCallback rejected, Handle<Value> hostDefined);
    555 
    556  [[nodiscard]] static GraphLoadingStateRecordObject* create(
    557      JSContext* cx, bool isLoading, uint32_t pendingModulesCount,
    558      Handle<PromiseObject*> promise, Handle<Value> hostDefined);
    559 
    560  static void finalize(JS::GCContext* gcx, JSObject* obj);
    561  static void trace(JSTracer* trc, JSObject* obj);
    562 
    563  // [[PromiseCapability]] : a PromiseCapability Record
    564  PromiseObject* promise();
    565 
    566  // [[IsLoading]] : a Boolean
    567  bool isLoading();
    568  void setIsLoading(bool isLoading);
    569 
    570  // [[PendingModulesCount]] : a non-negative integer
    571  uint32_t pendingModulesCount();
    572  void setPendingModulesCount(uint32_t count);
    573 
    574  VisitedModuleSet& visited();
    575 
    576  Value hostDefined();
    577 
    578  bool resolved(JSContext* cx, JS::Handle<JS::Value> hostDefined);
    579  bool rejected(JSContext* cx, JS::Handle<JS::Value> hostDefined,
    580                Handle<JS::Value> error);
    581 };
    582 
    583 JSObject* GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
    584 
    585 JSObject* StartDynamicModuleImport(JSContext* cx, HandleScript script,
    586                                   HandleValue specifier, HandleValue options);
    587 
    588 }  // namespace js
    589 
    590 template <>
    591 inline bool JSObject::is<js::ModuleNamespaceObject>() const {
    592  return js::IsDerivedProxyObject(this,
    593                                  &js::ModuleNamespaceObject::proxyHandler);
    594 }
    595 
    596 #endif /* builtin_ModuleObject_h */