Module.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, David Tuin <davidot@serenityos.org>
  4. * Copyright (c) 2023, networkException <networkexception@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <LibJS/CyclicModule.h>
  9. #include <LibJS/Module.h>
  10. #include <LibJS/Runtime/ModuleNamespaceObject.h>
  11. #include <LibJS/Runtime/ModuleRequest.h>
  12. #include <LibJS/Runtime/Promise.h>
  13. #include <LibJS/Runtime/VM.h>
  14. namespace JS {
  15. JS_DEFINE_ALLOCATOR(Module);
  16. Module::Module(Realm& realm, DeprecatedString filename, Script::HostDefined* host_defined)
  17. : m_realm(realm)
  18. , m_host_defined(host_defined)
  19. , m_filename(move(filename))
  20. {
  21. }
  22. Module::~Module() = default;
  23. void Module::visit_edges(Cell::Visitor& visitor)
  24. {
  25. Base::visit_edges(visitor);
  26. visitor.visit(m_realm);
  27. visitor.visit(m_environment);
  28. visitor.visit(m_namespace);
  29. if (m_host_defined)
  30. m_host_defined->visit_host_defined_self(visitor);
  31. }
  32. // 16.2.1.5.1.1 InnerModuleLinking ( module, stack, index ), https://tc39.es/ecma262/#sec-InnerModuleLinking
  33. ThrowCompletionOr<u32> Module::inner_module_linking(VM& vm, Vector<Module*>&, u32 index)
  34. {
  35. // 1. If module is not a Cyclic Module Record, then
  36. // a. Perform ? module.Link().
  37. TRY(link(vm));
  38. // b. Return index.
  39. return index;
  40. }
  41. // 16.2.1.5.2.1 InnerModuleEvaluation ( module, stack, index ), https://tc39.es/ecma262/#sec-innermoduleevaluation
  42. ThrowCompletionOr<u32> Module::inner_module_evaluation(VM& vm, Vector<Module*>&, u32 index)
  43. {
  44. // 1. If module is not a Cyclic Module Record, then
  45. // a. Let promise be ! module.Evaluate().
  46. auto promise = TRY(evaluate(vm));
  47. // b. Assert: promise.[[PromiseState]] is not pending.
  48. VERIFY(promise->state() != Promise::State::Pending);
  49. // c. If promise.[[PromiseState]] is rejected, then
  50. if (promise->state() == Promise::State::Rejected) {
  51. // i. Return ThrowCompletion(promise.[[PromiseResult]]).
  52. return throw_completion(promise->result());
  53. }
  54. // d. Return index.
  55. return index;
  56. }
  57. // 16.2.1.9 FinishLoadingImportedModule ( referrer, specifier, payload, result ), https://tc39.es/ecma262/#sec-FinishLoadingImportedModule
  58. // FIXME: We currently implement an outdated version of https://tc39.es/proposal-import-attributes, as such it is not possible to
  59. // use the exact steps from https://tc39.es/proposal-import-attributes/#sec-HostLoadImportedModule here.
  60. // FIXME: Support Realm for referrer.
  61. void finish_loading_imported_module(Realm& realm, Variant<JS::NonnullGCPtr<JS::Script>, JS::NonnullGCPtr<JS::CyclicModule>> referrer, ModuleRequest const& module_request, GraphLoadingState& payload, ThrowCompletionOr<Module*> const& result)
  62. {
  63. // 1. If result is a normal completion, then
  64. if (!result.is_error()) {
  65. auto loaded_modules = referrer.visit(
  66. [](JS::NonnullGCPtr<JS::Script> script) -> Vector<ModuleWithSpecifier> { return script->loaded_modules(); },
  67. [](JS::NonnullGCPtr<JS::CyclicModule> module) -> Vector<ModuleWithSpecifier> { return module->loaded_modules(); });
  68. bool found_record = false;
  69. // a.a. If referrer.[[LoadedModules]] contains a Record whose [[Specifier]] is specifier, then
  70. for (auto const& record : loaded_modules) {
  71. if (record.specifier == module_request.module_specifier) {
  72. // i. Assert: That Record's [[Module]] is result.[[Value]].
  73. VERIFY(record.module == result.value());
  74. found_record = true;
  75. }
  76. }
  77. // b. Else,
  78. if (!found_record) {
  79. auto* module = const_cast<Module*>(result.value());
  80. // i. Append the Record { [[Specifier]]: specifier, [[Module]]: result.[[Value]] } to referrer.[[LoadedModules]].
  81. loaded_modules.append(ModuleWithSpecifier {
  82. .specifier = module_request.module_specifier,
  83. .module = NonnullGCPtr<Module>(*module) });
  84. }
  85. }
  86. // FIXME: 2. If payload is a GraphLoadingState Record, then
  87. // a. Perform ContinueModuleLoading(payload, result)
  88. continue_module_loading(realm, payload, result);
  89. // FIXME: Else,
  90. // FIXME: a. Perform ContinueDynamicImport(payload, result).
  91. // 4. Return unused.
  92. }
  93. // 16.2.1.10 GetModuleNamespace ( module ), https://tc39.es/ecma262/#sec-getmodulenamespace
  94. ThrowCompletionOr<Object*> Module::get_module_namespace(VM& vm)
  95. {
  96. // 1. Assert: If module is a Cyclic Module Record, then module.[[Status]] is not unlinked.
  97. // FIXME: How do we check this without breaking encapsulation?
  98. // 2. Let namespace be module.[[Namespace]].
  99. auto* namespace_ = m_namespace.ptr();
  100. // 3. If namespace is empty, then
  101. if (!namespace_) {
  102. // a. Let exportedNames be ? module.GetExportedNames().
  103. auto exported_names = TRY(get_exported_names(vm));
  104. // b. Let unambiguousNames be a new empty List.
  105. Vector<DeprecatedFlyString> unambiguous_names;
  106. // c. For each element name of exportedNames, do
  107. for (auto& name : exported_names) {
  108. // i. Let resolution be ? module.ResolveExport(name).
  109. auto resolution = TRY(resolve_export(vm, name));
  110. // ii. If resolution is a ResolvedBinding Record, append name to unambiguousNames.
  111. if (resolution.is_valid())
  112. unambiguous_names.append(name);
  113. }
  114. // d. Set namespace to ModuleNamespaceCreate(module, unambiguousNames).
  115. namespace_ = module_namespace_create(vm, unambiguous_names);
  116. VERIFY(m_namespace);
  117. // Note: This set the local variable 'namespace' and not the member variable which is done by ModuleNamespaceCreate
  118. }
  119. // 4. Return namespace.
  120. return namespace_;
  121. }
  122. // 10.4.6.12 ModuleNamespaceCreate ( module, exports ), https://tc39.es/ecma262/#sec-modulenamespacecreate
  123. Object* Module::module_namespace_create(VM& vm, Vector<DeprecatedFlyString> unambiguous_names)
  124. {
  125. auto& realm = this->realm();
  126. // 1. Assert: module.[[Namespace]] is empty.
  127. VERIFY(!m_namespace);
  128. // 2. Let internalSlotsList be the internal slots listed in Table 34.
  129. // 3. Let M be MakeBasicObject(internalSlotsList).
  130. // 4. Set M's essential internal methods to the definitions specified in 10.4.6.
  131. // 5. Set M.[[Module]] to module.
  132. // 6. Let sortedExports be a List whose elements are the elements of exports ordered as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn.
  133. // 7. Set M.[[Exports]] to sortedExports.
  134. // 8. Create own properties of M corresponding to the definitions in 28.3.
  135. auto module_namespace = vm.heap().allocate<ModuleNamespaceObject>(realm, realm, this, move(unambiguous_names));
  136. // 9. Set module.[[Namespace]] to M.
  137. m_namespace = make_handle(module_namespace);
  138. // 10. Return M.
  139. return module_namespace;
  140. }
  141. }