LibWeb: Re-implement HTML::Navigator using IDL

Get rid of the bespoke NavigatorObject class and use the modern IDL
strategies for creating platform objects to re-implement Navigator and
its associcated mixin interfaces. While we're here, implement it in a
way that brings WorkerNavigator up to spec :^)
This commit is contained in:
Andrew Kaster 2022-10-08 20:53:08 -06:00 committed by Andreas Kling
parent 14e1513077
commit 2d5bee256e
Notes: sideshowbarker 2024-07-17 06:09:30 +09:00
27 changed files with 343 additions and 208 deletions

View file

@ -69,14 +69,12 @@ static ErrorOr<void> generate_exposed_interface_implementation(StringView class_
)~~~");
}
// FIXME: Special case window. We should convert Window, Location, and Navigator to use IDL
// FIXME: Special case window. We should convert Window and Location to use IDL
if (class_name == "Window"sv) {
generator.append(R"~~~(#include <LibWeb/Bindings/WindowConstructor.h>
#include <LibWeb/Bindings/WindowPrototype.h>
#include <LibWeb/Bindings/LocationConstructor.h>
#include <LibWeb/Bindings/LocationPrototype.h>
#include <LibWeb/Bindings/NavigatorConstructor.h>
#include <LibWeb/Bindings/NavigatorPrototype.h>
)~~~");
}
@ -108,12 +106,11 @@ void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global, JS::R
add_interface(gen, interface.name, interface.prototype_class, interface.constructor_class);
}
// FIXME: Special case window. We should convert Window, Location, and Navigator to use IDL
// FIXME: Special case window. We should convert Window and Location to use IDL
if (class_name == "Window"sv) {
auto gen = generator.fork();
add_interface(gen, "Window"sv, "WindowPrototype"sv, "WindowConstructor"sv);
add_interface(gen, "Location"sv, "LocationPrototype"sv, "LocationConstructor"sv);
add_interface(gen, "Navigator"sv, "NavigatorPrototype"sv, "NavigatorConstructor"sv);
}
generator.append(R"~~~(

View file

@ -1,39 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/NavigatorConstructor.h>
#include <LibWeb/Bindings/NavigatorPrototype.h>
namespace Web::Bindings {
NavigatorConstructor::NavigatorConstructor(JS::Realm& realm)
: NativeFunction(*realm.intrinsics().function_prototype())
{
}
NavigatorConstructor::~NavigatorConstructor() = default;
JS::ThrowCompletionOr<JS::Value> NavigatorConstructor::call()
{
return vm().throw_completion<JS::TypeError>(JS::ErrorType::ConstructorWithoutNew, "Navigator");
}
JS::ThrowCompletionOr<JS::Object*> NavigatorConstructor::construct(FunctionObject&)
{
return vm().throw_completion<JS::TypeError>(JS::ErrorType::NotAConstructor, "Navigator");
}
void NavigatorConstructor::initialize(JS::Realm& realm)
{
auto& vm = this->vm();
NativeFunction::initialize(realm);
define_direct_property(vm.names.prototype, &cached_web_prototype(realm, "Navigator"), 0);
define_direct_property(vm.names.length, JS::Value(0), JS::Attribute::Configurable);
}
}

View file

@ -1,28 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/NativeFunction.h>
namespace Web::Bindings {
class NavigatorConstructor : public JS::NativeFunction {
JS_OBJECT(NavigatorConstructor, JS::NativeFunction);
public:
explicit NavigatorConstructor(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual ~NavigatorConstructor() override;
virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::ThrowCompletionOr<JS::Object*> construct(JS::FunctionObject& new_target) override;
private:
virtual bool has_constructor() const override { return true; }
};
}

View file

@ -1,66 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Array.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/NavigatorObject.h>
#include <LibWeb/Bindings/NavigatorPrototype.h>
#include <LibWeb/Loader/ResourceLoader.h>
namespace Web {
namespace Bindings {
NavigatorObject::NavigatorObject(JS::Realm& realm)
: Object(cached_web_prototype(realm, "Navigator"))
{
}
void NavigatorObject::initialize(JS::Realm& realm)
{
auto& heap = this->heap();
auto* languages = MUST(JS::Array::create(realm, 0));
languages->indexed_properties().append(js_string(heap, "en-US"));
// FIXME: All of these should be in Navigator's prototype and be native accessors
u8 attr = JS::Attribute::Configurable | JS::Attribute::Writable | JS::Attribute::Enumerable;
define_direct_property("appCodeName", js_string(heap, "Mozilla"), attr);
define_direct_property("appName", js_string(heap, "Netscape"), attr);
define_direct_property("appVersion", js_string(heap, "4.0"), attr);
define_direct_property("language", languages->get_without_side_effects(0), attr);
define_direct_property("languages", languages, attr);
define_direct_property("platform", js_string(heap, "SerenityOS"), attr);
define_direct_property("product", js_string(heap, "Gecko"), attr);
define_native_accessor(realm, "userAgent", user_agent_getter, {}, JS::Attribute::Configurable | JS::Attribute::Enumerable);
define_native_accessor(realm, "cookieEnabled", cookie_enabled_getter, {}, JS::Attribute::Configurable | JS::Attribute::Enumerable);
define_native_function(realm, "javaEnabled", java_enabled, 0, JS::Attribute::Configurable | JS::Attribute::Enumerable);
// FIXME: Reflect actual connectivity status.
define_direct_property("onLine", JS::Value(true), attr);
}
JS_DEFINE_NATIVE_FUNCTION(NavigatorObject::user_agent_getter)
{
return JS::js_string(vm, ResourceLoader::the().user_agent());
}
JS_DEFINE_NATIVE_FUNCTION(NavigatorObject::cookie_enabled_getter)
{
// No way of disabling cookies right now :^)
return JS::Value(true);
}
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-javaenabled
JS_DEFINE_NATIVE_FUNCTION(NavigatorObject::java_enabled)
{
// The NavigatorPlugins mixin's javaEnabled() method steps are to return false.
return JS::Value(false);
}
}
}

View file

@ -1,30 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Object.h>
#include <LibWeb/Forward.h>
namespace Web {
namespace Bindings {
class NavigatorObject final : public JS::Object {
JS_OBJECT(NavigatorObject, JS::Object);
public:
NavigatorObject(JS::Realm&);
virtual void initialize(JS::Realm&) override;
virtual ~NavigatorObject() override = default;
private:
JS_DECLARE_NATIVE_FUNCTION(user_agent_getter);
JS_DECLARE_NATIVE_FUNCTION(cookie_enabled_getter);
JS_DECLARE_NATIVE_FUNCTION(java_enabled);
};
}
}

View file

@ -1,25 +0,0 @@
/*
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Forward.h>
namespace Web::Bindings {
class NavigatorPrototype final : public JS::Object {
JS_OBJECT(NavigatorPrototype, JS::Object);
public:
explicit NavigatorPrototype(JS::Realm& realm)
: JS::Object(*realm.intrinsics().object_prototype())
{
}
};
}

View file

@ -10,8 +10,6 @@ set(SOURCES
Bindings/LocationConstructor.cpp
Bindings/LocationObject.cpp
Bindings/MainThreadVM.cpp
Bindings/NavigatorConstructor.cpp
Bindings/NavigatorObject.cpp
Bindings/OptionConstructor.cpp
Bindings/PlatformObject.cpp
Bindings/WindowConstructor.cpp
@ -245,6 +243,8 @@ set(SOURCES
HTML/MessageChannel.cpp
HTML/MessageEvent.cpp
HTML/MessagePort.cpp
HTML/Navigator.cpp
HTML/NavigatorID.cpp
HTML/PageTransitionEvent.cpp
HTML/Parser/Entities.cpp
HTML/Parser/HTMLEncodingDetection.cpp

View file

@ -304,6 +304,7 @@ class MessageChannel;
class MessageEvent;
class MessagePort;
struct NavigationParams;
class Navigator;
class Origin;
class PageTransitionEvent;
class Path2D;

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/Navigator.h>
namespace Web::HTML {
JS::NonnullGCPtr<Navigator> Navigator::create(JS::Realm& realm)
{
return *realm.heap().allocate<Navigator>(realm, realm);
}
Navigator::Navigator(JS::Realm& realm)
: PlatformObject(realm)
{
set_prototype(&Bindings::cached_web_prototype(realm, "Navigator"));
}
Navigator::~Navigator() = default;
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/HTML/NavigatorConcurrentHardware.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/HTML/NavigatorLanguage.h>
#include <LibWeb/HTML/NavigatorOnLine.h>
namespace Web::HTML {
class Navigator : public Bindings::PlatformObject
, public NavigatorConcurrentHardwareMixin
, public NavigatorIDMixin
, public NavigatorLanguageMixin
, public NavigatorOnLineMixin {
WEB_PLATFORM_OBJECT(Navigator, Bindings::PlatformObject);
public:
static JS::NonnullGCPtr<Navigator> create(JS::Realm&);
// FIXME: Implement NavigatorContentUtilsMixin
// NavigatorCookies
// FIXME: Hook up to Agent level state
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-cookieenabled
bool cookie_enabled() const { return true; }
// NavigatorPlugins
// FIXME: Actually support pdf viewing
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-javaenabled
bool java_enabled() const { return false; }
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-pdfviewerenabled
bool pdf_viewer_enabled() const { return false; }
virtual ~Navigator() override;
private:
explicit Navigator(JS::Realm&);
};
}

View file

@ -0,0 +1,41 @@
#import <HTML/NavigatorID.idl>
#import <HTML/NavigatorLanguage.idl>
#import <HTML/NavigatorOnLine.idl>
#import <HTML/NavigatorConcurrentHardware.idl>
// https://html.spec.whatwg.org/multipage/system-state.html#navigator
[Exposed=Window]
interface Navigator {
// objects implementing this interface also implement the interfaces given below
};
// NOTE: As NavigatorContentUtils, NavigatorCookies, and NavigatorPlugins are not used in WorkerNavigator,
// we define them here.
// https://html.spec.whatwg.org/multipage/system-state.html#navigatorcontentutils
interface mixin NavigatorContentUtils {
// FIXME: [SecureContext] undefined registerProtocolHandler(DOMString scheme, USVString url);
// FIXME: [SecureContext] undefined unregisterProtocolHandler(DOMString scheme, USVString url);
};
// https://html.spec.whatwg.org/multipage/system-state.html#navigatorcookies
interface mixin NavigatorCookies {
readonly attribute boolean cookieEnabled;
};
// https://html.spec.whatwg.org/multipage/system-state.html#navigatorplugins
interface mixin NavigatorPlugins {
// FIXME: [SameObject] readonly attribute PluginArray plugins;
// FIXME: [SameObject] readonly attribute MimeTypeArray mimeTypes;
boolean javaEnabled();
readonly attribute boolean pdfViewerEnabled;
};
Navigator includes NavigatorID;
Navigator includes NavigatorLanguage;
Navigator includes NavigatorOnLine;
Navigator includes NavigatorContentUtils;
Navigator includes NavigatorCookies;
Navigator includes NavigatorPlugins;
Navigator includes NavigatorConcurrentHardware;

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
namespace Web::HTML {
class NavigatorConcurrentHardwareMixin {
public:
// https://html.spec.whatwg.org/multipage/workers.html#dom-navigator-hardwareconcurrency
unsigned long long hardware_concurrency() { return 1; }
};
}

View file

@ -0,0 +1,4 @@
// https://html.spec.whatwg.org/multipage/workers.html#navigatorconcurrenthardware
interface mixin NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/String.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/Loader/ResourceLoader.h>
namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appversion
String NavigatorIDMixin::app_version() const
{
// Must return the appropriate string that starts with "5.0 (", as follows:
// Let trail be the substring of default `User-Agent` value that follows the "Mozilla/" prefix.
auto user_agent_string = ResourceLoader::the().user_agent();
auto trail = user_agent_string.substring_view(strlen("Mozilla/"), user_agent_string.length() - strlen("Mozilla/"));
// If the navigator compatibility mode is Chrome or WebKit
// NOTE: We are using Chrome for now. Make sure to update all APIs if you add a toggle for this.
// Return trail.
return trail;
// If the navigator compatibility mode is Gecko
// If trail starts with "5.0 (Windows", then return "5.0 (Windows)".
// Otherwise, return the prefix of trail up to but not including the first U+003B (;), concatenated with the
// character U+0029 RIGHT PARENTHESIS. For example, "5.0 (Macintosh)", "5.0 (Android 10)", or "5.0 (X11)".
}
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-platform
String NavigatorIDMixin::platform() const
{
// Must return a string representing the platform on which the browser is executing (e.g. "MacIntel", "Win32",
// "Linux x86_64", "Linux armv81") or, for privacy and compatibility, a string that is commonly returned on another
// platform.
// FIXME: Use some portion of the user agent string to make spoofing work 100%
return "SerenityOS";
}
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-useragent
String NavigatorIDMixin::user_agent() const
{
// Must return the default `User-Agent` value.
return ResourceLoader::the().user_agent();
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
namespace Web::HTML {
class NavigatorIDMixin {
public:
// WARNING: Any information in this API that varies from user to user can be used to profile the user. In fact, if
// enough such information is available, a user can actually be uniquely identified. For this reason, user agent
// implementers are strongly urged to include as little information in this API as possible.
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appcodename
String app_code_name() const { return "Mozilla"sv; }
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appcodename
String app_name() const { return "Netscape"sv; }
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-appversion
String app_version() const;
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-platform
String platform() const;
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-product
String product() const { return "Gecko"sv; }
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-productsub
String product_sub() const { return "20030107"sv; } // Compatability mode "Chrome"
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-useragent
String user_agent() const;
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-vendor
String vendor() const { return "Google Inc."sv; } // Compatability mode "Chrome"
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-vendorsub
String vendor_sub() const { return ""sv; }
// NOTE: If the navigator compatibility mode is Gecko, then the user agent must also support the following partial interface:
// bool taint_enabled()
// String oscpu()
};
}

View file

@ -0,0 +1,12 @@
// https://html.spec.whatwg.org/multipage/system-state.html#navigatorid
interface mixin NavigatorID {
readonly attribute DOMString appCodeName; // constant "Mozilla"
readonly attribute DOMString appName; // constant "Netscape"
readonly attribute DOMString appVersion;
readonly attribute DOMString platform;
readonly attribute DOMString product; // constant "Gecko"
[Exposed=Window] readonly attribute DOMString productSub;
readonly attribute DOMString userAgent;
[Exposed=Window] readonly attribute DOMString vendor;
[Exposed=Window] readonly attribute DOMString vendorSub; // constant ""
};

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
#include <AK/Vector.h>
namespace Web::HTML {
class NavigatorLanguageMixin {
public:
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-language
String language() const { return m_current_preferred_languages[0]; }
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-languages
// FIXME: The same object must be returned until the user agent needs to return different values, or values in a
// different order.
Vector<String> languages() const { return m_current_preferred_languages; }
protected:
Vector<String> m_current_preferred_languages = { "en-US" };
};
}

View file

@ -0,0 +1,7 @@
// https://html.spec.whatwg.org/multipage/system-state.html#navigatorlanguage
interface mixin NavigatorLanguage {
readonly attribute DOMString language;
// FIXME: readonly attribute FrozenArray<DOMString> languages;
// This is supposed to be a FrozenArray that always returns the same object
sequence<DOMString> languages();
};

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
namespace Web::HTML {
class NavigatorOnLineMixin {
public:
// https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator-online
// FIXME: Reflect actual connectivity status.
bool on_line() const { return true; }
};
}

View file

@ -0,0 +1,4 @@
// https://html.spec.whatwg.org/multipage/system-state.html#navigatoronline
interface mixin NavigatorOnLine {
readonly attribute boolean onLine;
};

View file

@ -17,7 +17,6 @@
#include <LibWeb/Bindings/CSSNamespace.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/NavigatorObject.h>
#include <LibWeb/Bindings/Replaceable.h>
#include <LibWeb/Bindings/WindowExposedInterfaces.h>
#include <LibWeb/Bindings/WindowPrototype.h>
@ -33,6 +32,7 @@
#include <LibWeb/HTML/EventHandler.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/Navigator.h>
#include <LibWeb/HTML/Origin.h>
#include <LibWeb/HTML/PageTransitionEvent.h>
#include <LibWeb/HTML/Scripting/ClassicScript.h>
@ -95,6 +95,7 @@ void Window::visit_edges(JS::Cell::Visitor& visitor)
visitor.visit(m_screen.ptr());
visitor.visit(m_location_object);
visitor.visit(m_crypto);
visitor.visit(m_navigator);
for (auto& it : m_timers)
visitor.visit(it.value.ptr());
}
@ -813,9 +814,9 @@ void Window::initialize_web_interfaces(Badge<WindowEnvironmentSettingsObject>)
m_location_object = heap().allocate<Bindings::LocationObject>(realm, realm);
auto* m_navigator_object = heap().allocate<Bindings::NavigatorObject>(realm, realm);
define_direct_property("navigator", m_navigator_object, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_direct_property("clientInformation", m_navigator_object, JS::Attribute::Enumerable | JS::Attribute::Configurable);
m_navigator = heap().allocate<HTML::Navigator>(realm, realm);
define_direct_property("navigator", m_navigator, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_direct_property("clientInformation", m_navigator, JS::Attribute::Enumerable | JS::Attribute::Configurable);
// NOTE: location is marked as [LegacyUnforgeable], meaning it isn't configurable.
define_native_accessor(realm, "location", location_getter, location_setter, JS::Attribute::Enumerable);

View file

@ -157,6 +157,7 @@ private:
JS::GCPtr<HighResolutionTime::Performance> m_performance;
JS::GCPtr<Crypto::Crypto> m_crypto;
JS::GCPtr<CSS::Screen> m_screen;
JS::GCPtr<HTML::Navigator> m_navigator;
AnimationFrameCallbackDriver m_animation_frame_callback_driver;

View file

@ -79,7 +79,6 @@ private:
JS::GCPtr<WorkerLocation> m_location;
// FIXME: Implement WorkerNavigator according to the spec
JS::GCPtr<WorkerNavigator> m_navigator;
// FIXME: Add all these internal slots

View file

@ -5,6 +5,7 @@
*/
#include <LibJS/Heap/Heap.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/WorkerGlobalScope.h>
#include <LibWeb/HTML/WorkerNavigator.h>
@ -18,7 +19,7 @@ JS::NonnullGCPtr<WorkerNavigator> WorkerNavigator::create(WorkerGlobalScope& glo
WorkerNavigator::WorkerNavigator(WorkerGlobalScope& global_scope)
: PlatformObject(global_scope.realm())
{
// FIXME: Set prototype once we can get to worker scope prototypes.
set_prototype(&Bindings::cached_web_prototype(global_scope.realm(), "WorkerNavigator"));
}
WorkerNavigator::~WorkerNavigator() = default;

View file

@ -7,11 +7,18 @@
#pragma once
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/HTML/NavigatorConcurrentHardware.h>
#include <LibWeb/HTML/NavigatorID.h>
#include <LibWeb/HTML/NavigatorLanguage.h>
#include <LibWeb/HTML/NavigatorOnLine.h>
namespace Web::HTML {
// FIXME: Add Mixin APIs from https://html.spec.whatwg.org/multipage/workers.html#the-workernavigator-object
class WorkerNavigator : public Bindings::PlatformObject {
class WorkerNavigator : public Bindings::PlatformObject
, public NavigatorConcurrentHardwareMixin
, public NavigatorIDMixin
, public NavigatorLanguageMixin
, public NavigatorOnLineMixin {
WEB_PLATFORM_OBJECT(WorkerNavigator, Bindings::PlatformObject);
public:

View file

@ -1,8 +1,13 @@
#import <HTML/NavigatorID.idl>
#import <HTML/NavigatorLanguage.idl>
#import <HTML/NavigatorOnLine.idl>
#import <HTML/NavigatorConcurrentHardware.idl>
// https://html.spec.whatwg.org/multipage/workers.html#workernavigator
[Exposed=Worker]
interface WorkerNavigator {};
// FIXME: Add these mixins that are used to prevent duplication b/w WorkerNavigator and Navigator
// WorkerNavigator includes NavigatorID;
// WorkerNavigator includes NavigatorLanguage;
// WorkerNavigator includes NavigatorOnLine;
// WorkerNavigator includes NavigatorConcurrentHardware;
WorkerNavigator includes NavigatorID;
WorkerNavigator includes NavigatorLanguage;
WorkerNavigator includes NavigatorOnLine;
WorkerNavigator includes NavigatorConcurrentHardware;

View file

@ -146,6 +146,7 @@ libweb_js_bindings(HTML/ImageData)
libweb_js_bindings(HTML/MessageChannel)
libweb_js_bindings(HTML/MessageEvent)
libweb_js_bindings(HTML/MessagePort)
libweb_js_bindings(HTML/Navigator)
libweb_js_bindings(HTML/PageTransitionEvent)
libweb_js_bindings(HTML/Path2D)
libweb_js_bindings(HTML/PromiseRejectionEvent)