Skip to content
File

Blob: src/workerd/jsg/jsg.h

cpp3159 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// Main public interface to JSG library.
7//
8// Any files declaring an API to export to JavaScript will need to include this header.
9 
10#include "util.h"
11#include "wrappable.h"
12 
13#include <workerd/jsg/exception.h>
14#include <workerd/jsg/macro-meta.h>
15#include <workerd/jsg/memory.h>
16#include <workerd/util/strong-bool.h>
17 
18#include <v8-external-memory-accounter.h>
19#include <v8-forward.h>
20#include <v8-locker.h>
21#include <v8-profiler.h>
22#include <v8-regexp.h>
23 
24#include <capnp/schema-loader.h>
25#include <kj/debug.h>
26#include <kj/exception.h>
27#include <kj/function.h>
28#include <kj/one-of.h>
29#include <kj/string.h>
30#include <kj/time.h>
31 
32using kj::byte;
33using kj::uint;
34 
35#if _MSC_VER
36using ssize_t = long long;
37#endif
38 
39namespace workerd::jsg {
40kj::String stringifyHandle(v8::Local<v8::Value> value);
41}
42 
43namespace v8 {
44// Allows v8 handles to be passed to kj::str() as well as KJ_LOG and related macros.
45template <workerd::jsg::V8Value T>
46kj::String KJ_STRINGIFY(v8::Local<T> value) {
47 return workerd::jsg::stringifyHandle(value);
48}
49} // namespace v8
50 
51namespace workerd::jsg {
52 
53// =======================================================================================
54// Macros for declaring type glue.
55 
56#define JSG_RESOURCE_TYPE(Type, ...) \
57 static constexpr ::workerd::jsg::JsgKind JSG_KIND KJ_UNUSED = ::workerd::jsg::JsgKind::RESOURCE; \
58 using jsgSuper = jsgThis; \
59 using jsgThis = Type; \
60 inline kj::StringPtr jsgGetMemoryName() const override { \
61 return #Type##_kjc; \
62 } \
63 inline size_t jsgGetMemorySelfSize() const override { \
64 return sizeof(Type); \
65 } \
66 inline void jsgGetMemoryInfo(jsg::MemoryTracker& tracker) const override { \
67 const Type* self = static_cast<const Type*>(this); \
68 jsgSuper::jsgGetMemoryInfo(tracker); \
69 ::workerd::jsg::visitSubclassForMemoryInfo<Type>(self, tracker); \
70 } \
71 template <typename> \
72 friend constexpr bool ::workerd::jsg::resourceNeedsGcTracing(); \
73 template <typename T> \
74 friend void ::workerd::jsg::visitSubclassForGc(T* obj, ::workerd::jsg::GcVisitor& visitor); \
75 inline void jsgVisitForGc(::workerd::jsg::GcVisitor& visitor) override { \
76 jsgSuper::jsgVisitForGc(visitor); \
77 ::workerd::jsg::visitSubclassForGc<Type>(this, visitor); \
78 } \
79 static void jsgConfiguration(__VA_ARGS__); \
80 template <typename Registry, typename Self> \
81 static void registerMembers(Registry& registry, ##__VA_ARGS__)
82// Begins a block nested inside a C++ class to declare how that class should be accessible in
83// JavaScript. JSG_RESOURCE_TYPE declares that the class is a "resource type" in KJ parlance.
84//
85// https://github.com/sandstorm-io/capnproto/blob/master/style-guide.md#value-types-vs-resource-types
86//
87// In short, this means that the type is normally passed by reference, and that when JavaScript
88// code accesses members of the type, it calls back into C++. This differs from value types, which
89// are normally deep-copied into JavaScript objects such that C++ is no longer involved.
90//
91// Example usage:
92//
93// class MyApiType: public jsg::Object {
94// // Some type we want to expose to JavaScript.
95// public:
96// static jsg::Ref<MyType> constructor(bool b, kj::String s);
97// // Called when JavaScript invokes `new MyType()`. The name `constructor` is special.
98// // If you do not declare a constructor, then attempts to construct the type from
99// // JavaScript will throw an exception, but you'll still be able to construct it in C++
100// // using the regular C++ constructor(s).
101//
102// void foo(int i, kj::String str);
103// double bar();
104// // Methods that can be called from JavaScript.
105//
106// kj::StringPtr getBaz();
107// void setBaz(kj::String value);
108// // Methods implementing a property.
109//
110// JSG_RESOURCE_TYPE(MyApiType) {
111// JSG_METHOD(foo);
112// JSG_METHOD(bar);
113// JSG_INSTANCE_PROPERTY(baz, getBaz, setBaz);
114// }
115//
116// private:
117// void visitForGc(jsg::GcVisitor visitor);
118// // If this type contains any Ref or Value objects, it must implement visitForGc(), and when
119// // this is called, it must call `visitor.visit()` on all handles that it knows about. If
120// // the object doesn't hold any JS handles then it need not implement this. See the
121// // definition of GcVisitor, below, for more information.
122//
123// jsg::Value someValue;
124// jsg::Ref<MyOtherApiType> someOtherResourceObject;
125// jsg::V8Ref<v8::Map> someState;
126// // Objects of resource type may be destroyed outside of the isolate lock. Therefore, if you
127// // need to hold a reference to a V8 object in a resource type, you should use one of these
128// // classes / class templates. In particular, holding a raw v8::Global<T> may result in
129// // undefined behavior upon destruction.
130// };
131//
132// Notice that method parameters and return types are automatically converted between C++ and
133// JavaScript. You specify the full set of types that your JavaScript execution environment will
134// support when you declare your Isolate (usually in high-level code).
135//
136// Additionally, the following types are always supported:
137// - C++ double, int <-> JS Number
138// - C++ kj::Date <-> JS Date in return position, JS Date or millisecond unix epoch as argument
139// - C++ kj::String, kj::StringPtr <-> JS String
140// - C++ kj::Maybe<T> <-> JS null or T
141// - C++ jsg::Optional<T> <-> JS undefined or T
142// - C++ jsg::LenientOptional<T> <-> JS undefined or T (treats type errors as JS undefined)
143// - C++ kj::OneOf<T, U, ...> <-> JS T or U or ...
144// - C++ kj::Array<T> <-> JS Array of T
145// - C++ kj::Array<byte> <-> JS ArrayBuffer
146// - C++ jsg::Dict<T> <-> JS Object used as a map of strings to values of type T
147// - C++ jsg::Function<T(U, V, ...)> <-> JS Function
148// - C++ jsg::Promise<T> <-> JS Promise
149// - C++ jsg::Ref<T> <-> JavaScript resource type
150// - C++ v8::Local<T> <-> JavaScript value
151//
152// There is also some magic. If the first parameter to a method has type
153// `const v8::FunctionCallbackInfo<v8::Value>&`, then it will receive the FunctionCallbackInfo
154// as passed from V8. (For property accessors, this should be PropertyCallbackInfo instead.) This
155// gives you an escape hatch by which you can directly access the V8 context when needed. In this
156// case the second parameter to your method will correspond to the first parameter passed from
157// JavaScript.
158//
159// As another piece of magic, you can add some special types to the end of your parameter list in
160// order to receive functionality from the JavaScript environment itself. These parameters will not
161// actually correspond to JavaScript parameters, and should always be placed at the end of the
162// argument list. They are:
163//
164// - const jsg::TypeHandler<T>&: Provides callback which can be used to convert between V8 handles
165// and a C++ object of type T, and (for resource types) to allocate objects of type T on the V8
166// heap. The reference is valid only until your method returns.
167// - `v8::Isolate*`: Receives the V8 isolate pointer.
168//
169// In yet more magic, you can add a single configuration parameter to the JSG_RESOURCE_TYPE macro:
170//
171// class MyApiType: ... {
172// public:
173// JSG_RESOURCE_TYPE(MyApiType, uint apiVersion) {
174// if (apiVersion > 42) {
175// using namespace newapi;
176// JSG_NESTED_TYPE(Widget);
177// } else {
178// using namespace oldapi;
179// JSG_NESTED_TYPE(Widget);
180// }
181// }
182// };
183//
184// Populate the configuration parameter by passing it to the JSG isolate's constructor (the type
185// declared by JSG_DECLARE_ISOLATE_TYPE in setup.h).
186//
187// Different resource types may have different configuration types. However, all the configuration
188// types must be constructable from a single "meta" configuration type, which is the type of the
189// configuration passed to the JSG isolate's constructor.
190 
191// Use inside a JSG_RESOURCE_TYPE to declare that the resource type itself can be invoked as
192// a function.
193#define JSG_CALLABLE(name) \
194 do { \
195 registry.template registerCallable<decltype(&Self::name), &Self::name>(); \
196 } while (false)
197 
198// Use inside a JSG_RESOURCE_TYPE block to declare that the given method should be callable from
199// JavaScript on instances of the resource type.
200#define JSG_METHOD(name) \
201 do { \
202 static const char NAME[] = #name; \
203 registry.template registerMethod<NAME, &Self::name>(); \
204 } while (false)
205 
206// Like JSG_METHOD but allows you to specify a different name to use in JavaScript. This is
207// particularly useful when a JavaScript API wants to use a name that is a keyword in C++. For
208// example:
209//
210// JSG_METHOD_NAMED(delete, delete_);
211#define JSG_METHOD_NAMED(name, method) \
212 do { \
213 static const char NAME[] = #name; \
214 registry.template registerMethod<NAME, &Self::method>(); \
215 } while (false)
216 
217// Use inside a JSG_RESOURCE_TYPE block to declare that the given method should be callable from
218// JavaScript on the resource type's constructor.
219#define JSG_STATIC_METHOD(name) \
220 do { \
221 static const char NAME[] = #name; \
222 registry.template registerStaticMethod<NAME, decltype(Self::name), &Self::name>(); \
223 } while (false)
224 
225// Like JSG_METHOD_NAMED, but for static methods.
226#define JSG_STATIC_METHOD_NAMED(name, method) \
227 do { \
228 static const char NAME[] = #name; \
229 registry.template registerStaticMethod<NAME, decltype(Self::method), &Self::method>(); \
230 } while (false)
231 
232// Use inside a JSG_RESOURCE_TYPE block to make objects of this type iterable. Pass in the name of
233// a method returning an object satisfying the requirements of a JavaScript iterator. Note that this
234// will NOT automatically register the method for you -- you still need to use JSG_METHOD{,_NAMED}
235// if you plan to expose the method to JavaScript. For example:
236//
237// struct Iterable {
238// static Iterable constructor();
239// Iterator entries();
240// JSG_RESOURCE_TYPE {
241// JSG_ITERABLE(entries);
242// }
243// };
244//
245// will allow a resource type to be iterated over, but not its entries() function to be called.
246//
247// for (let x of new Iterable()) { /* ... */ } // GOOD
248// for (let x of new Iterable().entries()) { /* ... */ } // BAD!
249//
250// To enable the latter case, you would need to use JSG_METHOD(entries), and make Iterator itself
251// iterable.
252#define JSG_ITERABLE(method) \
253 do { \
254 static const char NAME[] = #method; \
255 registry.template registerIterable<NAME, decltype(&Self::method), &Self::method>(); \
256 } while (false)
257 
258// Use inside a JSG_RESOURCE_TYPE block to make objects of this type async iterable. Pass in the
259// name of a method returning a kj::Promise for an object satisfying the requirements of a
260// JavaScript iterator.
261#define JSG_ASYNC_ITERABLE(method) \
262 do { \
263 static const char NAME[] = #method; \
264 registry.template registerAsyncIterable<NAME, decltype(&Self::method), &Self::method>(); \
265 } while (false)
266 
267// JSG_DISPOSE and JSG_ASYNC_DISPOSE are used to make an object compatible with the
268// JavaScript using and await using keywords (respectively). These allow variables to
269// be defined in such a way that they will have their disposer functions automatically
270// called when the variable goes out of scope, for instance:
271//
272// class Foo { [Symbol.dispose]() { console.log('...'); }}
273// { using foo = new Foo(); }
274//
275// When the containing block exits, the [Symbol.dispose] function will be called on
276// the object, allowing cleanup actions to be performed.
277//
278// There are a number of guidelines that should be followed when implementing
279// disposer methods:
280//
281// 1. Always prefer Symbol.dispose over Symbol.asyncDispose, avoid defining both.
282// 2. Always assume that if the resource needs to be disposed, it's being disposed
283// in an exception case. Clean disposal should always be explicit.
284// 3. At least for the time being, the exception will not be available to the
285// disposer, so it will not be able to propagate the error
286// 4. Always implement disposal as an idempotent operation and remember that
287// users can call the disposer methods directly as many times as they want.
288// 5. Remember that errors thrown from within the disposer will mask the original
289// error using a SupressedError.
290#define JSG_DISPOSE(method) \
291 do { \
292 static const char NAME[] = #method; \
293 registry.template registerDispose<NAME, decltype(&Self::method), &Self::method>(); \
294 } while (false)
295#define JSG_ASYNC_DISPOSE(method) \
296 do { \
297 static const char NAME[] = #method; \
298 registry.template registerAsyncDispose<NAME, decltype(&Self::method), &Self::method>(); \
299 } while (false)
300 
301// Use inside a JSG_RESOURCE_TYPE block to declare a property on this object that should be
302// accessible to JavaScript. `name` is the JavaScript member name, while `getter` and `setter` are
303// the names of C++ methods that get and set this property.
304//
305// WARNING: This is usually not what you want. Usually you want JSG_PROTOTYPE_PROPERTY instead.
306// Note that V8 implements instance properties by modifying the instance immediately after
307// construction, which is inefficient and can break some optimizations. For example, any object
308// with an instance property will not be possible to collect during minor GCs, only major GCs.
309// Prototype properties are on the prototype, so have no runtime overhead until they are used.
310#define JSG_INSTANCE_PROPERTY(name, getter, setter) \
311 do { \
312 static const char NAME[] = #name; \
313 registry.template registerInstanceProperty<NAME, decltype(&Self::getter), &Self::getter, \
314 decltype(&Self::setter), &Self::setter>(); \
315 } while (false)
316 
317// Use inside a JSG_RESOURCE_TYPE block to declare a property on this object's prototype that
318// should be accessible to JavaScript. `name` is the JavaScript member name, while `getter` and
319// `setter` are the names of C++ methods that get and set this property.
320//
321// The key difference between JSG_INSTANCE_PROPERTY and JSG_PROTOTYPE_PROPERTY is in exactly how
322// the getters and setters are attached to created JavaScript object. Specifically,
323// JSG_INSTANCE_PROPERTY is similar to:
324//
325// class Foo1 {
326// constructor() {
327// Object.defineProperty(this, 'bar', {
328// get() { /* ... */ },
329// set(v) { /* ... */ },
330// });
331// }
332// }
333//
334// Whereas JSG_PROTOTYPE_PROPERTY is equivalent to:
335//
336// class Foo2 {
337// get bar() { /* ... */ }
338// set bar(v) { /* ... */ }
339// }
340//
341// The difference here is important because, in the former case, the properties are
342// defined directly on *instances* of Foo1 as own properties, while in latter case,
343// the properties are defined on the prototype of all Foo2 instances. In the former
344// case, using JSG_INSTANCE_PROPERTY, the properties are directly enumerable on all instances
345// of Foo1 such that calling Object.keys(new Foo1()) returns ['bar']. However, calling
346// Object.keys(new Foo2()) will return an empty array [] as prototype properties are
347// not directly enumerable.
348//
349// However, that's not the only critical difference. Because instance properties take
350// precedence over prototype properties, Foo1 is not properly subclassable. If I did:
351//
352// class MyFoo1 extends Foo1 {
353// get bar() { /** .. **/ }
354// }
355//
356// const myFoo1 = new MyFoo1();
357// console.log(myFoo1.bar);
358//
359// The getter specified in the constructor of Foo1 would be called rather than the
360// getter defined in the MyFoo1 class, which is not what a user would expect!
361// This means that any resource type that uses JSG_INSTANCE_PROPERTY to attach properties
362// will not be properly subclassable. To allow subclasses to work correctly, use
363// JSG_PROTOTYPE_PROPERTY instead.
364#define JSG_PROTOTYPE_PROPERTY(name, getter, setter) \
365 do { \
366 static const char NAME[] = #name; \
367 registry.template registerPrototypeProperty<NAME, decltype(&Self::getter), &Self::getter, \
368 decltype(&Self::setter), &Self::setter>(); \
369 } while (false)
370 
371// Like JSG_INSTANCE_PROPERTY but creates a property that will throw an exception if
372// JavaScript tries to assign to it.
373#define JSG_READONLY_INSTANCE_PROPERTY(name, getter) \
374 do { \
375 static const char NAME[] = #name; \
376 registry.template registerReadonlyInstanceProperty<NAME, decltype(&Self::getter), \
377 &Self::getter>(); \
378 } while (false)
379 
380// Like JSG_PROTOTYPE_PROPERTY but creates a property that will throw an exception if JavaScript
381// tries to assign to it.
382#define JSG_READONLY_PROTOTYPE_PROPERTY(name, getter) \
383 do { \
384 static const char NAME[] = #name; \
385 registry.template registerReadonlyPrototypeProperty<NAME, decltype(&Self::getter), \
386 &Self::getter>(); \
387 } while (false)
388 
389// A lazy property will call the getter the first time the property is access but will then
390// replace the property definition with a normal instance property using the returned value.
391// Keep in mind that, as an instance property, these lazily set properties cannot be overridden
392// by subclasses. They are set directly on the instance object itself when it is created.
393#define JSG_LAZY_INSTANCE_PROPERTY(name, getter) \
394 do { \
395 static const char NAME[] = #name; \
396 registry.template registerLazyInstanceProperty<NAME, decltype(&Self::getter), &Self::getter, \
397 false>(); \
398 } while (false)
399 
400#define JSG_LAZY_READONLY_INSTANCE_PROPERTY(name, getter) \
401 do { \
402 static const char NAME[] = #name; \
403 registry.template registerLazyInstanceProperty<NAME, decltype(&Self::getter), &Self::getter, \
404 true>(); \
405 } while (false)
406 
407// Use inside a JSG_RESOURCE_TYPE block to declare a property that should be shown when calling
408// `node:util`'s `inspect()` function on values of this type. These properties will be shown when
409// `console.log()`ing too, and should be used to expose internal state useful for debugging.
410// `name` is the name of the property (displayed in square brackets), while `getter` is the name of
411// the C++ method that gets this property's value.
412#define JSG_INSPECT_PROPERTY(name, getter) \
413 do { \
414 static const char NAME[] = #name; \
415 registry.template registerInspectProperty<NAME, decltype(&Self::getter), &Self::getter>(); \
416 } while (false)
417 
418// Use inside a JSG_RESOURCE_TYPE to expose a static property on the JavaScript constructor.
419// The property will be read-only and will call the specified static function when accessed.
420// The function should take no parameters or take jsg::Lock& as the first parameter.
421// Example:
422// static int getVersion() { return 42; }
423// JSG_RESOURCE_TYPE(MyClass) {
424// JSG_STATIC_READONLY_PROPERTY(getVersion); // Exposes as MyClass.getVersion
425// }
426#define JSG_STATIC_READONLY_PROPERTY(name) \
427 do { \
428 static const char NAME[] = #name; \
429 registry.template registerStaticProperty<NAME, decltype(Self::name), &Self::name>(); \
430 } while (false)
431 
432// Use inside a JSG_RESOURCE_TYPE to expose a static property with a different name than the
433// underlying C++ function. The property will be read-only and will call the specified static
434// getter function when accessed. The getter can optionally take jsg::Lock& as the first parameter.
435// Example:
436// static kj::Array<kj::String> getSupportedTypes() { ... }
437// JSG_RESOURCE_TYPE(MyClass) {
438// JSG_STATIC_READONLY_PROPERTY_NAMED(supportedTypes, getSupportedTypes); // MyClass.supportedTypes
439// }
440#define JSG_STATIC_READONLY_PROPERTY_NAMED(name, getter) \
441 do { \
442 static const char NAME[] = #name; \
443 registry.template registerStaticProperty<NAME, decltype(Self::getter), &Self::getter>(); \
444 } while (false)
445 
446// Use inside a JSG_RESOURCE_TYPE to create a static constant member on the constructor and
447// prototype of this object. Only primitive data types (booleans, strings, numbers) are allowed.
448// Unlike the JSG_INSTANCE_PROPERTY and JSG_READONLY_PROPERTY macros, this does not use a getter
449// -- it expects a static constexpr member of a primitive type available in the class by the same
450// name. For example:
451//
452// struct Interface {
453// static Interface constructor()
454// static constexpr int FOO_BAR = 123;
455// JSG_RESOURCE_TYPE {
456// JSG_STATIC_CONSTANT(FOO_BAR);
457// }
458// };
459//
460// will allow all of the following JS expressions to hold true:
461//
462// Interface.FOO_BAR === 123
463// Interface.prototype.FOO_BAR === 123
464// new Interface().FOO_BAR === 123
465// Object.getPrototypeOf(new Interface()).FOO_BAR === 123
466//
467// This is useful to implement constant interface members as specified in Web IDL:
468// https://heycam.github.io/webidl/#idl-constants
469//
470// TODO(someday): This should probably also support the null JS value.
471#define JSG_STATIC_CONSTANT(name) \
472 do { \
473 static const char NAME[] = #name; \
474 registry.template registerStaticConstant<NAME, decltype(Self::name)>(Self::name); \
475 } while (false)
476 
477// This works the same as JSG_STATIC_CONSTANT but allows us to provide an alias to an arbitrary c++
478// constant instead. For example:
479// struct Interface {
480// static Interface constructor()
481// JSG_RESOURCE_TYPE {
482// JSG_STATIC_CONSTANT_NAMED(FOO_BAR, SOME_SYSTEM_CONSTANT);
483// }
484// };
485#define JSG_STATIC_CONSTANT_NAMED(name, constant) \
486 do { \
487 static const char NAME[] = #name; \
488 registry.template registerStaticConstant<NAME, decltype(constant)>(constant); \
489 } while (false)
490 
491// Use inside a JSG_RESOURCE_TYPE block to declare that this type inherits from another type,
492// which must also have a JSG_RESOURCE_TYPE block. This type must singly, non-virtually inherit
493// from the specified type. (Multiple inheritance and virtual inheritance will not work since we
494// rely on the pointer to the superclass and the subclass having the same numeric value.)
495#define JSG_INHERIT(Type) \
496 static_assert(kj::canConvert<Self&, Type&>(), #Type " is not a superclass of this"); \
497 registry.template registerInherit<Type>()
498 
499// Use inside a JSG_RESOURCE_TYPE block to declare that this type inherits from an intrinsic
500// prototype. This is primarily useful to inherit from v8::kErrorPrototype, like DOMException, and
501// v8::kIteratorPrototype.
502#define JSG_INHERIT_INTRINSIC(intrinsic) \
503 do { \
504 static const char NAME[] = #intrinsic; \
505 registry.template registerInheritIntrinsic<NAME>(intrinsic); \
506 } while (false)
507 
508// An isDetected() operation which detects if the expression t.getTemplate(isolate, &u) is available
509// for instances `t`, `u` of types T and U.
510template <typename T, typename U>
511using HasGetTemplateOverload = decltype(kj::instance<T&>().getTemplate(
512 static_cast<v8::Isolate*>(nullptr), static_cast<U*>(nullptr)));
513 
514// Use inside a JSG_RESOURCE_TYPE block to declare that the given type should be visible as a
515// static member of this type. Typically, your "global" type would use several of these
516// declarations to make other types appear in the global scope. It is not necessary for the types
517// to be nested in C++.
518#define JSG_NESTED_TYPE(Type) \
519 do { \
520 /* Note that `Type` may be incomplete here, we should be OK with that. */ \
521 static const char NAME[] = #Type; \
522 registry.template registerNestedType<Type, NAME>(); \
523 } while (false)
524 
525#define JSG_NESTED_TYPE_NAMED(Type, Name) \
526 do { \
527 /* Note that `Type` may be incomplete here, we should be OK with that. */ \
528 static const char NAME[] = #Name; \
529 registry.template registerNestedType<Type, NAME>(); \
530 } while (false)
531 
532// Adds reflection to a resource type. See PropertyReflection<T> for usage.
533#define JSG_REFLECTION(...) \
534 static constexpr bool jsgHasReflection = true; \
535 template <typename TypeWrapper> \
536 void jsgInitReflection(TypeWrapper& wrapper) { \
537 jsgSuper::jsgInitReflection(wrapper); \
538 wrapper.initReflection(this, __VA_ARGS__); \
539 }
540 
541// Declares the type serializable. See jsg::Serializer for usage.
542#define JSG_SERIALIZABLE(TAG, ...) \
543 static_assert(static_cast<uint>(jsgSuper::jsgSerializeTag) != static_cast<uint>(TAG)); \
544 static constexpr auto jsgSerializeTag = TAG; \
545 static constexpr decltype(jsgSerializeTag) jsgSerializeOldTags[] = {__VA_ARGS__}; \
546 static constexpr auto jsgSerializeOneway = false
547 
548// Like JSG_SERIALIZABLE(), but the type has only a serialize() method and no deserialize(). It
549// is expected that the specified tag actually belongs to some other type, so a serialization
550// round trip will have the effect of replacing this type with that other type.
551//
552// Used e.g. for JsRpcTarget, which becomes JsRpcStub after serialization.
553#define JSG_ONEWAY_SERIALIZABLE(TAG) \
554 static_assert(static_cast<uint>(jsgSuper::jsgSerializeTag) != static_cast<uint>(TAG)); \
555 static constexpr auto jsgSerializeTag = TAG; \
556 static constexpr decltype(jsgSerializeTag) jsgSerializeOldTags[] = {}; \
557 static constexpr auto jsgSerializeOneway = true
558 
559// Declares a wildcard property getter. If a property is requested that isn't already present on
560// the object or its prototypes, the wildcard property getter will be given a chance to return the
561// property.
562//
563// WARNING: Be very careful about the property named "then". If it exists and is a function, V8
564// will treat your type as a custom thenable, i.e. as a kind of Promise, which means among other
565// things that any time a Promise would resolve to it, it will try to chain with it. You should
566// probably return kj::none when "then" is requested.
567//
568// Example:
569//
570// struct MyType {
571// // Get the value of the named dynamic property. Returns none if the property doesn't exist.
572// // `SomeType` can be any type that JSG is able to convert to JavaScript.
573// kj::Maybe<SomeType> getWildcard(jsg::Lock& js, kj::StringPtr name);
574//
575// JSG_RESOURCE_TYPE(MyType) {
576// JSG_WILDCARD_PROPERTY(getWildcard);
577// }
578// };
579#define JSG_WILDCARD_PROPERTY(method) \
580 do { \
581 registry.template registerWildcardProperty<Self, decltype(&Self::method), &Self::method>(); \
582 } while (false)
583 
584// Use inside a JSG_RESOURCE_TYPE block to declare that this type should be considered a "root" for
585// the purposes of automatically generating TypeScript definitions. All "root" types and their
586// recursively referenced types (e.g. method parameter/return types, property types, inherits, etc)
587// will be included in the generated TypeScript. See the `## TypeScript` section of the JSG README.md
588// for more details.
589#define JSG_TS_ROOT() registry.registerTypeScriptRoot()
590 
591// Use inside a JSG_RESOURCE_TYPE block to customise the generated TypeScript definition for this type.
592// This macro accepts a single override parameter containing a partial TypeScript statement definition.
593// Varargs are accepted so that overrides can contain `,` outside of balanced brackets. See the
594// `## TypeScript` section of the JSG README.md for many more details and examples.
595//
596// The varargs are stringified directly with `#__VA_ARGS__` to capture the user's source verbatim;
597// see the comment on `JSG_STRING_LITERAL` in macro-meta.h for why a forwarding helper would be
598// wrong here. The other `JSG_*_TS_OVERRIDE` and `JSG_*_TS_DEFINE` macros below follow the same
599// pattern for the same reason.
600#define JSG_TS_OVERRIDE(...) \
601 do { \
602 static const char OVERRIDE[] = #__VA_ARGS__; \
603 registry.template registerTypeScriptOverride<OVERRIDE>(); \
604 } while (false)
605 
606// Use inside a JSG_RESOURCE_TYPE block to insert additional TypeScript definitions next to the generated
607// TypeScript definition for this type. This macro accepts a single define parameter containing one or
608// more TypeScript definitions (e.g. interfaces, classes, type aliases, consts, ...). Varargs are accepted
609// so that defines can contain `,` outside of balanced brackets. See the `## TypeScript`section of the JSG
610// README.md for more details.
611#define JSG_TS_DEFINE(...) \
612 do { \
613 static const char DEFINE[] = #__VA_ARGS__; \
614 registry.template registerTypeScriptDefine<DEFINE>(); \
615 } while (false)
616 
617// Like JSG_TS_DEFINE, but accepts a string literal (e.g. a raw string R"(...)") instead of bare tokens.
618// This avoids the preprocessor parsing the TypeScript content as C++ tokens, which is necessary when the
619// TypeScript definition contains C++20 keywords like `module` that Clang rejects inside macro arguments.
620#define JSG_TS_DEFINE_LITERAL(jsg_string_literal) \
621 do { \
622 static const char DEFINE[] = jsg_string_literal; \
623 registry.template registerTypeScriptDefine<DEFINE>(); \
624 } while (false)
625 
626// Like JSG_TS_ROOT but for use with JSG_STRUCT. Should be placed adjacent to the JSG_STRUCT declaration,
627// inside the same `struct` definition. See the `## TypeScript` section of the JSG README.md for more
628// details.
629#define JSG_STRUCT_TS_ROOT() static constexpr bool _JSG_STRUCT_TS_ROOT_DO_NOT_USE_DIRECTLY = true
630 
631// Like JSG_TS_OVERRIDE but for use with JSG_STRUCT. Should be placed adjacent to the JSG_STRUCT
632// declaration, inside the same `struct` definition. See the `## TypeScript` section of the JSG README.md
633// for many more details and examples.
634#define JSG_STRUCT_TS_OVERRIDE(...) \
635 static constexpr char _JSG_STRUCT_TS_OVERRIDE_DO_NOT_USE_DIRECTLY[] = #__VA_ARGS__
636 
637// Like JSG_STRUCT_TS_OVERRIDE, however it enables dynamic selection of TS_OVERRIDE.
638// Should be placed adjacent to the JSG_STRUCT declaration, inside the same struct definition.
639#define JSG_STRUCT_TS_OVERRIDE_DYNAMIC(...) \
640 static void jsgConfiguration(__VA_ARGS__); \
641 template <typename Registry> \
642 static void registerTypeScriptDynamicOverride(Registry& registry, ##__VA_ARGS__)
643 
644// Like JSG_TS_DEFINE but for use with JSG_STRUCT. Should be placed adjacent to the JSG_STRUCT
645// declaration, inside the same `struct` definition. See the `## TypeScript`section of the JSG README.md
646// for more details.
647#define JSG_STRUCT_TS_DEFINE(...) \
648 static constexpr char _JSG_STRUCT_TS_DEFINE_DO_NOT_USE_DIRECTLY[] = #__VA_ARGS__
649 
650// Adds a group of javascript modules to the module registry when context is instantiated.
651// bundle is of a Bundle type from workerd/jsg/modules.capnp.
652// Modules will be resolved according to their type and module registry normal resolve rules.
653#define JSG_CONTEXT_JS_BUNDLE(bundle) \
654 do { \
655 registry.registerJsBundle(bundle); \
656 } while (false)
657 
658// true when T has _JSG_STRUCT_TS_ROOT_DO_NOT_USE_DIRECTLY field generated by JSG_STRUCT_TS_ROOT
659template <typename T>
660concept HasStructTypeScriptRoot = requires { T::_JSG_STRUCT_TS_ROOT_DO_NOT_USE_DIRECTLY; };
661 
662// true when T has _JSG_STRUCT_TS_OVERRIDE_DO_NOT_USE_DIRECTLY field generated by JSG_STRUCT_TS_OVERRIDE
663template <typename T>
664concept HasStructTypeScriptOverride = requires { T::_JSG_STRUCT_TS_OVERRIDE_DO_NOT_USE_DIRECTLY; };
665 
666// true when T has _JSG_STRUCT_TS_DEFINE_DO_NOT_USE_DIRECTLY field generated by JSG_STRUCT_TS_DEFINE
667template <typename T>
668concept HasStructTypeScriptDefine = requires { T::_JSG_STRUCT_TS_DEFINE_DO_NOT_USE_DIRECTLY; };
669 
670// Nest this inside a simple struct declaration in order to support translating it to/from a
671// JavaScript object / Web IDL dictionary.
672//
673// struct MyStruct {
674// double foo;
675// kj::String bar;
676// kj::String $public;
677//
678// JSG_STRUCT(foo, bar, $public);
679// };
680//
681// All of the types which are supported as method parameter / return types are also supported as
682// struct field types.
683//
684// Note that if you use `jsg::Optional<T>` as a field type, then the field will not be present at
685// all in JavaScript when the optional is null in C++ (as opposed to the field being present but
686// assigned the value `undefined`).
687//
688// Note that if a `validate` function is provided, then it will be called after the struct is
689// unwrapped from v8. This would be an appropriate time to throw an error.
690// Signature: void validate(jsg::Lock& js);
691// Example:
692// struct ValidatingFoo {
693// kj::String abc;
694// void validate(jsg::Lock& js) {
695// JSG_REQUIRE(abc.size() != 0, TypeError, "Field 'abc' had no length in 'ValidatingFoo'.");
696// }
697// JSG_STRUCT(abc);
698// };
699//
700// In this example the validate method would throw a `TypeError` if the size of the `abc` field was zero.
701//
702// Fields with a starting '$' will have that dollar sign prefix stripped in the JS binding. A
703// motivating example to enact that change was WebCrypto which has a field in a dictionary called
704// "public". '$' was chosen as a token we can use because it's a character for a C++ identifier. If
705// the Javascript field needs to contain '$' for some reason (which they probably shouldn't since
706// identifiers starting with $ are rare in JS land, especially for things the runtime would be
707// exporting), then you should be able to use '$$' as the identifier prefix in C++ since only the
708// first '$' gets stripped.
709#define JSG_STRUCT(...) \
710 static constexpr ::workerd::jsg::JsgKind JSG_KIND KJ_UNUSED = ::workerd::jsg::JsgKind::STRUCT; \
711 static constexpr char JSG_FOR_EACH(JSG_STRUCT_FIELD_NAME, , __VA_ARGS__); \
712 template <typename TypeWrapper, typename Self> \
713 using JsgFieldWrappers = \
714 ::workerd::jsg::TypeTuple<JSG_FOR_EACH(JSG_STRUCT_FIELD, , __VA_ARGS__)>; \
715 template <typename Self> \
716 static v8::Local<v8::DictionaryTemplate> jsgGetTemplate(v8::Isolate* isolate) { \
717 kj::Vector<std::string_view> names; \
718 JSG_FOR_EACH(JSG_STRUCT_FIELD_COL, , __VA_ARGS__); \
719 auto namesPtr = names.asPtr().asConst(); \
720 return v8::DictionaryTemplate::New( \
721 isolate, v8::MemorySpan<const std::string_view>(namesPtr.begin(), namesPtr.size())); \
722 } \
723 template <typename Registry, typename Self, typename Config> \
724 static void registerMembersInternal(Registry& registry, Config arg) { \
725 JSG_FOR_EACH(JSG_STRUCT_REGISTER_MEMBER, , __VA_ARGS__); \
726 if constexpr (::workerd::jsg::HasStructTypeScriptRoot<Self>) { \
727 registry.registerTypeScriptRoot(); \
728 } \
729 if constexpr (requires(jsg::GetConfiguration<Self> arg) { \
730 registerTypeScriptDynamicOverride<Registry>(registry, arg); \
731 }) { \
732 registerTypeScriptDynamicOverride<Registry>(registry, arg); \
733 } else if constexpr (::workerd::jsg::HasStructTypeScriptOverride<Self>) { \
734 registry.template registerTypeScriptOverride< \
735 Self::_JSG_STRUCT_TS_OVERRIDE_DO_NOT_USE_DIRECTLY>(); \
736 } \
737 if constexpr (::workerd::jsg::HasStructTypeScriptDefine<Self>) { \
738 registry \
739 .template registerTypeScriptDefine<Self::_JSG_STRUCT_TS_DEFINE_DO_NOT_USE_DIRECTLY>(); \
740 } \
741 } \
742 template <typename Registry, typename Self> \
743 static void registerMembers(Registry& registry) \
744 requires(!jsg::HasConfiguration<Self>) \
745 { \
746 registerMembersInternal<Registry, Self, void*>(registry, nullptr); \
747 } \
748 template <typename Registry, typename Self> \
749 static void registerMembers(Registry& registry, jsg::GetConfiguration<Self> arg) \
750 requires jsg::HasConfiguration<Self> \
751 { \
752 registerMembersInternal<Registry, Self, jsg::GetConfiguration<Self>>(registry, arg); \
753 }
754 
755template <size_t N>
756inline consteval size_t prefixLengthToStrip(const char (&s)[N]) {
757 return s[0] == '$' ? 1 : 0;
758}
759 
760// This string may not be what's actually exported to v8. For example, if it starts with a `$`, then
761// this value will still contain the `$` even though the `FieldWrapper` template argument will have
762// it stripped.
763#define JSG_STRUCT_FIELD_NAME(_, name) name##_JSG_NAME_DO_NOT_USE_DIRECTLY[] = #name
764 
765#define JSG_STRUCT_FIELD_COL(_, name) \
766 ::workerd::jsg::jsgAddToStructNames<decltype(::kj::instance<Self>().name), \
767 name##_JSG_NAME_DO_NOT_USE_DIRECTLY, ::workerd::jsg::prefixLengthToStrip(#name)>(names)
768 
769// (Internal implementation details for JSG_STRUCT.)
770#define JSG_STRUCT_FIELD(_, name) \
771 ::workerd::jsg::FieldWrapper<TypeWrapper, Self, decltype(::kj::instance<Self>().name), \
772 &Self::name, name##_JSG_NAME_DO_NOT_USE_DIRECTLY, \
773 ::workerd::jsg::prefixLengthToStrip(#name)>
774// (Internal implementation details for JSG_STRUCT.)
775#define JSG_STRUCT_REGISTER_MEMBER(_, name) \
776 registry.template registerStructProperty<decltype(::kj::instance<Self>().name), &Self::name>( \
777 name##_JSG_NAME_DO_NOT_USE_DIRECTLY)
778 
779// Indexes for adding API data to V8's Isolate object.
780enum SetDataIndex {
781 // The jsg::IsolateBase for a particular V8 isolate.
782 SET_DATA_ISOLATE_BASE,
783 // The TypeWrapper object for a particular V8 isolate.
784 SET_DATA_TYPE_WRAPPER,
785 // The lock associated with the V8 isolate.
786 SET_DATA_LOCK,
787 // The Worker::Isolate associated with the V8 isolate.
788 SET_DATA_ISOLATE,
789 // The address of the base of the 4Gbyte compressed pointer area.
790 // If we are using the sandbox it's also the base of the sandbox.
791 SET_DATA_CAGE_BASE,
792 // Used by JSG<->Rust integration.
793 SET_DATA_RUST_REALM,
794 // The number of slots workerd uses in the API data for Isolate objects.
795 SET_DATA_SLOTS_IN_USE,
796};
797 
798// =======================================================================================
799// Special types
800//
801// These types can be used in C++ to represent various JavaScript idioms / Web IDL types.
802 
803class Lock;
804WD_STRONG_BOOL(RequireEsm);
805 
806// Arbitrary V8 data, wrapped for storage from C++. You can't do much with it, so instead you
807// should probably use V8Ref<T>, a version of this that's strongly typed.
808//
809// When storing a Value inside a C++ object that is itself exported back to JavaScript, make sure
810// to implement GC visitation -- see GcVisitor, below.
811//
812// It is safe to destroy a strong jsg::Data object outside of the isolate lock. In this case,
813// the underlying V8 handles will be added to a queue, to be destroyed the next time a thread
814// locks the isolate. This means their destruction is non-deterministic, but that is true of V8
815// objects anyway, due to the GC. Weak jsg::Data (i.e., those which are reachable by V8's GC,
816// see GcVisitor below) must still be destroyed under the isolate lock to guard against concurrent
817// modification with the GC.
818//
819// Move construction and move assignment of strong jsg::Data is well-defined even without
820// holding the isolate lock. That is, it is safe to move Values unless you have implemented GC
821// visitation for them. Moving jsg::Data which are reachable via GC visitation is undefined
822// behavior outside of an isolate lock.
823class Data {
824 public:
825 Data(decltype(nullptr)) {}
826 ~Data() noexcept(false) {
827 destroy();
828 }
829 Data(Data&& other) noexcept: isolate(other.isolate), handle(kj::mv(other.handle)) {
830 KJ_IF_SOME(t, other.tracedHandle) {
831 moveFromTraced(other, t);
832 }
833 other.isolate = nullptr;
834 }
835 Data& operator=(Data&& other) {
836 if (this != &other) {
837 destroy();
838 isolate = other.isolate;
839 handle = kj::mv(other.handle);
840 other.isolate = nullptr;
841 KJ_IF_SOME(t, other.tracedHandle) {
842 moveFromTraced(other, t);
843 }
844 }
845 assertInvariant();
846 other.assertInvariant();
847 return *this;
848 }
849 KJ_DISALLOW_COPY(Data);
850 
851 Data(v8::Isolate* isolate, v8::Local<v8::Data> handle)
852 : isolate(isolate),
853 handle(isolate, handle) {}
854 
855 // Get the raw underlying v8 handle.
856 v8::Local<v8::Data> getHandle(v8::Isolate* isolate) const {
857 return handle.Get(isolate);
858 }
859 
860 // Get the raw underlying v8 handle.
861 v8::Local<v8::Data> getHandle(Lock& js) const;
862 
863 Data addRef(v8::Isolate* isolate) {
864 return Data(isolate, getHandle(isolate));
865 }
866 Data addRef(Lock& js);
867 
868 inline bool operator==(const Data& other) const {
869 return handle == other.handle;
870 }
871 inline bool operator==(const v8::Local<v8::Data>& other) const {
872 return handle == other;
873 }
874 
875 private:
876 // The isolate with which the handles below are associated.
877 v8::Isolate* isolate = nullptr;
878 
879 // Handle to the value which will be marked strong if any untraced C++ references exist, weak
880 // otherwise.
881 v8::Global<v8::Data> handle;
882 
883 // When `handle` is weak, `tracedHandle` is a copy of it used to integrate with V8 GC tracing.
884 // When `handle` is strong, we null out `tracedHandle`, because we don't need it, and it is
885 // illegal to hold onto a traced handle without actually marking it during each trace.
886 kj::Maybe<v8::TracedReference<v8::Data>> tracedHandle;
887 
888 friend class GcVisitor;
889 
890 void destroy();
891 
892 // Debugging helpers.
893 
894 // Assert that only empty values are associated with null isolates.
895 //
896 // Note that we use IASSERT (which is only enabled in debug) here because this function is
897 // intended to be invoked from the move ctor and assignment operator. We expect them to be
898 // invoked a lot and want them to be as optimizable as possible.
899 void assertInvariant() {
900 KJ_IASSERT(isolate != nullptr || handle.IsEmpty());
901 }
902 
903 // Implement move constructor when the source of the move has previously been visited for
904 // garbage collection.
905 void moveFromTraced(Data& other, v8::TracedReference<v8::Data>& otherTracedRef) noexcept;
906 
907 friend class MemoryTracker;
908};
909 
910// A drop-in replacement for v8::Global<T>. Its big feature is that, like jsg::Data, a
911// jsg::V8Ref<T> is safe to destroy outside of the isolate lock.
912//
913// Generally you should prefer using jsg::Value (for v8::Value) or jsg::Ref<T>. Use a
914// jsg::V8Ref<T> when you need the type-safety of holding a handle to a specific V8 type.
915template <typename T>
916class V8Ref: private Data {
917 public:
918 V8Ref(decltype(nullptr)): Data(nullptr) {}
919 V8Ref(v8::Isolate* isolate, v8::Local<T> handle): Data(isolate, handle) {}
920 V8Ref(V8Ref&& other) noexcept: Data(kj::mv(other)) {}
921 V8Ref& operator=(V8Ref&& other) {
922 Data::operator=(kj::mv(other));
923 return *this;
924 }
925 KJ_DISALLOW_COPY(V8Ref);
926 
927 v8::Local<T> getHandle(v8::Isolate* isolate) const {
928 if constexpr (std::is_base_of<v8::Value, T>()) {
929 // V8 doesn't let us cast directly from v8::Data to subtypes of v8::Value, so we're forced to
930 // use this double cast... Ech.
931 return Data::getHandle(isolate).template As<v8::Value>().template As<T>();
932 } else {
933 return Data::getHandle(isolate).template As<T>();
934 }
935 }
936 v8::Local<T> getHandle(jsg::Lock& js) const;
937 
938 V8Ref addRef(v8::Isolate* isolate) {
939 return V8Ref(isolate, getHandle(isolate));
940 }
941 V8Ref addRef(jsg::Lock& js);
942 
943 V8Ref deepClone(jsg::Lock& js);
944 
945 inline bool operator==(const V8Ref& other) const {
946 return Data::operator==(other);
947 }
948 inline bool operator==(const v8::Local<T>& other) const {
949 return Data::operator==(other);
950 }
951 
952 template <typename U>
953 V8Ref<U> cast(jsg::Lock& js);
954 
955 private:
956 friend class GcVisitor;
957 friend class MemoryTracker;
958};
959 
960using Value = V8Ref<v8::Value>;
961 
962// Like V8Ref but also implements `hashCode()`. Useful as a key into a kj::HashTable.
963//
964// T must v8::Object or a subclass (or anything that implements GetIdentityHash()).
965template <typename T>
966class HashableV8Ref: public V8Ref<T> {
967 public:
968 HashableV8Ref(decltype(nullptr)): V8Ref<T>(nullptr), identityHash(0) {}
969 HashableV8Ref(v8::Isolate* isolate, v8::Local<T> handle)
970 // TODO(perf): It's not clear if V8's `GetIdentityHash()` is intended to return uniform
971 // results as required for KJ hashing, so we pass it to `kj::hashCode()` to further hash
972 // it. This may be unnecessary. Note that there are several other call sites of
973 // `GetIdentityHash()` which do the same -- if we decide we don't need this we should fix
974 // all of them.
975 : V8Ref<T>(isolate, handle),
976 identityHash(kj::hashCode(handle->GetIdentityHash())) {}
977 HashableV8Ref(HashableV8Ref&& other) = default;
978 HashableV8Ref& operator=(HashableV8Ref&& other) = default;
979 KJ_DISALLOW_COPY(HashableV8Ref);
980 
981 HashableV8Ref addRef(v8::Isolate* isolate) {
982 return HashableV8Ref(isolate, this->getHandle(isolate), identityHash);
983 }
984 HashableV8Ref addRef(jsg::Lock& js);
985 
986 int hashCode() const {
987 return identityHash;
988 }
989 
990 private:
991 int identityHash;
992 
993 HashableV8Ref(v8::Isolate* isolate, v8::Local<T> handle, int identityHash)
994 : V8Ref<T>(isolate, handle),
995 identityHash(identityHash) {}
996};
997 
998template <V8Value T>
999void MemoryTracker::trackField(
1000 kj::StringPtr edgeName, const V8Ref<T>& value, kj::Maybe<kj::StringPtr> nodeName) {
1001 // Even though we're passing in a template T, casting to a v8::Value is sufficient here.
1002 trackField(edgeName, value.handle.Get(isolate_).template As<v8::Value>(), nodeName);
1003}
1004 
1005// A value of type T, or `undefined`.
1006//
1007// In C++, this has the same usage as kj::Maybe<T>. However, a null kj::Maybe<T> corresponds to
1008// `null` in JavaScript, whereas a null Optional<T> corresponds to `undefined` in JavaScript.
1009//
1010// Note: Due to Web IDL's undefined-to-nullable coercion rule, a null Maybe<T> can also unwrap
1011// from an `undefined` value explicitly passed to a non-optional nullable.
1012//
1013// There are two main use cases for Optional<T>: optional function/method parameters and optional
1014// JSG_STRUCT members. In both cases, a null value in C++ corresponds to the parameter/field not
1015// being present at all in JavaScript, or explicitly set to `undefined`.
1016//
1017// In Web IDL, function parameters are considered required unless marked `optional`, while
1018// dictionary (JSG_STRUCT) members are considered optional unless marked `required`. So, if you
1019// were implementing an API specified in Web IDL like so:
1020//
1021// dictionary Data {
1022// double number;
1023// required DOMString string;
1024// };
1025// void foo(optional Data data);
1026//
1027// An appropriate representation in C++ would be:
1028//
1029// struct Data {
1030// Optional<double> number;
1031// kj::String string;
1032// JSG_STRUCT(number, string);
1033// };
1034// void foo(Optional<Data> data);
1035template <typename T>
1036class Optional: public kj::Maybe<T> {
1037 public:
1038 // Inheriting constructors does not inherit copy/move constructors, so we declare a forwarding
1039 // constructor instead.
1040 template <typename... Params>
1041 Optional(Params&&... params): kj::Maybe<T>(kj::fwd<Params>(params)...) {}
1042};
1043 
1044// Identical to Optional, but rather than treating failures to unwrap a JS value to type T as an
1045// error, it just results in an unset LenientOptional.
1046template <typename T>
1047class LenientOptional: public kj::Maybe<T> {
1048 public:
1049 // Inheriting constructors does not inherit copy/move constructors, so we declare a forwarding
1050 // constructor instead.
1051 template <typename... Params>
1052 LenientOptional(Params&&... params): kj::Maybe<T>(kj::fwd<Params>(params)...) {}
1053};
1054 
1055// Use this type in a JSG_STRUCT to define a special field that will be filled in with a
1056// reference to the original struct's JavaScript representation. This is useful e.g. if you
1057// may need to pull additional fields out of the struct.
1058//
1059// Another option is to use jsg::Identified<MyStruct>, but sometimes storing the reference
1060// into a field of the unwrapped struct is more convenient.
1061class SelfRef: public V8Ref<v8::Object> {
1062 public:
1063 using V8Ref::V8Ref;
1064 
1065 // Convert the V8Ref<v8::Object> to a V8Ref<v8::Value>
1066 inline Value asValue(Lock& js) const;
1067};
1068 
1069template <typename U>
1070static constexpr bool isUsableStructField = !kj::isSameType<U, SelfRef>() &&
1071 !kj::isSameType<U, Unimplemented>() && !kj::isSameType<U, WontImplement>();
1072 
1073template <typename T, const char* name, size_t prefix>
1074void jsgAddToStructNames(auto& names) {
1075 constexpr const char* exportedName = name + prefix;
1076 if constexpr (isUsableStructField<T>) names.add(exportedName);
1077}
1078 
1079// A USVString has the exact same representation as a kj::String, but we guarantee that it meets
1080// the WHATWG definition of a "scalar value string". Particularly, a USVString will never contain
1081// invalid surrogate characters. A USVString should be used when implementing a Web API that
1082// requires this behaviour.
1083// See <https://infra.spec.whatwg.org/#scalar-value-string>
1084class USVString: public kj::String {
1085 public:
1086 // Inheriting constructors does not inherit copy/move constructors, so we declare a forwarding
1087 // constructor instead.
1088 template <typename... Params>
1089 explicit USVString(Params&&... params): kj::String(kj::fwd<Params>(params)...) {
1090 KJ_DASSERT(isValidUtf8());
1091 }
1092 
1093 private:
1094 // This is a seperate method to avoid including simdutf in the header file.
1095 bool isValidUtf8() const;
1096};
1097 
1098// A DOMString has the exact same representation as a kj::String, but may contain WTF-8 encoded
1099// data like unpaired surrogate characters, that are not strictly valid in UTF-8. A DOMString
1100// should be used when implementing a Web API that requires this behaviour, or when an explicit
1101// decision is made to accept potentially invalid strings.
1102class DOMString: public kj::String {
1103 public:
1104 // Inheriting constructors does not inherit copy/move constructors, so we declare a forwarding
1105 // constructor instead.
1106 template <typename... Params>
1107 explicit DOMString(Params&&... params): kj::String(kj::fwd<Params>(params)...) {}
1108};
1109 
1110// A Dict<V, K> in C++ corresponds to a JavaScript object that is being used as a string -> value
1111// map, where all the values are of type T.
1112//
1113// Note: A Dict<V, K> corresponds to a record<K, V> in the Web IDL language.
1114template <typename Value, typename Key = kj::String>
1115struct Dict {
1116 // TODO(someday): Maybe make this a map and not an array? Current use case doesn't care, though.
1117 
1118 // Field of an object.
1119 struct Field {
1120 Key name;
1121 Value value;
1122 
1123 JSG_MEMORY_INFO(Field) {
1124 tracker.trackField("name", name);
1125 tracker.trackField("value", value);
1126 }
1127 };
1128 
1129 kj::Array<Field> fields;
1130 
1131 JSG_MEMORY_INFO(Dict) {
1132 for (const auto& field: fields) {
1133 tracker.trackField(nullptr, field);
1134 }
1135 }
1136};
1137 
1138template <typename T>
1139class TypeHandler;
1140 
1141// When used as a function argument type, captures all remaining arguments passed to the method,
1142// unwrapping them all as type T.
1143template <typename T>
1144class Arguments: public kj::Array<T> {
1145 public:
1146 Arguments(kj::Array<T>&& value): kj::Array<T>(kj::mv(value)) {}
1147 
1148 using ElementType = T;
1149};
1150 
1151// Is `T` some specialization of `Arguments<U>`?
1152template <typename T>
1153struct IsArguments_ {
1154 static constexpr bool value = false;
1155};
1156template <typename T>
1157struct IsArguments_<Arguments<T>> {
1158 static constexpr bool value = true;
1159};
1160template <typename T>
1161constexpr bool isArguments() {
1162 return IsArguments_<T>::value;
1163}
1164 
1165template <typename T>
1166constexpr bool resourceNeedsGcTracing();
1167template <typename T>
1168void visitSubclassForGc(T* obj, GcVisitor& visitor);
1169 
1170// All resource types must inherit from this.
1171class Object: private Wrappable {
1172 public:
1173 using jsgThis = Object;
1174 
1175 // Objects that extend from jsg::Object should never be copied or moved
1176 // independently of their owning jsg::Ref so we explicitly delete the
1177 // copy and move constructors and assignment operators to be safe.
1178 KJ_DISALLOW_COPY_AND_MOVE(Object);
1179 
1180 // Since we explicitly delete the copy and move constructors, we have
1181 // to explicitly declare the default constructor.
1182 Object() = default;
1183 
1184 inline void jsgVisitForGc(GcVisitor& visitor) override {}
1185 
1186 // Subclasses should override these to provide appropriate information for
1187 // the heap snapshot process.
1188 inline kj::StringPtr jsgGetMemoryName() const override {
1189 return "Object";
1190 }
1191 inline size_t jsgGetMemorySelfSize() const override {
1192 return sizeof(Object);
1193 }
1194 inline void jsgGetMemoryInfo(MemoryTracker& tracker) const override {
1195 Wrappable::jsgGetMemoryInfo(tracker);
1196 }
1197 inline v8::Local<v8::Object> jsgGetMemoryInfoWrapperObject(v8::Isolate* isolate) override {
1198 return Wrappable::jsgGetMemoryInfoWrapperObject(isolate);
1199 }
1200 inline bool jsgGetMemoryInfoIsRootNode() const override {
1201 return Wrappable::jsgGetMemoryInfoIsRootNode();
1202 }
1203 
1204 static constexpr bool jsgHasReflection = false;
1205 template <typename TypeWrapper>
1206 inline void jsgInitReflection(TypeWrapper& wrapper) {}
1207 
1208 // Dummy invalid serialization tag. This is only used to detect when a subclass has defined their
1209 // own tag.
1210 static constexpr uint jsgSerializeTag = kj::maxValue;
1211 
1212 private:
1213 inline void visitForMemoryInfo(MemoryTracker& tracker) const {}
1214 inline void visitForGc(GcVisitor& visitor) {}
1215 template <typename>
1216 friend constexpr bool ::workerd::jsg::resourceNeedsGcTracing();
1217 template <typename T>
1218 friend void visitSubclassForGc(T* obj, GcVisitor& visitor);
1219 template <typename T>
1220 friend void visitSubclassForMemoryInfo(const T* obj, MemoryTracker& visitor);
1221 template <typename T>
1222 friend class Ref;
1223 friend class kj::Refcounted;
1224 template <typename T>
1225 friend kj::Own<T> kj::addRef(T& object);
1226 template <typename T, typename... Params>
1227 friend kj::Own<T> kj::refcounted(Params&&... params);
1228 friend class GcVisitor;
1229 template <typename, typename...>
1230 friend class TypeWrapper;
1231 template <typename, typename>
1232 friend class ResourceWrapper;
1233 template <typename>
1234 friend class ObjectWrapper;
1235 template <typename>
1236 friend class SelfPropertyReader;
1237 friend class MemoryTracker;
1238};
1239 
1240// Ref<T> is a reference to a resource type (a type with a JSG_RESOURCE_TYPE block) living on
1241// the V8 heap.
1242//
1243// Use Ref<T> when you want a long-lived reference to such a type. If you only need a reference
1244// that lasts until your method returns, you can specify the parameter type `T&` instead, which
1245// is more efficient. Use Ref<T> when you need to keep the reference longer than that.
1246//
1247// WARNING: When storing Ref<T> in a C++ object that itself is referenced from the JS heap,
1248// you must implement GC visitation; see GcVisitor, below.
1249//
1250// It is safe to destroy a jsg::Ref<T> object outside of the isolate lock. In this case,
1251// the underlying V8 handles will be added to a queue, to be destroyed the next time a thread
1252// locks the isolate. This means their destruction is non-deterministic, but that is true of V8
1253// objects anyway, due to the GC.
1254//
1255// Move construction and move assignment of strong jsg::Ref<T>s is well-defined even without
1256// holding the isolate lock. That is, it is safe to move Refs unless you have implemented GC
1257// visitation for them. Moving jsg::Ref<T>s which are reachable via GC visitation is undefined
1258// behavior outside of an isolate lock.
1259template <typename T>
1260class Ref {
1261 public:
1262 Ref(decltype(nullptr)): strong(false) {}
1263 Ref(Ref&& other) noexcept: inner(kj::mv(other.inner)), strong(true) {
1264 if (other.strong) {
1265 other.strong = false;
1266 } else {
1267 inner->addStrongRef();
1268 }
1269 }
1270 
1271 // Upgrade a KJ allocation to a Ref. This is useful if you want to allocate the object outside
1272 // the isolate lock and then bring it in later. The object must be allocated with
1273 // kj::refcounted. Once the Ref is constructed, the refcount is protected by the isolate lock
1274 // going forward; you can no longer add or remove refs outside the lock.
1275 explicit Ref(kj::Own<T> innerParam): inner(kj::mv(innerParam)), strong(true) {
1276 inner->addStrongRef();
1277 }
1278 template <typename U, typename = kj::EnableIf<kj::canConvert<U&, T&>()>>
1279 Ref(Ref<U>&& other) noexcept: inner(kj::mv(other.inner)),
1280 strong(true) {
1281 if (other.strong) {
1282 other.strong = false;
1283 } else {
1284 inner->addStrongRef();
1285 }
1286 }
1287 template <typename U>
1288 Ref& operator=(Ref<U>&& other) {
1289 destroy();
1290 inner = kj::mv(other.inner);
1291 strong = true;
1292 if (other.strong) {
1293 other.strong = false;
1294 } else {
1295 inner->addStrongRef();
1296 }
1297 return *this;
1298 }
1299 ~Ref() noexcept(false) {
1300 destroy();
1301 }
1302 KJ_DISALLOW_COPY(Ref);
1303 
1304 T& operator*() {
1305 return *inner;
1306 }
1307 T* operator->() {
1308 return inner.get();
1309 }
1310 T* get() {
1311 return inner.get();
1312 }
1313 
1314 const T& operator*() const {
1315 return *inner;
1316 }
1317 const T* operator->() const {
1318 return inner.get();
1319 }
1320 const T* get() const {
1321 return inner.get();
1322 }
1323 
1324 Ref addRef() & {
1325 return Ref(kj::addRef(*inner));
1326 }
1327 Ref addRef() && = delete; // would be redundant
1328 
1329 // If the object has a JS wrapper, return it. Note that the JS wrapper is initialized lazily
1330 // when the object is first passed to JS, so you can't be sure that it exists. To reliably
1331 // get a handle (creating it on-demand if necessary), use a TypeHandler<Ref<T>>.
1332 kj::Maybe<v8::Local<v8::Object>> tryGetHandle(v8::Isolate* isolate) {
1333 return inner->tryGetHandle(isolate);
1334 }
1335 
1336 kj::Maybe<v8::Local<v8::Object>> tryGetHandle(Lock& js);
1337 
1338 // Attach a JavaScript object which implements the JS interface for this C++ object. Normally,
1339 // this happens automatically the first time the Ref is passed across the FFI barrier into JS.
1340 // This method may be useful in order to use a different wrapper type than the one that would
1341 // be used automatically. This method is also useful when implementing TypeWrapperExtensions.
1342 //
1343 // It is an error to attach a wrapper when another wrapper is already attached. Hence,
1344 // typically this should only be called on a newly-allocated object.
1345 void attachWrapper(v8::Isolate* isolate, v8::Local<v8::Object> object) {
1346 inner->Wrappable::attachWrapper(isolate, object, resourceNeedsGcTracing<T>());
1347 }
1348 
1349 private:
1350 kj::Own<T> inner;
1351 
1352 // If this has ever been traced, the parent object from which the trace originated. This is kept
1353 // for debugging purposes only -- there should only ever be one parent for a particular ref.
1354 //
1355 // This field does NOT move when the Ref moves, because it's a property of the specific Ref
1356 // location.
1357 kj::Maybe<Wrappable&> parent;
1358 
1359 // True if the ref is currently counted in the target's strong refcount.
1360 bool strong;
1361 
1362 void destroy() {
1363 if (auto ptr = inner.get(); ptr != nullptr) {
1364 inner->maybeDeferDestruction(strong, kj::mv(inner), static_cast<Wrappable*>(ptr));
1365 }
1366 }
1367 
1368 template <typename>
1369 friend class Ref;
1370 template <typename U, typename... Params>
1371 friend Ref<U> alloc(Params&&... params);
1372 friend class Lock;
1373 template <typename U>
1374 friend Ref<U> _jsgThis(U* obj);
1375 template <typename, typename>
1376 friend class ResourceWrapper;
1377 template <typename>
1378 friend class ObjectWrapper;
1379 friend class GcVisitor;
1380};
1381 
1382template <MemoryRetainer T>
1383void MemoryTracker::trackField(
1384 kj::StringPtr edgeName, const Ref<T>& value, kj::Maybe<kj::StringPtr> nodeName) {
1385 trackField(edgeName, value.get(), nodeName);
1386}
1387 
1388template <typename T, typename... Params>
1389// TODO(js.alloc): When most of the jsg::alloc users are updated we can uncomment
1390// the deprecation here. When all uses are updated to use js.alloc, we can remove
1391// this method entirely.
1392//[[deprecated("Use js.alloc<T>(...) instead")]]
1393Ref<T> alloc(Params&&... params) {
1394 return Ref<T>(kj::refcounted<T>(kj::fwd<Params>(params)...));
1395}
1396 
1397template <typename T>
1398Ref<T> _jsgThis(T* obj) {
1399 return Ref<T>(kj::addRef(*obj));
1400}
1401 
1402#define JSG_THIS (::workerd::jsg::_jsgThis(this))
1403 
1404// Holds a value of type `T` and allows it to be passed to JavaScript multiple times, resulting
1405// in exactly the same JavaScript object each time (will compare equal using `===`). You may
1406// pass `MemoizedIdentity<T>` by reference, e.g. you could define a method of a JSG_RESOURCE_TYPE
1407// which returns `MemoizedIdentity<T>&`, returning a reference to a member of the object.
1408//
1409// Note that you don't need to wrap `jsg::Ref<T>` this way, as it already has the property that
1410// only one wrapper will be created. `MemoizedIdentity` can wrap any type that is convertible to
1411// JavaScript, including types that are otherwise pass-by-value.
1412template <typename T>
1413class MemoizedIdentity {
1414 public:
1415 inline MemoizedIdentity(T value): value(kj::mv(value)) {}
1416 
1417 inline MemoizedIdentity& operator=(T value) {
1418 this->value = kj::mv(value);
1419 return *this;
1420 }
1421 
1422 void visitForGc(GcVisitor& visitor);
1423 
1424 JSG_MEMORY_INFO(MemoizedIdentity) {
1425 KJ_SWITCH_ONEOF(value) {
1426 KJ_CASE_ONEOF(val, T) {
1427 if constexpr (MemoryRetainer<T>) {
1428 tracker.trackField("value", val);
1429 } else {
1430 tracker.trackFieldWithSize("value", sizeof(T));
1431 }
1432 }
1433 KJ_CASE_ONEOF(val, Value) {
1434 tracker.trackField("value", val);
1435 }
1436 }
1437 }
1438 
1439 private:
1440 kj::OneOf<T, Value> value;
1441 
1442 template <typename TypeWrapper>
1443 friend class MemoizedIdentityWrapper;
1444 friend class MemoryTracker;
1445};
1446 
1447// Accept this type from JavaScript when you want to receive an object's identity in addition to
1448// unwrapping it. This is useful, for example, if you need to be able to recognize when the
1449// application passes in the same object again later.
1450//
1451// `T` must be a type whose JavaScript representation is an Object (including Functions), since
1452// other types do not have a notion of identity-equality.
1453template <typename T>
1454struct Identified {
1455 // Handle to the original object.
1456 HashableV8Ref<v8::Object> identity;
1457 
1458 // The object's unwrapped value.
1459 T unwrapped;
1460 
1461 JSG_MEMORY_INFO(Identified) {
1462 tracker.trackField("identity", identity);
1463 if constexpr (MemoryRetainer<T>) {
1464 tracker.trackField("unwrapped", unwrapped);
1465 } else {
1466 tracker.trackFieldWithSize("unwrapped", sizeof(T));
1467 }
1468 }
1469};
1470 
1471// jsg::Name represents a value that is either a string or a v8::Symbol. It is most useful for
1472// use in APIs that can accept both interchangeably.
1473//
1474// Name implements hashCode() so it is suitable for use as a key in kj::HashMap, etc.
1475class Name final {
1476 public:
1477 explicit Name(kj::String string);
1478 explicit Name(kj::StringPtr string);
1479 explicit Name(Lock& js, v8::Local<v8::Symbol> symbol);
1480 KJ_DISALLOW_COPY(Name);
1481 Name(Name&&) = default;
1482 Name& operator=(Name&&) = default;
1483 
1484 inline int hashCode() const {
1485 return hash;
1486 }
1487 
1488 Name clone(jsg::Lock& js);
1489 
1490 kj::String toString(jsg::Lock& js);
1491 
1492 JSG_MEMORY_INFO(Name) {
1493 KJ_SWITCH_ONEOF(inner) {
1494 KJ_CASE_ONEOF(str, kj::String) {
1495 tracker.trackField("inner", str);
1496 }
1497 KJ_CASE_ONEOF(sym, V8Ref<v8::Symbol>) {
1498 tracker.trackField("inner", sym);
1499 }
1500 }
1501 }
1502 
1503 private:
1504 int hash;
1505 kj::OneOf<kj::String, V8Ref<v8::Symbol>> inner;
1506 
1507 kj::OneOf<kj::StringPtr, v8::Local<v8::Symbol>> getUnwrapped(v8::Isolate* isolate);
1508 
1509 friend class NameWrapper;
1510 
1511 void visitForGc(GcVisitor& visitor);
1512 
1513 friend class MemoryTracker;
1514};
1515 
1516// jsg::Function<T> behaves much like kj::Function<T>, but can be passed to/from JS. It works in
1517// both directions: you can receive a jsg::Function from JavaScript and call it from C++, and you
1518// can also initialize a jsg::Function from a C++ lambda and pass it back to JavaScript.
1519//
1520// Since the function could be backed by JavaScript, when calling it, you must always pass
1521// `jsg::Lock&` as the first parameter. When implementing a `jsg::Function` using a C++ lambda,
1522// the lambda should similarly take `jsg::Lock&` as the first parameter. Note that this first
1523// parameter is not declared in the function's signature. For example, `jsg::Function<int(int)>`
1524// declares a function that accepts a parameter of type int and returns an int. However, when
1525// actually calling it, you must still pass `jsg::Lock&`, with the `int` as the second parameter.
1526// (Of course, from the JavaScript side, the lock parameter is hidden, and the `int` is in fact
1527// the first parameter.)
1528//
1529// jsg::Function can be visited using a GcVisitor. If a jsg::Function is initialized from a
1530// C++ functor object that happens to have a public method `visitForGc(jsg::GcVisitor&)`, then
1531// it will arrange for that method to be called during GC tracing.
1532//
1533// Note that, obviously, a normal C++ lambda cannot have a `visitForGc()` method. So when writing
1534// a visitable function in C++, you have to write out a struct or class with an `operator()`
1535// method and a `visitForGc()` method. That's a bit of a pain, so the macro JSG_VISITABLE_LAMBDA()
1536// is provided to assist. This lets you write something like a lambda expression where some of the
1537// captured variables can be GC visited. Example:
1538//
1539// jsg::Function<void(int)> myFunc =
1540// JSG_VISITABLE_LAMBDA((foo = getFoo(), bar, &baz),
1541// (foo, baz.handle),
1542// (jsg::Lock& js, int param) {
1543// // ... body of function ...
1544// });
1545//
1546// The first parameter to JSG_VISITABLE_LAMBDA is your capture list, in exactly the syntax that a
1547// regular lambda would use, except in parentheses instead of square brackets. The second
1548// parameter is a parenthesized list of visitation expressions. This will literally be used as a
1549// parameter list to `gcVisitor.visit()`, e.g. in the above example
1550// `gcVisitor.visit(foo, baz.handle)` will be called when visited. Finally, the third parameter
1551// is the rest of the lambda expression -- parameter list followed by body block.
1552template <typename Signature>
1553class Function;
1554 
1555// Use this to unwrap a JavaScript function that should be called as a constructor (with `new`).
1556// The return type in this case is the constructed type. `Constructor` is a subclass of `Function`;
1557// it can be used in all the same ways.
1558template <typename T>
1559class Constructor;
1560 
1561// jsg::Promise<T> wraps a JavaScript promise. Use it when you want to pass Promises to or from
1562// JavaScript.
1563//
1564// jsg::Promise<T> offers a `.then()` method which looks a lot like kj::Promise<T>'s similar
1565// function, except that you must pass `Lock&` to it, and it passes `Lock&` back to the callback:
1566//
1567// Promise<int> promise = ...;
1568// Promise<kj::String> promise2 = promise.then(js,
1569// [](Lock& js, int val) { return kj::str(val); })
1570//
1571// Unlike kj::Promise, jsg::Promises run on the V8 microtask loop, NOT on the KJ event loop. That
1572// implies that the isolate is already locked and active during callbacks, and control does not
1573// return to the KJ event loop at all if a promise continuation is immediately runnable.
1574//
1575// `.catch_()` and two-argument `.then()` are supported. Thrown exceptions are represented using
1576// `jsg::Value`, since technically JavaScript allows throwing any type.
1577//
1578// The type T does not have to be convertible to/from JavaScript unless a Promise<T> is actually
1579// passed to/from JavaScript. That is, you can have an intermediate Promise<U> where U is a type
1580// that has no JavaScript representation. What actually happens is, when a Promise<T> is passed
1581// from JS into C++, JSG adds a .then() which unwraps the value T, and when a Promise<T> is
1582// passed back to JS, JSG adds a .then() to wrap the value again.
1583//
1584// If the type T is GC visitable (i.e. it is a type that you could pass to GcVisitor::visit()),
1585// then the system will arrange to correctly visit it when the T is wrapped in a Promise.
1586// Additionally, if a continuation function passed to `.then()` is GC-visitable, it will similarly
1587// be visited. JSG_VISITABLE_LAMBDA is a useful in conjunction with `.then()` (see jsg::Function,
1588// above).
1589//
1590// Unlike KJ promises, dropping a jsg::Promise does not cancel it. However, like a KJ promise,
1591// a jsg::Promise can only have `.then()` called on it once; the continuation consumes the value.
1592// This is so that pass-by-move C++ types can safely be passed through jsg::Promises. Of course,
1593// once returned to JavaScript, JS code is free to call `.then()` as many times as it wants; this
1594// restriction only applies to calling `.then()` in C++.
1595//
1596// When a JSG method returns a Promise, the system ensures that the object on which the method
1597// was called will not be GC'ed until the Promise resolves (or is itself GC'ed, indicating it will
1598// never resolve). This is a convenience so that method implementations that return promises do
1599// not need to carefully capture a reference to `JSG_THIS`.
1600//
1601// You can construct an immediate Promise value using js.resolvedPromise() and
1602// js.rejectedPromise() (see below).
1603//
1604// You can also create a promise/resolver pair:
1605//
1606// auto [promise, resolver] = js.newPromiseAndResolver<kj::String>();
1607// resolver.resolve(js, kj::str(foo));
1608//
1609// The Promise exposes a markAsHandled() API that will mark JavaScript Promise such that rejections
1610// are not reported to the isolate's unhandled rejection tracking mechanisms. Importantly, any then
1611// then() or catch_() continuation on either type will return an unhandled Promise. But, any
1612// whenResolved() continuation, and any type handler continuations added internally will be
1613// automatically marked handled. Use of markAsHandled() should be rare. It is largely used by Web
1614// Platform APIs in certain cases where consumption of a promise is optional, or where a promise
1615// rejection is likely to be surfaced via multiple promises (and therefore only needs to be handled
1616// once).
1617template <typename T>
1618class Promise;
1619 
1620template <typename T>
1621struct PromiseResolverPair;
1622 
1623// Convenience template to detect a `jsg::Promise` type.
1624template <typename T>
1625struct IsPromise_ {
1626 static constexpr bool value = false;
1627};
1628template <typename T>
1629struct IsPromise_<Promise<T>> {
1630 static constexpr bool value = true;
1631};
1632template <typename T>
1633constexpr bool isPromise() {
1634 return IsPromise_<T>::value;
1635}
1636 
1637// Convenience template to strip off `jsg::Promise`.
1638template <typename T>
1639struct RemovePromise_ {
1640 using Type = T;
1641};
1642template <typename T>
1643struct RemovePromise_<Promise<T>> {
1644 using Type = T;
1645};
1646template <typename T>
1647using RemovePromise = RemovePromise_<T>::Type;
1648 
1649// Convenience template to add `jsg::Promise` if it is not present.
1650template <typename T>
1651struct MaintainPromise_ {
1652 using Type = Promise<T>;
1653};
1654template <typename T>
1655struct MaintainPromise_<Promise<T>> {
1656 using Type = Promise<T>;
1657};
1658template <typename T>
1659using MaintainPromise = MaintainPromise_<T>::Type;
1660 
1661// Convenience template to calculate the return type of a function when passed parameter type T.
1662// `T = void` is understood to mean no parameters.
1663template <typename Func, typename T, bool passLock>
1664struct ReturnType_;
1665template <typename Func, typename T>
1666struct ReturnType_<Func, T, false> {
1667 using Type = decltype(kj::instance<Func>()(kj::instance<T>()));
1668};
1669template <typename Func, typename T>
1670struct ReturnType_<Func, T, true> {
1671 using Type = decltype(kj::instance<Func>()(kj::instance<Lock&>(), kj::instance<T>()));
1672};
1673template <typename Func>
1674struct ReturnType_<Func, void, false> {
1675 using Type = decltype(kj::instance<Func>()());
1676};
1677template <typename Func>
1678struct ReturnType_<Func, void, true> {
1679 using Type = decltype(kj::instance<Func>()(kj::instance<Lock&>()));
1680};
1681template <typename Func, typename T, bool passLock = false>
1682using ReturnType = ReturnType_<Func, T, passLock>::Type;
1683 
1684// Convenience template to produce a promise for the result of calling a function with the given
1685// parameter type. This wraps the function's result type in `jsg::Promise` UNLESS the function
1686// already returns a `jsg::Promise`, in which case the type is unchanged.
1687// TODO(cleanup): The passLock = false variation is currently only used for js.evalNow().
1688// It would be nice to refactor that a bit so we can clean up this template and simplify.
1689template <typename Func, typename Param, bool passLock>
1690using PromiseForResult = MaintainPromise<ReturnType<Func, Param, passLock>>;
1691 
1692// All types declared with JSG_RESOURCE_TYPE which are intended to be used as the global object
1693// must inherit jsg::ContextGlobal, in addition to inheriting jsg::Object
1694// (or a subclass of jsg::Object).
1695// jsg::Object should always be the first inherited class, and jsg::ContextGlobal second.
1696// The lifetime of the global object matches the lifetime of the JavaScript context.
1697class ContextGlobal {
1698 public:
1699 ContextGlobal() {}
1700 
1701 KJ_DISALLOW_COPY_AND_MOVE(ContextGlobal);
1702 
1703 const capnp::SchemaLoader& getSchemaLoader();
1704 
1705 private:
1706 // This opaque owner is used to keep the ModuleRegistry alive as long as the ContextGlobal
1707 // object is alive. This may be the legacy or new module registry, depending which one is
1708 // in use. We don't care about the actual type here, just that it is kept alive.
1709 kj::Own<void> moduleRegistryBackingOwner;
1710 kj::Maybe<const capnp::SchemaLoader&> schemaLoader;
1711 
1712 void setModuleRegistryBackingOwner(kj::Own<void> registry) {
1713 moduleRegistryBackingOwner = kj::mv(registry);
1714 }
1715 void setSchemaLoader(const capnp::SchemaLoader& schemaLoader);
1716 
1717 template <typename, typename>
1718 friend class ResourceWrapper;
1719};
1720 
1721// Reference to a JavaScript context whose global object wraps a C++ object of type T. This is
1722// similar to Ref but not the same, since JsContext provides access to the Context itself,
1723// which is more than just the global object.
1724template <typename T>
1725class JsContext {
1726 public:
1727 static_assert(
1728 std::is_base_of_v<ContextGlobal, T>, "context global type must extend jsg::ContextGlobal");
1729 
1730 JsContext(v8::Local<v8::Context> handle, Ref<T> object)
1731 : handle(v8::Isolate::GetCurrent(), handle),
1732 object(kj::mv(object)) {}
1733 
1734 JsContext(JsContext&&) = default;
1735 KJ_DISALLOW_COPY(JsContext);
1736 
1737 T& operator*() {
1738 return *object;
1739 }
1740 T* operator->() {
1741 return object.get();
1742 }
1743 
1744 v8::Local<v8::Context> getHandle(v8::Isolate* isolate) const {
1745 return handle.Get(isolate);
1746 }
1747 v8::Local<v8::Context> getHandle(Lock& js) const;
1748 
1749 private:
1750 v8::Global<v8::Context> handle;
1751 Ref<T> object;
1752};
1753 
1754class BufferSource;
1755 
1756constexpr bool hasPublicVisitForGc_(...) {
1757 return false;
1758}
1759template <typename T, typename = decltype(&T::visitForGc)>
1760constexpr bool hasPublicVisitForGc_(T*) {
1761 return true;
1762}
1763 
1764template <typename T>
1765constexpr bool hasPublicVisitForGc() {
1766 return hasPublicVisitForGc_(static_cast<T*>(nullptr));
1767}
1768 
1769// Visitor used during garbage collection. Any resource class that holds `Ref`s should
1770// implement GC visitation by declaring a private method like:
1771//
1772// private:
1773// void visitForGc(GcVisitor& visitor);
1774//
1775// In this method, call visitor.visit() on each `Ref` owned by the object.
1776//
1777// A `visitForGc()` method does NOT need to handle visiting superclasses. The JSG framework will
1778// automatically discover the presence of `visitForGc()` in each class in the hierarchy and will
1779// arrange for them all to be called. (Thus, when adding a new `visitForGc()` method to a class
1780// that has many subclasses, there is no need to update the subclasses.)
1781//
1782// Functors (freestanding functions/callbacks/lambdas, not declared as resources) can also
1783// implement GC visitation. To do so, implement the function as a struct with `operator()`, and
1784// also give the function a `visitForGc()` method. In this case, `visitForGc()` must be public.
1785//
1786// GC visitation is optional. If your type owns no `Ref`s, it can skip implementing
1787// `visitForGc()`. You can also omit `visitForGc()` if you don't care about the possibility of
1788// reference cycles. Any `Ref` which is not explicitly visited will not be eligible for
1789// garbage collection at all. Hence, failure to implement proper visitation may lead to memory
1790// leaks, but NOT to use-after-free.
1791//
1792// Note that GC visitation technically only collects JavaScript objects, including wrapper
1793// objects. C++ objects will not be collected if they contain reference cycles entirely in C++
1794// land. That is, if you have two C++ objects that contain `Ref`s to each other, and you
1795// implement GC visitation, the JavaScript wrapper objects wrapping these C++ objects will be
1796// collected, but the C++ objects will not -- a `Ref` can never becomes "dangling", and
1797// therefore the C++ objects cannot be destroyed because there's no correct order in which to
1798// destroy them. To avoid this situation, make sure your C++ objects have clear ownership, so
1799// that the reference graph is a DAG, just like you always would in C++.
1800class GcVisitor {
1801 public:
1802 template <typename T>
1803 void visit(Ref<T>& ref) {
1804 ref.inner->visitRef(*this, ref.parent, ref.strong);
1805 }
1806 
1807 template <typename T>
1808 void visit(kj::Maybe<Ref<T>>& maybeRef) {
1809 KJ_IF_SOME(ref, maybeRef) {
1810 visit(ref);
1811 }
1812 }
1813 
1814 void visit(Data& data);
1815 
1816 /// Visit a raw `v8::Global<Value>` + `v8::TracedReference<Data>` pair,
1817 /// implementing the same strongโ†”traced dual-mode switching as `visit(Data&)`.
1818 ///
1819 /// Used by the Rust JSG FFI to support `v8::Global<T>` fields on Rust
1820 /// resources without a full `jsg::Data` wrapper.
1821 void visit(v8::Global<v8::Value>& strong, v8::TracedReference<v8::Data>& traced);
1822 
1823 void visit(kj::Maybe<Data>& maybeData) {
1824 KJ_IF_SOME(data, maybeData) {
1825 visit(data);
1826 }
1827 }
1828 
1829 template <typename T>
1830 void visit(V8Ref<T>& value) {
1831 visit(static_cast<Data&>(value));
1832 }
1833 
1834 template <typename T>
1835 void visit(kj::Maybe<V8Ref<T>>& maybeValue) {
1836 KJ_IF_SOME(value, maybeValue) {
1837 visit(value);
1838 }
1839 }
1840 
1841 void visit(BufferSource& bufferSource);
1842 
1843 template <typename T, typename = kj::EnableIf<hasPublicVisitForGc<T>()>()>
1844 void visit(T& supportsVisit) {
1845 supportsVisit.visitForGc(*this);
1846 }
1847 
1848 template <typename T, typename = kj::EnableIf<hasPublicVisitForGc<T>()>()>
1849 void visit(kj::Maybe<T>& maybeSupportsVisit) {
1850 KJ_IF_SOME(supportsVisit, maybeSupportsVisit) {
1851 supportsVisit.visitForGc(*this);
1852 }
1853 }
1854 
1855 void visit() {}
1856 
1857 template <typename T, typename U, typename... Args>
1858 void visit(T& t, U& u, Args&... remaining) {
1859 visit(t);
1860 visit(u, kj::fwd<Args&>(remaining)...);
1861 }
1862 
1863 void visitAll(auto& collection) {
1864 for (auto& item: collection) {
1865 visit(item);
1866 }
1867 }
1868 
1869 private:
1870 Wrappable& parent;
1871 kj::Maybe<cppgc::Visitor&> cppgcVisitor;
1872 
1873 explicit GcVisitor(Wrappable& parent, kj::Maybe<cppgc::Visitor&> cppgcVisitor)
1874 : parent(parent),
1875 cppgcVisitor(cppgcVisitor) {}
1876 KJ_DISALLOW_COPY_AND_MOVE(GcVisitor);
1877 
1878 friend class Wrappable;
1879 friend class Object;
1880 friend class HeapTracer;
1881};
1882 
1883constexpr bool isGcVisitable_(...) {
1884 return false;
1885}
1886template <typename T, typename = decltype(kj::instance<GcVisitor>().visit(kj::instance<T&>()))>
1887constexpr bool isGcVisitable_(T*) {
1888 return true;
1889}
1890 
1891template <typename T>
1892constexpr bool isGcVisitable() {
1893 return isGcVisitable_(static_cast<T*>(nullptr));
1894}
1895 
1896// TypeHandler translates between V8 values and local values for a particular type T.
1897//
1898// When you define a function or method that is to be wrapped by V8, you can append TypeHandler
1899// references to your argument list, and they will automatically be filled in by the caller.
1900// This allows you to manually manage objects of this type in your code. For example, you could
1901// use this to manually test two different possible input types:
1902//
1903// void myMethod(v8::Local<v8::Value> handle,
1904// const TypeHandler<MyType1>& wrapper,
1905// const TypeHandler<MyType2>& wrapper) {
1906// KJ_IF_SOME(value1, wrapper.tryUnwrap(handle)) {
1907// value1.someMyType1Method();
1908// } KJ_IF_SOME(value2, wrapper.tryUnwrap(handle)) {
1909// value2.someMyType2Method();
1910// }
1911// }
1912//
1913// To use a JSG_RESOURCE_TYPE in the TypeHandler, it must be listed in your isolate type's
1914// JSG_DECLARE_ISOLATE_TYPE declaration. See JSG_DECLARE_ISOLATE_TYPE in setup.h for info.
1915// For resource types, also need to wrap in Ref, i.e. `TypeHandler<jsg::Ref<T>>`.
1916template <typename T>
1917class TypeHandler {
1918 public:
1919 // ---------------------------------------------------------------------------
1920 // Interface for value types (i.e. types not declared using JSG_RESOURCE_TYPE).
1921 //
1922 // This includes builtin types, e.g. `double` or `kj::String`.
1923 //
1924 // These methods will fail for resource types.
1925 
1926 // Wrap by value.
1927 virtual v8::Local<v8::Value> wrap(Lock& js, T value) const = 0;
1928 
1929 // Unwrap by value. Returns null if not the right type.
1930 virtual kj::Maybe<T> tryUnwrap(Lock& js, v8::Local<v8::Value> handle) const = 0;
1931};
1932 
1933// Utility that allows C++ code in a resource type to examine properties that have been added to
1934// its JavaScript wrapper.
1935//
1936// To use this, add a member of type `PropertyReflection<T>` to your resource type, then after
1937// your JSG_RESOURCE_TYPE block (NOT inside it; at the class scope), write
1938// `JSG_REFLECTION(name)`. You will then be able to use the reflection to read properties
1939// set on the JavaScript side, interpreting them as the type `T`.
1940//
1941// class Foo: public jsg::Object {
1942// public:
1943// ...
1944// JSG_RESOURCE_TYPE(EventTarget) {
1945// ...
1946// }
1947// JSG_REFLECTION(intReader, stringReader);
1948// private:
1949// PropertyReflection<int> intReader;
1950// PropertyReflection<kj::String> stringReader;
1951// }
1952//
1953// PropertyReflection's trick is that it isn't initialized until the JavaScript wrapper is
1954// created. Until that point, get() just always returns nullptr.
1955//
1956// PropertyReflection's main use case is reading event handler `onfoo` properties. That is,
1957// traditionally, instead of using `obj.addEventListener("foo", func)` to register an event
1958// handler, you can also do `obj.onfoo = func`.
1959template <typename T>
1960class PropertyReflection {
1961 public:
1962 // Read the property of this object called `name`, unwrapping it as type `T`.
1963 kj::Maybe<T> get(Lock& js, kj::StringPtr name);
1964 
1965 // Read the property of this object called `name`, unwrapping it as type `T`.
1966 kj::Maybe<T> get(v8::Isolate* isolate, kj::StringPtr name) {
1967 v8::HandleScope scope(isolate);
1968 KJ_IF_SOME(s, self) {
1969 KJ_IF_SOME(h, s.tryGetHandle(isolate)) {
1970 return unwrapper(isolate, h, name);
1971 }
1972 }
1973 return kj::none;
1974 }
1975 
1976 // TODO(someday): Support for reading Symbols and Privates?
1977 
1978 private:
1979 kj::Maybe<Wrappable&> self;
1980 
1981 using Unwrapper = kj::Maybe<T>(v8::Isolate*, v8::Local<v8::Object> object, kj::StringPtr name);
1982 Unwrapper* unwrapper = nullptr;
1983 
1984 template <typename, typename...>
1985 friend class TypeWrapper;
1986};
1987 
1988template <typename T>
1989concept CoercibleType = kj::isSameType<kj::String, T>() || kj::isSameType<USVString, T>() ||
1990 kj::isSameType<DOMString, T>() || kj::isSameType<bool, T>() || kj::isSameType<double, T>();
1991// When updating this list, be sure to keep the corresponding checks in the NonCoercibleWrapper
1992// class in value.h updated as well.
1993 
1994// By default types in JavaScript can be implicitly converted to other types as needed. This
1995// can lead to surprising results. For instance, passing null into an API method that accepts
1996// string will have the null coerced into the string value "null". The NonCoercible type can
1997// be used to disable automatic type coercion in APIs. For instance, NonCoercible<kj::String>
1998// will ensure that any value other than a string will be rejected with a TypeError.
1999//
2000// Here, T can be only one of several types that support coercion:
2001//
2002// * kj::String, jsg::USVString, jsg::DOMString (value must be a string)
2003// * bool (value must be a boolean)
2004// * double (value must be a number)
2005//
2006// It should be pointed out that using NonCoercible<T> runs counter to Web IDL and general
2007// Web Platform API best practices, which use type coercion fairly often. However, in certain
2008// Cloudflare-specific APIs, automatic coercion can cause surprising developer experience
2009// issues. Only use NonCoercible if you have a good reason to disable coercion. When in
2010// doubt, don't use it.
2011template <CoercibleType T>
2012struct NonCoercible {
2013 T value;
2014};
2015 
2016// -----------------------------------------------------------------------------
2017 
2018// A Sequence<T> in C++ corresponds to a Sequence IDL type. A sequence is a list of values
2019// that may or may not be an array. The key difference between the kj::Array mapping in
2020// JSG and a jsg::Sequence, is that the jsg::Sequence can be initialized from any object
2021// that exposes an @@iterable symbol. However, when a Sequence is surfaced back up to
2022// JavaScript, it will always be an array.
2023//
2024// At the C++ level, the Sequence itself is just a kj::Array<Value>.
2025//
2026// Both jsg::Sequence and jsg::Generator provide the ability to work with synchronous
2027// iterable/generator objects. The key difference is that jsg::Sequence will always
2028// produce a kj::Array of the elements, does not allow for early termination of the
2029// iteration, and does not provide access to the return value. jsg::Generator, on the
2030// other hand, allows performing an action on each individual item, terminating the
2031// iteration early, and retrieving the generators final return value, if any.
2032template <typename T>
2033struct Sequence;
2034 
2035// jsg::Generator wraps a JavaScript synchronous generator.
2036//
2037// jsg::Generator offers a `.forEach()` method that will invoke a callback function for
2038// each individual item produced by the generator:
2039//
2040// Generator<int> generator = ...;
2041// generator.forEach(js, [](Lock& js, int val, GeneratorContext<T> context) {
2042// // Do something with val.
2043// // To exit early from the iteration, either call `context.return_()`,
2044// // which will call the `.return()` method on the underlying generator,
2045// // or throw a JavaScript exception, which will call the `.throw()`
2046// // method on the underlying generator.
2047// });
2048//
2049// The Generator<T> is intended only to be used when receiving a Generator object as
2050// a parameter. Instances of Generator<T> cannot be passed back out to JavaScript. Refer
2051// to the documentation for JSG_ITERATOR to see how to create and pass Generator/Iterable
2052// objects back out to JavaScript.
2053//
2054// The `.forEach()` method is fully synchronous and will fully consume the generator
2055// before it returns. Calling `.forEach()` a second time on the generator will return
2056// immediately as a non-op.
2057template <typename T>
2058class Generator;
2059 
2060// The jsg::AsyncGenerator wraps a JavaScript asynchronous generator.
2061//
2062// The jsg::AsyncGenerator is similar to jsg::Generator except that it supports
2063// async iteration over the individual elements produced by the generator. The
2064// `.forEach()` method returns a `Promise<kj::Maybe<T>>>` that is resolved once the
2065// generator as been fully consumed. The callback passed in to `.forEach()` must
2066// also return a `Promise<void>` that is resolved whenever the item has been consumed
2067// and the iterator should advance to the next item.
2068//
2069// AsyncGenerator<int> generator = ...;
2070// generator.forEach(js, [](Lock& js, int val, GeneratorContext<T> context) {
2071// // Do something with val.
2072// // To exit early from the iteration, either call `context.return_()`,
2073// // which will call the `.return()` method on the underlying generator,
2074// // or throw a JavaScript exception, which will call the `.throw()`
2075// // method on the underlying generator.
2076// return js.resolvedPromise();
2077// }).then(js, [](Lock&, kj::Maybe<T>) { KJ_DBG("DONE!"); });
2078//
2079// The `.forEach()` method will fully consume the generator, returning a Promise
2080// that is resolved once the generator completes. Calling `.forEach()` a second
2081// time on the generator will return an immediately resolved promise.
2082template <typename T>
2083class AsyncGenerator;
2084 
2085// The jsg::GeneratorContext is used with both jsg::Generator and jsg::AsyncGenerator
2086// to allow for early termination of the generator iteration.
2087template <typename T>
2088class GeneratorContext;
2089 
2090// -----------------------------------------------------------------------------
2091 
2092struct JsgConfig {
2093 bool noSubstituteNull = false;
2094 bool unwrapCustomThenables = false;
2095 bool fetchIterableTypeSupport = false;
2096 bool fetchIterableTypeSupportOverrideAdjustment = false;
2097 bool fastApiEnabled = false;
2098};
2099 
2100static constexpr JsgConfig DEFAULT_JSG_CONFIG = {};
2101 
2102template <typename Config>
2103static const JsgConfig& getConfig(const Config& config) {
2104 if constexpr (kj::isSameType<Config, JsgConfig>() || kj::canConvert<Config, JsgConfig>()) {
2105 // Returning a reference to a parameter is harmless here since call sites pass in a reference to
2106 // config, which they can continue to use if returned here.
2107 // NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)
2108 return config;
2109 } else {
2110 return DEFAULT_JSG_CONFIG;
2111 }
2112}
2113 
2114// -----------------------------------------------------------------------------
2115 
2116class IsolateBase;
2117template <typename TypeWrapper>
2118class Isolate;
2119// Defined in setup.h -- most code doesn't need to use these directly.
2120 
2121template <typename T>
2122constexpr bool isV8Ref(T*) {
2123 return false;
2124}
2125template <typename T>
2126constexpr bool isV8Ref(V8Ref<T>*) {
2127 return true;
2128}
2129 
2130template <typename T>
2131constexpr bool isV8Ref() {
2132 return isV8Ref(static_cast<T*>(nullptr));
2133}
2134 
2135template <typename T>
2136constexpr bool isV8Local(T*) {
2137 return false;
2138}
2139template <typename T>
2140constexpr bool isV8Local(v8::Local<T>*) {
2141 return true;
2142}
2143 
2144template <typename T>
2145constexpr bool isV8Local() {
2146 return isV8Local(static_cast<T*>(nullptr));
2147}
2148 
2149template <typename T>
2150constexpr bool isV8MaybeLocal(T*) {
2151 return false;
2152}
2153template <typename T>
2154constexpr bool isV8MaybeLocal(v8::MaybeLocal<T>*) {
2155 return true;
2156}
2157 
2158template <typename T>
2159constexpr bool isV8MaybeLocal() {
2160 return isV8MaybeLocal(static_cast<T*>(nullptr));
2161}
2162 
2163class AsyncContextFrame;
2164template <typename T>
2165class JsRef;
2166 
2167#define JS_V8_SYMBOLS(V) \
2168 V(AsyncIterator) \
2169 V(HasInstance) \
2170 V(IsConcatSpreadable) \
2171 V(Iterator) \
2172 V(Match) \
2173 V(Replace) \
2174 V(Search) \
2175 V(Split) \
2176 V(ToPrimitive) \
2177 V(ToStringTag) \
2178 V(Unscopables) \
2179 V(Dispose) \
2180 V(AsyncDispose)
2181 
2182class JsValue;
2183class JsMessage;
2184#define JS_TYPE_CLASSES(V) \
2185 V(Object) \
2186 V(Boolean) \
2187 V(Array) \
2188 V(String) \
2189 V(Symbol) \
2190 V(BigInt) \
2191 V(Number) \
2192 V(Int32) \
2193 V(Uint32) \
2194 V(Date) \
2195 V(RegExp) \
2196 V(Map) \
2197 V(Set) \
2198 V(Promise) \
2199 V(Proxy) \
2200 V(Function) \
2201 V(Uint8Array) \
2202 V(ArrayBuffer) \
2203 V(ArrayBufferView)
2204 
2205#define V(Name) class Js##Name;
2206JS_TYPE_CLASSES(V)
2207#undef V
2208 
2209// JsBufferSource is not in JS_TYPE_CLASSES because there is no v8::BufferSource
2210// type (and hence no v8::Value::IsBufferSource() check). It is instead handled
2211// with special-case logic in JsValue::tryCast and JsValueWrapper.
2212class JsBufferSource;
2213 
2214#define V(Name) || kj::isSameType<T, Js##Name>()
2215template <typename T>
2216concept IsJsValue = kj::isSameType<T, JsValue>() ||
2217 kj::isSameType<T, JsMessage>() JS_TYPE_CLASSES(V) || kj::isSameType<T, JsBufferSource>();
2218#undef V
2219 
2220class DOMException;
2221class ExternalMemoryAdjustment;
2222 
2223// Used to save a reference to an isolate that is responsible for external memory usage.
2224// getAdjustment() can be invoked at any time to create a new RAII adjustment object
2225// pointing to this isolate.
2226//
2227// Each isolate has a singleton `ExternalMemoryTarget`, which all `ExternalMemoryAdjustment`s
2228// point to. The only purpose of this object is to hold a weak reference back to the isolate; the
2229// reference is nulled out when the isolate is destroyed.
2230class ExternalMemoryTarget: public kj::AtomicRefcounted {
2231 public:
2232 ExternalMemoryTarget(v8::Isolate* isolate): isolate(isolate) {}
2233 
2234 ExternalMemoryAdjustment getAdjustment(size_t amount) const;
2235 
2236 // Apply any deferred external memory updates. Must be called with isolate locked.
2237 void applyDeferredMemoryUpdate() const;
2238 
2239 // Disconnects the ExternalMemoryTarget from the isolate (called just before destroying the
2240 // isolate).
2241 void detach() const;
2242 
2243 // These two methods are for tests only.
2244 bool isIsolateAliveForTest() const;
2245 int64_t getPendingMemoryUpdateForTest() const;
2246 
2247 private:
2248 void maybeDeferAdjustment(ssize_t amount) const;
2249 void adjustNow(Lock& js, ssize_t amount) const;
2250 
2251 // Mutable so that it can be set null when the isolate is destroyed.
2252 mutable std::atomic<v8::Isolate*> isolate;
2253 static_assert(std::atomic<v8::Isolate*>::is_always_lock_free);
2254 
2255 // Tracks changes to external memory that were applied from a thread that did not hold the
2256 // isolate lock. These will be applied the next time the lock is taken.
2257 mutable std::atomic<int64_t> pendingExternalMemoryUpdate = {0};
2258 static_assert(std::atomic<int64_t>::is_always_lock_free);
2259 
2260 friend class ExternalMemoryAdjustment;
2261};
2262 
2263// RAII class to adjust the amount of external memory attributed to an isolate.
2264// The adjustment will be automatically decremented when the object is destroyed.
2265// The allocation amount can be adjusted up or down during the lifetime of an object.
2266class ExternalMemoryAdjustment final {
2267 public:
2268 ExternalMemoryAdjustment(kj::Arc<const ExternalMemoryTarget> externalMemory, size_t amount);
2269 ExternalMemoryAdjustment(ExternalMemoryAdjustment&& other) noexcept;
2270 ExternalMemoryAdjustment& operator=(ExternalMemoryAdjustment&& other);
2271 KJ_DISALLOW_COPY(ExternalMemoryAdjustment);
2272 ~ExternalMemoryAdjustment() noexcept(false);
2273 
2274 // Adjust the amount of external memory report up or down.
2275 void adjust(ssize_t amount);
2276 
2277 // Like adjust, except that the adjustment is applied immediately with no deferral.
2278 void adjustNow(Lock& js, ssize_t amount);
2279 
2280 // Set a specific amount of external memory to be attributed, overriding
2281 // the previous amount.
2282 void set(size_t amount);
2283 
2284 // Like set(), except that the adjustment is applied immediately with no deferral.
2285 void setNow(Lock& js, size_t amount);
2286 
2287 inline size_t getAmount() const {
2288 return amount;
2289 }
2290 
2291 private:
2292 kj::Arc<const ExternalMemoryTarget> externalMemory;
2293 size_t amount = 0;
2294 
2295 // If the isolate is locked, adjust the external memory immediately.
2296 // Otherwise, if we don't have the isolate locked, defer the adjustment to the next
2297 // time that we do.
2298 void maybeDeferAdjustment(ssize_t amount);
2299};
2300 
2301// If memory protection keys are enabled, provides the ability to run a function
2302// within the scope of a particular protection key associated with the isolate lock.
2303// This class is designed to be movable.
2304class MemoryProtectionKeyScope final {
2305 public:
2306 KJ_DISALLOW_COPY(MemoryProtectionKeyScope);
2307 MemoryProtectionKeyScope(MemoryProtectionKeyScope&&) = default;
2308 MemoryProtectionKeyScope& operator=(MemoryProtectionKeyScope&&) = default;
2309 
2310 auto runWithKey(auto func) {
2311#ifdef V8_ENABLE_SANDBOX
2312 PkeyScope scope(pkey);
2313#endif
2314 return func();
2315 }
2316 
2317 private:
2318#ifdef V8_ENABLE_SANDBOX
2319 int pkey;
2320 MemoryProtectionKeyScope(Lock&);
2321 
2322 struct PkeyScope {
2323 int key;
2324 int saved;
2325 PkeyScope(int pkey);
2326 ~PkeyScope();
2327 };
2328#else
2329 MemoryProtectionKeyScope(Lock&) {
2330 // No-op if sandboxing is not enabled.
2331 }
2332#endif
2333 
2334 friend class Lock;
2335};
2336 
2337// Represents an isolate lock, which allows the current thread to execute JavaScript code within
2338// an isolate. A thread must lock an isolate -- obtaining an instance of `Lock` -- before it can
2339// manipulate JavaScript objects or execute JavaScript code inside the isolate.
2340//
2341// The `Lock` interface also provides access to basic JavaScript functionality, such as the
2342// ability to construct basic JS values, throw and catch errors, etc.
2343//
2344// By convention, all functions which manipulate JavaScript take `Lock& js` as their first
2345// parameter. A `Lock&` reference must never be stored as an object member nor captured in a
2346// lambda, as `Lock`s are always constructed on the stack and so their lifetime is never
2347// guaranteed beyond the end of the function call.
2348//
2349// Methods declared with JSG_METHOD and similar macros may optionally take a `Lock&` as the
2350// first parameter. Template magic will automatically discover if the parameter is present and
2351// will populate it. Such methods are always invoked under lock whether or not they have a
2352// `Lock&` parameter, but it is recommended that you declare the parameter if the function
2353// touches the JS heap in any way. This way, if someone wants to call the method directly from
2354// C++, they know whether a lock is required.
2355//
2356// To create a lock in the first place, you have to create a specific instance of
2357// Isolate<TypeWrapper>::Lock. Usually this is only done in top-level code, and the Lock is
2358// passed down to everyone else from there. See setup.h for details.
2359 
2360class Lock {
2361 public:
2362 // The underlying V8 isolate, useful for directly calling V8 APIs. Hopefully, this is rarely
2363 // needed outside JSG itself.
2364 v8::Isolate* const v8Isolate;
2365 
2366 template <typename T, typename... Params>
2367 Ref<T> alloc(Params&&... params) {
2368 // TODO(soon): While it is possible to create jsg::Object instances outside of the
2369 // isolate lock, we intend to change that in order to improve memory accounting and
2370 // tracking of objects created while under lock. As such, all instances of jsg::alloc<T>(...)
2371 // are to be replaced by js.alloc<T>(...). For now, these are functionally equivalent.
2372 return Ref<T>(kj::refcounted<T>(kj::fwd<Params>(params)...));
2373 }
2374 
2375 // Like alloc() but attaches an external memory adjustment of size indicated by `accountedSize`.
2376 template <typename T, typename... Params>
2377 Ref<T> allocAccounted(size_t accountedSize, Params&&... params) {
2378 return Ref<T>(kj::refcounted<T>(kj::fwd<Params>(params)...)
2379 .attach(getExternalMemoryAdjustment(accountedSize)));
2380 }
2381 
2382 // When you want to temporarily use a memory allocation that is protected
2383 // by the isolate's memory protection key, use this to get a utility that
2384 // will capture the key and allow you to run a function with the key enabled.
2385 // The key use case is to allow tempporary access outside of the isolate lock
2386 // for things like ArrayBuffer backing stores.
2387 MemoryProtectionKeyScope getMemoryProtectionKeyScope() {
2388 return MemoryProtectionKeyScope(*this);
2389 }
2390 
2391 v8::Local<v8::Context> v8Context() {
2392 auto context = v8Isolate->GetCurrentContext();
2393 KJ_ASSERT(!context.IsEmpty(), "Isolate has no currently active v8::Context::Scope");
2394 return context;
2395 }
2396 
2397 // Get the current Lock for the given V8 isolate. Segfaults if the isolate is not locked.
2398 //
2399 // This method is intended to be used in callbacks from V8 that pass an isolate pointer but
2400 // don't provide any further context. Most code should rely on the caller passing in a `Lock&`.
2401 static Lock& from(v8::Isolate* v8Isolate) {
2402 return *reinterpret_cast<Lock*>(v8Isolate->GetData(SET_DATA_LOCK));
2403 }
2404 
2405 // TODO(someday): A clang-tidy rule to enforce use of Lock::current over
2406 // v8::Isolate::GetCurrent would be helpful.
2407 static Lock& current() {
2408 return from(v8::Isolate::GetCurrent());
2409 }
2410 
2411 // RAII construct that reports amount of external memory to be manually attributed to
2412 // the isolate. When the returned ExtrernalMemoryAdjuster is dropped, the amount will
2413 // be subtracted from the isolate's external memory accounting. If the adjuster is
2414 // dropped while the isolate lock is not being held, the adjustment will be deferred
2415 // until the next time the lock is held. The ExternalMemoryAdjustment itself can be
2416 // moved and can be used to increment or decrement the amount of external memory
2417 // held.
2418 ExternalMemoryAdjustment getExternalMemoryAdjustment(int64_t amount = 0);
2419 
2420 // Used to save a reference to an isolate that is responsible for external memory usage.
2421 // getAdjustment() can be invoked at any time to create a new RAII adjustment object
2422 // pointing to this isolate
2423 kj::Arc<const ExternalMemoryTarget> getExternalMemoryTarget();
2424 
2425 Value parseJson(kj::ArrayPtr<const char> data);
2426 Value parseJson(v8::Local<v8::String> text);
2427 template <typename T>
2428 kj::String serializeJson(V8Ref<T>& value) {
2429 return serializeJson(value.getHandle(*this));
2430 }
2431 template <typename T>
2432 kj::String serializeJson(V8Ref<T>&& value) {
2433 // Callers expect the rvalue-reference to be consumed, and to ensure
2434 // that, explicitly move it into a local variable
2435 auto moved = kj::mv(value);
2436 return serializeJson(moved.getHandle(*this));
2437 }
2438 
2439 void recursivelyFreeze(Value& value);
2440 
2441 // ---------------------------------------------------------------------------
2442 // Exception-related stuff
2443 
2444 // Converts the KJ exception to a JS exception. If the KJ exception is a tunneled JavaScript
2445 // error, this reproduces the original error. If it is not a tunneled error, then it is treated
2446 // as an internal error: the KJ exception message is logged to stderr, and a JavaScript error
2447 // is returned with a generic description.
2448 Value exceptionToJs(kj::Exception&& exception, ExceptionToJsOptions options = {});
2449 
2450 JsRef<JsValue> exceptionToJsValue(kj::Exception&& exception, ExceptionToJsOptions options = {});
2451 
2452 // Encodes the given JavaScript exception into a KJ exception, formatting the description in
2453 // such a way that hopefully exceptionToJs() can reproduce something equivalent to the original
2454 // JavaScript error.
2455 kj::Exception exceptionToKj(const JsValue& exception);
2456 
2457 // Encodes the given JavaScript exception into a KJ exception, formatting the description in
2458 // such a way that hopefully exceptionToJs() can reproduce something equivalent to the original
2459 // JavaScript error.
2460 kj::Exception exceptionToKj(Value&& exception);
2461 
2462 // Throws a JavaScript exception. The exception is scheduled on the isolate, and then an
2463 // instance of `JsExceptionThrown` is thrown in C++. All places where JavaScript calls into C++
2464 // via JSG understand how to handle this and propagate the exception back to JavaScript.
2465 [[noreturn]] void throwException(Value&& exception);
2466 
2467 [[noreturn]] void throwException(kj::Exception&& exception, ExceptionToJsOptions options = {}) {
2468 throwException(exceptionToJs(kj::mv(exception), options));
2469 }
2470 
2471 [[noreturn]] void throwException(const JsValue& exception);
2472 
2473 // Invokes `func()` synchronously, catching exceptions. In the event of an exception,
2474 // `errorHandler()` will be called, passing the exception as type `jsg::Value`.
2475 //
2476 // KJ exceptions are also caught and will be converted to JS exceptions using exceptionToJs().
2477 //
2478 // Some kinds of exceptions explicitly will not be caught:
2479 // - Exceptions where JavaScript execution cannot continue, such as the "uncatchable exception"
2480 // produced by IsolateBase::TerminateExecution().
2481 // - C++ exceptions other than `kj::Exception`, e.g. `std::bad_alloc`. These exceptions are
2482 // assumed to be serious enough that they cannot be caught as if they were JavaScript errors,
2483 // and instead unwind must continue until C++ catches them.
2484 //
2485 // func() and errorHandler() must return the same type; the value they return will be returned
2486 // from `tryCatch()` itself.
2487 template <typename Func, typename ErrorHandler>
2488 auto tryCatch(Func&& func,
2489 ErrorHandler&& errorHandler,
2490 // If an exception occurs, convert KJ exceptions to JS exceptions
2491 // using these options.
2492 ExceptionToJsOptions options = {}) -> decltype(func()) {
2493 Value error = nullptr;
2494 
2495 {
2496 v8::TryCatch tryCatch(v8Isolate);
2497 try {
2498 return func();
2499 } catch (JsExceptionThrown&) {
2500 // If tryCatch.HasCaught() is false, it typically means that JsExceptionThrown
2501 // was thrown without an exception actually being scheduled on the isolate.
2502 // This may happen in particular when the JsExceptionThrown was the result of
2503 // TerminateExecution() but V8 has since cleared the terminate flag because all
2504 // JavaScript call frames have been unwound. Hence, we want to treat this the
2505 // same as if `CanContinue()` returned false.
2506 // TODO(cleanup): Do more investigation, maybe explicitly check for the termination
2507 // flag or arrange to maintain our own separate termination flag to avoid confusion.
2508 if (!tryCatch.CanContinue() || !tryCatch.HasCaught() || tryCatch.Exception().IsEmpty()) {
2509 tryCatch.ReThrow();
2510 throw;
2511 }
2512 
2513 error = Value(v8Isolate, tryCatch.Exception());
2514 } catch (kj::Exception& e) {
2515 error = exceptionToJs(kj::mv(e), options);
2516 }
2517 }
2518 
2519 // We have to make sure the `v8::TryCatch` is off the stack before invoking `errorHandler`,
2520 // otherwise the same `TryCatch` will catch any exceptions the error handler throws, ugh.
2521 return errorHandler(kj::mv(error));
2522 }
2523 
2524 // Like tryCatch() but returns a Promise<T> that resolves to the result of func() or
2525 // rejects with the result of errorHandler() if an exception is thrown.
2526 template <typename T, typename Func>
2527 Promise<T> tryOrReject(Func&& func) {
2528 return tryCatch([&]() -> Promise<T> { return toPromise(func()); },
2529 [&](Value&& error) -> Promise<T> { return rejectedPromise<T>(kj::mv(error)); });
2530 }
2531 
2532 // ---------------------------------------------------------------------------
2533 // Promise-related stuff
2534 
2535 // Get a pair of a Promise<T> and a Promise<T>::Resolver that resolves the promise. You should
2536 // call this like:
2537 //
2538 // auto [promise, resolver] = js.newPromiseAndResolver();
2539 template <typename T>
2540 PromiseResolverPair<T> newPromiseAndResolver();
2541 
2542 // Construct an immediately-resolved promise resolving to the given value.
2543 template <typename T>
2544 Promise<T> resolvedPromise(T&& value);
2545 
2546 // Construct an immediately-resolved promise resolving to the given value.
2547 Promise<void> resolvedPromise();
2548 
2549 // Construct an immediately-rejected promise throwing the given exception.
2550 template <typename T>
2551 Promise<T> rejectedPromise(v8::Local<v8::Value> exception);
2552 
2553 // Construct an immediately-rejected promise throwing the given exception.
2554 template <typename T>
2555 Promise<T> rejectedPromise(jsg::Value exception);
2556 
2557 // Construct an immediately-rejected promise throwing the given exception.
2558 template <typename T>
2559 Promise<T> rejectedPromise(kj::Exception&& exception, ExceptionToJsOptions options = {});
2560 
2561 // Like above, but return a pure-JS promise, not a typed Promise.
2562 JsPromise rejectedJsPromise(jsg::JsValue exception);
2563 JsPromise rejectedJsPromise(kj::Exception&& exception, ExceptionToJsOptions options = {});
2564 JsPromise resolvedJsPromise(jsg::JsValue value);
2565 
2566 // Like `kj::evalNow()`, but returns a jsg::Promise for the result. Synchronous exceptions are
2567 // caught and returned as a rejected promise.
2568 //
2569 // If an exception is caught as a result of TerminateExecution() being called, it is rethrown
2570 // to the caller, not encapsulated in a promise.
2571 //
2572 // Note `func` is NOT expected to take `Lock&` as a parameter, as normally func should be a lambda
2573 // that captures `[&]`, so will capture the caller's lock reference. Capturing the lock here is
2574 // allowed since `func` is invoked synchronously.
2575 template <class Func>
2576 PromiseForResult<Func, void, false> evalNow(Func&& func);
2577 
2578 // ---------------------------------------------------------------------------
2579 // Name/Symbol stuff
2580 
2581 // Creates a Name encapsulating a new unique v8::Symbol.
2582 Name newSymbol(kj::StringPtr symbol);
2583 
2584 // Creates a Name encapsulating a name from the global symbol registry.
2585 // Equivalent to Symbol.for(symbol) in JavaScript.
2586 Name newSharedSymbol(kj::StringPtr symbol);
2587 
2588 // Similar to newSharedSymbol except that it uses a separate isolate registry
2589 // that is not accessible by JavaScript.
2590 Name newApiSymbol(kj::StringPtr symbol);
2591 
2592 // ---------------------------------------------------------------------------
2593 // Logging stuff
2594 
2595 inline bool areWarningsLogged() const {
2596 return warningsLogged;
2597 }
2598 
2599 // Emits the warning only if there is anywhere for the log to go (for instance,
2600 // if debug logging is enabled or the inspector is being used).
2601 void logWarning(kj::StringPtr message);
2602 
2603 // TODO(later): Add the other log variants from IoContext? eg. logWarningOnce,
2604 // logErrorOnce, logUncaughtException, etc.
2605 
2606 // ---------------------------------------------------------------------------
2607 // v8 Local handle related stuff
2608 // TODO(cleanup): Direct use of v8::Local handles is discouraged and is something we are trying
2609 // to move away from. However, there are still plenty of cases where we need to do so. The
2610 // methods here help avoid directly using v8::Isolate and serve as an interim until we can
2611 // eliminate direct use as much as possible.
2612 // Convenience methods to unwrap various types of V8 values. All of these could be done manually
2613 // via the V8 API, but these methods are much easier.
2614 
2615 v8::Local<v8::Value> v8Undefined();
2616 v8::Local<v8::Value> v8Null();
2617 
2618 v8::Local<v8::Value> v8Error(kj::StringPtr message);
2619 v8::Local<v8::Value> v8TypeError(kj::StringPtr message);
2620 
2621 void v8Set(v8::Local<v8::Object> obj, V8Ref<v8::String>& name, Value& value);
2622 void v8Set(v8::Local<v8::Object> obj, kj::StringPtr name, v8::Local<v8::Value> value);
2623 void v8Set(v8::Local<v8::Object> obj, kj::StringPtr name, Value& value);
2624 v8::Local<v8::Value> v8Get(v8::Local<v8::Object> obj, kj::StringPtr name);
2625 v8::Local<v8::Value> v8Get(v8::Local<v8::Array> obj, uint idx);
2626 bool v8Has(v8::Local<v8::Object> obj, kj::StringPtr name);
2627 bool v8HasOwn(v8::Local<v8::Object> obj, kj::StringPtr name);
2628 
2629 template <typename T>
2630 V8Ref<T> v8Ref(v8::Local<T> local);
2631 Data v8Data(v8::Local<v8::Data> data);
2632 
2633 kj::String serializeJson(v8::Local<v8::Value> value);
2634 
2635 v8::Local<v8::String> wrapString(kj::StringPtr text);
2636 virtual v8::Local<v8::ArrayBuffer> wrapBytes(kj::Array<byte> data) = 0;
2637 virtual v8::Local<v8::Function> wrapSimpleFunction(v8::Local<v8::Context> context,
2638 jsg::Function<void(const v8::FunctionCallbackInfo<v8::Value>& info)> simpleFunction) = 0;
2639 
2640 // A variation on wrapSimpleFunction that allows for a return value. While the wrapSimpleFunction
2641 // implementation passes the FunctionCallbackInfo into the called function, any call to
2642 // GetReturnValue().Set(...) to specify a return value will be ignored by the FunctorCallback
2643 // wrapper. The wrapReturningFunction variation forces the wrapper to use the version that
2644 // pays attention to the return value.
2645 virtual v8::Local<v8::Function> wrapReturningFunction(v8::Local<v8::Context> context,
2646 jsg::Function<v8::Local<v8::Value>(const v8::FunctionCallbackInfo<v8::Value>& info)>
2647 returningFunction) = 0;
2648 virtual v8::Local<v8::Function> wrapPromiseReturningFunction(v8::Local<v8::Context> context,
2649 jsg::Function<jsg::Promise<jsg::Value>(const v8::FunctionCallbackInfo<v8::Value>& info)>
2650 returningFunction) = 0;
2651 // TODO(later): See if we can easily combine wrapSimpleFunction and wrapReturningFunction
2652 // into one.
2653 
2654 virtual v8::Local<v8::Promise> wrapSimplePromise(Promise<Value> promise) = 0;
2655 
2656 bool toBool(v8::Local<v8::Value> value);
2657 virtual kj::String toString(v8::Local<v8::Value> value) = 0;
2658 virtual jsg::Dict<v8::Local<v8::Value>> toDict(v8::Local<v8::Value> value) = 0;
2659 virtual jsg::Dict<JsValue> toDict(const jsg::JsValue& value) = 0;
2660 virtual Promise<Value> toPromise(v8::Local<v8::Value> promise) = 0;
2661 
2662 // ---------------------------------------------------------------------------
2663 // Setup stuff
2664 
2665 // Use to enable/disable dynamic code evaluation (via eval(), new Function(), or WebAssembly).
2666 void setAllowEval(bool allow);
2667 
2668 void setCaptureThrowsAsRejections(bool capture);
2669 void setUsingEnhancedErrorSerialization();
2670 void setUsingFastJsgStruct();
2671 bool isUsingFastJsgStruct() const;
2672 bool isUsingEnhancedErrorSerialization() const;
2673 
2674 void setNodeJsCompatEnabled();
2675 void setNodeJsProcessV2Enabled();
2676 void setRequireReturnsDefaultExportEnabled();
2677 void setThrowOnUnrecognizedImportAssertion();
2678 bool getThrowOnUnrecognizedImportAssertion() const;
2679 void setToStringTag();
2680 void setImmutablePrototype();
2681 void setSpecCompliantPropertyAttributes();
2682 void disableTopLevelAwait();
2683 
2684 using Logger = void(Lock&, kj::StringPtr);
2685 void setLoggerCallback(kj::Function<Logger>&& logger);
2686 
2687 using ErrorReporter = void(Lock&, kj::String, const JsValue&, const JsMessage&);
2688 void setErrorReporterCallback(kj::Function<ErrorReporter>&& errorReporter);
2689 
2690 // ---------------------------------------------------------------------------
2691 // Misc. Stuff
2692 
2693 // Sends an immediate request for full GC, this function is to ONLY be used in testing, otherwise
2694 // it will throw. If a need for a minor GC is needed look at the call in jsg.c++ and the
2695 // implementation in setup.c++. Use responsibly.
2696 void requestGcForTesting() const;
2697 
2698 // Runs the given function synchronously with a v8::HandleScope on the stack.
2699 // If the fn returns a v8::Local<T> or v8::MaybeLocal<T> type, then
2700 // v8::EscapableHandleScope is used ensuring that the v8::Local<T> return
2701 // value is properly handled.
2702 auto withinHandleScope(auto&& fn) {
2703 using Ret = decltype(fn());
2704 if constexpr (IsJsValue<Ret>) {
2705 v8::EscapableHandleScope scope(v8Isolate);
2706 v8::Local<v8::Value> value = fn();
2707 return Ret(scope.Escape(value));
2708 } else if constexpr (isV8Local<Ret>()) {
2709 v8::EscapableHandleScope scope(v8Isolate);
2710 return scope.Escape(fn());
2711 } else if constexpr (isV8MaybeLocal<Ret>()) {
2712 v8::EscapableHandleScope scope(v8Isolate);
2713 return scope.EscapeMaybe(fn());
2714 } else {
2715 v8::HandleScope scope(v8Isolate);
2716 return fn();
2717 }
2718 }
2719 
2720 virtual Ref<DOMException> domException(
2721 kj::String name, kj::String message, kj::Maybe<kj::String> stackValue = kj::none) = 0;
2722 
2723 // Get the prototype object for the given C++ type (which must be a JSG_RESOURCE_TYPE).
2724 //
2725 // WARNING: A malicious script can tamper with this by overwriting the `prototype` property
2726 // of the class object.
2727 template <typename T>
2728 JsObject getPrototypeFor();
2729 
2730 // ====================================================================================
2731 JsObject global() KJ_WARN_UNUSED_RESULT;
2732 JsValue undefined() KJ_WARN_UNUSED_RESULT;
2733 JsValue null() KJ_WARN_UNUSED_RESULT;
2734 JsBoolean boolean(bool val) KJ_WARN_UNUSED_RESULT;
2735 JsNumber num(double) KJ_WARN_UNUSED_RESULT;
2736 JsNumber num(float) KJ_WARN_UNUSED_RESULT;
2737 JsInt32 num(int8_t) KJ_WARN_UNUSED_RESULT;
2738 JsInt32 num(int16_t) KJ_WARN_UNUSED_RESULT;
2739 JsInt32 num(int32_t) KJ_WARN_UNUSED_RESULT;
2740 JsUint32 num(uint8_t) KJ_WARN_UNUSED_RESULT;
2741 JsUint32 num(uint16_t) KJ_WARN_UNUSED_RESULT;
2742 JsUint32 num(uint32_t) KJ_WARN_UNUSED_RESULT;
2743 JsBigInt bigInt(int64_t) KJ_WARN_UNUSED_RESULT;
2744 JsBigInt bigInt(uint64_t) KJ_WARN_UNUSED_RESULT;
2745 JsString str() KJ_WARN_UNUSED_RESULT;
2746 JsString str(kj::ArrayPtr<const char16_t>) KJ_WARN_UNUSED_RESULT;
2747 JsString str(kj::ArrayPtr<const uint16_t>) KJ_WARN_UNUSED_RESULT;
2748 JsString str(kj::ArrayPtr<const char>) KJ_WARN_UNUSED_RESULT;
2749 JsString str(kj::ArrayPtr<const kj::byte>) KJ_WARN_UNUSED_RESULT;
2750 JsString strIntern(kj::StringPtr) KJ_WARN_UNUSED_RESULT;
2751 JsString strExtern(kj::ArrayPtr<const char>) KJ_WARN_UNUSED_RESULT;
2752 JsString strExtern(kj::ArrayPtr<const uint16_t>) KJ_WARN_UNUSED_RESULT;
2753 JsSymbol symbol(kj::StringPtr) KJ_WARN_UNUSED_RESULT;
2754 JsSymbol symbolShared(kj::StringPtr) KJ_WARN_UNUSED_RESULT;
2755 JsSymbol symbolInternal(kj::StringPtr) KJ_WARN_UNUSED_RESULT;
2756 JsObject obj() KJ_WARN_UNUSED_RESULT;
2757 JsObject obj(kj::ArrayPtr<const kj::StringPtr> keys,
2758 kj::ArrayPtr<jsg::JsValue> values) KJ_WARN_UNUSED_RESULT;
2759 JsObject objNoProto() KJ_WARN_UNUSED_RESULT;
2760 JsObject objNoProto(
2761 kj::ArrayPtr<kj::StringPtr> keys, kj::ArrayPtr<jsg::JsValue> values) KJ_WARN_UNUSED_RESULT;
2762 JsMap map() KJ_WARN_UNUSED_RESULT;
2763 JsValue external(void*) KJ_WARN_UNUSED_RESULT;
2764 JsValue error(kj::StringPtr message) KJ_WARN_UNUSED_RESULT;
2765 JsValue typeError(kj::StringPtr message) KJ_WARN_UNUSED_RESULT;
2766 JsValue rangeError(kj::StringPtr message) KJ_WARN_UNUSED_RESULT;
2767 JsDate date(double timestamp) KJ_WARN_UNUSED_RESULT;
2768 JsDate date(kj::Date date) KJ_WARN_UNUSED_RESULT;
2769 JsDate date(kj::StringPtr date) KJ_WARN_UNUSED_RESULT;
2770 
2771 // Returns a JsObject that is backed internally by a v8::External object that
2772 // takes ownership over the inner.
2773 template <typename T>
2774 JsObject opaque(T&& inner) KJ_WARN_UNUSED_RESULT;
2775 
2776 // Returns a jsg::BufferSource whose underlying JavaScript handle is a Uint8Array.
2777 BufferSource bytes(kj::Array<kj::byte> data) KJ_WARN_UNUSED_RESULT;
2778 
2779 // Returns a jsg::BufferSource whose underlying JavaScript handle is an ArrayBuffer
2780 // as opposed to the default Uint8Array. May copy and move the bytes if they are
2781 // not in the right sandbox.
2782 BufferSource arrayBuffer(kj::Array<kj::byte> data) KJ_WARN_UNUSED_RESULT;
2783 
2784 enum class AllocOption { ZERO_INITIALIZED, UNINITIALIZED };
2785 
2786 // Utility method to safely allocate a v8::BackingStore with allocation failure handling.
2787 // Throws a javascript error if allocation fails.
2788 //
2789 // IMPORTANT: This method can trigger garbage collection, which may move or invalidate V8
2790 // objects. Do NOT call this method while:
2791 // - A v8::String::ValueView is alive (it holds internal V8 heap locks)
2792 // - You have raw pointers to V8 heap data (e.g., from view.data8(), view.data16())
2793 //
2794 // Safe pattern: Copy V8 string data to off-heap memory FIRST (e.g., via JsString::writeInto()
2795 // into kj::SmallArray), THEN call allocBackingStore(). See TextEncoder::encode() for example.
2796 std::unique_ptr<v8::BackingStore> allocBackingStore(
2797 size_t size, AllocOption init_mode = AllocOption::ZERO_INITIALIZED) KJ_WARN_UNUSED_RESULT;
2798 
2799 enum RegExpFlags {
2800 kNONE = v8::RegExp::Flags::kNone,
2801 kGLOBAL = v8::RegExp::Flags::kGlobal,
2802 kIGNORE_CASE = v8::RegExp::Flags::kIgnoreCase,
2803 kMULTILINE = v8::RegExp::Flags::kMultiline,
2804 kSTICKY = v8::RegExp::Flags::kSticky,
2805 kUNICODE = v8::RegExp::Flags::kUnicode,
2806 kDOTALL = v8::RegExp::Flags::kDotAll,
2807 kLINEAR = v8::RegExp::Flags::kLinear,
2808 kHAS_INDICES = v8::RegExp::Flags::kHasIndices,
2809 kUNICODE_SETS = v8::RegExp::Flags::kUnicodeSets,
2810 };
2811 
2812 JsRegExp regexp(kj::StringPtr pattern,
2813 RegExpFlags flags = RegExpFlags::kNONE,
2814 kj::Maybe<uint32_t> backtrackLimit = kj::none) KJ_WARN_UNUSED_RESULT;
2815 
2816 template <typename... Args>
2817 requires(std::assignable_from<JsValue&, Args> && ...)
2818 JsArray arr(const Args&... args) KJ_WARN_UNUSED_RESULT;
2819 
2820 JsArray arr(kj::ArrayPtr<JsValue> values) KJ_WARN_UNUSED_RESULT;
2821 
2822 // Create a JavaScript array from the given kj::ArrayPtr, passing each
2823 // item through the given transformation function to create the appropriate
2824 // JsValue.
2825 template <typename T, typename Func>
2826 JsArray arr(kj::ArrayPtr<T> values, Func fn) KJ_WARN_UNUSED_RESULT;
2827 
2828 template <typename... Args>
2829 requires(std::assignable_from<JsValue&, Args> && ...)
2830 JsSet set(const Args&... args) KJ_WARN_UNUSED_RESULT;
2831 
2832#define V(Name) JsSymbol symbol##Name() KJ_WARN_UNUSED_RESULT;
2833 JS_V8_SYMBOLS(V)
2834#undef V
2835 
2836 void runMicrotasks();
2837 
2838 // Request an extra microtask checkpoint after the current one completes.
2839 void requestExtraMicrotaskCheckpoint();
2840 
2841 // Sets the terminate-execution flag on the isolate so that the next time code tries to run, it
2842 // will be terminated. (But note that V8 only checks the flag at certain times, so it's possible
2843 // some code will actually execute before termination kicks in.)
2844 void terminateNextExecution();
2845 
2846 // Terminates exution immediately, forcing V8 to see the flag and react to it before returning.
2847 // Always throws JsExceptionThrown.
2848 [[noreturn]] void terminateExecutionNow();
2849 
2850 bool pumpMsgLoop();
2851 
2852 // Logs and reports the error to tail workers (if called within an request),
2853 // the inspector (if attached), or to KJ_LOG(Info).
2854 virtual void reportError(const JsValue& value) = 0;
2855 
2856 // Store the worker environment.
2857 virtual void setWorkerEnv(V8Ref<v8::Object> value) = 0;
2858 
2859 // Retrieve the worker environment.
2860 virtual kj::Maybe<V8Ref<v8::Object>> getWorkerEnv() = 0;
2861 
2862 // Store the worker exports.
2863 virtual void setWorkerExports(V8Ref<v8::Object> value) = 0;
2864 
2865 // Retrieve the worker exports.
2866 virtual kj::Maybe<V8Ref<v8::Object>> getWorkerExports() = 0;
2867 
2868 // Resolve an internal module namespace from the given specifier.
2869 // This variation can be used only for internal built-ins.
2870 kj::Maybe<JsObject> resolveInternalModule(kj::StringPtr specifier);
2871 
2872 // Resolve a user-importable built-in module namespace from the given specifier.
2873 // Unlike resolveInternalModule, this only searches user-importable built-ins
2874 // (PUBLIC_BUILTIN context), excluding internal-only modules and worker bundle
2875 // modules. Use this for user-facing APIs like process.getBuiltinModule() that
2876 // must not expose internal modules or return user bundle overrides.
2877 // Only valid when the new module registry is in use.
2878 kj::Maybe<JsObject> resolvePublicBuiltinModule(kj::StringPtr specifier);
2879 
2880 // Resolve a module namespace from the given specifier.
2881 // This variation includes modules from the worker bundle.
2882 kj::Maybe<JsObject> resolveModule(
2883 kj::StringPtr specifier, RequireEsm requireEsm = RequireEsm::NO);
2884 
2885 // Returns the capnp::SchemaLoader for this isolate/context
2886 template <typename T>
2887 const capnp::SchemaLoader& getCapnpSchemaLoader() const {
2888 return KJ_ASSERT_NONNULL(
2889 jsg::getAlignedPointerFromEmbedderData<T>(
2890 v8Isolate->GetCurrentContext(), ContextPointerSlot::GLOBAL_WRAPPER))
2891 .getSchemaLoader();
2892 }
2893 
2894 private:
2895 // Mark the jsg::Lock as being disallowed from being passed as a parameter into
2896 // a kj promise coroutine. Note that this only blocks directly passing the Lock
2897 // in. Types that have the Lock included as a member field won't be caught and
2898 // should themselves be marked with KJ_DISALLOW_AS_COROUTINE_PARAM. Note also
2899 // that this would not stop someone from passing the v8::Isolate reference into
2900 // the coroutine and using `Lock::from(...)` to get the Lock. Don't do that.
2901 // jsg::Lock should NOT be used within a kj promise coroutine.
2902 KJ_DISALLOW_AS_COROUTINE_PARAM;
2903 friend class IsolateBase;
2904 template <typename TypeWrapper>
2905 friend class Isolate;
2906 
2907 Lock(v8::Isolate* v8Isolate);
2908 ~Lock() noexcept(false);
2909 
2910 v8::Locker locker;
2911 v8::Isolate::Scope isolateScope;
2912 
2913 void* previousData;
2914 
2915 bool warningsLogged;
2916 
2917 friend class JsObject;
2918 virtual kj::Maybe<Object&> getInstance(v8::Local<v8::Object> obj, const std::type_info& type) = 0;
2919 virtual v8::Local<v8::Object> getPrototypeFor(const std::type_info& type) = 0;
2920};
2921 
2922// Ensures that the given fn is run within both a handlescope and the context scope.
2923// The lock must be assignable to a jsg::Lock, and the context must be or be assignable
2924// to a v8::Local<v8::Context>. The context will be evaluated within the handle scope.
2925#define JSG_WITHIN_CONTEXT_SCOPE(lock, context, fn) \
2926 (static_cast<jsg::Lock&>(lock)).withinHandleScope([&]() -> auto { \
2927 v8::Local<v8::Context> ctx = context; \
2928 KJ_ASSERT(!ctx.IsEmpty(), "unable to enter invalid v8::Context"); \
2929 v8::Context::Scope scope(ctx); \
2930 return fn(static_cast<jsg::Lock&>(lock)); \
2931 })
2932 
2933// The V8StackScope is used only as a marker to prove that we are running in the V8 stack
2934// established by calling runInV8Stack(...)
2935class V8StackScope final {
2936 public:
2937 KJ_DISALLOW_COPY_AND_MOVE(V8StackScope);
2938 
2939 private:
2940 V8StackScope() = default;
2941 KJ_DISALLOW_AS_COROUTINE_PARAM;
2942 
2943 static auto runInV8StackImpl(void* pos, auto callback) __attribute__((noinline)) {
2944#if V8_HAS_STACK_START_MARKER
2945 // This currently depends on a V8 patch which hasn't been upstreamed. Note that workerd does
2946 // not use this patch; it's only used internally. The patch is needed in order to work around
2947 // oddities of our internal environment which do not apply to workerd. For workerd, V8's default
2948 // behavior is just fine.
2949 v8::StackStartMarker marker(pos);
2950#endif
2951 // We create a V8StackScope only as proof that we are running in the V8 stack.
2952 V8StackScope stackScope;
2953 return callback(stackScope);
2954 }
2955 
2956 friend auto runInV8Stack(auto callback);
2957};
2958 
2959// Ensures that a v8::StackStartMarker is allocated on the stack before calling the callback.
2960// This must be used, for instance, before taking an isolate lock.
2961// The reason why Isolate::Lock doesn't take care of this automatically is because it is often
2962// allocated on the heap. The purpose of using runInV8Stack is to capture the start of the stack
2963// range that V8 must scan when performing conservative stack-scanning garbage collection.
2964auto runInV8Stack(auto callback) {
2965 return V8StackScope::runInV8StackImpl(__builtin_frame_address(0), kj::mv(callback));
2966};
2967 
2968// Returns true if we are currently executing C++ destructors as a result of garbage collection
2969// occurring.
2970bool isInGcDestructor();
2971 
2972// =======================================================================================
2973// inline implementation details
2974 
2975template <typename T>
2976template <typename U>
2977V8Ref<U> V8Ref<T>::cast(jsg::Lock& js) {
2978 return js.v8Ref(getHandle(js).template As<U>());
2979}
2980 
2981template <typename T>
2982inline kj::Maybe<T> PropertyReflection<T>::get(Lock& js, kj::StringPtr name) {
2983 return get(js.v8Isolate, name);
2984}
2985 
2986template <typename T>
2987inline V8Ref<T> Lock::v8Ref(v8::Local<T> local) {
2988 return V8Ref(v8Isolate, local);
2989}
2990 
2991inline Data Lock::v8Data(v8::Local<v8::Data> local) {
2992 return Data(v8Isolate, local);
2993}
2994 
2995inline v8::Local<v8::Value> Lock::v8Undefined() {
2996 return v8::Undefined(v8Isolate);
2997}
2998 
2999inline v8::Local<v8::Value> Lock::v8Null() {
3000 return v8::Null(v8Isolate);
3001}
3002 
3003inline Data Data::addRef(jsg::Lock& js) {
3004 return Data(js.v8Isolate, getHandle(js));
3005}
3006 
3007template <typename T>
3008kj::Maybe<v8::Local<v8::Object>> Ref<T>::tryGetHandle(Lock& js) {
3009 return tryGetHandle(js.v8Isolate);
3010}
3011 
3012template <typename T>
3013inline V8Ref<T> V8Ref<T>::addRef(jsg::Lock& js) {
3014 return js.v8Ref(getHandle(js));
3015}
3016 
3017template <typename T>
3018V8Ref<T> V8Ref<T>::deepClone(jsg::Lock& js) {
3019 return js.v8Ref(jsg::deepClone(js.v8Context(), getHandle(js)).template As<T>());
3020}
3021 
3022template <typename T>
3023inline HashableV8Ref<T> HashableV8Ref<T>::addRef(jsg::Lock& js) {
3024 return HashableV8Ref(js.v8Isolate, this->getHandle(js), identityHash);
3025}
3026 
3027template <typename T>
3028inline v8::Local<T> V8Ref<T>::getHandle(jsg::Lock& js) const {
3029 return getHandle(js.v8Isolate);
3030}
3031 
3032inline v8::Local<v8::Data> Data::getHandle(jsg::Lock& js) const {
3033 return getHandle(js.v8Isolate);
3034}
3035 
3036template <typename T>
3037inline v8::Local<v8::Context> JsContext<T>::getHandle(Lock& js) const {
3038 return handle.Get(js.v8Isolate);
3039}
3040 
3041inline Value SelfRef::asValue(Lock& js) const {
3042 return Value(js.v8Isolate, getHandle(js).As<v8::Value>());
3043}
3044 
3045namespace _ {
3046 
3047// Helper class for JSG_TRY / JSG_CATCH macros.
3048//
3049// Sets up a v8::TryCatch on construction and converts caught exceptions to jsg::Value.
3050// Handles both JsExceptionThrown (returns V8 exception directly) and kj::Exception
3051// (converts via Lock::exceptionToJs()).
3052//
3053// This class is an implementation detail of the JSG_TRY / JSG_CATCH macros and should
3054// not be used directly.
3055class JsgCatchScope {
3056 public:
3057 explicit JsgCatchScope(Lock& js);
3058 
3059 // Converts the in-flight exception to a jsg::Value and stores it.
3060 // Called by JSG_CATCH macro.
3061 void catchException(ExceptionToJsOptions options = {});
3062 
3063 // Returns the caught exception. Must be called after catchException().
3064 Value& getCaughtException() {
3065 return KJ_ASSERT_NONNULL(caughtException);
3066 }
3067 
3068 private:
3069 Lock& js;
3070 
3071 // Simple wrapper to work around v8::TryCatch's deleted operator new.
3072 struct Holder {
3073 v8::TryCatch tryCatch;
3074 explicit Holder(v8::Isolate* isolate): tryCatch(isolate) {}
3075 };
3076 
3077 // We use two separate Maybe members rather than kj::OneOf<Holder, Value> because v8::TryCatch
3078 // has deleted copy/move constructors, making it incompatible with OneOf's internal storage.
3079 // The tryCatchHolder is active during the try block and released by catchException(), which
3080 // then populates caughtException.
3081 
3082 // Active during the try block, consumed by catchException().
3083 kj::Maybe<Holder> tryCatchHolder;
3084 
3085 // Populated by catchException(), returned by getCaughtException().
3086 kj::Maybe<Value> caughtException;
3087};
3088 
3089} // namespace _
3090 
3091// JSG_TRY / JSG_CATCH macros for exception handling in JSG code.
3092//
3093// These macros provide clean exception handling that automatically converts both JavaScript
3094// exceptions (JsExceptionThrown) and KJ exceptions (kj::Exception) to jsg::Value. This is
3095// the recommended way to handle exceptions in JSG code.
3096//
3097// Usage:
3098// JSG_TRY(js) {
3099// someCodeThatMightThrow();
3100// } JSG_CATCH(exception) {
3101// // `exception` is a jsg::Value& containing the caught exception
3102// return js.rejectedPromise<void>(kj::mv(exception));
3103// }
3104//
3105// With ExceptionToJsOptions:
3106// JSG_TRY(js) {
3107// someCodeThatMightThrow();
3108// } JSG_CATCH(exception, {.ignoreDetail = true}) {
3109// // Handle exception with custom conversion options
3110// }
3111//
3112// JSG_TRY(js): Sets up exception handling with the given jsg::Lock. The `js` parameter makes
3113// the isolate explicit and enables future coroutine support.
3114//
3115// JSG_CATCH(name, ...): Catches any exception and converts it to a jsg::Value. The `name`
3116// parameter is a user-chosen identifier that will be a `jsg::Value&` in the handler block.
3117// Optional ExceptionToJsOptions can be passed as a second argument.
3118//
3119// IMPORTANT: The code block following JSG_CATCH is NOT a true catch handler:
3120// - You CANNOT rethrow with `throw` (there is no current exception)
3121//
3122// To rethrow the exception, use: js.throwException(kj::mv(exception));
3123 
3124// Since we have two macros -- JSG_TRY and JSG_CATCH -- which must both access the same state,
3125// we use a hard-coded variable name. This causes benign shadowing in nested JSG_TRY/JSG_CATCHes,
3126// so we disable shadowing warnings. The `_jsg` prefix makes name collision unlikely.
3127#define JSG_TRY(js) \
3128 KJ_SILENCE_SHADOWING_BEGIN \
3129 if (::workerd::jsg::_::JsgCatchScope _jsgTryCatch(js); true) try KJ_SILENCE_SHADOWING_END
3130 
3131#define JSG_CATCH(exception, ...) \
3132 catch (...) { \
3133 _jsgTryCatch.catchException(__VA_ARGS__); \
3134 goto KJ_UNIQUE_NAME(_jsgTryCatchHandler); \
3135 } \
3136 else KJ_UNIQUE_NAME(_jsgTryCatchHandler) \
3137 : if (auto& exception = _jsgTryCatch.getCaughtException(); false) {} \
3138 else
3139 
3140} // namespace workerd::jsg
3141 
3142// clang-format off
3143// These includes are needed for the JSG type glue macros to work.
3144#include "promise.h"
3145#include "modules.h"
3146#include "resource.h"
3147// JSG has very entrenched include cycles
3148// NOLINTNEXTLINE(misc-header-include-cycle)
3149#include "jsvalue.h"
3150// clang-format on
3151 
3152// The main JSG API no longer depends on the Type Wrapper, but to avoid extensive changes in
3153// external code using JSG we still want it to be available when including jsg.h. This technically
3154// violates Bazel's encapsulation philosophy (type-wrapper.h should not be visible from jsg.h), so
3155// we only make jsg.h available for external code as part of the main jsg target including type-wrapper.h.
3156#ifndef JSG_IMPLEMENTATION
3157#include <workerd/jsg/type-wrapper.h>
3158#endif // JSG_IMPLEMENTATION