// Copyright 2017 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_MODULE_H_
|
#define V8_OBJECTS_MODULE_H_
|
|
#include "src/objects.h"
|
#include "src/objects/fixed-array.h"
|
|
// Has to be the last include (doesn't have include guards):
|
#include "src/objects/object-macros.h"
|
|
namespace v8 {
|
namespace internal {
|
|
template <typename T>
|
class Handle;
|
class Isolate;
|
class JSModuleNamespace;
|
class ModuleDescriptor;
|
class ModuleInfo;
|
class ModuleInfoEntry;
|
class String;
|
class Zone;
|
|
// The runtime representation of an ECMAScript module.
|
class Module : public Struct, public NeverReadOnlySpaceObject {
|
public:
|
using NeverReadOnlySpaceObject::GetHeap;
|
using NeverReadOnlySpaceObject::GetIsolate;
|
|
DECL_CAST(Module)
|
DECL_VERIFIER(Module)
|
DECL_PRINTER(Module)
|
|
// The code representing this module, or an abstraction thereof.
|
// This is either a SharedFunctionInfo, a JSFunction, a JSGeneratorObject, or
|
// a ModuleInfo, depending on the state (status) the module is in. See
|
// Module::ModuleVerify() for the precise invariant.
|
DECL_ACCESSORS(code, Object)
|
|
// Arrays of cells corresponding to regular exports and regular imports.
|
// A cell's position in the array is determined by the cell index of the
|
// associated module entry (which coincides with the variable index of the
|
// associated variable).
|
DECL_ACCESSORS(regular_exports, FixedArray)
|
DECL_ACCESSORS(regular_imports, FixedArray)
|
|
// The complete export table, mapping an export name to its cell.
|
// TODO(neis): We may want to remove the regular exports from the table.
|
DECL_ACCESSORS(exports, ObjectHashTable)
|
|
// Hash for this object (a random non-zero Smi).
|
DECL_INT_ACCESSORS(hash)
|
|
// Status.
|
DECL_INT_ACCESSORS(status)
|
enum Status {
|
// Order matters!
|
kUninstantiated,
|
kPreInstantiating,
|
kInstantiating,
|
kInstantiated,
|
kEvaluating,
|
kEvaluated,
|
kErrored
|
};
|
|
// The exception in the case {status} is kErrored.
|
Object* GetException();
|
|
// The shared function info in case {status} is not kEvaluating, kEvaluated or
|
// kErrored.
|
SharedFunctionInfo* GetSharedFunctionInfo() const;
|
|
// The namespace object (or undefined).
|
DECL_ACCESSORS(module_namespace, HeapObject)
|
|
// Modules imported or re-exported by this module.
|
// Corresponds 1-to-1 to the module specifier strings in
|
// ModuleInfo::module_requests.
|
DECL_ACCESSORS(requested_modules, FixedArray)
|
|
// [script]: Script from which the module originates.
|
DECL_ACCESSORS(script, Script)
|
|
// The value of import.meta inside of this module.
|
// Lazily initialized on first access. It's the hole before first access and
|
// a JSObject afterwards.
|
DECL_ACCESSORS(import_meta, Object)
|
|
// Get the ModuleInfo associated with the code.
|
inline ModuleInfo* info() const;
|
|
// Implementation of spec operation ModuleDeclarationInstantiation.
|
// Returns false if an exception occurred during instantiation, true
|
// otherwise. (In the case where the callback throws an exception, that
|
// exception is propagated.)
|
static V8_WARN_UNUSED_RESULT bool Instantiate(
|
Isolate* isolate, Handle<Module> module, v8::Local<v8::Context> context,
|
v8::Module::ResolveCallback callback);
|
|
// Implementation of spec operation ModuleEvaluation.
|
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
|
Isolate* isolate, Handle<Module> module);
|
|
Cell* GetCell(int cell_index);
|
static Handle<Object> LoadVariable(Isolate* isolate, Handle<Module> module,
|
int cell_index);
|
static void StoreVariable(Handle<Module> module, int cell_index,
|
Handle<Object> value);
|
|
// 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<Module> module,
|
int module_request);
|
|
// Get the namespace object for [module]. If it doesn't exist yet, it is
|
// created.
|
static Handle<JSModuleNamespace> GetModuleNamespace(Isolate* isolate,
|
Handle<Module> module);
|
|
static const int kCodeOffset = HeapObject::kHeaderSize;
|
static const int kExportsOffset = kCodeOffset + kPointerSize;
|
static const int kRegularExportsOffset = kExportsOffset + kPointerSize;
|
static const int kRegularImportsOffset = kRegularExportsOffset + kPointerSize;
|
static const int kHashOffset = kRegularImportsOffset + kPointerSize;
|
static const int kModuleNamespaceOffset = kHashOffset + kPointerSize;
|
static const int kRequestedModulesOffset =
|
kModuleNamespaceOffset + kPointerSize;
|
static const int kStatusOffset = kRequestedModulesOffset + kPointerSize;
|
static const int kDfsIndexOffset = kStatusOffset + kPointerSize;
|
static const int kDfsAncestorIndexOffset = kDfsIndexOffset + kPointerSize;
|
static const int kExceptionOffset = kDfsAncestorIndexOffset + kPointerSize;
|
static const int kScriptOffset = kExceptionOffset + kPointerSize;
|
static const int kImportMetaOffset = kScriptOffset + kPointerSize;
|
static const int kSize = kImportMetaOffset + kPointerSize;
|
|
private:
|
friend class Factory;
|
|
DECL_ACCESSORS(exception, Object)
|
|
// TODO(neis): Don't store those in the module object?
|
DECL_INT_ACCESSORS(dfs_index)
|
DECL_INT_ACCESSORS(dfs_ancestor_index)
|
|
// Helpers for Instantiate and Evaluate.
|
|
static void CreateExport(Isolate* isolate, Handle<Module> module,
|
int cell_index, Handle<FixedArray> names);
|
static void CreateIndirectExport(Isolate* isolate, Handle<Module> module,
|
Handle<String> name,
|
Handle<ModuleInfoEntry> entry);
|
|
// The [must_resolve] argument indicates whether or not an exception should be
|
// thrown in case the module does not provide an export named [name]
|
// (including when a cycle is detected). An exception is always thrown in the
|
// case of conflicting star exports.
|
//
|
// If [must_resolve] is true, a null result indicates an exception. If
|
// [must_resolve] is false, a null result may or may not indicate an
|
// exception (so check manually!).
|
class ResolveSet;
|
static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExport(
|
Isolate* isolate, Handle<Module> 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<Module> module, Handle<String> name,
|
int module_request, MessageLocation loc, bool must_resolve,
|
ResolveSet* resolve_set);
|
|
static V8_WARN_UNUSED_RESULT MaybeHandle<Cell> ResolveExportUsingStarExports(
|
Isolate* isolate, Handle<Module> 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<Module> module, v8::Local<v8::Context> context,
|
v8::Module::ResolveCallback callback);
|
static V8_WARN_UNUSED_RESULT bool FinishInstantiate(
|
Isolate* isolate, Handle<Module> module,
|
ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index, Zone* zone);
|
static V8_WARN_UNUSED_RESULT bool RunInitializationCode(
|
Isolate* isolate, Handle<Module> module);
|
|
static V8_WARN_UNUSED_RESULT MaybeHandle<Object> Evaluate(
|
Isolate* isolate, Handle<Module> module,
|
ZoneForwardList<Handle<Module>>* stack, unsigned* dfs_index);
|
|
static V8_WARN_UNUSED_RESULT bool MaybeTransitionComponent(
|
Isolate* isolate, Handle<Module> module,
|
ZoneForwardList<Handle<Module>>* stack, Status new_status);
|
|
// Set module's status back to kUninstantiated and reset other internal state.
|
// This is used when instantiation fails.
|
static void Reset(Isolate* isolate, Handle<Module> module);
|
static void ResetGraph(Isolate* isolate, Handle<Module> module);
|
|
// To set status to kErrored, RecordError should be used.
|
void SetStatus(Status status);
|
void RecordError(Isolate* isolate);
|
|
#ifdef DEBUG
|
// For --trace-module-status.
|
void PrintStatusTransition(Status new_status);
|
#endif // DEBUG
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(Module);
|
};
|
|
// When importing a module namespace (import * as foo from "bar"), a
|
// JSModuleNamespace object (representing module "bar") is created and bound to
|
// the declared variable (foo). A module can have at most one namespace object.
|
class JSModuleNamespace : public JSObject {
|
public:
|
DECL_CAST(JSModuleNamespace)
|
DECL_PRINTER(JSModuleNamespace)
|
DECL_VERIFIER(JSModuleNamespace)
|
|
// The actual module whose namespace is being represented.
|
DECL_ACCESSORS(module, Module)
|
|
// Retrieve the value exported by [module] under the given [name]. If there is
|
// no such export, return Just(undefined). If the export is uninitialized,
|
// schedule an exception and return Nothing.
|
V8_WARN_UNUSED_RESULT MaybeHandle<Object> GetExport(Isolate* isolate,
|
Handle<String> name);
|
|
// Return the (constant) property attributes for the referenced property,
|
// which is assumed to correspond to an export. If the export is
|
// uninitialized, schedule an exception and return Nothing.
|
static V8_WARN_UNUSED_RESULT Maybe<PropertyAttributes> GetPropertyAttributes(
|
LookupIterator* it);
|
|
// In-object fields.
|
enum {
|
kToStringTagFieldIndex,
|
kInObjectFieldCount,
|
};
|
|
static const int kModuleOffset = JSObject::kHeaderSize;
|
static const int kHeaderSize = kModuleOffset + kPointerSize;
|
|
static const int kSize = kHeaderSize + kPointerSize * kInObjectFieldCount;
|
|
private:
|
DISALLOW_IMPLICIT_CONSTRUCTORS(JSModuleNamespace);
|
};
|
|
// ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope.
|
class ModuleInfo : public FixedArray {
|
public:
|
DECL_CAST(ModuleInfo)
|
|
static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone,
|
ModuleDescriptor* descr);
|
|
inline FixedArray* module_requests() const;
|
inline FixedArray* special_exports() const;
|
inline FixedArray* regular_exports() const;
|
inline FixedArray* regular_imports() const;
|
inline FixedArray* namespace_imports() const;
|
inline FixedArray* module_request_positions() const;
|
|
// Accessors for [regular_exports].
|
int RegularExportCount() const;
|
String* RegularExportLocalName(int i) const;
|
int RegularExportCellIndex(int i) const;
|
FixedArray* RegularExportExportNames(int i) const;
|
|
#ifdef DEBUG
|
inline bool Equals(ModuleInfo* other) const;
|
#endif
|
|
private:
|
friend class Factory;
|
friend class ModuleDescriptor;
|
enum {
|
kModuleRequestsIndex,
|
kSpecialExportsIndex,
|
kRegularExportsIndex,
|
kNamespaceImportsIndex,
|
kRegularImportsIndex,
|
kModuleRequestPositionsIndex,
|
kLength
|
};
|
enum {
|
kRegularExportLocalNameOffset,
|
kRegularExportCellIndexOffset,
|
kRegularExportExportNamesOffset,
|
kRegularExportLength
|
};
|
DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfo);
|
};
|
|
class ModuleInfoEntry : public Struct {
|
public:
|
DECL_CAST(ModuleInfoEntry)
|
DECL_PRINTER(ModuleInfoEntry)
|
DECL_VERIFIER(ModuleInfoEntry)
|
|
DECL_ACCESSORS(export_name, Object)
|
DECL_ACCESSORS(local_name, Object)
|
DECL_ACCESSORS(import_name, Object)
|
DECL_INT_ACCESSORS(module_request)
|
DECL_INT_ACCESSORS(cell_index)
|
DECL_INT_ACCESSORS(beg_pos)
|
DECL_INT_ACCESSORS(end_pos)
|
|
static Handle<ModuleInfoEntry> New(Isolate* isolate,
|
Handle<Object> export_name,
|
Handle<Object> local_name,
|
Handle<Object> import_name,
|
int module_request, int cell_index,
|
int beg_pos, int end_pos);
|
|
static const int kExportNameOffset = HeapObject::kHeaderSize;
|
static const int kLocalNameOffset = kExportNameOffset + kPointerSize;
|
static const int kImportNameOffset = kLocalNameOffset + kPointerSize;
|
static const int kModuleRequestOffset = kImportNameOffset + kPointerSize;
|
static const int kCellIndexOffset = kModuleRequestOffset + kPointerSize;
|
static const int kBegPosOffset = kCellIndexOffset + kPointerSize;
|
static const int kEndPosOffset = kBegPosOffset + kPointerSize;
|
static const int kSize = kEndPosOffset + kPointerSize;
|
|
private:
|
DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfoEntry);
|
};
|
|
} // namespace internal
|
} // namespace v8
|
|
#include "src/objects/object-macros-undef.h"
|
|
#endif // V8_OBJECTS_MODULE_H_
|