blob: 2a3249bf1b394b83c0db1f08826c91a903f877cc [file] [log] [blame]
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_OBJECTS_SOURCE_TEXT_MODULE_H_
#define V8_OBJECTS_SOURCE_TEXT_MODULE_H_
#include "src/objects/contexts.h"
#include "src/objects/module.h"
#include "src/objects/promise.h"
#include "src/zone/zone-containers.h"
#include "torque-generated/bit-fields.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class UnorderedModuleSet;
class StructBodyDescriptor;
#include "torque-generated/src/objects/source-text-module-tq.inc"
// The runtime representation of an ECMAScript Source Text Module Record.
// https://tc39.github.io/ecma262/#sec-source-text-module-records
class SourceTextModule
: public TorqueGeneratedSourceTextModule<SourceTextModule, Module> {
public:
NEVER_READ_ONLY_SPACE
DECL_VERIFIER(SourceTextModule)
DECL_PRINTER(SourceTextModule)
// The shared function info in case {status} is not kEvaluating, kEvaluated or
// kErrored.
Tagged<SharedFunctionInfo> GetSharedFunctionInfo() const;
Tagged<Script> GetScript() const;
// Whether or not this module is an async module. Set during module creation
// and does not change afterwards.
DECL_BOOLEAN_ACCESSORS(async)
// Get the SourceTextModuleInfo associated with the code.
inline Tagged<SourceTextModuleInfo> info() const;
Tagged<Cell> GetCell(int cell_index);
static Handle<Object> LoadVariable(Isolate* isolate,
Handle<SourceTextModule> module,
int cell_index);
static void StoreVariable(Handle<SourceTextModule> module, int cell_index,
Handle<Object> value);
static int ImportIndex(int cell_index);
static int ExportIndex(int cell_index);
// Used by builtins to fulfill or reject the promise associated
// with async SourceTextModules. Return Nothing if the execution is
// terminated.
static Maybe<bool> AsyncModuleExecutionFulfilled(
Isolate* isolate, Handle<SourceTextModule> module);
static void AsyncModuleExecutionRejected(Isolate* isolate,
Handle<SourceTextModule> module,
Handle<Object> exception);
// Get the namespace object for [module_request] of [module]. If it doesn't
// exist yet, it is created.
static Handle<JSModuleNamespace> GetModuleNamespace(
Isolate* isolate, Handle<SourceTextModule> module, int module_request);
// Get the import.meta object of [module]. If it doesn't exist yet, it is
// created and passed to the embedder callback for initialization.
V8_EXPORT_PRIVATE static MaybeHandle<JSObject> GetImportMeta(
Isolate* isolate, Handle<SourceTextModule> module);
using BodyDescriptor =
SubclassBodyDescriptor<Module::BodyDescriptor,
FixedBodyDescriptor<kCodeOffset, kSize, kSize>>;
static constexpr unsigned kFirstAsyncEvaluatingOrdinal = 2;
enum ExecuteAsyncModuleContextSlots {
kModule = Context::MIN_CONTEXT_SLOTS,
kContextLength,
};
V8_EXPORT_PRIVATE
std::vector<std::tuple<Handle<SourceTextModule>, Handle<JSMessageObject>>>
GetStalledTopLevelAwaitMessages(Isolate* isolate);
private:
friend class Factory;
friend class Module;
struct AsyncEvaluatingOrdinalCompare;
using AsyncParentCompletionSet =
ZoneSet<Handle<SourceTextModule>, AsyncEvaluatingOrdinalCompare>;
// Appends a tuple of module and generator to the async parent modules
// ArrayList.
inline static void AddAsyncParentModule(Isolate* isolate,
Handle<SourceTextModule> module,
Handle<SourceTextModule> parent);
// Get the non-hole cycle root. Only valid when status >= kEvaluated.
inline Handle<SourceTextModule> GetCycleRoot(Isolate* isolate) const;
// Returns a SourceTextModule, the
// ith parent in depth first traversal order of a given async child.
inline Handle<SourceTextModule> GetAsyncParentModule(Isolate* isolate,
int index);
// Returns the number of async parent modules for a given async child.
inline int AsyncParentModuleCount();
inline bool IsAsyncEvaluating() const;
inline bool HasPendingAsyncDependencies();
inline void IncrementPendingAsyncDependencies();
inline void DecrementPendingAsyncDependencies();
// Bits for flags.
DEFINE_TORQUE_GENERATED_SOURCE_TEXT_MODULE_FLAGS()
// async_evaluating_ordinal, top_level_capability, pending_async_dependencies,
// and async_parent_modules are used exclusively during evaluation of async
// modules and the modules which depend on them.
//
// If >1, this module is async and evaluating or currently evaluating an async
// child. The integer is an ordinal for when this module first started async
// evaluation and is used for sorting async parent modules when determining
// which parent module can start executing after an async evaluation
// completes.
//
// If 1, this module has finished async evaluating.
//
// If 0, this module is not async or has not been async evaluated.
static constexpr unsigned kNotAsyncEvaluated = 0;
static constexpr unsigned kAsyncEvaluateDidFinish = 1;
static_assert(kNotAsyncEvaluated < kAsyncEvaluateDidFinish);
static_assert(kAsyncEvaluateDidFinish < kFirstAsyncEvaluatingOrdinal);
static_assert(kMaxModuleAsyncEvaluatingOrdinal ==
AsyncEvaluatingOrdinalBits::kMax);
DECL_PRIMITIVE_ACCESSORS(async_evaluating_ordinal, unsigned)
// The parent modules of a given async dependency, use async_parent_modules()
// to retrieve the ArrayList representation.
DECL_ACCESSORS(async_parent_modules, Tagged<ArrayList>)
// Helpers for Instantiate and Evaluate.
static void CreateExport(Isolate* isolate, Handle<SourceTextModule> module,
int cell_index, Handle<FixedArray> names);
static void CreateIndirectExport(Isolate* isolate,
Handle<SourceTextModule> module,
Handle<String> name,
Handle<SourceTextModuleInfoEntry> entry);
static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport(
Isolate* isolate, Handle<SourceTextModule> module,
Handle<String> module_specifier, Handle<String> export_name,
MessageLocation loc, bool must_resolve, ResolveSet* resolve_set);
static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveImport(
Isolate* isolate, Handle<SourceTextModule> module, Handle<String> name,
int module_request_index, MessageLocation loc, bool must_resolve,
ResolveSet* resolve_set);
static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports(
Isolate* isolate, Handle<SourceTextModule> module,
Handle<String> module_specifier, Handle<String> export_name,
MessageLocation loc, bool must_resolve, ResolveSet* resolve_set);
static V8_WARN_UNUSED_RESULT bool PrepareInstantiate(
Isolate* isolate, Handle<SourceTextModule> module,
v8::Local<v8::Context> context,
v8::Module::ResolveModuleCallback callback,
Module::DeprecatedResolveCallback callback_without_import_assertions);
static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
Isolate* isolate, Handle<SourceTextModule> module,
ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index,
Zone* zone);
static V8_WARN_UNUSED_RESULT bool RunInitializationCode(
Isolate* isolate, Handle<SourceTextModule> module);
static void FetchStarExports(Isolate* isolate,
Handle<SourceTextModule> module, Zone* zone,
UnorderedModuleSet* visited);
static void GatherAsyncParentCompletions(Isolate* isolate, Zone* zone,
Handle<SourceTextModule> start,
AsyncParentCompletionSet* exec_list);
// Implementation of spec concrete method Evaluate.
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
Isolate* isolate, Handle<SourceTextModule> module);
// Implementation of spec abstract operation InnerModuleEvaluation.
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> InnerModuleEvaluation(
Isolate* isolate, Handle<SourceTextModule> module,
ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index);
// Returns true if the evaluation exception was catchable by js, and false
// for termination exceptions.
bool MaybeHandleEvaluationException(
Isolate* isolate, ZoneForwardList<Handle<SourceTextModule>>* stack);
static V8_WARN_UNUSED_RESULT bool MaybeTransitionComponent(
Isolate* isolate, Handle<SourceTextModule> module,
ZoneForwardList<Handle<SourceTextModule>>* stack, Status new_status);
// Implementation of spec ExecuteModule is broken up into
// InnerExecuteAsyncModule for asynchronous modules and ExecuteModule
// for synchronous modules.
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> InnerExecuteAsyncModule(
Isolate* isolate, Handle<SourceTextModule> module,
Handle<JSPromise> capability);
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> ExecuteModule(
Isolate* isolate, Handle<SourceTextModule> module,
MaybeHandle<Object>* exception_out);
// Implementation of spec ExecuteAsyncModule. Return Nothing if the execution
// is been terminated.
static V8_WARN_UNUSED_RESULT Maybe<bool> ExecuteAsyncModule(
Isolate* isolate, Handle<SourceTextModule> module);
static void Reset(Isolate* isolate, Handle<SourceTextModule> module);
V8_EXPORT_PRIVATE void InnerGetStalledTopLevelAwaitModule(
Isolate* isolate, UnorderedModuleSet* visited,
std::vector<Handle<SourceTextModule>>* result);
TQ_OBJECT_CONSTRUCTORS(SourceTextModule)
};
// SourceTextModuleInfo is to SourceTextModuleDescriptor what ScopeInfo is to
// Scope.
class SourceTextModuleInfo : public FixedArray {
public:
DECL_CAST(SourceTextModuleInfo)
template <typename IsolateT>
static Handle<SourceTextModuleInfo> New(IsolateT* isolate, Zone* zone,
SourceTextModuleDescriptor* descr);
inline Tagged<FixedArray> module_requests() const;
inline Tagged<FixedArray> special_exports() const;
inline Tagged<FixedArray> regular_exports() const;
inline Tagged<FixedArray> regular_imports() const;
inline Tagged<FixedArray> namespace_imports() const;
// Accessors for [regular_exports].
int RegularExportCount() const;
Tagged<String> RegularExportLocalName(int i) const;
int RegularExportCellIndex(int i) const;
Tagged<FixedArray> RegularExportExportNames(int i) const;
#ifdef DEBUG
inline bool Equals(Tagged<SourceTextModuleInfo> other) const;
#endif
private:
template <typename Impl>
friend class FactoryBase;
friend class SourceTextModuleDescriptor;
enum {
kModuleRequestsIndex,
kSpecialExportsIndex,
kRegularExportsIndex,
kNamespaceImportsIndex,
kRegularImportsIndex,
kLength
};
enum {
kRegularExportLocalNameOffset,
kRegularExportCellIndexOffset,
kRegularExportExportNamesOffset,
kRegularExportLength
};
OBJECT_CONSTRUCTORS(SourceTextModuleInfo, FixedArray);
};
class ModuleRequest
: public TorqueGeneratedModuleRequest<ModuleRequest, Struct> {
public:
NEVER_READ_ONLY_SPACE
DECL_VERIFIER(ModuleRequest)
template <typename IsolateT>
static Handle<ModuleRequest> New(IsolateT* isolate, Handle<String> specifier,
Handle<FixedArray> import_attributes,
int position);
// The number of entries in the import_attributes FixedArray that are used for
// a single attribute.
static const size_t kAttributeEntrySize = 3;
using BodyDescriptor = StructBodyDescriptor;
TQ_OBJECT_CONSTRUCTORS(ModuleRequest)
};
class SourceTextModuleInfoEntry
: public TorqueGeneratedSourceTextModuleInfoEntry<SourceTextModuleInfoEntry,
Struct> {
public:
DECL_VERIFIER(SourceTextModuleInfoEntry)
template <typename IsolateT>
static Handle<SourceTextModuleInfoEntry> New(
IsolateT* isolate, Handle<PrimitiveHeapObject> export_name,
Handle<PrimitiveHeapObject> local_name,
Handle<PrimitiveHeapObject> import_name, int module_request,
int cell_index, int beg_pos, int end_pos);
using BodyDescriptor = StructBodyDescriptor;
TQ_OBJECT_CONSTRUCTORS(SourceTextModuleInfoEntry)
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_SOURCE_TEXT_MODULE_H_