aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/scripts/generate-classes.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/scripts/generate-classes.ts')
-rw-r--r--src/bun.js/scripts/generate-classes.ts138
1 files changed, 136 insertions, 2 deletions
diff --git a/src/bun.js/scripts/generate-classes.ts b/src/bun.js/scripts/generate-classes.ts
index 7755d59aa..21fba1807 100644
--- a/src/bun.js/scripts/generate-classes.ts
+++ b/src/bun.js/scripts/generate-classes.ts
@@ -35,12 +35,108 @@ 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 ZigDOMJITArgType(type) {
+ return {
+ ["bool"]: "bool",
+ ["int"]: "i32",
+ ["JSUint8Array"]: "*JSC.JSUint8Array",
+ ["JSString"]: "*JSC.JSString",
+ ["JSValue"]: "JSC.JSValue",
+ }[type];
+}
+
+function ZigDOMJITFunctionType(thisName, { args, returns }) {
+ return `fn (*${thisName}, *JSC.JSGlobalObject, ${args
+ .map(ZigDOMJITArgType)
+ .join(", ")}) callconv(.C) ${ZigDOMJITArgType("JSValue")}`;
+}
+
+function DOMJITReturnType(type) {
+ return {
+ ["bool"]: "bool",
+ ["int"]: "int32_t",
+ ["JSUint8Array"]: "JSC::JSUint8Array*",
+ ["JSString"]: "JSString*",
+ ["JSValue"]: "EncodedJSValue",
+ }[type];
+}
+
+function DOMJITFunctionDeclaration(jsClassName, fnName, { args, returns }) {
+ const argNames = args.map((arg, i) => `${argTypeName(arg)} arg${i}`);
+ return `
+ extern "C" JSC_DECLARE_JIT_OPERATION_WITHOUT_WTF_INTERNAL(${DOMJITName(
+ fnName
+ )}Wrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, ${argNames.join(
+ ", "
+ )}));
+ extern "C" EncodedJSValue ${DOMJITName(
+ fnName
+ )}(void* ptr, JSC::JSGlobalObject * lexicalGlobalObject, ${argNames.join(
+ ", "
+ )});
+
+ static const JSC::DOMJIT::Signature DOMJITSignatureFor${fnName}(${DOMJITName(
+ fnName
+ )}Wrapper,
+ ${jsClassName}::info(),
+ JSC::DOMJIT::Effect::forReadWrite(JSC::DOMJIT::HeapRange::top(), JSC::DOMJIT::HeapRange::top()),
+ ${DOMJITType("JSValue")}, ${args.map(DOMJITType).join(", ")});
+`.trim();
+}
+
+function DOMJITFunctionDefinition(jsClassName, fnName, { args }) {
+ const argNames = args.map((arg, i) => `${argTypeName(arg)} arg${i}`);
+ return `
+JSC_DEFINE_JIT_OPERATION(${DOMJITName(
+ fnName
+ )}Wrapper, EncodedJSValue, (JSC::JSGlobalObject * lexicalGlobalObject, void* thisValue, ${argNames.join(
+ ", "
+ )}))
+{
+ VM& vm = JSC::getVM(lexicalGlobalObject);
+ IGNORE_WARNINGS_BEGIN("frame-address")
+ CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+ IGNORE_WARNINGS_END
+ JSC::JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+ return ${DOMJITName(
+ fnName
+ )}(reinterpret_cast<${jsClassName}*>(thisValue)->wrapped(), lexicalGlobalObject, ${args
+ .map((b, i) => "arg" + i)
+ .join(", ")});
+}
+`;
+}
+
function appendSymbols(
to: Map<string, string>,
symbolName: (name: string) => string,
prop
) {
- var { defaultValue, getter, setter, accesosr, fn, cache } = prop;
+ var { defaultValue, getter, setter, accesosr, fn, DOMJIT, cache } = prop;
if (accesosr) {
getter = accesosr.getter;
@@ -56,6 +152,9 @@ function appendSymbols(
}
if (fn && !to.get(fn)) {
+ if (DOMJIT) {
+ to.set(DOMJITName(fn), symbolName(DOMJITName(fn)));
+ }
to.set(fn, symbolName(fn));
}
}
@@ -75,6 +174,7 @@ function propRow(
fn,
length = 0,
cache,
+ DOMJIT,
} = prop;
if (accesosr) {
@@ -107,6 +207,12 @@ function propRow(
}
if (fn !== undefined) {
+ if (DOMJIT) {
+ // { "getElementById"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsTestDOMJITPrototypeFunction_getElementById, &DOMJITSignatureForTestDOMJITGetElementById } },
+ return `
+ { "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, ${fn}, &DOMJITSignatureFor${symbol} } }
+ `.trim();
+ }
return `
{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, ${fn}, ${
length || 0
@@ -202,6 +308,7 @@ ${generateHashTable(
true
)}
+
const ClassInfo ${proto}::s_info = { "${typeName}"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${proto}) };
${renderFieldsImpl(protoSymbolName, typeName, obj, protoFields)}
@@ -504,6 +611,21 @@ function renderDecls(symbolName, typeName, proto) {
`.trim(),
"\n"
);
+
+ if (proto[name].DOMJIT) {
+ rows.push(
+ DOMJITFunctionDeclaration(
+ className(typeName),
+ symbolName(typeName, name),
+ proto[name].DOMJIT
+ ),
+ DOMJITFunctionDefinition(
+ className(typeName),
+ symbolName(typeName, name),
+ proto[name].DOMJIT
+ )
+ );
+ }
}
}
@@ -992,6 +1114,7 @@ function generateZig(
/// Set the cached value for ${name} on ${typeName}
/// This value will be visited by the garbage collector.
pub fn ${name}SetCached(thisValue: JSC.JSValue, globalObject: *JSC.JSGlobalObject, value: JSC.JSValue) void {
+ JSC.markBinding(@src());
${protoSymbolName(
typeName,
name
@@ -1029,7 +1152,7 @@ function generateZig(
}
[...Object.values(proto)].forEach(
- ({ getter, setter, accessor, fn, cache }) => {
+ ({ getter, setter, accessor, fn, cache, DOMJIT }) => {
if (accessor) {
getter = accessor.getter;
setter = accessor.setter;
@@ -1053,6 +1176,17 @@ function generateZig(
}
if (fn) {
+ if (DOMJIT) {
+ output += `
+ if (@TypeOf(${typeName}.${DOMJITName(fn)}) != ${ZigDOMJITFunctionType(
+ typeName,
+ DOMJIT
+ )})
+ @compileLog(
+ "Expected ${typeName}.${DOMJITName(fn)} to be a DOMJIT function"
+ );`;
+ }
+
output += `
if (@TypeOf(${typeName}.${fn}) != CallbackType)
@compileLog(