From 53a2a12af3ce53e96d6c0fdbd4b5cded6980b9ca Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:46:12 +0000 Subject: [PATCH 1/2] codegen: remove the unreachable DOMJIT paths from the class generator --- src/codegen/class-definitions.ts | 23 +-- src/codegen/generate-classes.ts | 198 +----------------------- src/runtime/crypto/crypto.classes.ts | 10 -- src/runtime/server/server.classes.ts | 8 - src/runtime/webcore/encoding.classes.ts | 5 - 5 files changed, 5 insertions(+), 239 deletions(-) diff --git a/src/codegen/class-definitions.ts b/src/codegen/class-definitions.ts index dc7ab394710d..52c6e12d6237 100644 --- a/src/codegen/class-definitions.ts +++ b/src/codegen/class-definitions.ts @@ -57,11 +57,6 @@ export type Field = length?: number; passThis?: boolean; invalidThisBehavior?: InvalidThisBehavior; - DOMJIT?: { - returns: string; - args?: [string, string] | [string, string, string] | [string] | []; - pure?: boolean; - }; } & PropertyAttribute) | { internal: true } | { @@ -267,21 +262,7 @@ export function define( estimatedSize, structuredClone, values, - klass: Object.fromEntries( - Object.entries(klass) - .sort(([a], [b]) => a.localeCompare(b)) - .map(([k, v]) => { - v["DOMJIT"] = undefined; - return [k, v]; - }), - ), - proto: Object.fromEntries( - Object.entries(proto) - .sort(([a], [b]) => a.localeCompare(b)) - .map(([k, v]) => { - v["DOMJIT"] = undefined; - return [k, v]; - }), - ), + klass: Object.fromEntries(Object.entries(klass).sort(([a], [b]) => a.localeCompare(b))), + proto: Object.fromEntries(Object.entries(proto).sort(([a], [b]) => a.localeCompare(b))), }); } diff --git a/src/codegen/generate-classes.ts b/src/codegen/generate-classes.ts index e8839a4493db..52b02fc54f87 100644 --- a/src/codegen/generate-classes.ts +++ b/src/codegen/generate-classes.ts @@ -55,100 +55,12 @@ function constructorName(typeName) { return `JS${typeName}Constructor`; } -function DOMJITName(fnName) { - return `${fnName}WithoutTypeChecks`; -} - -function argTypeName(arg) { - return { - ["bool"]: "bool", - ["int"]: "int32_t", - ["JSUint8Array"]: "JSC::JSUint8Array*", - ["JSString"]: "JSC::JSString*", - ["JSValue"]: "JSC::JSValue", - }[arg]; -} - -function DOMJITType(type) { - return { - ["bool"]: "JSC::SpecBoolean", - ["int"]: "JSC::SpecInt32Only", - ["JSUint8Array"]: "JSC::SpecUint8Array", - ["JSString"]: "JSC::SpecString", - ["JSValue"]: "JSC::SpecHeapTop", - }[type]; -} - -function DOMJITFunctionDeclaration(jsClassName, fnName, symName, { args, returns, pure = false }) { - const argNames = args.map((arg, i) => `${argTypeName(arg)} arg${i}`); - const formattedArgs = argNames.length > 0 ? `, ${argNames.join(", ")}` : ""; - const domJITArgs = args.length > 0 ? `, ${args.map(DOMJITType).join(", ")}` : ""; - externs += ` -extern JSC_CALLCONV JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${DOMJITName(symName)}(void* ptr, JSC::JSGlobalObject * lexicalGlobalObject${formattedArgs}); - `; - - return ( - ` -extern JSC_CALLCONV JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(${DOMJITName( - fnName, - )}Wrapper, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})); -static const JSC::DOMJIT::Signature DOMJITSignatureFor${fnName}(${DOMJITName(fnName)}Wrapper, - ${jsClassName}::info(), - ${ - pure - ? "JSC::DOMJIT::Effect::forPure()" - : "JSC::DOMJIT::Effect::forReadWrite(JSC::DOMJIT::HeapRange::top(), JSC::DOMJIT::HeapRange::top())" - }, - ${returns === "JSString" ? "JSC::SpecString" : DOMJITType("JSValue")}${domJITArgs}); -`.trim() + "\n" - ); -} - -function DOMJITFunctionDefinition(jsClassName, fnName, symName, { args }, fn) { - const argNames = args.map((arg, i) => `${argTypeName(arg)} arg${i}`); - const formattedArgs = argNames.length > 0 ? `, ${argNames.join(", ")}` : ""; - const retArgs = argNames.length > 0 ? `, ${args.map((b, i) => "arg" + i).join(", ")}` : ""; - - return ` -JSC_DEFINE_JIT_OPERATION(${DOMJITName( - fnName, - )}Wrapper, JSC::EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue${formattedArgs})) -{ - auto& vm = JSC::getVM(lexicalGlobalObject); - IGNORE_WARNINGS_BEGIN("frame-address") - CallFrame* callFrame = DECLARE_CALL_FRAME(vm); - IGNORE_WARNINGS_END - JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame); -#if BUN_DEBUG - ${jsClassName}* wrapper = reinterpret_cast<${jsClassName}*>(thisValue); - JSC::EncodedJSValue result = ${DOMJITName(symName)}(wrapper->wrapped(), lexicalGlobalObject${retArgs}); - JSValue decoded = JSValue::decode(result); - if (wrapper->m_${fn}_expectedResultType) { - if (decoded.isCell() && !decoded.isEmpty()) { - ASSERT_WITH_MESSAGE(wrapper->m_${fn}_expectedResultType.value().has_value(), "DOMJIT function return type changed!"); - ASSERT_WITH_MESSAGE(wrapper->m_${fn}_expectedResultType.value().value() == decoded.asCell()->type(), "DOMJIT function return type changed!"); - } else { - ASSERT_WITH_MESSAGE(!wrapper->m_${fn}_expectedResultType.value().has_value(), "DOMJIT function return type changed!"); - } - } else if (!decoded.isEmpty()) { - wrapper->m_${fn}_expectedResultType = decoded.isCell() - ? std::optional(decoded.asCell()->type()) - : std::optional(std::nullopt); - } - return { result }; -#endif - return {${DOMJITName(symName)}(reinterpret_cast<${jsClassName}*>(thisValue)->wrapped(), lexicalGlobalObject${retArgs})}; -} -`.trim(); -} - function zigExportName(to: Map, symbolName: (name: string) => string, prop) { - var { getter, setter, fn, DOMJIT, cache } = prop; + var { getter, setter, fn } = prop; const exportNames = { getter: "", setter: "", fn: "", - DOMJIT: "", }; if (getter && !to.get(getter)) { @@ -160,9 +72,6 @@ function zigExportName(to: Map, symbolName: (name: string) => st } if (fn && !to.get(fn)) { - if (DOMJIT) { - to.set(DOMJITName(fn), (exportNames.DOMJIT = symbolName(DOMJITName(fn)))); - } to.set(fn, (exportNames.fn = symbolName(fn))); } @@ -182,11 +91,8 @@ function propRow( setter, fn, length = 0, - cache, - DOMJIT, enumerable = true, configurable = false, - value, builtin, writable = false, } = (defaultPropertyAttributes ? Object.assign({}, defaultPropertyAttributes, prop) : prop) as any; @@ -232,12 +138,6 @@ function propRow( } } } `.trim(); } else if (fn !== undefined) { - if (DOMJIT) { - // { "getElementById"_s, static_cast(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsTestDOMJITPrototypeFunction_getElementById, &DOMJITSignatureForTestDOMJITGetElementById } }, - return ` - { "${name}"_s, static_cast(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction${extraPropertyAttributes}), NoIntrinsic, { HashTableValue::DOMJITFunctionType, ${fn}, &DOMJITSignatureFor${symbol} } } - `.trim(); - } return ` { "${name}"_s, static_cast(JSC::PropertyAttribute::Function${extraPropertyAttributes}), NoIntrinsic, { HashTableValue::NativeFunctionType, ${fn}, ${ length || 0 @@ -726,24 +626,6 @@ function renderDecls(symbolName, typeName, proto) { `.trim(), "\n", ); - - if (proto[name].DOMJIT) { - rows.push( - DOMJITFunctionDeclaration( - className(typeName), - symbolName(typeName, name), - symbolName(typeName, proto[name].fn), - proto[name].DOMJIT, - ), - DOMJITFunctionDefinition( - className(typeName), - symbolName(typeName, name), - symbolName(typeName, proto[name].fn), - proto[name].DOMJIT, - proto[name].fn, - ), - ); - } } } @@ -980,25 +862,6 @@ JSC_DEFINE_HOST_FUNCTION(${symbolName(typeName, name)}Callback, (JSGlobalObject ASSERT_WITH_MESSAGE(!JSValue::decode(result).isEmpty() or DECLARE_TOP_EXCEPTION_SCOPE(vm).exception() != 0, \"${typeName}.${proto[name].fn} returned an empty value without an exception\"); - ${ - !proto[name].DOMJIT - ? "" - : ` - JSValue decoded = JSValue::decode(result); - if (thisObject->m_${fn}_expectedResultType) { - if (decoded.isCell() && !decoded.isEmpty()) { - ASSERT_WITH_MESSAGE(thisObject->m_${fn}_expectedResultType.value().has_value(), "DOMJIT function return type changed!"); - ASSERT_WITH_MESSAGE(thisObject->m_${fn}_expectedResultType.value().value() == decoded.asCell()->type(), "DOMJIT function return type changed!"); - } else { - ASSERT_WITH_MESSAGE(!thisObject->m_${fn}_expectedResultType.value().has_value(), "DOMJIT function return type changed!"); - } - } else if (!decoded.isEmpty()) { - thisObject->m_${fn}_expectedResultType = decoded.isCell() - ? std::optional(decoded.asCell()->type()) - : std::optional(std::nullopt); - }` - } - #if ASSERT_ENABLED JSValue decodedValue = JSValue::decode(result); if (!decodedValue.isEmpty() && decodedValue.isCell()) { @@ -1204,8 +1067,6 @@ function generateClassHeader(typeName, obj: ClassDefinition) { - ${domJITTypeCheckFields(proto, klass)} - ${weakOwner} ${DECLARE_VISIT_CHILDREN} @@ -1217,23 +1078,6 @@ function generateClassHeader(typeName, obj: ClassDefinition) { `.trim(); } -function domJITTypeCheckFields(proto, klass) { - var output = "#if BUN_DEBUG\n"; - for (const name in proto) { - const { DOMJIT, fn } = proto[name]; - if (!DOMJIT) continue; - output += `std::optional> m_${fn}_expectedResultType = std::nullopt;\n`; - } - - for (const name in klass) { - const { DOMJIT, fn } = klass[name]; - if (!DOMJIT) continue; - output += `std::optional> m_${fn}_expectedResultType = std::nullopt;\n`; - } - output += "#endif\n"; - return output; -} - /** The (heap-analyzer property name, backing member) rows analyzeHeap reports. */ function cachedFieldTable(obj: ClassDefinition): { member: string; name: string }[] { return allCachedValues(obj).map(([name, cacheName]) => ({ member: cacheName, name })); @@ -1649,16 +1493,6 @@ function generateImpl(typeName, obj: ClassDefinition) { // \`(ret == 0) == hasException()\` biconditional in debug builds. // ────────────────────────────────────────────────────────────────────────── -function RustDOMJITArgType(type) { - return { - ["bool"]: "bool", - ["int"]: "i32", - ["JSUint8Array"]: "*mut bun_jsc::JSUint8Array", - ["JSString"]: "*mut bun_jsc::JSString", - ["JSValue"]: "JSValue", - }[type]; -} - /** camelCase / PascalCase → snake_case, then escape Rust reserved words. */ function rustSnakeIdent(name: string): string { // getURLSchemeV2 → get_url_scheme_v2; HTTPServer → http_server; crc32 → crc32 @@ -2013,7 +1847,7 @@ function generateRust( const seen = new Map(); const exportNames = name => zigExportName(seen, n => protoSymbolName(typeName, n), proto[name]); for (const name in proto) { - const { getter, setter, fn, this: thisValue = false, passThis, DOMJIT } = proto[name]; + const { getter, setter, fn, this: thisValue = false, passThis } = proto[name]; const names = exportNames(name); if (thisValue && !sharedThis && (names.getter || names.setter)) { @@ -2044,17 +1878,6 @@ function generateRust( if (names.fn) { const id = rustSnakeIdent(fn); - if (names.DOMJIT) { - const { args } = DOMJIT; - const argDecl = args.map((t, i) => `arg${i}: ${RustDOMJITArgType(t)}`).join(", "); - const argFwd = args.map((_, i) => `arg${i}`).join(", "); - const fastId = rustSnakeIdent(DOMJITName(fn)); - thunk( - names.DOMJIT, - `(this: ${recv}, global: &JSGlobalObject${args.length ? ", " + argDecl : ""}) -> JSValue`, - ` ${T}::${fastId}(this, global${args.length ? ", " + argFwd : ""})`, - ); - } thunk( names.fn, `(this: ${recv}, global: &JSGlobalObject, callframe: &CallFrame${passThis ? ", js_this_value: JSValue" : ""}) -> JSValue`, @@ -2071,7 +1894,7 @@ function generateRust( const seen = new Map(); const exportNames = name => zigExportName(seen, n => classSymbolName(typeName, n), klass[name]); for (const name in klass) { - const { getter, setter, fn, DOMJIT } = klass[name]; + const { getter, setter, fn } = klass[name]; const names = exportNames(name); if (names.getter) { @@ -2094,17 +1917,6 @@ function generateRust( if (names.fn) { const id = rustSnakeIdent(fn); - if (names.DOMJIT) { - const { args } = DOMJIT; - const argDecl = args.map((t, i) => `arg${i}: ${RustDOMJITArgType(t)}`).join(", "); - const argFwd = args.map((_, i) => `arg${i}`).join(", "); - const fastId = rustSnakeIdent(DOMJITName(fn)); - thunk( - names.DOMJIT, - `(global: &JSGlobalObject, this_value: JSValue${args.length ? ", " + argDecl : ""}) -> JSValue`, - ` ${T}::${fastId}(global, this_value${args.length ? ", " + argFwd : ""})`, - ); - } thunk( names.fn, `(global: &JSGlobalObject, callframe: &CallFrame) -> JSValue`, @@ -2347,10 +2159,6 @@ const GENERATED_CLASSES_IMPL_HEADER_PRE = ` #include #include -#include -#include -#include - #include "JSDOMConvertBufferSource.h" #include "ZigGeneratedClasses.h" #include "WebCoreJSBuiltins.h" diff --git a/src/runtime/crypto/crypto.classes.ts b/src/runtime/crypto/crypto.classes.ts index 5d51b4aa9c3b..73f26f903ad6 100644 --- a/src/runtime/crypto/crypto.classes.ts +++ b/src/runtime/crypto/crypto.classes.ts @@ -53,19 +53,9 @@ export default [ randomUUID: { fn: "randomUUID", length: 1, - DOMJIT: { - returns: "JSString", - "pure": false, - args: [], - }, }, timingSafeEqual: { fn: "timingSafeEqual", - DOMJIT: { - returns: "JSValue", - "pure": false, - args: ["JSUint8Array", "JSUint8Array"], - }, length: 2, }, }, diff --git a/src/runtime/server/server.classes.ts b/src/runtime/server/server.classes.ts index e28a179994cc..8f15506e0cdd 100644 --- a/src/runtime/server/server.classes.ts +++ b/src/runtime/server/server.classes.ts @@ -278,18 +278,10 @@ export default [ publishText: { fn: "publishText", length: 2, - DOMJIT: { - returns: "int", - args: ["JSString", "JSString"], - }, }, publishBinary: { fn: "publishBinary", length: 2, - DOMJIT: { - returns: "int", - args: ["JSString", "JSUint8Array"], - }, }, ping: { fn: "ping", diff --git a/src/runtime/webcore/encoding.classes.ts b/src/runtime/webcore/encoding.classes.ts index 6f82d983b32c..453caae67af0 100644 --- a/src/runtime/webcore/encoding.classes.ts +++ b/src/runtime/webcore/encoding.classes.ts @@ -23,11 +23,6 @@ export default [ decode: { fn: "decode", length: 1, - - DOMJIT: { - returns: "JSString", - args: ["JSUint8Array"], - }, }, }, }), From 4561f4798a3ac30ad6a894e3b9a060e8a993108d Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:39:36 +0000 Subject: [PATCH 2/2] Remove the stale DOMJIT notes next to the class definitions --- src/runtime/crypto/crypto.classes.ts | 7 ------- src/runtime/server/server.classes.ts | 18 ------------------ src/runtime/webcore/Crypto.rs | 9 --------- 3 files changed, 34 deletions(-) diff --git a/src/runtime/crypto/crypto.classes.ts b/src/runtime/crypto/crypto.classes.ts index 73f26f903ad6..a366a0434295 100644 --- a/src/runtime/crypto/crypto.classes.ts +++ b/src/runtime/crypto/crypto.classes.ts @@ -42,13 +42,6 @@ export default [ proto: { getRandomValues: { fn: "getRandomValues", - // https://discord.com/channels/876711213126520882/1276103693665828894/1276133319033229363 - // https://discord.com/channels/876711213126520882/1276103693665828894/1276127092047609919 - // DOMJIT: { - // returns: "JSValue", - // "pure": false, - // args: ["JSUint8Array"], - // }, }, randomUUID: { fn: "randomUUID", diff --git a/src/runtime/server/server.classes.ts b/src/runtime/server/server.classes.ts index 8f15506e0cdd..4ca39417e54f 100644 --- a/src/runtime/server/server.classes.ts +++ b/src/runtime/server/server.classes.ts @@ -252,28 +252,10 @@ export default [ sendText: { fn: "sendText", length: 2, - // ASSERTION FAILED: m_data[index].lockCount - // /Users/jarred/actions-runner/_work/WebKit/WebKit/Source/JavaScriptCore/dfg/DFGRegisterBank.h(204) : void JSC::DFG::RegisterBank::unlock(RegID) [BankInfo = JSC::GPRInfo] - // 1 0x102740124 WTFCrash - // 3 0x103076bac JSC::MacroAssemblerARM64::add64(JSC::AbstractMacroAssembler::TrustedImm64, JSC::ARM64Registers::RegisterID, JSC::ARM64Registers::RegisterID) - // 4 0x10309a2d0 JSC::DFG::SpeculativeJIT::compileCallDOM(JSC::DFG::Node*)::$_0::operator()(JSC::DFG::Edge) const - // DOMJIT: { - // returns: "int", - // args: ["JSString", "bool"], - // }, }, sendBinary: { fn: "sendBinary", length: 2, - // ASSERTION FAILED: m_data[index].lockCount - // /Users/jarred/actions-runner/_work/WebKit/WebKit/Source/JavaScriptCore/dfg/DFGRegisterBank.h(204) : void JSC::DFG::RegisterBank::unlock(RegID) [BankInfo = JSC::GPRInfo] - // 1 0x102740124 WTFCrash - // 3 0x103076bac JSC::MacroAssemblerARM64::add64(JSC::AbstractMacroAssembler::TrustedImm64, JSC::ARM64Registers::RegisterID, JSC::ARM64Registers::RegisterID) - // 4 0x10309a2d0 JSC::DFG::SpeculativeJIT::compileCallDOM(JSC::DFG::Node*)::$_0::operator()(JSC::DFG::Edge) const - // DOMJIT: { - // returns: "int", - // args: ["JSUint8Array", "bool"], - // }, }, publishText: { fn: "publishText", diff --git a/src/runtime/webcore/Crypto.rs b/src/runtime/webcore/Crypto.rs index 071b6279b433..07315d7e89ea 100644 --- a/src/runtime/webcore/Crypto.rs +++ b/src/runtime/webcore/Crypto.rs @@ -22,11 +22,6 @@ impl Crypto { crate::node::crypto::timing_safe_equal(global, callframe) } - // DOMJIT fast path — non-standard signature (typed-array args unwrapped by codegen). - // DOMJIT operations report failure by throwing on the VM and returning the empty - // value (`JSValue::ZERO`); the generated wrapper returns the raw EncodedJSValue and - // the JIT checks for a pending exception after the call. - #[bun_jsc::host_fn(method)] pub(crate) fn get_random_values( &self, @@ -76,8 +71,6 @@ impl Crypto { Ok(arguments[0]) } - // DOMJIT fast path. - #[bun_jsc::host_fn(method)] pub(crate) fn random_uuid( &self, @@ -97,8 +90,6 @@ impl Crypto { str.into_js(global) } - // DOMJIT fast path. - // `#[JsClass]` emits `CryptoClass__construct` calling this. pub(crate) fn constructor( global: &JSGlobalObject,