mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 23:37:36 +00:00
LibJS+LibWeb: Make CyclicModule & GraphLoadingState GC-allocated
This allows them to participate in the ownership graph and fixes a lifetime issue in module loading found by ASAN. Co-Authored-By: networkException <networkexception@serenityos.org>
This commit is contained in:
parent
aa7501a66a
commit
0817d8bda6
6 changed files with 60 additions and 24 deletions
|
@ -35,8 +35,17 @@ void CyclicModule::visit_edges(Cell::Visitor& visitor)
|
|||
visitor.visit(loaded_module.module);
|
||||
}
|
||||
|
||||
void GraphLoadingState::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(promise_capability);
|
||||
visitor.visit(host_defined);
|
||||
for (auto* module : visited)
|
||||
visitor.visit(*module);
|
||||
}
|
||||
|
||||
// 16.2.1.5.1 LoadRequestedModules ( [ hostDefined ] ), https://tc39.es/ecma262/#sec-LoadRequestedModules
|
||||
PromiseCapability& CyclicModule::load_requested_modules(JS::Realm& realm, Optional<GraphLoadingState::HostDefined> host_defined)
|
||||
PromiseCapability& CyclicModule::load_requested_modules(JS::Realm& realm, GCPtr<GraphLoadingState::HostDefined> host_defined)
|
||||
{
|
||||
// 1. If hostDefined is not present, let hostDefined be EMPTY.
|
||||
// NOTE: The empty state is handled by hostDefined being an optional without value.
|
||||
|
@ -45,7 +54,7 @@ PromiseCapability& CyclicModule::load_requested_modules(JS::Realm& realm, Option
|
|||
auto promise_capability = MUST(new_promise_capability(realm.vm(), realm.intrinsics().promise_constructor()));
|
||||
|
||||
// 3. Let state be the GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: pc, [[HostDefined]]: hostDefined }.
|
||||
auto state = GraphLoadingState { .promise_capability = promise_capability, .is_loading = true, .pending_module_count = 1, .visited = {}, .host_defined = move(host_defined) };
|
||||
auto state = heap().allocate_without_realm<GraphLoadingState>(promise_capability, true, 1, HashTable<CyclicModule*> {}, move(host_defined));
|
||||
|
||||
// 4. Perform InnerModuleLoading(state, module).
|
||||
inner_module_loading(state);
|
||||
|
|
|
@ -25,18 +25,33 @@ enum class ModuleStatus {
|
|||
class CyclicModule;
|
||||
|
||||
// https://tc39.es/ecma262/#graphloadingstate-record
|
||||
struct GraphLoadingState {
|
||||
struct HostDefined {
|
||||
virtual ~HostDefined() = default;
|
||||
struct GraphLoadingState : public Cell {
|
||||
JS_CELL(GraphLoadingState, Cell);
|
||||
|
||||
virtual void visit_edges(Cell::Visitor&) { }
|
||||
public:
|
||||
struct HostDefined : Cell {
|
||||
JS_CELL(HostDefined, Cell);
|
||||
|
||||
public:
|
||||
virtual ~HostDefined() = default;
|
||||
};
|
||||
|
||||
GCPtr<PromiseCapability> promise_capability; // [[PromiseCapability]]
|
||||
bool is_loading { false }; // [[IsLoading]]
|
||||
size_t pending_module_count { 0 }; // [[PendingModulesCount]]
|
||||
HashTable<CyclicModule*> visited; // [[Visited]]
|
||||
Optional<HostDefined> host_defined; // [[HostDefined]]
|
||||
GCPtr<HostDefined> host_defined; // [[HostDefined]]
|
||||
|
||||
private:
|
||||
GraphLoadingState(GCPtr<PromiseCapability> promise_capability, bool is_loading, size_t pending_module_count, HashTable<CyclicModule*> visited, GCPtr<HostDefined> host_defined)
|
||||
: promise_capability(move(promise_capability))
|
||||
, is_loading(is_loading)
|
||||
, pending_module_count(pending_module_count)
|
||||
, visited(move(visited))
|
||||
, host_defined(move(host_defined))
|
||||
{
|
||||
}
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
};
|
||||
|
||||
// 16.2.1.5 Cyclic Module Records, https://tc39.es/ecma262/#cyclic-module-record
|
||||
|
@ -50,7 +65,7 @@ public:
|
|||
virtual ThrowCompletionOr<void> link(VM& vm) override final;
|
||||
virtual ThrowCompletionOr<Promise*> evaluate(VM& vm) override final;
|
||||
|
||||
virtual PromiseCapability& load_requested_modules(Realm&, Optional<GraphLoadingState::HostDefined>);
|
||||
virtual PromiseCapability& load_requested_modules(Realm&, GCPtr<GraphLoadingState::HostDefined>);
|
||||
virtual void inner_module_loading(GraphLoadingState& state);
|
||||
|
||||
Vector<ModuleRequest> const& requested_modules() const { return m_requested_modules; }
|
||||
|
|
|
@ -228,7 +228,7 @@ public:
|
|||
// Our implementation of this proposal is outdated however, as such we try to adapt the proposal and living standard
|
||||
// to match our implementation for now.
|
||||
// 16.2.1.8 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload ), https://tc39.es/proposal-import-attributes/#sec-HostLoadImportedModule
|
||||
Function<void(Realm&, Variant<NonnullGCPtr<Script>, NonnullGCPtr<CyclicModule>>, ModuleRequest const&, Optional<GraphLoadingState::HostDefined>, GraphLoadingState&)> host_load_imported_module;
|
||||
Function<void(Realm&, Variant<NonnullGCPtr<Script>, NonnullGCPtr<CyclicModule>>, ModuleRequest const&, GCPtr<GraphLoadingState::HostDefined>, GraphLoadingState&)> host_load_imported_module;
|
||||
|
||||
Function<ThrowCompletionOr<NonnullGCPtr<Module>>(ScriptOrModule, ModuleRequest const&)> host_resolve_imported_module;
|
||||
Function<ThrowCompletionOr<void>(ScriptOrModule, ModuleRequest, PromiseCapability const&)> host_import_module_dynamically;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue