Repository: LadybirdBrowser/ladybird
File: Libraries/LibWeb/Bindings/MainThreadVM.cpp (C++)

Code before:
        // 1. Let global be finalizationRegistry.[[Realm]]'s global object.
        auto& global = finalization_registry.realm().global_object();

        // 2. Queue a global task on the JavaScript engine task source given global to perform the following steps:
        HTML::queue_global_task(HTML::Task::Source::JavaScriptEngine, global, GC::create_function(s_main_thread_vm->heap(), [&finalization_registry] {
            // 1. Let entry be finalizationRegistry.[[CleanupCallback]].[[Callback]].[[Realm]].
            auto& entry = *finalization_registry.cleanup_callback().callback().realm();

            // 2. Prepare to run script with entry.
            HTML::prepare_to_run_script(entry);

            // 3. Let result be the result of performing CleanupFinalizationRegistry(finalizationRegistry).
            auto result = finalization_registry.cleanup();

            // 4. Clean up after running script with entry.
            HTML::clean_up_after_running_script(entry);

            // 5. If result is an abrupt completion, then report the exception given by result.[[Value]].
            if (result.is_error())
                HTML::report_exception(result, entry);
        }));
    };

    // 8.1.5.4.3 HostEnqueuePromiseJob(job, realm), https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuepromisejob
    // // https://whatpr.org/html/9893/webappapis.html#hostenqueuepromisejob
    // FIXME: Update this for the latest version of the spec where it uses job settings instead.
    s_main_thread_vm->host_enqueue_promise_job = [](GC::Ref<GC::Function<JS::ThrowCompletionOr<JS::Value>()>> job, JS::Realm* realm) {
        auto& vm = *s_main_thread_vm;

        // IMPLEMENTATION DEFINED: The JS spec says we must take implementation defined steps to make the currently active script or module at the time of HostEnqueuePromiseJob being invoked
        //                         also be the active script or module of the job at the time of its invocation.
        //                         This means taking it here now and passing it through to the lambda.
        auto script_or_module = vm.get_active_script_or_module();

        // 1. Queue a microtask to perform the following steps:
        // This instance of "queue a microtask" uses the "implied document". The best fit for "implied document" here is "If the task is being queued by or for a script, then return the script's settings object's responsible document."
        // Do note that "implied document" from the spec is handwavy and the spec authors are trying to get rid of it: https://github.com/whatwg/html/issues/4980
        auto* script = active_script();

        auto& heap = realm ? realm->heap() : vm.heap();
        HTML::queue_a_microtask(script ? script->settings_object().responsible_document().ptr() : nullptr, GC::create_function(heap, [&vm, realm, job = move(job), script_or_module = move(script_or_module)] {
            // The dummy execution context has to be kept up here to keep it alive for the duration of the function.
            OwnPtr<JS::ExecutionContext> dummy_execution_context;

            if (realm) {
                // 1. If realm is not null, then prepare to run script with realm.
                HTML::prepare_to_run_script(*realm);

                // IMPLEMENTATION DEFINED: Additionally to preparing to run a script, we also prepare to run a callback here. This matches WebIDL's
                //                         invoke_callback() / call_user_object_operation() functions, and prevents a crash in host_make_job_callback()
                //                         when getting the incumbent settings object.

Review comment (suggestion):
If I understand this FIXME properly, this is more-so just the fact that this is implementing the shadow realm proposal integration MR of https://whatpr.org/html/9893/webappapis.html#hostenqueuepromisejob linked above which uses realm instead of settings object since shadow realms do not have a settings object

Code after:
        auto& global = finalization_registry.realm().global_object();

        // 2. Queue a global task on the JavaScript engine task source given global to perform the following steps:
        HTML::queue_global_task(HTML::Task::Source::JavaScriptEngine, global, GC::create_function(s_main_thread_vm->heap(), [&finalization_registry] {
            // 1. Let entry be finalizationRegistry.[[CleanupCallback]].[[Callback]].[[Realm]].
            auto& entry = *finalization_registry.cleanup_callback().callback().realm();

            // 2. Prepare to run script with entry.
            HTML::prepare_to_run_script(entry);

            // 3. Let result be the result of performing CleanupFinalizationRegistry(finalizationRegistry).
            auto result = finalization_registry.cleanup();

            // 4. Clean up after running script with entry.
            HTML::clean_up_after_running_script(entry);

            // 5. If result is an abrupt completion, then report the exception given by result.[[Value]].
            if (result.is_error())
                HTML::report_exception(result, entry);
        }));
    };

    // 8.1.5.4.3 HostEnqueuePromiseJob(job, realm), https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuepromisejob
    // // https://whatpr.org/html/9893/webappapis.html#hostenqueuepromisejob
    s_main_thread_vm->host_enqueue_promise_job = [](GC::Ref<GC::Function<JS::ThrowCompletionOr<JS::Value>()>> job, JS::Realm* realm) {
        auto& vm = *s_main_thread_vm;

        // IMPLEMENTATION DEFINED: The JS spec says we must take implementation defined steps to make the currently active script or module at the time of HostEnqueuePromiseJob being invoked
        //                         also be the active script or module of the job at the time of its invocation.
        //                         This means taking it here now and passing it through to the lambda.
        auto script_or_module = vm.get_active_script_or_module();

        // 1. Queue a microtask to perform the following steps:
        // This instance of "queue a microtask" uses the "implied document". The best fit for "implied document" here is "If the task is being queued by or for a script, then return the script's settings object's responsible document."
        // Do note that "implied document" from the spec is handwavy and the spec authors are trying to get rid of it: https://github.com/whatwg/html/issues/4980
        auto* script = active_script();

        auto& heap = realm ? realm->heap() : vm.heap();
        HTML::queue_a_microtask(script ? script->settings_object().responsible_document().ptr() : nullptr, GC::create_function(heap, [&vm, realm, job = move(job), script_or_module = move(script_or_module)] {
            // The dummy execution context has to be kept up here to keep it alive for the duration of the function.
            OwnPtr<JS::ExecutionContext> dummy_execution_context;

            if (realm) {
                // 1. If realm is not null, then prepare to run script with realm.
                HTML::prepare_to_run_script(*realm);

                // IMPLEMENTATION DEFINED: Additionally to preparing to run a script, we also prepare to run a callback here. This matches WebIDL's
                //                         invoke_callback() / call_user_object_operation() functions, and prevents a crash in host_make_job_callback()
                //                         when getting the incumbent settings object.
                HTML::prepare_to_run_callback(*realm);