mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-19 10:20:22 +00:00
When an async function is resumed from a microtask and hits another await with a non-thenable value (primitive or already-settled native promise), and the microtask queue is empty, we can resolve the await synchronously without suspending. No other microtask can observe the difference in execution order, making this optimization safe. This avoids the overhead of creating a GC::Function for the microtask job, enqueuing/dequeuing from the microtask queue, and the execution context push/pop that comes with it. A new VM host hook, host_promise_job_queue_is_empty, is added so both the standalone js binary and LibWeb can provide the appropriate check for their respective job queue implementations.
43 lines
1.2 KiB
C++
43 lines
1.2 KiB
C++
/*
|
|
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <LibJS/Bytecode/Interpreter.h>
|
|
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
|
#include <LibJS/Runtime/GeneratorObject.h>
|
|
#include <LibJS/Runtime/Object.h>
|
|
#include <LibJS/Runtime/Promise.h>
|
|
|
|
namespace JS {
|
|
|
|
class AsyncFunctionDriverWrapper final : public Promise {
|
|
JS_OBJECT(AsyncFunctionDriverWrapper, Promise);
|
|
GC_DECLARE_ALLOCATOR(AsyncFunctionDriverWrapper);
|
|
|
|
public:
|
|
[[nodiscard]] static GC::Ref<Promise> create(Realm&, GeneratorObject*);
|
|
|
|
virtual ~AsyncFunctionDriverWrapper() override = default;
|
|
void visit_edges(Cell::Visitor&) override;
|
|
|
|
void continue_async_execution(VM&, Value, bool is_successful);
|
|
void schedule_resume(Value, bool is_fulfilled);
|
|
|
|
private:
|
|
AsyncFunctionDriverWrapper(Realm&, GC::Ref<GeneratorObject>, GC::Ref<Promise> top_level_promise);
|
|
ThrowCompletionOr<void> await(Value);
|
|
|
|
GC::Ref<GeneratorObject> m_generator_object;
|
|
GC::Ref<Promise> m_top_level_promise;
|
|
GC::Ptr<Promise> m_current_promise { nullptr };
|
|
OwnPtr<ExecutionContext> m_suspended_execution_context;
|
|
|
|
GC::Ptr<NativeFunction> m_on_settled;
|
|
bool m_is_initial_execution { true };
|
|
};
|
|
|
|
}
|