Serenity Operating System
1/*
2 * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/DeprecatedFlyString.h>
10#include <AK/Diagnostics.h>
11#include <LibJS/Runtime/VM.h>
12#include <LibWeb/Bindings/PlatformObject.h>
13#include <LibWeb/HTML/Scripting/Environments.h>
14
15namespace Web::WebIDL {
16
17// The following have a legacy code value but *don't* produce it as
18// DOMException.code value when used as name (and are therefore omitted here):
19// - DOMStringSizeError (DOMSTRING_SIZE_ERR = 2)
20// - NoDataAllowedError (NO_DATA_ALLOWED_ERR = 6)
21// - ValidationError (VALIDATION_ERR = 16)
22#define ENUMERATE_DOM_EXCEPTION_LEGACY_CODES \
23 __ENUMERATE(IndexSizeError, 1) \
24 __ENUMERATE(HierarchyRequestError, 3) \
25 __ENUMERATE(WrongDocumentError, 4) \
26 __ENUMERATE(InvalidCharacterError, 5) \
27 __ENUMERATE(NoModificationAllowedError, 7) \
28 __ENUMERATE(NotFoundError, 8) \
29 __ENUMERATE(NotSupportedError, 9) \
30 __ENUMERATE(InUseAttributeError, 10) \
31 __ENUMERATE(InvalidStateError, 11) \
32 __ENUMERATE(SyntaxError, 12) \
33 __ENUMERATE(InvalidModificationError, 13) \
34 __ENUMERATE(NamespaceError, 14) \
35 __ENUMERATE(InvalidAccessError, 15) \
36 __ENUMERATE(TypeMismatchError, 17) \
37 __ENUMERATE(SecurityError, 18) \
38 __ENUMERATE(NetworkError, 19) \
39 __ENUMERATE(AbortError, 20) \
40 __ENUMERATE(URLMismatchError, 21) \
41 __ENUMERATE(QuotaExceededError, 22) \
42 __ENUMERATE(TimeoutError, 23) \
43 __ENUMERATE(InvalidNodeTypeError, 24) \
44 __ENUMERATE(DataCloneError, 25)
45
46// https://webidl.spec.whatwg.org/#idl-DOMException-error-names
47// Same order as in the spec document, also matches the legacy codes order above.
48#define ENUMERATE_DOM_EXCEPTION_ERROR_NAMES \
49 __ENUMERATE(IndexSizeError) /* Deprecated */ \
50 __ENUMERATE(HierarchyRequestError) \
51 __ENUMERATE(WrongDocumentError) \
52 __ENUMERATE(InvalidCharacterError) \
53 __ENUMERATE(NoModificationAllowedError) \
54 __ENUMERATE(NotFoundError) \
55 __ENUMERATE(NotSupportedError) \
56 __ENUMERATE(InUseAttributeError) \
57 __ENUMERATE(InvalidStateError) \
58 __ENUMERATE(SyntaxError) \
59 __ENUMERATE(InvalidModificationError) \
60 __ENUMERATE(NamespaceError) \
61 __ENUMERATE(InvalidAccessError) /* Deprecated */ \
62 __ENUMERATE(TypeMismatchError) /* Deprecated */ \
63 __ENUMERATE(SecurityError) \
64 __ENUMERATE(NetworkError) \
65 __ENUMERATE(AbortError) \
66 __ENUMERATE(URLMismatchError) \
67 __ENUMERATE(QuotaExceededError) \
68 __ENUMERATE(TimeoutError) \
69 __ENUMERATE(InvalidNodeTypeError) \
70 __ENUMERATE(DataCloneError) \
71 __ENUMERATE(EncodingError) \
72 __ENUMERATE(NotReadableError) \
73 __ENUMERATE(UnknownError) \
74 __ENUMERATE(ConstraintError) \
75 __ENUMERATE(DataError) \
76 __ENUMERATE(TransactionInactiveError) \
77 __ENUMERATE(ReadOnlyError) \
78 __ENUMERATE(VersionError) \
79 __ENUMERATE(OperationError) \
80 __ENUMERATE(NotAllowedError)
81
82static u16 get_legacy_code_for_name(DeprecatedFlyString const& name)
83{
84#define __ENUMERATE(ErrorName, code) \
85 if (name == #ErrorName) \
86 return code;
87 ENUMERATE_DOM_EXCEPTION_LEGACY_CODES
88#undef __ENUMERATE
89 return 0;
90}
91
92// https://webidl.spec.whatwg.org/#idl-DOMException
93class DOMException final : public Bindings::PlatformObject {
94 WEB_PLATFORM_OBJECT(DOMException, Bindings::PlatformObject);
95
96public:
97 static JS::NonnullGCPtr<DOMException> create(JS::Realm& realm, DeprecatedFlyString const& name, DeprecatedFlyString const& message);
98
99 // JS constructor has message first, name second
100 // FIXME: This is a completely pointless footgun, let's use the same order for both factories.
101 static JS::NonnullGCPtr<DOMException> construct_impl(JS::Realm& realm, DeprecatedFlyString const& message, DeprecatedFlyString const& name);
102
103 virtual ~DOMException() override;
104
105 DeprecatedFlyString const& name() const { return m_name; }
106 DeprecatedFlyString const& message() const { return m_message; }
107 u16 code() const { return get_legacy_code_for_name(m_name); }
108
109protected:
110 DOMException(JS::Realm&, DeprecatedFlyString const& name, DeprecatedFlyString const& message);
111
112 virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
113
114private:
115 DeprecatedFlyString m_name;
116 DeprecatedFlyString m_message;
117};
118
119#define __ENUMERATE(ErrorName) \
120 class ErrorName final { \
121 public: \
122 static JS::NonnullGCPtr<DOMException> create(JS::Realm& realm, DeprecatedFlyString const& message) \
123 { \
124 return DOMException::create(realm, #ErrorName, message); \
125 } \
126 };
127ENUMERATE_DOM_EXCEPTION_ERROR_NAMES
128#undef __ENUMERATE
129
130}
131
132namespace Web {
133
134inline JS::Completion throw_completion(JS::NonnullGCPtr<WebIDL::DOMException> exception)
135{
136 return JS::throw_completion(JS::Value(static_cast<JS::Object*>(exception.ptr())));
137}
138
139}