diff options
author | 2022-08-17 19:26:10 -0700 | |
---|---|---|
committer | 2022-08-17 19:26:10 -0700 | |
commit | c720bdc324e40385676b0d465ae9df8bfc4ec37b (patch) | |
tree | 3da42427c5f51ff737106155eff76360f34a81ec /src/bun.js/generate-classes.js | |
parent | bc412e1f6fb4057b25981772b48c1f7d228fcebb (diff) | |
download | bun-c720bdc324e40385676b0d465ae9df8bfc4ec37b.tar.gz bun-c720bdc324e40385676b0d465ae9df8bfc4ec37b.tar.zst bun-c720bdc324e40385676b0d465ae9df8bfc4ec37b.zip |
Move around some things
Diffstat (limited to 'src/bun.js/generate-classes.js')
-rw-r--r-- | src/bun.js/generate-classes.js | 1360 |
1 files changed, 0 insertions, 1360 deletions
diff --git a/src/bun.js/generate-classes.js b/src/bun.js/generate-classes.js deleted file mode 100644 index b033e606d..000000000 --- a/src/bun.js/generate-classes.js +++ /dev/null @@ -1,1360 +0,0 @@ -function symbolName(typeName, name) { - return `${typeName}__${name}`; -} - -function protoSymbolName(typeName, name) { - return `${typeName}Prototype__${name}`; -} - -function classSymbolName(typeName, name) { - return `${typeName}Class__${name}`; -} - -function subspaceFor(typeName) { - return `m_subspaceFor${typeName}`; -} - -function clientSubspaceFor(typeName) { - return `m_clientSubspaceFor${typeName}`; -} - -function prototypeName(typeName) { - return `JS${typeName}Prototype`; -} - -function className(typeName) { - return `JS${typeName}`; -} - -function constructorName(typeName) { - return `JS${typeName}Constructor`; -} - -function appendSymbols(to, symbolName, prop) { - var { defaultValue, getter, setter, accesosr, fn } = prop; - - if (accesosr) { - getter = accesosr.getter; - setter = accesosr.setter; - } - - if (getter) { - to.push([getter, symbolName(getter)]); - } - - if (setter) { - to.push([setter, symbolName(setter)]); - } - - if (fn) { - to.push([fn, symbolName(fn)]); - } -} -function propRow(symbolName, typeName, name, prop, isWrapped = true) { - var { - defaultValue, - getter, - setter, - fn, - accesosr, - fn, - length = 0, - cache, - } = prop; - - if (accesosr) { - getter = accesosr.getter; - setter = accesosr.setter; - } - - var symbol = symbolName(typeName, name); - - if (isWrapped) { - if (getter) { - getter = symbol + "GetterWrap"; - } - if (setter) { - setter = symbol + "SetterWrap"; - } - if (fn) { - fn = symbol + "Callback"; - } - } else { - if (getter) { - getter = symbolName(typeName, getter); - } - if (setter) { - setter = symbolName(typeName, setter); - } - if (fn) { - fn = symbolName(typeName, fn); - } - } - - if (fn !== undefined) { - return ` -{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(${fn}), (intptr_t)(${ - length || 0 - }) } } -`.trim(); - } else if (getter && setter) { - return ` - -{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(${getter}), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(${setter}) } } -`.trim(); - } else if (defaultValue) { - } else if (getter) { - return `{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(${getter}), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } } -`.trim(); - } else if (setter) { - return `{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(0), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(${setter}) } } - `.trim(); - } - - throw "Unsupported property"; -} - -function generateHashTable( - nameToUse, - symbolName, - typeName, - obj, - props = {}, - wrapped -) { - const rows = []; - - for (const name in props) { - rows.push(propRow(symbolName, typeName, name, props[name], wrapped)); - } - - // static const HashTableValue JSWebSocketPrototypeTableValues[] = { - // { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocketConstructor), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "URL"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_URL), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "url"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_url), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "readyState"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_readyState), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "bufferedAmount"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_bufferedAmount), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "onopen"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_onopen), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSWebSocket_onopen) } }, - // { "onmessage"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_onmessage), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSWebSocket_onmessage) } }, - // { "onerror"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_onerror), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSWebSocket_onerror) } }, - // { "onclose"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_onclose), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSWebSocket_onclose) } }, - // { "protocol"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_protocol), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "extensions"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_extensions), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(0) } }, - // { "binaryType"_s, static_cast<unsigned>(JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute), NoIntrinsic, { (intptr_t) static_cast<PropertySlot::GetValueFunc>(jsWebSocket_binaryType), (intptr_t) static_cast<PutPropertySlot::PutValueFunc>(setJSWebSocket_binaryType) } }, - // { "send"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsWebSocketPrototypeFunction_send), (intptr_t)(1) } }, - // { "close"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { (intptr_t) static_cast<RawNativeFunction>(jsWebSocketPrototypeFunction_close), (intptr_t)(0) } }, - // { "CONNECTING"_s, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(0) } }, - // { "OPEN"_s, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(1) } }, - // { "CLOSING"_s, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(2) } }, - // { "CLOSED"_s, JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::ConstantInteger, NoIntrinsic, { (long long)(3) } }, - // }; - return ` - static const HashTableValue ${nameToUse}TableValues[] = { -${rows.join(" ,\n")} - }; -`; -} - -function generatePrototype(typeName, obj) { - const proto = prototypeName(typeName); - const { proto: protoFields } = obj; - return ` -${ - "construct" in obj - ? `extern "C" void* ${classSymbolName( - typeName, - "construct" - )}(JSC::JSGlobalObject*, JSC::CallFrame*); -JSC_DECLARE_CUSTOM_GETTER(js${typeName}Constructor);` - : "" -} -${ - "finalize" in obj - ? `extern "C" void ${classSymbolName(typeName, "finalize")}(void*);` - : "" -} - -${renderDecls(protoSymbolName, typeName, protoFields)} -STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(${proto}, ${proto}::Base); - -${generateHashTable( - prototypeName(typeName), - protoSymbolName, - typeName, - obj, - - protoFields, - true -)} - -const ClassInfo ${proto}::s_info = { "${typeName}"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${proto}) }; - -${renderFieldsImpl(protoSymbolName, typeName, obj, protoFields)} - -void ${proto}::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject) -{ - Base::finishCreation(vm); - reifyStaticProperties(vm, ${className( - typeName - )}::info(), ${proto}TableValues, *this); - JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); -} - - - -`; -} - -function generateConstructorHeader(typeName) { - const name = constructorName(typeName); - const proto = prototypeName(typeName); - - return ` - class ${proto} final : public JSC::JSNonFinalObject { - public: - using Base = JSC::JSNonFinalObject; - - static ${proto}* create(JSC::VM& vm, JSGlobalObject* globalObject, JSC::Structure* structure) - { - ${proto}* ptr = new (NotNull, JSC::allocateCell<${proto}>(vm)) ${proto}(vm, globalObject, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template<typename CellType, JSC::SubspaceAccess> - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - - private: - ${proto}(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); - }; - - class ${name} final : public JSC::InternalFunction { - public: - using Base = JSC::InternalFunction; - static ${name}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, ${prototypeName( - typeName - )}* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<${name}, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.${clientSubspaceFor( - typeName - )}Constructor.get(); }, - [](auto& spaces, auto&& space) { spaces.${clientSubspaceFor( - typeName - )}Constructor = WTFMove(space); }, - [](auto& spaces) { return spaces.${subspaceFor( - typeName - )}Constructor.get(); }, - [](auto& spaces, auto&& space) { spaces.${subspaceFor( - typeName - )}Constructor = WTFMove(space); }); - } - - - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, ${prototypeName( - typeName - )}* prototype); - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - DECLARE_EXPORT_INFO; - private: - ${name}(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, ${prototypeName( - typeName - )}* prototype); - }; - - `; -} - -function generateConstructorImpl(typeName, obj) { - const name = constructorName(typeName); - const { klass: fields } = obj; - const hashTable = - Object.keys(fields).length > 0 - ? generateHashTable(name, classSymbolName, typeName, obj, fields, false) - : ""; - - const hashTableIdentifier = hashTable.length ? `${name}TableValues` : ""; - return ` -${renderStaticDecls(classSymbolName, typeName, fields)} -${hashTable} - -void ${name}::finishCreation(VM& vm, JSC::JSGlobalObject* globalObject, ${prototypeName( - typeName - )}* prototype) -{ - Base::finishCreation(vm, 0, "${typeName}"_s, PropertyAdditionMode::WithoutStructureTransition); - ${ - hashTableIdentifier.length - ? `reifyStaticProperties(vm, &${name}::s_info, ${hashTableIdentifier}, *this);` - : "" - } - ASSERT(inherits(info())); -} - -${name}* ${name}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, ${prototypeName( - typeName - )}* prototype) { - ${name}* ptr = new (NotNull, JSC::allocateCell<${name}>(vm)) ${name}(vm, structure, construct); - ptr->finishCreation(vm, globalObject, prototype); - return ptr; -} - -JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES ${name}::construct(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - JSC::VM &vm = globalObject->vm(); - JSObject* newTarget = asObject(callFrame->newTarget()); - auto* constructor = globalObject->${className(typeName)}Constructor(); - Structure* structure = globalObject->${className(typeName)}Structure(); - if (constructor != newTarget) { - auto scope = DECLARE_THROW_SCOPE(vm); - - auto* functionGlobalObject = reinterpret_cast<Zig::GlobalObject*>( - // ShadowRealm functions belong to a different global object. - getFunctionRealm(globalObject, newTarget) - ); - RETURN_IF_EXCEPTION(scope, {}); - structure = InternalFunction::createSubclassStructure( - globalObject, - newTarget, - functionGlobalObject->${className(typeName)}Structure() - ); - } - - void* ptr = ${classSymbolName( - typeName, - "construct" - )}(globalObject, callFrame); - - if (UNLIKELY(!ptr)) { - return JSValue::encode(JSC::jsUndefined()); - } - - ${className(typeName)}* instance = ${className( - typeName - )}::create(vm, globalObject, structure, ptr); - - return JSValue::encode(instance); -} - -extern "C" EncodedJSValue ${typeName}__create(Zig::GlobalObject* globalObject, void* ptr) { - auto &vm = globalObject->vm(); - JSC::Structure* structure = globalObject->${className(typeName)}Structure(); - ${className(typeName)}* instance = ${className( - typeName - )}::create(vm, globalObject, structure, ptr); - return JSValue::encode(instance); -} - -void ${name}::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, ${prototypeName( - typeName - )}* prototype) -{ - -} - -const ClassInfo ${name}::s_info = { "Function"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${name}) }; - - - - - - `; -} - -function renderCachedFieldsHeader(typeName, klass, proto) { - const rows = []; - for (const name in klass) { - if ("cache" in klass[name]) { - rows.push(`mutable JSC::WriteBarrier<JSC::Unknown> m_${name};`); - } - } - - for (const name in proto) { - if ("cache" in proto[name]) { - rows.push(`mutable JSC::WriteBarrier<JSC::Unknown> m_${name};`); - } - } - - return rows.join("\n"); -} - -function renderDecls(symbolName, typeName, proto) { - const rows = []; - - for (const name in proto) { - if ( - "getter" in proto[name] || - ("accessor" in proto[name] && proto[name].getter) - ) { - rows.push( - `extern "C" JSC::EncodedJSValue ${symbolName( - typeName, - proto[name].getter || proto[name].accessor.getter - )}(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject);`, - ` - JSC_DECLARE_CUSTOM_GETTER(${symbolName(typeName, name)}GetterWrap); - `.trim(), - "\n" - ); - } - - if ( - "setter" in proto[name] || - ("accessor" in proto[name] && proto[name].setter) - ) { - rows - .push( - `extern "C" bool ${symbolName( - typeName, - proto[name].setter || proto[name].accessor.setter - )}(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, EncoedJSValue value);`, - ` - JSC_DECLARE_CUSTOM_SETTER(${symbolName(typeName, name)}SetterWrap); - `, - "\n" - ) - .trim(); - } - - if ("fn" in proto[name]) { - rows.push( - `extern "C" EncodedJSValue ${symbolName( - typeName, - proto[name].fn - )}(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame);`, - - ` - JSC_DECLARE_HOST_FUNCTION(${symbolName(typeName, name)}Callback); - `.trim(), - "\n" - ); - } - } - - return rows.join("\n"); -} - -function renderStaticDecls(symbolName, typeName, fields) { - const rows = []; - - for (const name in fields) { - if ( - "getter" in fields[name] || - ("accessor" in fields[name] && fields[name].getter) - ) { - rows.push( - `extern "C" JSC_DECLARE_CUSTOM_GETTER(${symbolName( - typeName, - fields[name].getter || fields[name].accessor.getter - )});` - ); - } - - if ( - "setter" in fields[name] || - ("accessor" in fields[name] && fields[name].setter) - ) { - rows.push( - `extern "C" JSC_DECLARE_CUSTOM_SETTER(${symbolName( - typeName, - fields[name].setter || fields[name].accessor.setter - )});` - ); - } - - if ("fn" in fields[name]) { - rows.push( - `extern "C" JSC_DECLARE_HOST_FUNCTION(${symbolName( - typeName, - fields[name].fn - )});` - ); - } - } - - return rows.join("\n"); -} - -function renderFieldsImpl(symbolName, typeName, obj, proto) { - const rows = []; - - if (obj.construct) { - rows.push(` - -JSC_DEFINE_CUSTOM_GETTER(js${typeName}Constructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) -{ - VM& vm = JSC::getVM(lexicalGlobalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); - auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - auto* prototype = jsDynamicCast<${prototypeName( - typeName - )}*>(JSValue::decode(thisValue)); - - if (UNLIKELY(!prototype)) - return throwVMTypeError(lexicalGlobalObject, throwScope); - return JSValue::encode(globalObject->${className(typeName)}Constructor()); -} - -`); - } - - for (const name in proto) { - if ("cache" in proto[name]) { - rows.push(` -JSC_DEFINE_CUSTOM_GETTER(${symbolName( - typeName, - name - )}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - auto& vm = lexicalGlobalObject->vm(); - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); - ${className(typeName)}* thisObject = jsCast<${className( - typeName - )}*>(JSValue::decode(thisValue)); - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - - if (JSValue cachedValue = thisObject->m_${name}.get()) - return JSValue::encode(cachedValue); - - JSC::JSValue result = JSC::JSValue::decode( - ${symbolName( - typeName, - proto[name].getter - )}(thisObject->wrapped(), globalObject) - ); - RETURN_IF_EXCEPTION(throwScope, {}); - thisObject->m_${name}.set(vm, thisObject, result); - RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); -} -`); - } else if ( - "getter" in proto[name] || - ("accessor" in proto[name] && proto[name].getter) - ) { - rows.push(` -JSC_DEFINE_CUSTOM_GETTER(${symbolName( - typeName, - name - )}GetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) -{ - auto& vm = lexicalGlobalObject->vm(); - Zig::GlobalObject *globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject); - auto throwScope = DECLARE_THROW_SCOPE(vm); - ${className(typeName)}* thisObject = jsCast<${className( - typeName - )}*>(JSValue::decode(thisValue)); - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - JSC::EncodedJSValue result = ${symbolName( - typeName, - proto[name].getter - )}(thisObject->wrapped(), globalObject); - RETURN_IF_EXCEPTION(throwScope, {}); - RELEASE_AND_RETURN(throwScope, result); -} - `); - } - - if ( - "setter" in proto[name] || - ("accessor" in proto[name] && proto[name].setter) - ) { - rows.push( - ` -JSC_DEFINE_CUSTOM_SETTER(${symbolName( - typeName, - name - )}SetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, EncodedJSValue encodedValue, PropertyName attributeName)) -{ - auto& vm = lexicalGlobalObject> - auto throwScope = DECLARE_THROW_SCOPE(vm); - ${className(typeName)}* thisObject = jsCast<${className( - typeName - )}*>(JSValue::decode(thisValue)); - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - auto result = ${symbolName( - typeName, - roto[name].setter || proto[name].accessor.setter - )}(thisObject->wrapped(), lexicalGlobalObject, encodedValue); - - RELEASE_AND_RETURN(throwScope, result); -} -` - ); - } - - if ("fn" in proto[name]) { - rows.push(` -JSC_DEFINE_HOST_FUNCTION(${symbolName( - typeName, - name - )}Callback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) -{ - auto& vm = lexicalGlobalObject->vm(); - - ${className(typeName)}* thisObject = jsDynamicCast<${className( - typeName - )}*>(callFrame->thisValue()); - - if (UNLIKELY(!thisObject)) { - auto throwScope = DECLARE_THROW_SCOPE(vm); - return throwVMTypeError(lexicalGlobalObject, throwScope); - } - - JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); - - return ${symbolName( - typeName, - proto[name].fn - )}(thisObject->wrapped(), lexicalGlobalObject, callFrame); -} -`); - } - } - - return rows.join("\n"); -} - -function generateClassHeader(typeName, obj) { - var { klass, proto, JSType = "Object" } = obj; - const name = className(typeName); - - const DECLARE_VISIT_CHILDREN = [ - ...Object.values(klass), - ...Object.values(proto), - ].find((a) => !!a.cache) - ? "DECLARE_VISIT_CHILDREN;" - : ""; - - return ` - class ${name} final : public JSC::JSDestructibleObject { - public: - using Base = JSC::JSDestructibleObject; - static ${name}* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx); - - DECLARE_EXPORT_INFO; - template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - if constexpr (mode == JSC::SubspaceAccess::Concurrently) - return nullptr; - return WebCore::subspaceForImpl<${name}, WebCore::UseCustomHeapCellType::No>( - vm, - [](auto& spaces) { return spaces.${clientSubspaceFor( - typeName - )}.get(); }, - [](auto& spaces, auto&& space) { spaces.${clientSubspaceFor( - typeName - )} = WTFMove(space); }, - [](auto& spaces) { return spaces.${subspaceFor( - typeName - )}.get(); }, - [](auto& spaces, auto&& space) { spaces.${subspaceFor( - typeName - )} = WTFMove(space); }); - } - - static void destroy(JSC::JSCell*); - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(static_cast<JSC::JSType>(${JSType}), StructureFlags), info()); - } - - static JSObject* createPrototype(VM& vm, JSDOMGlobalObject* globalObject); - - ~${name}(); - - void* wrapped() const { return m_ctx; } - - void detach() - { - m_ctx = nullptr; - } - - static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); - static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(${name}, m_ctx); } - - void* m_ctx { nullptr }; - - - ${name}(JSC::VM& vm, JSC::Structure* structure, void* sinkPtr) - : Base(vm, structure) - { - m_ctx = sinkPtr; - } - - void finishCreation(JSC::VM&); - - ${DECLARE_VISIT_CHILDREN} - - ${renderCachedFieldsHeader(typeName, klass, proto)} - }; - `; -} - -function generateClassImpl(typeName, obj) { - const { klass: fields, finalize, proto, construct } = obj; - const name = className(typeName); - var symbolName = classSymbolName; - - const DEFINE_VISIT_CHILDREN_LIST = [ - ...Object.entries(fields), - ...Object.entries(proto), - ] - .filter(([name, { cache }]) => !!cache) - .map(([name]) => ` visitor.append(thisObject->m_${name});`) - .join("\n"); - - var DEFINE_VISIT_CHILDREN = ""; - if (DEFINE_VISIT_CHILDREN_LIST.length) { - DEFINE_VISIT_CHILDREN = ` -template<typename Visitor> -void ${name}::visitChildrenImpl(JSCell* cell, Visitor& visitor) -{ - ${name}* thisObject = jsCast<${name}*>(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, info()); - Base::visitChildren(thisObject, visitor); -${DEFINE_VISIT_CHILDREN_LIST} -} - -DEFINE_VISIT_CHILDREN(${name}); - `.trim(); - } - - var output = ``; - - if (finalize) { - output += ` -${name}::~${name}() -{ - if (m_ctx) { - ${classSymbolName(typeName, "finalize")}(m_ctx); - } -} -`; - } else { - output += ` -${name}::~${name}() -{ -} -`; - } - - output += ` - - - -void ${name}::destroy(JSCell* cell) -{ - static_cast<${name}*>(cell)->${name}::~${name}(); -} - -const ClassInfo ${name}::s_info = { "${typeName}"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(${name}) }; - -void ${name}::finishCreation(VM& vm) -{ - Base::finishCreation(vm); - ASSERT(inherits(info())); -} - -${name}* ${name}::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, void* ctx) { - ${name}* ptr = new (NotNull, JSC::allocateCell<${name}>(vm)) ${name}(vm, structure, ctx); - ptr->finishCreation(vm); - return ptr; -} - - -extern "C" void* ${typeName}__fromJS(JSC::EncodedJSValue value) { - ${className(typeName)}* object = JSC::jsDynamicCast<${className( - typeName - )}*>(JSValue::decode(value)); - if (!object) - return nullptr; - - return object->wrapped(); -} - -extern "C" bool ${typeName}__dangerouslySetPtr(JSC::EncodedJSValue value, void* ptr) { - ${className(typeName)}* object = JSC::jsDynamicCast<${className( - typeName - )}*>(JSValue::decode(value)); - if (!object) - return false; - - object->m_ctx = ptr; - return true; -} - - -extern "C" const size_t ${typeName}__ptrOffset = ${className( - typeName - )}::offsetOfWrapped(); - -void ${name}::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) -{ - auto* thisObject = jsCast<${name}*>(cell); - if (void* wrapped = thisObject->wrapped()) { - // if (thisObject->scriptExecutionContext()) - // analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); - } - Base::analyzeHeap(cell, analyzer); -} - -JSObject* ${name}::createPrototype(VM& vm, JSDOMGlobalObject* globalObject) -{ - return ${prototypeName(typeName)}::create(vm, globalObject, ${prototypeName( - typeName - )}::createStructure(vm, globalObject, globalObject->objectPrototype())); -} - -${DEFINE_VISIT_CHILDREN} - - `.trim(); - - return output; -} - -function generateHeader(typeName, obj) { - return ( - generateClassHeader(typeName, obj).trim() + - "\n" + - generateConstructorHeader(typeName).trim() + - "\n" - ); -} - -function generateImpl(typeName, obj) { - const proto = obj.proto; - return [ - Object.keys(proto).length > 0 && generatePrototype(typeName, obj).trim(), - generateConstructorImpl(typeName, obj).trim(), - Object.keys(proto).length > 0 && generateClassImpl(typeName, obj).trim(), - ] - .filter(Boolean) - .join("\n\n"); -} - -function generateZig( - typeName, - { klass = {}, proto = {}, construct, finalize } -) { - const exports = []; - - if (construct) { - exports.push([`constructor`, classSymbolName(typeName, "construct")]); - } - - if (finalize) { - exports.push([`finalize`, classSymbolName(typeName, "finalize")]); - } - - Object.values(klass).map((a) => - appendSymbols(exports, (name) => classSymbolName(typeName, name), a) - ); - Object.values(proto).map((a) => - appendSymbols(exports, (name) => protoSymbolName(typeName, name), a) - ); - - function typeCheck() { - var output = ""; - - if (construct) { - output += ` - if (@TypeOf(${typeName}.constructor) != (fn(*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) ?*${typeName})) { - @compileLog("${typeName}.constructor is not a constructor"); - } - `; - } - - if (finalize) { - output += ` - if (@TypeOf(${typeName}.finalize) != (fn(*${typeName}) callconv(.C) void)) { - @compileLog("${typeName}.finalize is not a finalizer"); - } - `; - } - - [...Object.values(proto)].forEach(({ getter, setter, accessor, fn }) => { - if (accessor) { - getter = accessor.getter; - setter = accessor.setter; - } - - if (getter) { - output += ` - if (@TypeOf(${typeName}.${getter}) != GetterType) - @compileLog( - "Expected ${typeName}.${getter} to be a getter" - ); -`; - } - - if (setter) { - output += ` - if (@TypeOf(${typeName}.${setter}) != SetterType) - @compileLog( - "Expected ${typeName}.${setter} to be a setter" - );`; - } - - if (fn) { - output += ` - if (@TypeOf(${typeName}.${fn}) != CallbackType) - @compileLog( - "Expected ${typeName}.${fn} to be a callback" - );`; - } - }); - - [...Object.values(klass)].forEach(({ getter, setter, accessor, fn }) => { - if (accessor) { - getter = accessor.getter; - setter = accessor.setter; - } - - if (getter) { - output += ` - if (@TypeOf(${typeName}.${getter}) != StaticGetterType) - @compileLog( - "Expected ${typeName}.${getter} to be a static getter" - ); -`; - } - - if (setter) { - output += ` - if (@TypeOf(${typeName}.${setter}) != StaticSetterType) - @compileLog( - "Expected ${typeName}.${setter} to be a static setter" - );`; - } - - if (fn) { - output += ` - if (@TypeOf(${typeName}.${fn}) != StaticCallbackType) - @compileLog( - "Expected ${typeName}.${fn} to be a static callback" - );`; - } - }); - - return output; - } - - return ` - -pub const ${className(typeName)} = struct { - const ${typeName} = Classes.${typeName}; - const GetterType = fn(*${typeName}, *JSC.JSGlobalObject) callconv(.C) JSC.JSValue; - const SetterType = fn(*${typeName}, *JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; - const CallbackType = fn(*${typeName}, *JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; - - /// Return the pointer to the wrapped object. - /// If the object does not match the type, return null. - pub fn fromJS(value: JSC.JSValue) ?*${typeName} { - JSC.markBinding(); - return ${symbolName(typeName, "fromJS")}(value); - } - - /// Create a new instance of ${typeName} - pub fn toJS(this: *${typeName}, globalObject: *JSC.JSGlobalObject) JSC.JSValue { - JSC.markBinding(); - if (comptime Environment.allow_assert) { - const value__ = ${symbolName( - typeName, - "create" - )}(globalObject, this); - std.debug.assert(value__.as(${typeName}).? == this); // If this fails, likely a C ABI issue. - return value__; - } else { - return ${symbolName(typeName, "create")}(globalObject, this); - } - } - - /// Modify the internal ptr to point to a new instance of ${typeName}. - pub fn dangerouslySetPtr(value: JSC.JSValue, ptr: ?*${typeName}) bool { - JSC.markBinding(); - return ${symbolName(typeName, "dangerouslySetPtr")}(value, ptr); - } - - extern fn ${symbolName(typeName, "fromJS")}(JSC.JSValue) ?*${typeName}; - - extern fn ${symbolName( - typeName, - "create" - )}(globalObject: *JSC.JSGlobalObject, ptr: ?*${typeName}) JSC.JSValue; - - extern fn ${typeName}__dangerouslySetPtr(JSC.JSValue, ?*${typeName}) bool; - - comptime { - ${typeCheck()} - if (!JSC.is_bindgen) { -${exports - .sort(([a], [b]) => a.localeCompare(b)) - .map( - ([internalName, externalName]) => - `@export(${typeName}.${internalName}, .{.name = "${externalName}"});` - ) - .join("\n ")} - } - } -}; - - -`; -} - -function generateLazyClassStructureHeader( - typeName, - { klass = {}, proto = {} } -) { - return ` - JSC::Structure* ${className( - typeName - )}Structure() { return m_${className( - typeName - )}.getInitializedOnMainThread(this); } - JSC::JSObject* ${className( - typeName - )}Constructor() { return m_${className( - typeName - )}.constructorInitializedOnMainThread(this); } - JSC::JSValue ${className(typeName)}Prototype() { return m_${className( - typeName - )}.prototypeInitializedOnMainThread(this); } - JSC::LazyClassStructure m_${className(typeName)}; - `.trim(); -} - -function generateLazyClassStructureImpl(typeName, { klass = {}, proto = {} }) { - return ` - m_${className(typeName)}.initLater( - [](LazyClassStructure::Initializer& init) { - init.setPrototype(WebCore::${className( - typeName - )}::createPrototype(init.vm, reinterpret_cast<Zig::GlobalObject*>(init.global))); - init.setStructure(WebCore::${className( - typeName - )}::createStructure(init.vm, init.global, init.prototype)); - init.setConstructor(WebCore::${constructorName( - typeName - )}::create(init.vm, init.global, WebCore::${constructorName( - typeName - )}::createStructure(init.vm, init.global, init.global->functionPrototype()), jsCast<WebCore::${prototypeName( - typeName - )}*>(init.prototype))); - }); - - - `.trim(); -} - -function define({ klass = {}, proto = {}, ...rest } = {}) { - return { - ...rest, - klass: Object.fromEntries( - Object.entries(klass).sort(([a], [b]) => a.localeCompare(b)) - ), - proto: Object.fromEntries( - Object.entries(proto).sort(([a], [b]) => a.localeCompare(b)) - ), - }; -} - -const classes = [ - define({ - name: "Request", - construct: true, - finalize: true, - klass: {}, - JSType: "0b11101110", - proto: { - url: { - getter: "getURL", - cache: true, - }, - - // body: { - // getter: "getBody", - // }, - - text: { fn: "getText" }, - json: { fn: "getJSON" }, - arrayBuffer: { fn: "getArrayBuffer" }, - blob: { fn: "getBlob" }, - clone: { fn: "doClone", length: 1 }, - cache: { - getter: "getCache", - }, - credentials: { - getter: "getCredentials", - }, - destination: { - getter: "getDestination", - }, - headers: { - getter: "getHeaders", - cache: true, - }, - integrity: { - getter: "getIntegrity", - }, - method: { - getter: "getMethod", - }, - mode: { - getter: "getMode", - }, - redirect: { - getter: "getRedirect", - }, - referrer: { - getter: "getReferrer", - }, - referrerPolicy: { - getter: "getReferrerPolicy", - }, - url: { - getter: "getUrl", - cache: true, - }, - bodyUsed: { - getter: "getBodyUsed", - }, - }, - }), - - define({ - name: "Response", - construct: true, - finalize: true, - JSType: "0b11101110", - klass: { - json: { - fn: "constructJSON", - }, - redirect: { - fn: "constructRedirect", - }, - error: { - fn: "constructError", - }, - }, - proto: { - url: { - getter: "getURL", - cache: true, - }, - - // body: { - // getter: "getBody", - // }, - - text: { fn: "getText" }, - json: { fn: "getJSON" }, - arrayBuffer: { fn: "getArrayBuffer" }, - blob: { fn: "getBlob" }, - clone: { fn: "doClone", length: 1 }, - - type: { - getter: "getResponseType", - }, - headers: { - getter: "getHeaders", - cache: true, - }, - - statusText: { - getter: "getStatusText", - cache: true, - }, - status: { - getter: "getStatus", - }, - ok: { - getter: "getOK", - }, - bodyUsed: { - getter: "getBodyUsed", - }, - }, - }), -]; - -const GENERATED_CLASSES_HEADER = ` -// GENERATED CODE - DO NOT MODIFY BY HAND -// Generated by src/bun.js/generate-classes.js -#pragma once - -#include "root.h" - -namespace Zig { -} - -#include "JSDOMWrapper.h" -#include <wtf/NeverDestroyed.h> - -namespace WebCore { -using namespace Zig; -using namespace JSC; - -`; - -const GENERATED_CLASSES_FOOTER = ` -} - -`; - -const GENERATED_CLASSES_IMPL_HEADER = ` -// GENERATED CODE - DO NOT MODIFY BY HAND -// Generated by src/bun.js/generate-classes.js -#include "root.h" - -#include "ZigGlobalObject.h" - -#include <JavaScriptCore/DOMJITAbstractHeap.h> -#include "DOMJITIDLConvert.h" -#include "DOMJITIDLType.h" -#include "DOMJITIDLTypeFilter.h" -#include "DOMJITHelpers.h" -#include <JavaScriptCore/DFGAbstractHeap.h> - -#include "JSDOMConvertBufferSource.h" -#include "ZigGeneratedClasses.h" - - - - -namespace WebCore { - -using namespace JSC; -using namespace Zig; - -`; - -const GENERATED_CLASSES_IMPL_FOOTER = ` - -} // namespace WebCore - -`; - -function initLazyClasses(initLaterFunctions) { - return ` - -void GlobalObject::initGeneratedLazyClasses() { - ${initLaterFunctions.map((a) => a.trim()).join("\n ")} -} - -`.trim(); -} - -function visitLazyClasses(classes) { - return ` - -template<typename Visitor> -void GlobalObject::visitGeneratedLazyClasses(GlobalObject *thisObject, Visitor& visitor) -{ - ${classes - .map((a) => `thisObject->m_${className(a.name)}.visit(visitor);`) - .join("\n ")} -} - - `.trim(); -} - -const ZIG_GENERATED_CLASSES_HEADER = ` -const JSC = @import("javascript_core"); -const Classes = @import("./generated_classes_list.zig").Classes; -const Environment = @import("../../env.zig"); -const std = @import("std"); - -const StaticGetterType = fn(*JSC.JSGlobalObject) callconv(.C) JSC.JSValue; -const StaticSetterType = fn(*JSC.JSGlobalObject, JSC.JSValue) callconv(.C) bool; -const StaticCallbackType = fn(*JSC.JSGlobalObject, *JSC.CallFrame) callconv(.C) JSC.JSValue; - - - -`; -await Bun.write(`${import.meta.dir}/bindings/generated_classes.zig`, [ - ZIG_GENERATED_CLASSES_HEADER, - ...classes.map((a) => generateZig(a.name, a).trim()).join("\n"), -]); -await Bun.write(`${import.meta.dir}/bindings/ZigGeneratedClasses.h`, [ - GENERATED_CLASSES_HEADER, - ...classes.map((a) => generateHeader(a.name, a)), - GENERATED_CLASSES_FOOTER, -]); -await Bun.write(`${import.meta.dir}/bindings/ZigGeneratedClasses.cpp`, [ - GENERATED_CLASSES_IMPL_HEADER, - ...classes.map((a) => generateImpl(a.name, a)), - GENERATED_CLASSES_IMPL_FOOTER, -]); -await Bun.write( - `${import.meta.dir}/bindings/ZigGeneratedClasses+lazyStructureHeader.h`, - classes.map((a) => generateLazyClassStructureHeader(a.name, a)).join("\n") -); - -await Bun.write( - `${import.meta.dir}/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h`, - classes.map((a) => - [ - `std::unique_ptr<GCClient::IsoSubspace> ${clientSubspaceFor(a.name)};`, - `std::unique_ptr<GCClient::IsoSubspace> ${clientSubspaceFor( - a.name - )}Constructor;`, - ].join("\n") - ) -); - -await Bun.write( - `${import.meta.dir}/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h`, - classes.map((a) => - [ - `std::unique_ptr<IsoSubspace> ${subspaceFor(a.name)};`, - `std::unique_ptr<IsoSubspace> ${subspaceFor(a.name)}Constructor;`, - ].join("\n") - ) -); - -await Bun.write( - `${import.meta.dir}/bindings/ZigGeneratedClasses+lazyStructureImpl.h`, - initLazyClasses( - classes.map((a) => generateLazyClassStructureImpl(a.name, a)) - ) + - "\n" + - visitLazyClasses(classes) -); |