Understanding the JavaScript binding layer in workerd
JSG (JavaScript Glue) is the macro-driven C++/V8 binding layer that bridges C++ types with JavaScript. It provides automatic type conversion and exposes C++ classes as JavaScript-visible resources.
// Read-only property on prototypeJSG_READONLY_PROTOTYPE_PROPERTY(name, getter);// Read-write property on prototypeJSG_PROTOTYPE_PROPERTY(name, getter, setter);// Read-only property on instanceJSG_READONLY_INSTANCE_PROPERTY(name, getter);// Static constant on constructorJSG_STATIC_CONSTANT(name);
Prefer JSG_PROTOTYPE_PROPERTY over JSG_INSTANCE_PROPERTY. Instance properties break GC optimization and should only be used with specific justification.
class CustomError: public jsg::Object { JSG_RESOURCE_TYPE(CustomError) { JSG_INHERIT_INTRINSIC(v8::kErrorPrototype); JSG_READONLY_PROTOTYPE_PROPERTY(code, getCode); } int getCode() { return errorCode; }private: int errorCode;};
// GOOD: Pass by reference (borrowed)void processRequest(Request& request);// GOOD: Take ownership with jsg::Refvoid storeRequest(jsg::Ref<Request> request);// BAD: Raw pointer with unclear lifetimevoid processRequest(Request* request);
Use JSG error macros for JavaScript-facing errors:
// Require a condition, throw if falseJSG_REQUIRE(value > 0, TypeError, "Value must be positive");// Require non-null, throw if emptyauto& item = JSG_REQUIRE_NONNULL(maybeItem, DOMNotFoundError, "Item not found");// Unconditionally throwJSG_FAIL_REQUIRE(DOMInvalidStateError, "Cannot call after closed");
Available error types:
TypeError - Wrong argument type
RangeError - Value out of range
Error - Generic error
DOMException types - DOMInvalidStateError, DOMNotSupportedError, etc.
// GOOD: Take lock by reference in methodsvoid doAsync(jsg::Lock& js) { auto promise = asyncOperation(); return js.awaitIo(kj::mv(promise));}// BAD: Store lock or pass into promise continuationvoid doBad(jsg::Lock& js) { return asyncOperation().then([&js]() { // BAD: captures lock // This is unsafe });}