Skip to content
File

Blob: src/workerd/jsg/dom-exception.h

cpp114 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#pragma once
6 
7#include "jsg.h"
8 
9#define JSG_DOM_EXCEPTION_FOR_EACH_ERROR_NAME(f) \
10 f(INDEX_SIZE_ERR, 1, "IndexSizeError") f(DOMSTRING_SIZE_ERR, 2, "DOMStringSizeError") \
11 f(HIERARCHY_REQUEST_ERR, 3, "HierarchyRequestError") f(WRONG_DOCUMENT_ERR, 4, \
12 "WrongDocumentError") f(INVALID_CHARACTER_ERR, 5, "InvalidCharacterError") \
13 f(NO_DATA_ALLOWED_ERR, 6, "NoDataAllowedError") \
14 f(NO_MODIFICATION_ALLOWED_ERR, 7, "NoModificationAllowedError") f( \
15 NOT_FOUND_ERR, 8, "NotFoundError") f(NOT_SUPPORTED_ERR, 9, "NotSupportedError") \
16 f(INUSE_ATTRIBUTE_ERR, 10, "InUseAttributeError") f( \
17 INVALID_STATE_ERR, 11, "InvalidStateError") f(SYNTAX_ERR, 12, "SyntaxError") \
18 f(INVALID_MODIFICATION_ERR, 13, "InvalidModificationError") f(NAMESPACE_ERR, \
19 14, "NamespaceError") f(INVALID_ACCESS_ERR, 15, "InvalidAccessError") \
20 f(VALIDATION_ERR, 16, "ValidationError") f(TYPE_MISMATCH_ERR, 17, \
21 "TypeMismatchError") f(SECURITY_ERR, 18, "SecurityError") \
22 f(NETWORK_ERR, 19, "NetworkError") f(ABORT_ERR, 20, "AbortError") \
23 f(URL_MISMATCH_ERR, 21, "URLMismatchError") \
24 f(QUOTA_EXCEEDED_ERR, 22, "QuotaExceededError") \
25 f(TIMEOUT_ERR, 23, "TimeoutError") \
26 f(INVALID_NODE_TYPE_ERR, 24, "InvalidNodeTypeError") \
27 f(DATA_CLONE_ERR, 25, "DataCloneError")
28 
29namespace workerd::jsg {
30class Serializer;
31class Deserializer;
32 
33// JSG allows DOMExceptions to be tunneled through kj::Exceptions (see exceptionToJs() for
34// details). While this feature is activated conditionally at run-time, and thus does not depend
35// on any specific concrete C++ type, JSG needs to be able to unit test the tunneled exception
36// functionality, thus the existence of this implementation.
37//
38// Note that DOMException is currently the only user-defined exception to get this special
39// treatment because it is the only non-builtin JS exception that standard web APIs are allowed to
40// throw, per Web IDL.
41//
42// Users of JSG are free (and encouraged) to use this implementation, but they can also opt into
43// the same tunneled exception feature by defining their own globally-accessible type named
44// "DOMException".
45class DOMException: public Object {
46 public:
47 DOMException(kj::String message, kj::String name): message(kj::mv(message)), name(kj::mv(name)) {}
48 
49 // JS API
50 
51 static Ref<DOMException> constructor(const v8::FunctionCallbackInfo<v8::Value>& args,
52 Optional<kj::String> message,
53 Optional<kj::String> name);
54 
55 kj::StringPtr getName() const;
56 kj::StringPtr getMessage() const;
57 int getCode() const;
58 
59#define JSG_DOM_EXCEPTION_CONSTANT_CXX(name, code, friendlyName) static constexpr int name = code;
60#define JSG_DOM_EXCEPTION_CONSTANT_JS(name, code, friendlyName) JSG_STATIC_CONSTANT(name);
61 
62 // Define constexpr codes for every INDEX_SIZE_ERR, DOMSTRING_SIZE_ERR, etc.
63 JSG_DOM_EXCEPTION_FOR_EACH_ERROR_NAME(JSG_DOM_EXCEPTION_CONSTANT_CXX)
64 
65 JSG_RESOURCE_TYPE(DOMException) {
66 JSG_INHERIT_INTRINSIC(v8::kErrorPrototype);
67 
68 // TODO(conform): Per the spec, these should be prototype properties
69 // and not instance properties. Fixing this does require use of the
70 // flags.getJsgPropertyOnPrototypeTemplate() compatibility flag.
71 // The standard definition of DOMException can be found here:
72 // https://webidl.spec.whatwg.org/#idl-DOMException
73 JSG_LAZY_READONLY_INSTANCE_PROPERTY(message, getMessage);
74 JSG_LAZY_READONLY_INSTANCE_PROPERTY(name, getName);
75 JSG_LAZY_READONLY_INSTANCE_PROPERTY(code, getCode);
76 
77 // Declare static JS constants for every INDEX_SIZE_ERR, DOMSTRING_SIZE_ERR, etc.
78 JSG_DOM_EXCEPTION_FOR_EACH_ERROR_NAME(JSG_DOM_EXCEPTION_CONSTANT_JS)
79 
80 JSG_TS_OVERRIDE({
81 get stack(): any;
82 set stack(value: any);
83 });
84 }
85 JSG_REFLECTION(stack);
86 
87#undef JSG_DOM_EXCEPTION_CONSTANT_CXX
88#undef JSG_DOM_EXCEPTION_CONSTANT_JS
89 
90 void visitForMemoryInfo(MemoryTracker& tracker) const {
91 tracker.trackField("message", message);
92 tracker.trackField("name", name);
93 }
94 
95 // TODO(cleanup): The value is taken from worker-interface.capnp, which we can't
96 // depend on directly here because we cannot introduce the dependency into JSG.
97 // Therefore we have to set it manually. A better solution long term is to actually
98 // move DOMException into workerd/api, but we'll do that separately.
99 static constexpr uint SERIALIZATION_TAG = 7;
100 static constexpr uint SERIALIZATION_TAG_V2 = 8;
101 JSG_SERIALIZABLE(SERIALIZATION_TAG_V2, SERIALIZATION_TAG);
102 
103 void serialize(jsg::Lock& js, jsg::Serializer& serializer);
104 static jsg::Ref<DOMException> deserialize(
105 jsg::Lock& js, uint tag, jsg::Deserializer& deserializer);
106 
107 private:
108 kj::String message;
109 kj::String name;
110 PropertyReflection<kj::String> stack;
111};
112 
113} // namespace workerd::jsg