2021-09-14 18:51:16 +00:00
/*
2023-02-19 21:07:52 +00:00
* Copyright ( c ) 2021 - 2023 , Andreas Kling < kling @ serenityos . org >
2022-01-18 18:29:17 +00:00
* Copyright ( c ) 2022 , David Tuin < davidot @ serenityos . org >
2021-09-14 18:51:16 +00:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2023-01-02 20:07:18 +00:00
# include <AK/Debug.h>
2022-01-18 18:29:17 +00:00
# include <AK/QuickSort.h>
2023-06-24 14:07:15 +00:00
# include <LibJS/Bytecode/Interpreter.h>
2022-11-23 12:28:01 +00:00
# include <LibJS/Parser.h>
2023-12-06 10:35:40 +00:00
# include <LibJS/Runtime/AsyncFunctionDriverWrapper.h>
2022-01-18 18:29:17 +00:00
# include <LibJS/Runtime/ECMAScriptFunctionObject.h>
2023-08-07 17:59:00 +00:00
# include <LibJS/Runtime/GlobalEnvironment.h>
2022-01-18 18:29:17 +00:00
# include <LibJS/Runtime/ModuleEnvironment.h>
2023-12-06 10:35:40 +00:00
# include <LibJS/Runtime/PromiseCapability.h>
2021-09-14 18:51:16 +00:00
# include <LibJS/SourceTextModule.h>
namespace JS {
2023-11-19 08:45:05 +00:00
JS_DEFINE_ALLOCATOR ( SourceTextModule ) ;
2023-12-02 15:20:01 +00:00
// 16.2.2.2 Static Semantics: WithClauseToAttributes, https://tc39.es/proposal-import-attributes/#sec-with-clause-to-attributes
static Vector < ImportAttribute > with_clause_to_assertions ( Vector < ImportAttribute > const & source_attributes )
2022-01-27 01:44:03 +00:00
{
2023-12-02 15:20:01 +00:00
// WithClause : AttributesKeyword { WithEntries , opt }
// 1. Let attributes be WithClauseToAttributes of WithEntries.
Vector < ImportAttribute > attributes ;
2022-01-27 01:44:03 +00:00
// AssertEntries : AssertionKey : StringLiteral
2023-12-02 15:20:01 +00:00
// AssertEntries : AssertionKey : StringLiteral , WithEntries
for ( auto const & attribute : source_attributes ) {
// 1. Let key be the PropName of AttributeKey.
// 2. Let entry be the ImportAttribute Record { [[Key]]: key, [[Value]]: SV of StringLiteral }.
// 3. Return « entry ».
attributes . empend ( attribute ) ;
2022-01-27 01:44:03 +00:00
}
2023-12-02 15:20:01 +00:00
// 2. Sort attributes according to the lexicographic order of their [[Key]] fields, treating the value of each such field as a sequence of UTF-16 code unit values. NOTE: This sorting is observable only in that hosts are prohibited from distinguishing among attributes by the order they occur in.
2022-01-27 01:44:03 +00:00
// Note: The sorting is done in construction of the ModuleRequest object.
2023-12-02 15:20:01 +00:00
// 3. Return attributes.
return attributes ;
2022-01-27 01:44:03 +00:00
}
2022-01-18 18:29:17 +00:00
// 16.2.1.3 Static Semantics: ModuleRequests, https://tc39.es/ecma262/#sec-static-semantics-modulerequests
2023-12-02 15:20:01 +00:00
static Vector < ModuleRequest > module_requests ( Program & program )
2022-01-18 18:29:17 +00:00
{
// A List of all the ModuleSpecifier strings used by the module represented by this record to request the importation of a module.
// Note: The List is source text occurrence ordered!
struct RequestedModuleAndSourceIndex {
2022-11-27 00:15:37 +00:00
u32 source_offset { 0 } ;
2023-02-19 21:07:52 +00:00
ModuleRequest const * module_request { nullptr } ;
2022-01-18 18:29:17 +00:00
} ;
Vector < RequestedModuleAndSourceIndex > requested_modules_with_indices ;
2022-11-27 00:15:37 +00:00
for ( auto & import_statement : program . imports ( ) )
2023-03-06 13:17:01 +00:00
requested_modules_with_indices . empend ( import_statement - > start_offset ( ) , & import_statement - > module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
2022-01-27 01:44:03 +00:00
for ( auto & export_statement : program . exports ( ) ) {
2023-03-06 13:17:01 +00:00
for ( auto & export_entry : export_statement - > entries ( ) ) {
2022-01-27 00:54:47 +00:00
if ( ! export_entry . is_module_request ( ) )
2022-01-18 18:29:17 +00:00
continue ;
2023-03-06 13:17:01 +00:00
requested_modules_with_indices . empend ( export_statement - > start_offset ( ) , & export_statement - > module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
}
}
2023-12-02 15:20:01 +00:00
// Note: The List is source code occurrence ordered. https://tc39.es/proposal-import-attributes/#table-cyclic-module-fields
2022-01-27 01:44:03 +00:00
quick_sort ( requested_modules_with_indices , [ & ] ( RequestedModuleAndSourceIndex const & lhs , RequestedModuleAndSourceIndex const & rhs ) {
2022-11-27 00:15:37 +00:00
return lhs . source_offset < rhs . source_offset ;
2022-01-27 01:44:03 +00:00
} ) ;
2022-01-18 18:29:17 +00:00
2022-01-27 01:44:03 +00:00
Vector < ModuleRequest > requested_modules_in_source_order ;
2022-01-18 18:29:17 +00:00
requested_modules_in_source_order . ensure_capacity ( requested_modules_with_indices . size ( ) ) ;
for ( auto & module : requested_modules_with_indices ) {
2023-12-02 15:20:01 +00:00
// 16.2.1.3 Static Semantics: ModuleRequests, https://tc39.es/proposal-import-attributes/#sec-static-semantics-modulerequests
if ( module . module_request - > attributes . is_empty ( ) ) {
2022-01-27 01:44:03 +00:00
// ExportDeclaration : export ExportFromClause FromClause ;
// ImportDeclaration : import ImportClause FromClause ;
2023-12-02 15:20:01 +00:00
// 2. Let specifier be SV of FromClause.
// 3. Return a List whose sole element is the ModuleRequest Record { [[Specifer]]: specifier, [[Attributes]]: « » }.
2022-01-27 01:44:03 +00:00
requested_modules_in_source_order . empend ( module . module_request - > module_specifier ) ;
} else {
2023-12-02 15:20:01 +00:00
// ExportDeclaration : export ExportFromClause FromClause WithClause ;
// ImportDeclaration : import ImportClause FromClause WithClause ;
2022-01-27 01:44:03 +00:00
2023-12-02 15:20:01 +00:00
// 1. Let specifier be the SV of FromClause.
// 2. Let attributes be WithClauseToAttributes of WithClause.
auto attributes = with_clause_to_assertions ( module . module_request - > attributes ) ;
// NOTE: We have to modify the attributes in place because else it might keep unsupported ones.
const_cast < ModuleRequest * > ( module . module_request ) - > attributes = move ( attributes ) ;
2022-01-27 01:44:03 +00:00
2023-12-02 15:20:01 +00:00
// 3. Return a List whose sole element is the ModuleRequest Record { [[Specifer]]: specifier, [[Attributes]]: attributes }.
requested_modules_in_source_order . empend ( module . module_request - > module_specifier , module . module_request - > attributes ) ;
2022-01-27 01:44:03 +00:00
}
2022-01-18 18:29:17 +00:00
}
return requested_modules_in_source_order ;
}
2022-10-02 19:18:33 +00:00
SourceTextModule : : SourceTextModule ( Realm & realm , StringView filename , Script : : HostDefined * host_defined , bool has_top_level_await , NonnullRefPtr < Program > body , Vector < ModuleRequest > requested_modules ,
2022-01-18 18:29:17 +00:00
Vector < ImportEntry > import_entries , Vector < ExportEntry > local_export_entries ,
Vector < ExportEntry > indirect_export_entries , Vector < ExportEntry > star_export_entries ,
2023-02-19 21:07:52 +00:00
RefPtr < ExportStatement const > default_export )
2022-10-02 19:18:33 +00:00
: CyclicModule ( realm , filename , has_top_level_await , move ( requested_modules ) , host_defined )
2022-01-18 18:29:17 +00:00
, m_ecmascript_code ( move ( body ) )
2023-11-27 15:45:45 +00:00
, m_execution_context ( ExecutionContext : : create ( realm . heap ( ) ) )
2022-01-18 18:29:17 +00:00
, m_import_entries ( move ( import_entries ) )
, m_local_export_entries ( move ( local_export_entries ) )
, m_indirect_export_entries ( move ( indirect_export_entries ) )
, m_star_export_entries ( move ( star_export_entries ) )
, m_default_export ( move ( default_export ) )
{
}
2022-09-05 12:31:25 +00:00
void SourceTextModule : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_import_meta ) ;
2023-12-13 09:24:30 +00:00
m_execution_context - > visit_edges ( visitor ) ;
2022-09-05 12:31:25 +00:00
}
2021-09-14 18:51:16 +00:00
// 16.2.1.6.1 ParseModule ( sourceText, realm, hostDefined ), https://tc39.es/ecma262/#sec-parsemodule
2022-11-23 11:39:23 +00:00
Result < NonnullGCPtr < SourceTextModule > , Vector < ParserError > > SourceTextModule : : parse ( StringView source_text , Realm & realm , StringView filename , Script : : HostDefined * host_defined )
2021-09-14 18:51:16 +00:00
{
// 1. Let body be ParseText(sourceText, Module).
auto parser = Parser ( Lexer ( source_text , filename ) , Program : : Type : : Module ) ;
auto body = parser . parse_program ( ) ;
// 2. If body is a List of errors, return body.
if ( parser . has_errors ( ) )
return parser . errors ( ) ;
2022-01-18 18:29:17 +00:00
// 3. Let requestedModules be the ModuleRequests of body.
2023-12-02 15:20:01 +00:00
auto requested_modules = module_requests ( * body ) ;
2022-01-18 18:29:17 +00:00
// 4. Let importEntries be ImportEntries of body.
Vector < ImportEntry > import_entries ;
for ( auto const & import_statement : body - > imports ( ) )
2023-03-06 13:17:01 +00:00
import_entries . extend ( import_statement - > entries ( ) ) ;
2022-01-18 18:29:17 +00:00
// 5. Let importedBoundNames be ImportedLocalNames(importEntries).
// Note: Since we have to potentially extract the import entry we just use importEntries
// In the future it might be an optimization to have a set/map of string to speed up the search.
// 6. Let indirectExportEntries be a new empty List.
Vector < ExportEntry > indirect_export_entries ;
// 7. Let localExportEntries be a new empty List.
Vector < ExportEntry > local_export_entries ;
// 8. Let starExportEntries be a new empty List.
Vector < ExportEntry > star_export_entries ;
// Note: Not in the spec but makes it easier to find the default.
2023-02-19 21:07:52 +00:00
RefPtr < ExportStatement const > default_export ;
2022-01-18 18:29:17 +00:00
// 9. Let exportEntries be ExportEntries of body.
// 10. For each ExportEntry Record ee of exportEntries, do
for ( auto const & export_statement : body - > exports ( ) ) {
2023-03-06 13:17:01 +00:00
if ( export_statement - > is_default_export ( ) ) {
2022-01-18 18:29:17 +00:00
VERIFY ( ! default_export ) ;
2023-03-06 13:17:01 +00:00
VERIFY ( export_statement - > entries ( ) . size ( ) = = 1 ) ;
VERIFY ( export_statement - > has_statement ( ) ) ;
2022-01-18 18:29:17 +00:00
2023-03-06 13:17:01 +00:00
auto const & entry = export_statement - > entries ( ) [ 0 ] ;
2022-11-23 11:16:51 +00:00
VERIFY ( entry . kind = = ExportEntry : : Kind : : NamedExport ) ;
2022-01-27 00:54:47 +00:00
VERIFY ( ! entry . is_module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
VERIFY ( import_entries . find_if (
[ & ] ( ImportEntry const & import_entry ) {
return import_entry . local_name = = entry . local_or_import_name ;
} )
. is_end ( ) ) ;
default_export = export_statement ;
}
2023-03-06 13:17:01 +00:00
for ( auto const & export_entry : export_statement - > entries ( ) ) {
2022-01-18 18:29:17 +00:00
2022-08-29 20:12:25 +00:00
// Special case, export {} from "module" should add "module" to
// required_modules but not any import or export so skip here.
2022-11-23 11:16:51 +00:00
if ( export_entry . kind = = ExportEntry : : Kind : : EmptyNamedExport ) {
2023-03-06 13:17:01 +00:00
VERIFY ( export_statement - > entries ( ) . size ( ) = = 1 ) ;
2022-08-29 20:12:25 +00:00
break ;
}
2022-01-18 18:29:17 +00:00
// a. If ee.[[ModuleRequest]] is null, then
2022-01-27 00:54:47 +00:00
if ( ! export_entry . is_module_request ( ) ) {
2022-01-18 18:29:17 +00:00
auto in_imported_bound_names = import_entries . find_if (
[ & ] ( ImportEntry const & import_entry ) {
return import_entry . local_name = = export_entry . local_or_import_name ;
} ) ;
// i. If ee.[[LocalName]] is not an element of importedBoundNames, then
if ( in_imported_bound_names . is_end ( ) ) {
// 1. Append ee to localExportEntries.
local_export_entries . empend ( export_entry ) ;
}
// ii. Else,
else {
// 1. Let ie be the element of importEntries whose [[LocalName]] is the same as ee.[[LocalName]].
auto & import_entry = * in_imported_bound_names ;
// 2. If ie.[[ImportName]] is namespace-object, then
2022-01-27 00:54:47 +00:00
if ( import_entry . is_namespace ) {
2022-01-18 18:29:17 +00:00
// a. NOTE: This is a re-export of an imported module namespace object.
// b. Append ee to localExportEntries.
local_export_entries . empend ( export_entry ) ;
}
// 3. Else,
else {
// a. NOTE: This is a re-export of a single name.
// b. Append the ExportEntry Record { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } to indirectExportEntries.
2022-01-27 00:54:47 +00:00
indirect_export_entries . empend ( ExportEntry : : indirect_export_entry ( import_entry . module_request ( ) , import_entry . import_name , export_entry . export_name ) ) ;
2022-01-18 18:29:17 +00:00
}
}
}
// b. Else if ee.[[ImportName]] is all-but-default, then
2022-11-23 11:16:51 +00:00
else if ( export_entry . kind = = ExportEntry : : Kind : : ModuleRequestAllButDefault ) {
2022-01-18 18:29:17 +00:00
// i. Assert: ee.[[ExportName]] is null.
VERIFY ( export_entry . export_name . is_null ( ) ) ;
// ii. Append ee to starExportEntries.
star_export_entries . empend ( export_entry ) ;
}
// c. Else,
else {
// i. Append ee to indirectExportEntries.
indirect_export_entries . empend ( export_entry ) ;
}
}
}
// 11. Let async be body Contains await.
bool async = body - > has_top_level_await ( ) ;
// 12. Return Source Text Module Record {
// [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[CycleRoot]]: empty, [[HasTLA]]: async,
// [[AsyncEvaluation]]: false, [[TopLevelCapability]]: empty, [[AsyncParentModules]]: « »,
// [[PendingAsyncDependencies]]: empty, [[Status]]: unlinked, [[EvaluationError]]: empty,
// [[HostDefined]]: hostDefined, [[ECMAScriptCode]]: body, [[Context]]: empty, [[ImportMeta]]: empty,
// [[RequestedModules]]: requestedModules, [[ImportEntries]]: importEntries, [[LocalExportEntries]]: localExportEntries,
// [[IndirectExportEntries]]: indirectExportEntries, [[StarExportEntries]]: starExportEntries, [[DFSIndex]]: empty, [[DFSAncestorIndex]]: empty }.
2022-12-14 17:40:33 +00:00
return realm . heap ( ) . allocate_without_realm < SourceTextModule > (
2022-09-05 12:31:25 +00:00
realm ,
filename ,
2022-10-02 19:18:33 +00:00
host_defined ,
2022-09-05 12:31:25 +00:00
async ,
move ( body ) ,
move ( requested_modules ) ,
move ( import_entries ) ,
move ( local_export_entries ) ,
move ( indirect_export_entries ) ,
move ( star_export_entries ) ,
2022-12-14 17:40:33 +00:00
move ( default_export ) ) ;
2021-09-14 18:51:16 +00:00
}
2022-01-18 18:29:17 +00:00
// 16.2.1.6.2 GetExportedNames ( [ exportStarSet ] ), https://tc39.es/ecma262/#sec-getexportednames
2023-01-09 00:23:00 +00:00
ThrowCompletionOr < Vector < DeprecatedFlyString > > SourceTextModule : : get_exported_names ( VM & vm , Vector < Module * > export_star_set )
2021-09-14 18:51:16 +00:00
{
2022-01-18 18:29:17 +00:00
dbgln_if ( JS_MODULE_DEBUG , " [JS MODULE] get_export_names of {} " , filename ( ) ) ;
2023-12-02 12:02:52 +00:00
// 1. Assert: module.[[Status]] is not new.
VERIFY ( m_status ! = ModuleStatus : : New ) ;
// 2. If exportStarSet is not present, set exportStarSet to a new empty List.
2022-01-18 18:29:17 +00:00
// Note: This is done by default argument
2023-12-02 12:02:52 +00:00
// 3. If exportStarSet contains module, then
2022-01-18 18:29:17 +00:00
if ( export_star_set . contains_slow ( this ) ) {
// a. Assert: We've reached the starting point of an export * circularity.
// FIXME: How do we check that?
// b. Return a new empty List.
2023-01-09 00:23:00 +00:00
return Vector < DeprecatedFlyString > { } ;
2022-01-18 18:29:17 +00:00
}
2023-12-02 12:02:52 +00:00
// 4. Append module to exportStarSet.
2022-01-18 18:29:17 +00:00
export_star_set . append ( this ) ;
2023-12-02 12:02:52 +00:00
// 5. Let exportedNames be a new empty List.
2023-01-09 00:23:00 +00:00
Vector < DeprecatedFlyString > exported_names ;
2022-01-18 18:29:17 +00:00
2023-12-02 12:02:52 +00:00
// 6. For each ExportEntry Record e of module.[[LocalExportEntries]], do
2022-01-18 18:29:17 +00:00
for ( auto & entry : m_local_export_entries ) {
// a. Assert: module provides the direct binding for this export.
// FIXME: How do we check that?
2023-12-02 12:02:52 +00:00
// b. Assert: e.[[ExportName]] is not null.
VERIFY ( ! entry . export_name . is_null ( ) ) ;
// c. Append e.[[ExportName]] to exportedNames.
2022-01-18 18:29:17 +00:00
exported_names . empend ( entry . export_name ) ;
}
2023-12-02 12:02:52 +00:00
// 7. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
2022-01-18 18:29:17 +00:00
for ( auto & entry : m_indirect_export_entries ) {
2023-12-02 12:02:52 +00:00
// a. a. Assert: module imports a specific binding for this export.
2022-01-18 18:29:17 +00:00
// FIXME: How do we check that?
2023-12-02 12:02:52 +00:00
// b. Assert: e.[[ExportName]] is not null.
VERIFY ( ! entry . export_name . is_null ( ) ) ;
// c. Append e.[[ExportName]] to exportedNames.
2022-01-18 18:29:17 +00:00
exported_names . empend ( entry . export_name ) ;
}
2023-12-02 12:02:52 +00:00
// 8. For each ExportEntry Record e of module.[[StarExportEntries]], do
2022-01-18 18:29:17 +00:00
for ( auto & entry : m_star_export_entries ) {
2023-12-02 12:02:52 +00:00
// a. Assert: e.[[ModuleRequest]] is not null.
2023-12-02 12:16:45 +00:00
// b. Let requestedModule be GetImportedModule(module, e.[[ModuleRequest]]).
auto requested_module = get_imported_module ( entry . module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
2023-12-02 12:02:52 +00:00
// c. Let starNames be ? requestedModule.GetExportedNames(exportStarSet).
2022-01-18 18:29:17 +00:00
auto star_names = TRY ( requested_module - > get_exported_names ( vm , export_star_set ) ) ;
2023-12-02 12:02:52 +00:00
// d. For each element n of starNames, do
2022-01-18 18:29:17 +00:00
for ( auto & name : star_names ) {
// i. If SameValue(n, "default") is false, then
if ( name ! = " default " sv ) {
// 1. If n is not an element of exportedNames, then
if ( ! exported_names . contains_slow ( name ) ) {
// a. Append n to exportedNames.
exported_names . empend ( name ) ;
}
}
}
}
2023-12-02 12:02:52 +00:00
// 9. Return exportedNames.
2022-01-18 18:29:17 +00:00
return exported_names ;
2021-09-14 18:51:16 +00:00
}
2022-01-18 18:29:17 +00:00
// 16.2.1.6.4 InitializeEnvironment ( ), https://tc39.es/ecma262/#sec-source-text-module-record-initialize-environment
2022-05-02 18:54:39 +00:00
ThrowCompletionOr < void > SourceTextModule : : initialize_environment ( VM & vm )
2021-09-14 18:51:16 +00:00
{
2022-01-18 18:29:17 +00:00
// 1. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
for ( auto & entry : m_indirect_export_entries ) {
// a. Let resolution be ? module.ResolveExport(e.[[ExportName]]).
auto resolution = TRY ( resolve_export ( vm , entry . export_name ) ) ;
// b. If resolution is null or ambiguous, throw a SyntaxError exception.
if ( ! resolution . is_valid ( ) )
2022-08-16 19:33:17 +00:00
return vm . throw_completion < SyntaxError > ( ErrorType : : InvalidOrAmbiguousExportEntry , entry . export_name ) ;
2022-01-18 18:29:17 +00:00
// c. Assert: resolution is a ResolvedBinding Record.
VERIFY ( resolution . is_valid ( ) ) ;
}
// 2. Assert: All named exports from module are resolvable.
// Note: We check all the indirect export entries above in step 1 and all
// the local named exports are resolvable by construction.
// 3. Let realm be module.[[Realm]].
// 4. Assert: realm is not undefined.
// Note: This must be true because we use a reference.
// 5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
2022-12-14 17:40:33 +00:00
auto environment = vm . heap ( ) . allocate_without_realm < ModuleEnvironment > ( & realm ( ) . global_environment ( ) ) ;
2022-01-18 18:29:17 +00:00
// 6. Set module.[[Environment]] to env.
set_environment ( environment ) ;
// 7. For each ImportEntry Record in of module.[[ImportEntries]], do
for ( auto & import_entry : m_import_entries ) {
2023-12-02 12:16:45 +00:00
// a. Let importedModule be GetImportedModule(module, in.[[ModuleRequest]]).
auto imported_module = get_imported_module ( import_entry . module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
// b. NOTE: The above call cannot fail because imported module requests are a subset of module.[[RequestedModules]], and these have been resolved earlier in this algorithm.
// c. If in.[[ImportName]] is namespace-object, then
2022-01-27 00:54:47 +00:00
if ( import_entry . is_namespace ) {
2022-01-18 18:29:17 +00:00
// i. Let namespace be ? GetModuleNamespace(importedModule).
auto * namespace_ = TRY ( imported_module - > get_module_namespace ( vm ) ) ;
// ii. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
2022-08-21 14:12:43 +00:00
MUST ( environment - > create_immutable_binding ( vm , import_entry . local_name , true ) ) ;
2022-01-18 18:29:17 +00:00
2022-12-14 12:26:10 +00:00
// iii. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
MUST ( environment - > initialize_binding ( vm , import_entry . local_name , namespace_ , Environment : : InitializeBindingHint : : Normal ) ) ;
2022-01-18 18:29:17 +00:00
}
// d. Else,
else {
// i. Let resolution be ? importedModule.ResolveExport(in.[[ImportName]]).
auto resolution = TRY ( imported_module - > resolve_export ( vm , import_entry . import_name ) ) ;
// ii. If resolution is null or ambiguous, throw a SyntaxError exception.
if ( ! resolution . is_valid ( ) )
2022-08-16 19:33:17 +00:00
return vm . throw_completion < SyntaxError > ( ErrorType : : InvalidOrAmbiguousExportEntry , import_entry . import_name ) ;
2022-01-18 18:29:17 +00:00
// iii. If resolution.[[BindingName]] is namespace, then
if ( resolution . is_namespace ( ) ) {
// 1. Let namespace be ? GetModuleNamespace(resolution.[[Module]]).
auto * namespace_ = TRY ( resolution . module - > get_module_namespace ( vm ) ) ;
// 2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
2022-08-21 14:12:43 +00:00
MUST ( environment - > create_immutable_binding ( vm , import_entry . local_name , true ) ) ;
2022-01-18 18:29:17 +00:00
2022-12-14 12:26:10 +00:00
// 3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace, normal).
MUST ( environment - > initialize_binding ( vm , import_entry . local_name , namespace_ , Environment : : InitializeBindingHint : : Normal ) ) ;
2022-01-18 18:29:17 +00:00
}
// iv. Else,
else {
2022-05-02 18:54:39 +00:00
// 1. Perform env.CreateImportBinding(in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
2022-01-18 18:29:17 +00:00
MUST ( environment - > create_import_binding ( import_entry . local_name , resolution . module , resolution . export_name ) ) ;
}
}
}
// 8. Let moduleContext be a new ECMAScript code execution context.
// Note: this has already been created during the construction of this object.
// 9. Set the Function of moduleContext to null.
// 10. Assert: module.[[Realm]] is not undefined.
// Note: This must be true because we use a reference.
// 11. Set the Realm of moduleContext to module.[[Realm]].
2023-11-27 15:45:45 +00:00
m_execution_context - > realm = & realm ( ) ;
2022-01-18 18:29:17 +00:00
// 12. Set the ScriptOrModule of moduleContext to module.
2023-11-27 15:45:45 +00:00
m_execution_context - > script_or_module = NonnullGCPtr < Module > ( * this ) ;
2022-01-18 18:29:17 +00:00
// 13. Set the VariableEnvironment of moduleContext to module.[[Environment]].
2023-11-27 15:45:45 +00:00
m_execution_context - > variable_environment = environment ;
2022-01-18 18:29:17 +00:00
// 14. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
2023-11-27 15:45:45 +00:00
m_execution_context - > lexical_environment = environment ;
2022-01-18 18:29:17 +00:00
// 15. Set the PrivateEnvironment of moduleContext to null.
// 16. Set module.[[Context]] to moduleContext.
// Note: We're already working on that one.
// 17. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
2023-11-27 15:45:45 +00:00
TRY ( vm . push_execution_context ( * m_execution_context , { } ) ) ;
2022-01-18 18:29:17 +00:00
// 18. Let code be module.[[ECMAScriptCode]].
// 19. Let varDeclarations be the VarScopedDeclarations of code.
// Note: We just loop through them in step 21.
// 20. Let declaredVarNames be a new empty List.
2023-01-09 00:23:00 +00:00
Vector < DeprecatedFlyString > declared_var_names ;
2022-01-18 18:29:17 +00:00
// 21. For each element d of varDeclarations, do
// a. For each element dn of the BoundNames of d, do
2023-02-27 22:13:37 +00:00
// NOTE: Due to the use of MUST with `create_mutable_binding` and `initialize_binding` below,
2023-07-20 15:00:43 +00:00
// an exception should not result from `for_each_var_declared_identifier`.
MUST ( m_ecmascript_code - > for_each_var_declared_identifier ( [ & ] ( auto const & identifier ) {
auto const & name = identifier . string ( ) ;
2022-01-18 18:29:17 +00:00
// i. If dn is not an element of declaredVarNames, then
if ( ! declared_var_names . contains_slow ( name ) ) {
// 1. Perform ! env.CreateMutableBinding(dn, false).
2022-08-21 14:12:43 +00:00
MUST ( environment - > create_mutable_binding ( vm , name , false ) ) ;
2022-01-18 18:29:17 +00:00
2022-12-14 12:26:10 +00:00
// 2. Perform ! env.InitializeBinding(dn, undefined, normal).
MUST ( environment - > initialize_binding ( vm , name , js_undefined ( ) , Environment : : InitializeBindingHint : : Normal ) ) ;
2022-01-18 18:29:17 +00:00
// 3. Append dn to declaredVarNames.
declared_var_names . empend ( name ) ;
}
2023-02-27 22:13:37 +00:00
} ) ) ;
2022-01-18 18:29:17 +00:00
// 22. Let lexDeclarations be the LexicallyScopedDeclarations of code.
// Note: We only loop through them in step 24.
// 23. Let privateEnv be null.
PrivateEnvironment * private_environment = nullptr ;
// 24. For each element d of lexDeclarations, do
2023-02-27 22:13:37 +00:00
// NOTE: Due to the use of MUST in the callback, an exception should not result from `for_each_lexically_scoped_declaration`.
MUST ( m_ecmascript_code - > for_each_lexically_scoped_declaration ( [ & ] ( Declaration const & declaration ) {
2022-01-18 18:29:17 +00:00
// a. For each element dn of the BoundNames of d, do
2023-02-27 22:13:37 +00:00
// NOTE: Due to the use of MUST with `create_immutable_binding`, `create_mutable_binding` and `initialize_binding` below,
2023-07-20 14:40:14 +00:00
// an exception should not result from `for_each_bound_identifier`.
MUST ( declaration . for_each_bound_identifier ( [ & ] ( auto const & identifier ) {
auto const & name = identifier . string ( ) ;
2022-01-18 18:29:17 +00:00
// i. If IsConstantDeclaration of d is true, then
if ( declaration . is_constant_declaration ( ) ) {
// 1. Perform ! env.CreateImmutableBinding(dn, true).
2022-08-21 14:12:43 +00:00
MUST ( environment - > create_immutable_binding ( vm , name , true ) ) ;
2022-01-18 18:29:17 +00:00
}
// ii. Else,
else {
// 1. Perform ! env.CreateMutableBinding(dn, false).
2022-08-21 14:12:43 +00:00
MUST ( environment - > create_mutable_binding ( vm , name , false ) ) ;
2022-01-18 18:29:17 +00:00
}
// iii. If d is a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
if ( declaration . is_function_declaration ( ) ) {
VERIFY ( is < FunctionDeclaration > ( declaration ) ) ;
auto const & function_declaration = static_cast < FunctionDeclaration const & > ( declaration ) ;
// 1. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
2022-09-01 22:46:37 +00:00
// NOTE: Special case if the function is a default export of an anonymous function
// it has name "*default*" but internally should have name "default".
2023-01-09 00:23:00 +00:00
DeprecatedFlyString function_name = function_declaration . name ( ) ;
2022-09-01 22:46:37 +00:00
if ( function_name = = ExportStatement : : local_name_for_default )
function_name = " default " sv ;
2023-07-05 15:17:16 +00:00
auto function = ECMAScriptFunctionObject : : create ( realm ( ) , function_name , function_declaration . source_text ( ) , function_declaration . body ( ) , function_declaration . parameters ( ) , function_declaration . function_length ( ) , function_declaration . local_variables_names ( ) , environment , private_environment , function_declaration . kind ( ) , function_declaration . is_strict_mode ( ) , function_declaration . might_need_arguments_object ( ) , function_declaration . contains_direct_call_to_eval ( ) ) ;
2022-01-18 18:29:17 +00:00
2022-12-14 12:26:10 +00:00
// 2. Perform ! env.InitializeBinding(dn, fo, normal).
MUST ( environment - > initialize_binding ( vm , name , function , Environment : : InitializeBindingHint : : Normal ) ) ;
2022-01-18 18:29:17 +00:00
}
2023-02-27 22:13:37 +00:00
} ) ) ;
} ) ) ;
2022-01-18 18:29:17 +00:00
// Note: The default export name is also part of the local lexical declarations but
// instead of making that a special case in the parser we just check it here.
// This is only needed for things which are not declarations.
// For more info check Parser::parse_export_statement.
// Furthermore, that declaration is not constant. so we take 24.a.ii
if ( m_default_export ) {
VERIFY ( m_default_export - > has_statement ( ) ) ;
auto const & statement = m_default_export - > statement ( ) ;
if ( ! is < Declaration > ( statement ) ) {
auto const & name = m_default_export - > entries ( ) [ 0 ] . local_or_import_name ;
dbgln_if ( JS_MODULE_DEBUG , " [JS MODULE] Adding default export to lexical declarations: local name: {}, Expression: {} " , name , statement . class_name ( ) ) ;
// 1. Perform ! env.CreateMutableBinding(dn, false).
2022-08-21 14:12:43 +00:00
MUST ( environment - > create_mutable_binding ( vm , name , false ) ) ;
2022-01-18 18:29:17 +00:00
// Note: Since this is not a function declaration 24.a.iii never applies
}
}
// 25. Remove moduleContext from the execution context stack.
vm . pop_execution_context ( ) ;
2022-05-02 18:54:39 +00:00
// 26. Return unused.
return { } ;
2022-01-18 18:29:17 +00:00
}
// 16.2.1.6.3 ResolveExport ( exportName [ , resolveSet ] ), https://tc39.es/ecma262/#sec-resolveexport
2023-01-09 00:23:00 +00:00
ThrowCompletionOr < ResolvedBinding > SourceTextModule : : resolve_export ( VM & vm , DeprecatedFlyString const & export_name , Vector < ResolvedBinding > resolve_set )
2022-01-18 18:29:17 +00:00
{
2023-12-02 12:08:31 +00:00
// 1. Assert: module.[[Status]] is not new.
VERIFY ( m_status ! = ModuleStatus : : New ) ;
// 2. If resolveSet is not present, set resolveSet to a new empty List.
2022-01-18 18:29:17 +00:00
// Note: This is done by the default argument.
2023-12-02 12:08:31 +00:00
// 3. For each Record { [[Module]], [[ExportName]] } r of resolveSet, do
2022-01-18 18:29:17 +00:00
for ( auto & [ type , module , exported_name ] : resolve_set ) {
// a. If module and r.[[Module]] are the same Module Record and SameValue(exportName, r.[[ExportName]]) is true, then
if ( module = = this & & exported_name = = export_name ) {
// i. Assert: This is a circular import request.
// ii. Return null.
return ResolvedBinding : : null ( ) ;
}
}
2023-12-02 12:08:31 +00:00
// 4. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveSet.
2022-01-18 18:29:17 +00:00
resolve_set . append ( { ResolvedBinding : : Type : : BindingName , this , export_name } ) ;
2023-12-02 12:08:31 +00:00
// 5. For each ExportEntry Record e of module.[[LocalExportEntries]], do
2022-01-18 18:29:17 +00:00
for ( auto & entry : m_local_export_entries ) {
// a. If SameValue(exportName, e.[[ExportName]]) is true, then
if ( export_name ! = entry . export_name )
continue ;
// i. Assert: module provides the direct binding for this export.
// FIXME: What does this mean?
// ii. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }.
return ResolvedBinding {
ResolvedBinding : : Type : : BindingName ,
this ,
entry . local_or_import_name ,
} ;
}
// 5. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
for ( auto & entry : m_indirect_export_entries ) {
// a. If SameValue(exportName, e.[[ExportName]]) is true, then
if ( export_name ! = entry . export_name )
continue ;
2023-12-02 12:08:31 +00:00
// i. Assert: e.[[ModuleRequest]] is not null.
2023-12-02 12:16:45 +00:00
// ii. Let importedModule be GetImportedModule(module, e.[[ModuleRequest]]).
auto imported_module = get_imported_module ( entry . module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
2023-12-02 12:08:31 +00:00
// iii. If e.[[ImportName]] is all, then
2022-11-23 11:16:51 +00:00
if ( entry . kind = = ExportEntry : : Kind : : ModuleRequestAll ) {
2022-01-18 18:29:17 +00:00
// 1. Assert: module does not provide the direct binding for this export.
// FIXME: What does this mean? / How do we check this
// 2. Return ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }.
return ResolvedBinding {
ResolvedBinding : : Type : : Namespace ,
imported_module . ptr ( ) ,
{ }
} ;
}
2023-12-02 12:08:31 +00:00
// iv. Else,
2022-01-18 18:29:17 +00:00
else {
// 1. Assert: module imports a specific binding for this export.
// FIXME: What does this mean? / How do we check this
2022-05-02 18:54:39 +00:00
// 2. Return ? importedModule.ResolveExport(e.[[ImportName]], resolveSet).
2022-01-18 18:29:17 +00:00
return imported_module - > resolve_export ( vm , entry . local_or_import_name , resolve_set ) ;
}
}
2023-12-02 12:08:31 +00:00
// 7. If SameValue(exportName, "default") is true, then
2022-01-18 18:29:17 +00:00
if ( export_name = = " default " sv ) {
// a. Assert: A default export was not explicitly defined by this module.
// FIXME: What does this mean? / How do we check this
// b. Return null.
return ResolvedBinding : : null ( ) ;
// c. NOTE: A default export cannot be provided by an export * from "mod" declaration.
}
2023-12-02 12:08:31 +00:00
// 8. Let starResolution be null.
2022-01-18 18:29:17 +00:00
ResolvedBinding star_resolution = ResolvedBinding : : null ( ) ;
2023-12-02 12:08:31 +00:00
// 9. For each ExportEntry Record e of module.[[StarExportEntries]], do
2022-01-18 18:29:17 +00:00
for ( auto & entry : m_star_export_entries ) {
2023-12-02 12:08:31 +00:00
// a. Assert: e.[[ModuleRequest]] is not null.
2023-12-02 12:16:45 +00:00
// b. Let importedModule be GetImportedModule(module, e.[[ModuleRequest]]).
auto imported_module = get_imported_module ( entry . module_request ( ) ) ;
2022-01-18 18:29:17 +00:00
2023-12-02 12:08:31 +00:00
// c. Let resolution be ? importedModule.ResolveExport(exportName, resolveSet).
2022-01-18 18:29:17 +00:00
auto resolution = TRY ( imported_module - > resolve_export ( vm , export_name , resolve_set ) ) ;
2023-12-02 12:08:31 +00:00
// d. If resolution is ambiguous, return ambiguous.
2022-01-18 18:29:17 +00:00
if ( resolution . is_ambiguous ( ) )
return ResolvedBinding : : ambiguous ( ) ;
2023-12-02 12:08:31 +00:00
// e. If resolution is not null, then
2022-01-18 18:29:17 +00:00
if ( resolution . type = = ResolvedBinding : : Null )
continue ;
// i. Assert: resolution is a ResolvedBinding Record.
VERIFY ( resolution . is_valid ( ) ) ;
// ii. If starResolution is null, set starResolution to resolution.
if ( star_resolution . type = = ResolvedBinding : : Null ) {
star_resolution = resolution ;
}
// iii. Else,
else {
// 1. Assert: There is more than one * import that includes the requested name.
// FIXME: Assert this
// 2. If resolution.[[Module]] and starResolution.[[Module]] are not the same Module Record, return ambiguous.
if ( resolution . module ! = star_resolution . module )
return ResolvedBinding : : ambiguous ( ) ;
// 3. If resolution.[[BindingName]] is namespace and starResolution.[[BindingName]] is not namespace, or if resolution.[[BindingName]] is not namespace and starResolution.[[BindingName]] is namespace, return ambiguous.
if ( resolution . is_namespace ( ) ! = star_resolution . is_namespace ( ) )
return ResolvedBinding : : ambiguous ( ) ;
// 4. If resolution.[[BindingName]] is a String, starResolution.[[BindingName]] is a String, and SameValue(resolution.[[BindingName]], starResolution.[[BindingName]]) is false, return ambiguous.
if ( ! resolution . is_namespace ( ) & & resolution . export_name ! = star_resolution . export_name ) {
// Note: Because we know from the previous if that either both are namespaces or both are string we can check just one
return ResolvedBinding : : ambiguous ( ) ;
}
}
}
2023-12-02 12:08:31 +00:00
// 10. Return starResolution.
2022-01-18 18:29:17 +00:00
return star_resolution ;
}
// 16.2.1.6.5 ExecuteModule ( [ capability ] ), https://tc39.es/ecma262/#sec-source-text-module-record-execute-module
2022-10-02 11:11:30 +00:00
ThrowCompletionOr < void > SourceTextModule : : execute_module ( VM & vm , GCPtr < PromiseCapability > capability )
2022-01-18 18:29:17 +00:00
{
2022-10-02 11:11:30 +00:00
dbgln_if ( JS_MODULE_DEBUG , " [JS MODULE] SourceTextModule::execute_module({}, PromiseCapability @ {}) " , filename ( ) , capability . ptr ( ) ) ;
2022-01-18 18:29:17 +00:00
// 1. Let moduleContext be a new ECMAScript code execution context.
2023-11-27 15:45:45 +00:00
auto module_context = ExecutionContext : : create ( vm . heap ( ) ) ;
2022-01-18 18:29:17 +00:00
// Note: This is not in the spec but we require it.
2023-11-27 15:45:45 +00:00
module_context - > is_strict_mode = true ;
2022-01-18 18:29:17 +00:00
// 2. Set the Function of moduleContext to null.
// 3. Set the Realm of moduleContext to module.[[Realm]].
2023-11-27 15:45:45 +00:00
module_context - > realm = & realm ( ) ;
2022-01-18 18:29:17 +00:00
// 4. Set the ScriptOrModule of moduleContext to module.
2023-11-27 15:45:45 +00:00
module_context - > script_or_module = NonnullGCPtr < Module > ( * this ) ;
2022-01-18 18:29:17 +00:00
// 5. Assert: module has been linked and declarations in its module environment have been instantiated.
2023-12-02 11:38:21 +00:00
VERIFY ( m_status ! = ModuleStatus : : New ) ;
VERIFY ( m_status ! = ModuleStatus : : Unlinked ) ;
VERIFY ( m_status ! = ModuleStatus : : Linking ) ;
VERIFY ( environment ( ) ) ;
2022-01-18 18:29:17 +00:00
// 6. Set the VariableEnvironment of moduleContext to module.[[Environment]].
2023-11-27 15:45:45 +00:00
module_context - > variable_environment = environment ( ) ;
2022-01-18 18:29:17 +00:00
// 7. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
2023-11-27 15:45:45 +00:00
module_context - > lexical_environment = environment ( ) ;
2022-01-18 18:29:17 +00:00
// 8. Suspend the currently running execution context.
// FIXME: We don't have suspend yet
// 9. If module.[[HasTLA]] is false, then
if ( ! m_has_top_level_await ) {
// a. Assert: capability is not present.
2022-10-02 11:11:30 +00:00
VERIFY ( capability = = nullptr ) ;
2022-01-18 18:29:17 +00:00
// b. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
2023-11-27 15:45:45 +00:00
TRY ( vm . push_execution_context ( * module_context , { } ) ) ;
2022-01-18 18:29:17 +00:00
// c. Let result be the result of evaluating module.[[ECMAScriptCode]].
2023-06-24 14:07:15 +00:00
Completion result ;
2024-02-04 07:00:54 +00:00
auto maybe_executable = Bytecode : : compile ( vm , m_ecmascript_code , { } , FunctionKind : : Normal , " ShadowRealmEval " sv ) ;
2023-08-07 17:59:00 +00:00
if ( maybe_executable . is_error ( ) )
result = maybe_executable . release_error ( ) ;
else {
auto executable = maybe_executable . release_value ( ) ;
2023-09-21 07:26:32 +00:00
auto value_and_frame = vm . bytecode_interpreter ( ) . run_and_return_frame ( * executable , nullptr ) ;
2023-08-07 17:59:00 +00:00
if ( value_and_frame . value . is_error ( ) ) {
result = value_and_frame . value . release_error ( ) ;
} else {
// Resulting value is in the accumulator.
2023-11-27 16:27:51 +00:00
result = value_and_frame . frame - > registers ( ) [ 0 ] . value_or ( js_undefined ( ) ) ;
2023-06-24 14:07:15 +00:00
}
}
2022-01-18 18:29:17 +00:00
2022-12-20 21:09:57 +00:00
// d. Let env be moduleContext's LexicalEnvironment.
2023-11-27 15:45:45 +00:00
auto env = module_context - > lexical_environment ;
2022-12-20 21:09:57 +00:00
VERIFY ( is < DeclarativeEnvironment > ( * env ) ) ;
// e. Set result to DisposeResources(env, result).
2023-02-26 23:09:02 +00:00
result = dispose_resources ( vm , static_cast < DeclarativeEnvironment * > ( env . ptr ( ) ) , result ) ;
2022-12-20 21:09:57 +00:00
// f. Suspend moduleContext and remove it from the execution context stack.
2022-01-18 18:29:17 +00:00
vm . pop_execution_context ( ) ;
2022-12-20 21:09:57 +00:00
// g. Resume the context that is now on the top of the execution context stack as the running execution context.
2022-01-18 18:29:17 +00:00
// FIXME: We don't have resume yet.
2022-12-20 21:09:57 +00:00
// h. If result is an abrupt completion, then
2022-05-02 18:54:39 +00:00
if ( result . is_error ( ) ) {
// i. Return ? result.
2023-06-24 14:07:15 +00:00
return result . release_error ( ) ;
2022-05-02 18:54:39 +00:00
}
2022-01-18 18:29:17 +00:00
}
// 10. Else,
2022-05-02 18:54:39 +00:00
else {
// a. Assert: capability is a PromiseCapability Record.
2022-10-02 11:11:30 +00:00
VERIFY ( capability ! = nullptr ) ;
2022-01-18 18:29:17 +00:00
2022-05-02 18:54:39 +00:00
// b. Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
2023-12-06 10:35:40 +00:00
// AD-HOC: We implement asynchronous execution via synthetic generator functions,
// so we fake "AsyncBlockStart" here by creating an async function to wrap
// the top-level module code.
// FIXME: Improve this situation, so we can match the spec better.
auto module_wrapper_function = ECMAScriptFunctionObject : : create (
realm ( ) , " module code with top-level await " , StringView { } , this - > m_ecmascript_code ,
{ } , 0 , { } , environment ( ) , nullptr , FunctionKind : : Async , true , false , false ) ;
module_wrapper_function - > set_is_module_wrapper ( true ) ;
// AD-HOC: We push/pop the moduleContext around the call to ensure that the async execution context
// captures the module execution context.
vm . push_execution_context ( * module_context ) ;
auto result = call ( vm , Value { module_wrapper_function } , js_undefined ( ) , ReadonlySpan < Value > { } ) ;
vm . pop_execution_context ( ) ;
// AD-HOC: This is basically analogous to what AsyncBlockStart would do.
if ( result . is_throw_completion ( ) ) {
MUST ( call ( vm , * capability - > reject ( ) , js_undefined ( ) , result . throw_completion ( ) . value ( ) . value ( ) ) ) ;
} else {
MUST ( call ( vm , * capability - > resolve ( ) , js_undefined ( ) , result . value ( ) ) ) ;
}
2022-05-02 18:54:39 +00:00
}
2022-01-18 18:29:17 +00:00
2022-05-02 18:54:39 +00:00
// 11. Return unused.
return { } ;
2021-09-14 18:51:16 +00:00
}
}