mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 19:18:12 +00:00
LibWeb: Start implementing "create and initialize a Document" from HTML
The way we've been creating DOM::Document has been pretty far from what the spec tells us to do, and this is a first big step towards getting us closer to spec. The new Document::create_and_initialize() is called by FrameLoader after loading a "text/html" resource. We create the JS Realm and the Window object when creating the Document (previously, we'd do it on first access to Document::interpreter().) The realm execution context is owned by the Environment Settings Object.
This commit is contained in:
parent
0781bdb23e
commit
602f927982
13 changed files with 315 additions and 78 deletions
|
@ -366,4 +366,28 @@ void queue_mutation_observer_microtask(DOM::Document& document)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-new-javascript-realm
|
||||||
|
NonnullOwnPtr<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM& vm, Function<JS::Value(JS::Realm&)> create_global_object, Function<JS::Value(JS::Realm&)> create_global_this_value)
|
||||||
|
{
|
||||||
|
// 1. Perform InitializeHostDefinedRealm() with the provided customizations for creating the global object and the global this binding.
|
||||||
|
// 2. Let realm execution context be the running JavaScript execution context.
|
||||||
|
auto realm_execution_context = MUST(JS::Realm::initialize_host_defined_realm(vm, move(create_global_object), move(create_global_this_value)));
|
||||||
|
|
||||||
|
// 3. Remove realm execution context from the JavaScript execution context stack.
|
||||||
|
vm.execution_context_stack().remove_first_matching([&realm_execution_context](auto* execution_context) {
|
||||||
|
return execution_context == realm_execution_context.ptr();
|
||||||
|
});
|
||||||
|
|
||||||
|
// NO-OP: 4. Let realm be realm execution context's Realm component.
|
||||||
|
// NO-OP: 5. Set realm's agent to agent.
|
||||||
|
|
||||||
|
// FIXME: 6. If agent's agent cluster's cross-origin isolation mode is "none", then:
|
||||||
|
// 1. Let global be realm's global object.
|
||||||
|
// 2. Let status be ! global.[[Delete]]("SharedArrayBuffer").
|
||||||
|
// 3. Assert: status is true.
|
||||||
|
|
||||||
|
// 7. Return realm execution context.
|
||||||
|
return realm_execution_context;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,5 +49,6 @@ struct WebEngineCustomJobCallbackData final : public JS::JobCallback::CustomData
|
||||||
HTML::ClassicScript* active_script();
|
HTML::ClassicScript* active_script();
|
||||||
JS::VM& main_thread_vm();
|
JS::VM& main_thread_vm();
|
||||||
void queue_mutation_observer_microtask(DOM::Document&);
|
void queue_mutation_observer_microtask(DOM::Document&);
|
||||||
|
NonnullOwnPtr<JS::ExecutionContext> create_a_new_javascript_realm(JS::VM&, Function<JS::Value(JS::Realm&)> create_global_object, Function<JS::Value(JS::Realm&)> create_global_this_value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include <LibWeb/HTML/HTMLScriptElement.h>
|
#include <LibWeb/HTML/HTMLScriptElement.h>
|
||||||
#include <LibWeb/HTML/HTMLTitleElement.h>
|
#include <LibWeb/HTML/HTMLTitleElement.h>
|
||||||
#include <LibWeb/HTML/MessageEvent.h>
|
#include <LibWeb/HTML/MessageEvent.h>
|
||||||
|
#include <LibWeb/HTML/NavigationParams.h>
|
||||||
#include <LibWeb/HTML/Origin.h>
|
#include <LibWeb/HTML/Origin.h>
|
||||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||||
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
#include <LibWeb/HTML/Scripting/ExceptionReporter.h>
|
||||||
|
@ -74,6 +75,196 @@
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/origin.html#obtain-browsing-context-navigation
|
||||||
|
static NonnullRefPtr<HTML::BrowsingContext> obtain_a_browsing_context_to_use_for_a_navigation_response(
|
||||||
|
HTML::BrowsingContext& browsing_context,
|
||||||
|
HTML::SandboxingFlagSet sandbox_flags,
|
||||||
|
HTML::CrossOriginOpenerPolicy navigation_coop,
|
||||||
|
HTML::CrossOriginOpenerPolicyEnforcementResult coop_enforcement_result)
|
||||||
|
{
|
||||||
|
// 1. If browsingContext is not a top-level browsing context, return browsingContext.
|
||||||
|
if (!browsing_context.is_top_level())
|
||||||
|
return browsing_context;
|
||||||
|
|
||||||
|
// 2. If coopEnforcementResult's needs a browsing context group switch is false, then:
|
||||||
|
if (!coop_enforcement_result.needs_a_browsing_context_group_switch) {
|
||||||
|
// 1. If coopEnforcementResult's would need a browsing context group switch due to report-only is true,
|
||||||
|
if (coop_enforcement_result.would_need_a_browsing_context_group_switch_due_to_report_only) {
|
||||||
|
// FIXME: set browsing context's virtual browsing context group ID to a new unique identifier.
|
||||||
|
}
|
||||||
|
// 2. Return browsingContext.
|
||||||
|
return browsing_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Let newBrowsingContext be the result of creating a new top-level browsing context.
|
||||||
|
VERIFY(browsing_context.page());
|
||||||
|
auto new_browsing_context = HTML::BrowsingContext::create_a_new_browsing_context(*browsing_context.page(), nullptr, nullptr);
|
||||||
|
|
||||||
|
// FIXME: 4. If navigationCOOP's value is "same-origin-plus-COEP", then set newBrowsingContext's group's
|
||||||
|
// cross-origin isolation mode to either "logical" or "concrete". The choice of which is implementation-defined.
|
||||||
|
|
||||||
|
// 5. If sandboxFlags is not empty, then:
|
||||||
|
if (!sandbox_flags.is_empty()) {
|
||||||
|
// 1. Assert navigationCOOP's value is "unsafe-none".
|
||||||
|
VERIFY(navigation_coop.value == HTML::CrossOriginOpenerPolicyValue::UnsafeNone);
|
||||||
|
|
||||||
|
// 2. Assert: newBrowsingContext's popup sandboxing flag set is empty.
|
||||||
|
|
||||||
|
// 3. Set newBrowsingContext's popup sandboxing flag set to a clone of sandboxFlags.
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: 6. Discard browsingContext.
|
||||||
|
|
||||||
|
// 7. Return newBrowsingContext.
|
||||||
|
return new_browsing_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#initialise-the-document-object
|
||||||
|
NonnullRefPtr<Document> Document::create_and_initialize(Type type, String content_type, HTML::NavigationParams navigation_params)
|
||||||
|
{
|
||||||
|
// 1. Let browsingContext be the result of the obtaining a browsing context to use for a navigation response
|
||||||
|
// given navigationParams's browsing context, navigationParams's final sandboxing flag set,
|
||||||
|
// navigationParams's cross-origin opener policy, and navigationParams's COOP enforcement result.
|
||||||
|
auto browsing_context = obtain_a_browsing_context_to_use_for_a_navigation_response(
|
||||||
|
navigation_params.browsing_context,
|
||||||
|
navigation_params.final_sandboxing_flag_set,
|
||||||
|
navigation_params.cross_origin_opener_policy,
|
||||||
|
navigation_params.coop_enforcement_result);
|
||||||
|
|
||||||
|
// FIXME: 2. Let permissionsPolicy be the result of creating a permissions policy from a response
|
||||||
|
// given browsingContext, navigationParams's origin, and navigationParams's response.
|
||||||
|
|
||||||
|
// 3. Let creationURL be navigationParams's response's URL.
|
||||||
|
auto creation_url = navigation_params.response->url();
|
||||||
|
|
||||||
|
// 4. If navigationParams's request is non-null, then set creationURL to navigationParams's request's current URL.
|
||||||
|
if (navigation_params.request) {
|
||||||
|
creation_url = navigation_params.request->current_url();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<HTML::Window> window;
|
||||||
|
|
||||||
|
// 5. If browsingContext is still on its initial about:blank Document,
|
||||||
|
// and navigationParams's history handling is "replace",
|
||||||
|
// and browsingContext's active document's origin is same origin-domain with navigationParams's origin,
|
||||||
|
// then do nothing.
|
||||||
|
if (browsing_context->still_on_its_initial_about_blank_document()
|
||||||
|
&& navigation_params.history_handling == HTML::HistoryHandlingBehavior::Replace
|
||||||
|
&& (browsing_context->active_document() && browsing_context->active_document()->origin().is_same_origin(navigation_params.origin))) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Otherwise:
|
||||||
|
else {
|
||||||
|
// FIXME: 1. Let oacHeader be the result of getting a structured field value given `Origin-Agent-Cluster` and "item" from response's header list.
|
||||||
|
|
||||||
|
// FIXME: 2. Let requestsOAC be true if oacHeader is not null and oacHeader[0] is the boolean true; otherwise false.
|
||||||
|
[[maybe_unused]] auto requests_oac = false;
|
||||||
|
|
||||||
|
// FIXME: 3. If navigationParams's reserved environment is a non-secure context, then set requestsOAC to false.
|
||||||
|
|
||||||
|
// FIXME: 4. Let agent be the result of obtaining a similar-origin window agent given navigationParams's origin, browsingContext's group, and requestsOAC.
|
||||||
|
|
||||||
|
// 5. Let realm execution context be the result of creating a new JavaScript realm given agent and the following customizations:
|
||||||
|
auto realm_execution_context = Bindings::create_a_new_javascript_realm(
|
||||||
|
Bindings::main_thread_vm(),
|
||||||
|
[&](JS::Realm& realm) -> JS::Value {
|
||||||
|
// - For the global object, create a new Window object.
|
||||||
|
window = HTML::Window::create();
|
||||||
|
auto* global_object = realm.heap().allocate_without_global_object<Bindings::WindowObject>(realm, *window);
|
||||||
|
VERIFY(window->wrapper() == global_object);
|
||||||
|
return global_object;
|
||||||
|
},
|
||||||
|
[](JS::Realm&) -> JS::Value {
|
||||||
|
// FIXME: - For the global this binding, use browsingContext's WindowProxy object.
|
||||||
|
return JS::js_undefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 6. Let topLevelCreationURL be creationURL.
|
||||||
|
auto top_level_creation_url = creation_url;
|
||||||
|
|
||||||
|
// 7. Let topLevelOrigin be navigationParams's origin.
|
||||||
|
auto top_level_origin = navigation_params.origin;
|
||||||
|
|
||||||
|
// 8. If browsingContext is not a top-level browsing context, then:
|
||||||
|
if (!browsing_context->is_top_level()) {
|
||||||
|
// 1. Let parentEnvironment be browsingContext's container's relevant settings object.
|
||||||
|
auto& parent_environment = browsing_context->container()->document().relevant_settings_object();
|
||||||
|
|
||||||
|
// 2. Set topLevelCreationURL to parentEnvironment's top-level creation URL.
|
||||||
|
top_level_creation_url = parent_environment.top_level_creation_url;
|
||||||
|
|
||||||
|
// 3. Set topLevelOrigin to parentEnvironment's top-level origin.
|
||||||
|
top_level_origin = parent_environment.top_level_origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. Set up a window environment settings object with creationURL, realm execution context,
|
||||||
|
// navigationParams's reserved environment, topLevelCreationURL, and topLevelOrigin.
|
||||||
|
|
||||||
|
// FIXME: Why do we assume `creation_url` is non-empty here? Is this a spec bug?
|
||||||
|
// FIXME: Why do we assume `top_level_creation_url` is non-empty here? Is this a spec bug?
|
||||||
|
HTML::WindowEnvironmentSettingsObject::setup(
|
||||||
|
creation_url.value(),
|
||||||
|
move(realm_execution_context),
|
||||||
|
navigation_params.reserved_environment,
|
||||||
|
top_level_creation_url.value(),
|
||||||
|
top_level_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: 7. Let loadTimingInfo be a new document load timing info with its navigation start time set to response's timing info's start time.
|
||||||
|
|
||||||
|
// 8. Let document be a new Document,
|
||||||
|
// whose type is type,
|
||||||
|
// content type is contentType,
|
||||||
|
// FIXME: origin is navigationParams's origin,
|
||||||
|
// FIXME: policy container is navigationParams's policy container,
|
||||||
|
// FIXME: permissions policy is permissionsPolicy,
|
||||||
|
// FIXME: active sandboxing flag set is navigationParams's final sandboxing flag set,
|
||||||
|
// FIXME: and cross-origin opener policy is navigationParams's cross-origin opener policy,
|
||||||
|
// FIXME: load timing info is loadTimingInfo,
|
||||||
|
// FIXME: and navigation id is navigationParams's id.
|
||||||
|
auto document = Document::create();
|
||||||
|
document->m_type = type;
|
||||||
|
document->m_content_type = content_type;
|
||||||
|
|
||||||
|
document->m_window = window;
|
||||||
|
window->set_associated_document(*document);
|
||||||
|
|
||||||
|
// 9. Set document's URL to creationURL.
|
||||||
|
document->m_url = creation_url.value();
|
||||||
|
|
||||||
|
// 10. Set document's current document readiness to "loading".
|
||||||
|
document->m_readiness = HTML::DocumentReadyState::Loading;
|
||||||
|
|
||||||
|
// FIXME: 11. Run CSP initialization for a Document given document.
|
||||||
|
|
||||||
|
// 12. If navigationParams's request is non-null, then:
|
||||||
|
if (navigation_params.request) {
|
||||||
|
// FIXME: 1. Set document's referrer to the empty string.
|
||||||
|
// FIXME: 2. Let referrer be navigationParams's request's referrer.
|
||||||
|
// FIXME: 3. If referrer is a URL record, then set document's referrer to the serialization of referrer.
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: 13. Let historyHandling be navigationParams's history handling.
|
||||||
|
|
||||||
|
// FIXME: 14: Let navigationTimingType be the result of switching on navigationParams's history handling...
|
||||||
|
|
||||||
|
// FIXME: 15. Let redirectCount be 0 if navigationParams's has cross-origin redirects is true;
|
||||||
|
// otherwise navigationParams's request's redirect count.
|
||||||
|
|
||||||
|
// FIXME: 16. Create the navigation timing entry for document, with navigationParams's response's timing info,
|
||||||
|
// redirectCount, navigationTimingType, and navigationParams's response's service worker timing info.
|
||||||
|
|
||||||
|
// FIXME: 17. If navigationParams's response has a `Refresh` header, then...
|
||||||
|
|
||||||
|
// FIXME: 18. If navigationParams's commit early hints is not null, then call navigationParams's commit early hints with document.
|
||||||
|
|
||||||
|
// FIXME: 19. Process link headers given document, navigationParams's response, and "pre-media".
|
||||||
|
|
||||||
|
// 20. Return document.
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Document> Document::create_with_global_object(Bindings::WindowObject&)
|
NonnullRefPtr<Document> Document::create_with_global_object(Bindings::WindowObject&)
|
||||||
{
|
{
|
||||||
return Document::create();
|
return Document::create();
|
||||||
|
@ -891,52 +1082,16 @@ HTML::EnvironmentSettingsObject& Document::relevant_settings_object()
|
||||||
|
|
||||||
JS::Realm& Document::realm()
|
JS::Realm& Document::realm()
|
||||||
{
|
{
|
||||||
return interpreter().realm();
|
VERIFY(m_window);
|
||||||
|
VERIFY(m_window->wrapper());
|
||||||
|
VERIFY(m_window->wrapper()->associated_realm());
|
||||||
|
return *m_window->wrapper()->associated_realm();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Interpreter& Document::interpreter()
|
JS::Interpreter& Document::interpreter()
|
||||||
{
|
{
|
||||||
if (!m_interpreter) {
|
if (!m_interpreter) {
|
||||||
// FIXME: This is all ad-hoc. It loosely follows steps 6.4 to 6.9 of https://html.spec.whatwg.org/#initialise-the-document-object
|
m_interpreter = JS::Interpreter::create_with_existing_realm(realm());
|
||||||
auto& vm = Bindings::main_thread_vm();
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-new-javascript-realm
|
|
||||||
// FIXME: Put all this into it's own function that can be used outside of Document.
|
|
||||||
|
|
||||||
// 1. Perform InitializeHostDefinedRealm() with the provided customizations for creating the global object and the global this binding.
|
|
||||||
// FIXME: Use WindowProxy as the global this value.
|
|
||||||
m_interpreter = JS::Interpreter::create<Bindings::WindowObject>(vm, *m_window);
|
|
||||||
|
|
||||||
// 2. Let realm execution context be the running JavaScript execution context.
|
|
||||||
auto& realm_execution_context = vm.running_execution_context();
|
|
||||||
|
|
||||||
// 3. Remove realm execution context from the JavaScript execution context stack.
|
|
||||||
vm.execution_context_stack().remove_first_matching([&realm_execution_context](auto* execution_context) {
|
|
||||||
return execution_context == &realm_execution_context;
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME: 4. Let realm be realm execution context's Realm component.
|
|
||||||
// FIXME: 5. Set realm's agent to agent.
|
|
||||||
|
|
||||||
// FIXME: 6. If agent's agent cluster's cross-origin isolation mode is "none", then:
|
|
||||||
// 1. Let global be realm's global object.
|
|
||||||
// 2. Let status be ! global.[[Delete]]("SharedArrayBuffer").
|
|
||||||
// 3. Assert: status is true.
|
|
||||||
|
|
||||||
// FIXME: 7. Return realm execution context. (Requires being in it's own function as mentioned above)
|
|
||||||
|
|
||||||
// == End of "create a JavaScript realm" ==
|
|
||||||
|
|
||||||
// FIXME: 6. Let topLevelCreationURL be creationURL.
|
|
||||||
// FIXME: 7. Let topLevelOrigin be navigationParams's origin.
|
|
||||||
// FIXME: 8. If browsingContext is not a top-level browsing context, then:
|
|
||||||
// 1. Let parentEnvironment be browsingContext's container's relevant settings object.
|
|
||||||
// 2. Set topLevelCreationURL to parentEnvironment's top-level creation URL.
|
|
||||||
// 3. Set topLevelOrigin to parentEnvironment's top-level origin.
|
|
||||||
|
|
||||||
// FIXME: 9. Set up a window environment settings object with creationURL, realm execution context, navigationParams's reserved environment, topLevelCreationURL, and topLevelOrigin.
|
|
||||||
// (This is missing reserved environment, topLevelCreationURL and topLevelOrigin. It also assumes creationURL is the document's URL, when it's really "navigationParams's response's URL.")
|
|
||||||
HTML::WindowEnvironmentSettingsObject::setup(m_url, realm_execution_context);
|
|
||||||
}
|
}
|
||||||
return *m_interpreter;
|
return *m_interpreter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,8 @@ public:
|
||||||
HTML
|
HTML
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static NonnullRefPtr<Document> create_and_initialize(Type, String content_type, HTML::NavigationParams);
|
||||||
|
|
||||||
static NonnullRefPtr<Document> create(AK::URL const& url = "about:blank"sv);
|
static NonnullRefPtr<Document> create(AK::URL const& url = "about:blank"sv);
|
||||||
static NonnullRefPtr<Document> create_with_global_object(Bindings::WindowObject&);
|
static NonnullRefPtr<Document> create_with_global_object(Bindings::WindowObject&);
|
||||||
virtual ~Document() override;
|
virtual ~Document() override;
|
||||||
|
|
|
@ -202,6 +202,8 @@ class BrowsingContextContainer;
|
||||||
class CanvasRenderingContext2D;
|
class CanvasRenderingContext2D;
|
||||||
class ClassicScript;
|
class ClassicScript;
|
||||||
class CloseEvent;
|
class CloseEvent;
|
||||||
|
struct CrossOriginOpenerPolicy;
|
||||||
|
struct CrossOriginOpenerPolicyEnforcementResult;
|
||||||
class DOMParser;
|
class DOMParser;
|
||||||
class DOMStringMap;
|
class DOMStringMap;
|
||||||
struct Environment;
|
struct Environment;
|
||||||
|
@ -287,11 +289,13 @@ class ImageData;
|
||||||
class MessageChannel;
|
class MessageChannel;
|
||||||
class MessageEvent;
|
class MessageEvent;
|
||||||
class MessagePort;
|
class MessagePort;
|
||||||
|
struct NavigationParams;
|
||||||
class Origin;
|
class Origin;
|
||||||
class PageTransitionEvent;
|
class PageTransitionEvent;
|
||||||
struct PolicyContainer;
|
struct PolicyContainer;
|
||||||
class PromiseRejectionEvent;
|
class PromiseRejectionEvent;
|
||||||
class WorkerDebugConsoleClient;
|
class WorkerDebugConsoleClient;
|
||||||
|
struct SandboxingFlagSet;
|
||||||
class Storage;
|
class Storage;
|
||||||
class SubmitEvent;
|
class SubmitEvent;
|
||||||
class TextMetrics;
|
class TextMetrics;
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
EnvironmentSettingsObject::EnvironmentSettingsObject(JS::ExecutionContext& realm_execution_context)
|
EnvironmentSettingsObject::EnvironmentSettingsObject(NonnullOwnPtr<JS::ExecutionContext> realm_execution_context)
|
||||||
: m_realm_execution_context(realm_execution_context)
|
: m_realm_execution_context(move(realm_execution_context))
|
||||||
{
|
{
|
||||||
// Register with the responsible event loop so we can perform step 4 of "perform a microtask checkpoint".
|
// Register with the responsible event loop so we can perform step 4 of "perform a microtask checkpoint".
|
||||||
responsible_event_loop().register_environment_settings_object({}, *this);
|
responsible_event_loop().register_environment_settings_object({}, *this);
|
||||||
|
@ -31,7 +31,7 @@ EnvironmentSettingsObject::~EnvironmentSettingsObject()
|
||||||
JS::ExecutionContext& EnvironmentSettingsObject::realm_execution_context()
|
JS::ExecutionContext& EnvironmentSettingsObject::realm_execution_context()
|
||||||
{
|
{
|
||||||
// NOTE: All environment settings objects are created with a realm execution context, so it's stored and returned here in the base class.
|
// NOTE: All environment settings objects are created with a realm execution context, so it's stored and returned here in the base class.
|
||||||
return m_realm_execution_context;
|
return *m_realm_execution_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object%27s-realm
|
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object%27s-realm
|
||||||
|
|
|
@ -105,10 +105,10 @@ struct EnvironmentSettingsObject
|
||||||
bool is_scripting_disabled() const;
|
bool is_scripting_disabled() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit EnvironmentSettingsObject(JS::ExecutionContext& realm_execution_context);
|
explicit EnvironmentSettingsObject(NonnullOwnPtr<JS::ExecutionContext>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JS::ExecutionContext& m_realm_execution_context;
|
NonnullOwnPtr<JS::ExecutionContext> m_realm_execution_context;
|
||||||
EventLoop* m_responsible_event_loop { nullptr };
|
EventLoop* m_responsible_event_loop { nullptr };
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/webappapis.html#outstanding-rejected-promises-weak-set
|
// https://html.spec.whatwg.org/multipage/webappapis.html#outstanding-rejected-promises-weak-set
|
||||||
|
|
|
@ -10,17 +10,17 @@
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
WindowEnvironmentSettingsObject::WindowEnvironmentSettingsObject(Window& window, JS::ExecutionContext& execution_context)
|
WindowEnvironmentSettingsObject::WindowEnvironmentSettingsObject(Window& window, NonnullOwnPtr<JS::ExecutionContext> execution_context)
|
||||||
: EnvironmentSettingsObject(execution_context)
|
: EnvironmentSettingsObject(move(execution_context))
|
||||||
, m_window(window)
|
, m_window(window)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/window-object.html#set-up-a-window-environment-settings-object
|
// https://html.spec.whatwg.org/multipage/window-object.html#set-up-a-window-environment-settings-object
|
||||||
void WindowEnvironmentSettingsObject::setup(AK::URL& creation_url, JS::ExecutionContext& execution_context)
|
void WindowEnvironmentSettingsObject::setup(AK::URL const& creation_url, NonnullOwnPtr<JS::ExecutionContext> execution_context, Optional<Environment> reserved_environment, AK::URL top_level_creation_url, Origin top_level_origin)
|
||||||
{
|
{
|
||||||
// 1. Let realm be the value of execution context's Realm component.
|
// 1. Let realm be the value of execution context's Realm component.
|
||||||
auto* realm = execution_context.realm;
|
auto* realm = execution_context->realm;
|
||||||
VERIFY(realm);
|
VERIFY(realm);
|
||||||
|
|
||||||
// 2. Let window be realm's global object.
|
// 2. Let window be realm's global object.
|
||||||
|
@ -29,17 +29,32 @@ void WindowEnvironmentSettingsObject::setup(AK::URL& creation_url, JS::Execution
|
||||||
|
|
||||||
// 3. Let settings object be a new environment settings object whose algorithms are defined as follows:
|
// 3. Let settings object be a new environment settings object whose algorithms are defined as follows:
|
||||||
// NOTE: See the functions defined for this class.
|
// NOTE: See the functions defined for this class.
|
||||||
auto settings_object = adopt_own(*new WindowEnvironmentSettingsObject(window, execution_context));
|
auto settings_object = adopt_own(*new WindowEnvironmentSettingsObject(window, move(execution_context)));
|
||||||
|
|
||||||
// FIXME: 4. If reservedEnvironment is non-null, then:
|
// 4. If reservedEnvironment is non-null, then:
|
||||||
// FIXME: 1. Set settings object's id to reservedEnvironment's id, target browsing context to reservedEnvironment's target browsing context, and active service worker to reservedEnvironment's active service worker.
|
if (reserved_environment.has_value()) {
|
||||||
// FIXME: 2. Set reservedEnvironment's id to the empty string.
|
// FIXME: 1. Set settings object's id to reservedEnvironment's id,
|
||||||
|
// target browsing context to reservedEnvironment's target browsing context,
|
||||||
|
// and active service worker to reservedEnvironment's active service worker.
|
||||||
|
settings_object->target_browsing_context = reserved_environment->target_browsing_context;
|
||||||
|
|
||||||
// FIXME: 5. Otherwise, set settings object's id to a new unique opaque string, settings object's target browsing context to null, and settings object's active service worker to null.
|
// FIXME: 2. Set reservedEnvironment's id to the empty string.
|
||||||
settings_object->target_browsing_context = nullptr;
|
}
|
||||||
|
|
||||||
// FIXME: 6. Set settings object's creation URL to creationURL, settings object's top-level creation URL to topLevelCreationURL, and settings object's top-level origin to topLevelOrigin.
|
// 5. Otherwise, ...
|
||||||
|
else {
|
||||||
|
// FIXME: ...set settings object's id to a new unique opaque string,
|
||||||
|
// settings object's target browsing context to null,
|
||||||
|
// and settings object's active service worker to null.
|
||||||
|
settings_object->target_browsing_context = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Set settings object's creation URL to creationURL,
|
||||||
|
// settings object's top-level creation URL to topLevelCreationURL,
|
||||||
|
// and settings object's top-level origin to topLevelOrigin.
|
||||||
settings_object->creation_url = creation_url;
|
settings_object->creation_url = creation_url;
|
||||||
|
settings_object->top_level_creation_url = top_level_creation_url;
|
||||||
|
settings_object->top_level_origin = top_level_origin;
|
||||||
|
|
||||||
// 7. Set realm's [[HostDefined]] field to settings object.
|
// 7. Set realm's [[HostDefined]] field to settings object.
|
||||||
realm->set_host_defined(move(settings_object));
|
realm->set_host_defined(move(settings_object));
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Web::HTML {
|
||||||
|
|
||||||
class WindowEnvironmentSettingsObject final : public EnvironmentSettingsObject {
|
class WindowEnvironmentSettingsObject final : public EnvironmentSettingsObject {
|
||||||
public:
|
public:
|
||||||
static void setup(AK::URL& creation_url, JS::ExecutionContext& execution_context /* FIXME: null or an environment reservedEnvironment, a URL topLevelCreationURL, and an origin topLevelOrigin */);
|
static void setup(AK::URL const& creation_url, NonnullOwnPtr<JS::ExecutionContext>, Optional<Environment>, AK::URL top_level_creation_url, Origin top_level_origin);
|
||||||
|
|
||||||
virtual ~WindowEnvironmentSettingsObject() override = default;
|
virtual ~WindowEnvironmentSettingsObject() override = default;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public:
|
||||||
virtual CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() override;
|
virtual CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowEnvironmentSettingsObject(Window&, JS::ExecutionContext& execution_context);
|
WindowEnvironmentSettingsObject(Window&, NonnullOwnPtr<JS::ExecutionContext>);
|
||||||
|
|
||||||
NonnullRefPtr<Window> m_window;
|
NonnullRefPtr<Window> m_window;
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,17 +18,17 @@ class WorkerEnvironmentSettingsObject final
|
||||||
: public EnvironmentSettingsObject
|
: public EnvironmentSettingsObject
|
||||||
, public Weakable<WorkerEnvironmentSettingsObject> {
|
, public Weakable<WorkerEnvironmentSettingsObject> {
|
||||||
public:
|
public:
|
||||||
WorkerEnvironmentSettingsObject(DOM::Document& document, JS::ExecutionContext& execution_context)
|
WorkerEnvironmentSettingsObject(DOM::Document& document, NonnullOwnPtr<JS::ExecutionContext> execution_context)
|
||||||
: EnvironmentSettingsObject(execution_context)
|
: EnvironmentSettingsObject(move(execution_context))
|
||||||
, m_document(document)
|
, m_document(document)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static WeakPtr<WorkerEnvironmentSettingsObject> setup(DOM::Document& document, JS::ExecutionContext& execution_context /* FIXME: null or an environment reservedEnvironment, a URL topLevelCreationURL, and an origin topLevelOrigin */)
|
static WeakPtr<WorkerEnvironmentSettingsObject> setup(DOM::Document& document, NonnullOwnPtr<JS::ExecutionContext> execution_context /* FIXME: null or an environment reservedEnvironment, a URL topLevelCreationURL, and an origin topLevelOrigin */)
|
||||||
{
|
{
|
||||||
auto* realm = execution_context.realm;
|
auto* realm = execution_context->realm;
|
||||||
VERIFY(realm);
|
VERIFY(realm);
|
||||||
auto settings_object = adopt_own(*new WorkerEnvironmentSettingsObject(document, execution_context));
|
auto settings_object = adopt_own(*new WorkerEnvironmentSettingsObject(document, move(execution_context)));
|
||||||
settings_object->target_browsing_context = nullptr;
|
settings_object->target_browsing_context = nullptr;
|
||||||
realm->set_host_defined(move(settings_object));
|
realm->set_host_defined(move(settings_object));
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ Worker::Worker(FlyString const& script_url, WorkerOptions const options, DOM::Do
|
||||||
, m_worker_vm(JS::VM::create(adopt_own(m_custom_data)))
|
, m_worker_vm(JS::VM::create(adopt_own(m_custom_data)))
|
||||||
, m_interpreter(JS::Interpreter::create<JS::GlobalObject>(m_worker_vm))
|
, m_interpreter(JS::Interpreter::create<JS::GlobalObject>(m_worker_vm))
|
||||||
, m_interpreter_scope(*m_interpreter)
|
, m_interpreter_scope(*m_interpreter)
|
||||||
, m_execution_context(m_worker_vm->heap())
|
|
||||||
, m_implicit_port(MessagePort::create())
|
, m_implicit_port(MessagePort::create())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -153,22 +152,23 @@ void Worker::run_a_worker(AK::URL& url, EnvironmentSettingsObject& outside_setti
|
||||||
|
|
||||||
// FIXME: This is because I don't know all the libraries well enough to properly setup the environment to spec
|
// FIXME: This is because I don't know all the libraries well enough to properly setup the environment to spec
|
||||||
// let alone making it a parallel implementation.
|
// let alone making it a parallel implementation.
|
||||||
m_execution_context.current_node = nullptr;
|
auto execution_context = make<JS::ExecutionContext>(m_worker_vm->heap());
|
||||||
m_execution_context.this_value = m_worker_scope;
|
execution_context->current_node = nullptr;
|
||||||
m_execution_context.function_name = "(global execution context)"sv;
|
execution_context->this_value = m_worker_scope;
|
||||||
m_execution_context.lexical_environment = &m_worker_realm->global_environment();
|
execution_context->function_name = "(global execution context)"sv;
|
||||||
m_execution_context.variable_environment = &m_worker_realm->global_environment();
|
execution_context->lexical_environment = &m_worker_realm->global_environment();
|
||||||
m_execution_context.realm = m_worker_realm;
|
execution_context->variable_environment = &m_worker_realm->global_environment();
|
||||||
|
execution_context->realm = m_worker_realm;
|
||||||
|
|
||||||
m_worker_vm->push_execution_context(m_execution_context);
|
m_worker_vm->push_execution_context(*execution_context);
|
||||||
m_worker_realm->set_global_object(*m_worker_scope, m_worker_scope);
|
m_worker_realm->set_global_object(m_worker_scope, m_worker_scope);
|
||||||
|
|
||||||
// 8. Let worker global scope be the global object of realm execution context's Realm component.
|
// 8. Let worker global scope be the global object of realm execution context's Realm component.
|
||||||
// NOTE: This is the DedicatedWorkerGlobalScope or SharedWorkerGlobalScope object created in the previous step.
|
// NOTE: This is the DedicatedWorkerGlobalScope or SharedWorkerGlobalScope object created in the previous step.
|
||||||
|
|
||||||
// 9. Set up a worker environment settings object with realm execution context,
|
// 9. Set up a worker environment settings object with realm execution context,
|
||||||
// outside settings, and unsafeWorkerCreationTime, and let inside settings be the result.
|
// outside settings, and unsafeWorkerCreationTime, and let inside settings be the result.
|
||||||
m_inner_settings = WorkerEnvironmentSettingsObject::setup(*m_document, m_execution_context);
|
m_inner_settings = WorkerEnvironmentSettingsObject::setup(*m_document, move(execution_context));
|
||||||
|
|
||||||
// 10. Set worker global scope's name to the value of options's name member.
|
// 10. Set worker global scope's name to the value of options's name member.
|
||||||
// FIXME: name property requires the SharedWorkerGlobalScope or DedicatedWorkerGlobalScope child class to be used
|
// FIXME: name property requires the SharedWorkerGlobalScope or DedicatedWorkerGlobalScope child class to be used
|
||||||
|
|
|
@ -88,7 +88,6 @@ private:
|
||||||
NonnullOwnPtr<JS::Interpreter> m_interpreter;
|
NonnullOwnPtr<JS::Interpreter> m_interpreter;
|
||||||
WeakPtr<WorkerEnvironmentSettingsObject> m_inner_settings;
|
WeakPtr<WorkerEnvironmentSettingsObject> m_inner_settings;
|
||||||
JS::VM::InterpreterExecutionScope m_interpreter_scope;
|
JS::VM::InterpreterExecutionScope m_interpreter_scope;
|
||||||
JS::ExecutionContext m_execution_context;
|
|
||||||
WeakPtr<JS::Realm> m_worker_realm;
|
WeakPtr<JS::Realm> m_worker_realm;
|
||||||
RefPtr<WorkerDebugConsoleClient> m_console;
|
RefPtr<WorkerDebugConsoleClient> m_console;
|
||||||
JS::GlobalObject* m_worker_scope;
|
JS::GlobalObject* m_worker_scope;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
#include <LibWeb/DOM/Text.h>
|
#include <LibWeb/DOM/Text.h>
|
||||||
#include <LibWeb/HTML/BrowsingContext.h>
|
#include <LibWeb/HTML/BrowsingContext.h>
|
||||||
#include <LibWeb/HTML/HTMLIFrameElement.h>
|
#include <LibWeb/HTML/HTMLIFrameElement.h>
|
||||||
|
#include <LibWeb/HTML/NavigationParams.h>
|
||||||
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
#include <LibWeb/HTML/Parser/HTMLParser.h>
|
||||||
#include <LibWeb/ImageDecoding.h>
|
#include <LibWeb/ImageDecoding.h>
|
||||||
#include <LibWeb/Loader/FrameLoader.h>
|
#include <LibWeb/Loader/FrameLoader.h>
|
||||||
|
@ -253,7 +254,25 @@ bool FrameLoader::load(const AK::URL& url, Type type)
|
||||||
|
|
||||||
void FrameLoader::load_html(StringView html, const AK::URL& url)
|
void FrameLoader::load_html(StringView html, const AK::URL& url)
|
||||||
{
|
{
|
||||||
auto document = DOM::Document::create(url);
|
auto response = make<Fetch::Infrastructure::Response>();
|
||||||
|
response->url_list().append(url);
|
||||||
|
HTML::NavigationParams navigation_params {
|
||||||
|
.id = {},
|
||||||
|
.request = nullptr,
|
||||||
|
.response = move(response),
|
||||||
|
.origin = HTML::Origin {},
|
||||||
|
.policy_container = HTML::PolicyContainer {},
|
||||||
|
.final_sandboxing_flag_set = HTML::SandboxingFlagSet {},
|
||||||
|
.cross_origin_opener_policy = HTML::CrossOriginOpenerPolicy {},
|
||||||
|
.coop_enforcement_result = HTML::CrossOriginOpenerPolicyEnforcementResult {},
|
||||||
|
.reserved_environment = {},
|
||||||
|
.browsing_context = browsing_context(),
|
||||||
|
};
|
||||||
|
auto document = DOM::Document::create_and_initialize(
|
||||||
|
DOM::Document::Type::HTML,
|
||||||
|
"text/html",
|
||||||
|
move(navigation_params));
|
||||||
|
|
||||||
auto parser = HTML::HTMLParser::create(document, html, "utf-8");
|
auto parser = HTML::HTMLParser::create(document, html, "utf-8");
|
||||||
parser->run(url);
|
parser->run(url);
|
||||||
browsing_context().set_active_document(&parser->document());
|
browsing_context().set_active_document(&parser->document());
|
||||||
|
@ -348,7 +367,25 @@ void FrameLoader::resource_did_load()
|
||||||
dbgln_if(RESOURCE_DEBUG, "This content has MIME type '{}', encoding unknown", resource()->mime_type());
|
dbgln_if(RESOURCE_DEBUG, "This content has MIME type '{}', encoding unknown", resource()->mime_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto document = DOM::Document::create();
|
auto response = make<Fetch::Infrastructure::Response>();
|
||||||
|
response->url_list().append(url);
|
||||||
|
HTML::NavigationParams navigation_params {
|
||||||
|
.id = {},
|
||||||
|
.request = nullptr,
|
||||||
|
.response = move(response),
|
||||||
|
.origin = HTML::Origin {},
|
||||||
|
.policy_container = HTML::PolicyContainer {},
|
||||||
|
.final_sandboxing_flag_set = HTML::SandboxingFlagSet {},
|
||||||
|
.cross_origin_opener_policy = HTML::CrossOriginOpenerPolicy {},
|
||||||
|
.coop_enforcement_result = HTML::CrossOriginOpenerPolicyEnforcementResult {},
|
||||||
|
.reserved_environment = {},
|
||||||
|
.browsing_context = browsing_context(),
|
||||||
|
};
|
||||||
|
auto document = DOM::Document::create_and_initialize(
|
||||||
|
DOM::Document::Type::HTML,
|
||||||
|
"text/html",
|
||||||
|
move(navigation_params));
|
||||||
|
|
||||||
document->set_url(url);
|
document->set_url(url);
|
||||||
document->set_encoding(resource()->encoding());
|
document->set_encoding(resource()->encoding());
|
||||||
document->set_content_type(resource()->mime_type());
|
document->set_content_type(resource()->mime_type());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue