diff --git a/src/workerd/api/api-rtti-test.c++ b/src/workerd/api/api-rtti-test.c++ index 135730f7c2f..f97d0c98f1d 100644 --- a/src/workerd/api/api-rtti-test.c++ +++ b/src/workerd/api/api-rtti-test.c++ @@ -8,19 +8,17 @@ // Test building rtti for various APIs. -JSG_RTTI_DECLARE_CONFIGURATION_TYPE(workerd::CompatibilityFlags::Reader); - namespace workerd::api { namespace { KJ_TEST("WorkerGlobalScope") { CompatibilityFlags::Reader flags; - jsg::rtti::Builder().structure(flags); + jsg::rtti::Builder(flags).structure(); } KJ_TEST("ServiceWorkerGlobalScope") { CompatibilityFlags::Reader flags; - jsg::rtti::Builder().structure(flags); + jsg::rtti::Builder(flags).structure(); } } // namespace diff --git a/src/workerd/jsg/rtti-test.c++ b/src/workerd/jsg/rtti-test.c++ index 6494239bca8..006600ca29a 100644 --- a/src/workerd/jsg/rtti-test.c++ +++ b/src/workerd/jsg/rtti-test.c++ @@ -7,7 +7,6 @@ #include struct MockConfig {}; -JSG_RTTI_DECLARE_CONFIGURATION_TYPE(MockConfig); namespace workerd::jsg::rtti { namespace { @@ -15,7 +14,7 @@ namespace { template kj::String tType() { // returns textual encoding of rtti. - Builder builder; + Builder builder((MockConfig())); auto type = builder.type(); capnp::TextCodec codec; return codec.encode(type); @@ -24,8 +23,8 @@ kj::String tType() { template kj::String tStructure() { // returns textual encoding of structure. - Builder builder; - auto type = builder.structure(MockConfig()); + Builder builder((MockConfig())); + auto type = builder.structure(); capnp::TextCodec codec; return codec.encode(type); } @@ -111,7 +110,7 @@ KJ_TEST("builtins") { KJ_EXPECT(tType() == "(builtin = (type = v8Isolate))"); KJ_EXPECT(tType() == "(builtin = (type = v8Function))"); KJ_EXPECT(tType() == "(builtin = (type = kjDate))"); - KJ_EXPECT(tType() == "(builtin = (type = flags))"); + KJ_EXPECT(tType() == "(builtin = (type = configuration))"); KJ_EXPECT(tType>() == "(builtin = (type = jsgTypeHandler))"); } diff --git a/src/workerd/jsg/rtti.capnp b/src/workerd/jsg/rtti.capnp index aabff1d7138..17fde93c566 100644 --- a/src/workerd/jsg/rtti.capnp +++ b/src/workerd/jsg/rtti.capnp @@ -135,8 +135,8 @@ struct BuiltinType { v8Function @7; # v8::Function - flags @8; - # CompatibilityFlags::Reader + configuration @8; + # api meta configuration object jsgLock @9; # jsg::Lock diff --git a/src/workerd/jsg/rtti.h b/src/workerd/jsg/rtti.h index 59967486bfc..5704f01b250 100644 --- a/src/workerd/jsg/rtti.h +++ b/src/workerd/jsg/rtti.h @@ -10,6 +10,7 @@ // compatibility etc. #include +#include #include #include @@ -17,33 +18,39 @@ namespace workerd::jsg::rtti { namespace impl { -template +template struct BuildRtti; // Struct for partial specialization. } // namespace impl +template class Builder { // User's entry point into rtti. // Builder owns capnp builder for all the objects it returns, so usual capnp builder // rules apply. public: + const MetaConfiguration& config; + + Builder(const MetaConfiguration& config) : config(config) {} + template Type::Reader type() { auto type = builder.initRoot(); - impl::BuildRtti::build(type); + impl::BuildRtti::build(type, *this); return type; } - template - Structure::Reader structure(MetaConfiguration&& config) { + template + Structure::Reader structure() { auto structure = builder.initRoot(); - impl::BuildRtti::build(structure, kj::fwd(config)); + impl::BuildRtti::build(structure, *this); return structure; } private: + kj::TreeMap symbols; capnp::MallocMessageBuilder builder; }; @@ -82,49 +89,50 @@ struct FunctionTraits { using ArgsTuple = std::tuple; }; -template +template struct TupleRttiBuilder { - static inline void build(capnp::List::Builder builder) { - build(std::make_integer_sequence>{}, builder); + static inline void build(capnp::List::Builder builder, Builder& rtti) { + build(std::make_integer_sequence>{}, builder, rtti); } private: template static inline void build(std::integer_sequence seq, - capnp::List::Builder builder) { - ((buildIndex(builder)), ...); + capnp::List::Builder builder, + Builder& rtti) { + ((buildIndex(builder, rtti)), ...); } template - static inline void buildIndex(capnp::List::Builder builder) { - BuildRtti>::build(builder[I]); + static inline void buildIndex(capnp::List::Builder builder, Builder& rtti) { + BuildRtti>::build(builder[I], rtti); } }; // Primitives -template<> -struct BuildRtti { - static void build(Type::Builder builder) { builder.setVoidt(); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { builder.setVoidt(); } }; -template<> -struct BuildRtti { - static void build(Type::Builder builder) { builder.setBoolt(); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { builder.setBoolt(); } }; -template<> -struct BuildRtti { - static void build(Type::Builder builder) { builder.setUnknown(); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { builder.setUnknown(); } }; // Numbers #define DECLARE_NUMBER_TYPE(T) \ -template<> \ -struct BuildRtti { \ - static void build(Type::Builder builder) { builder.initNumber().setName(#T); } \ +template \ +struct BuildRtti { \ + static void build(Type::Builder builder, Builder& rtti) { builder.initNumber().setName(#T); } \ }; #define FOR_EACH_NUMBER_TYPE(F) \ @@ -147,9 +155,9 @@ FOR_EACH_NUMBER_TYPE(DECLARE_NUMBER_TYPE) // Strings #define DECLARE_STRING_TYPE(T) \ -template<> \ -struct BuildRtti { \ - static void build(Type::Builder builder) { builder.initString().setName(#T); } \ +template \ +struct BuildRtti { \ + static void build(Type::Builder builder, Builder& rtti) { builder.initString().setName(#T); } \ }; #define FOR_EACH_STRING_TYPE(F) \ @@ -167,129 +175,161 @@ FOR_EACH_STRING_TYPE(DECLARE_STRING_TYPE) // Object Types -template<> -struct BuildRtti { - static void build(Type::Builder builder) { builder.setObject(); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { builder.setObject(); } }; // References -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; // Generic Types -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initMaybe().initValue()); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initMaybe().initValue(), rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initMaybe().initValue()); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initMaybe().initValue(), rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initArray().initElement()); } + +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initArray().initElement(), rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initArray().initElement()); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initArray().initElement(), rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initArray().initElement()); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initArray().initElement(), rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { auto dict = builder.initDict(); - BuildRtti::build(dict.initKey()); - BuildRtti::build(dict.initValue()); + BuildRtti::build(dict.initKey(), rtti); + BuildRtti::build(dict.initValue(), rtti); } }; -template -struct BuildRtti> { +template +struct BuildRtti> { using Seq = std::index_sequence_for; using Tuple = std::tuple; template - static inline void buildVariant(capnp::List::Builder builder) { - BuildRtti>::build(builder[I]); + static inline void buildVariant(capnp::List::Builder builder, Builder& rtti) { + BuildRtti>::build(builder[I], rtti); } template static inline void buildVariants(std::integer_sequence seq, - capnp::List::Builder builder) { - ((buildVariant(builder)), ...); + capnp::List::Builder builder, + Builder& rtti) { + ((buildVariant(builder, rtti)), ...); } - static void build(Type::Builder builder) { + static void build(Type::Builder builder, Builder& rtti) { auto variants = builder.initOneOf().initVariants(Seq::size()); - buildVariants(Seq{}, variants); + buildVariants(Seq{}, variants, rtti); } }; // Promises -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initPromise().initValue()); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initPromise().initValue(), rtti); + } }; -template -struct BuildRtti> { - static void build(Type::Builder builder) { BuildRtti::build(builder.initPromise().initValue()); } +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder.initPromise().initValue(), rtti); + } }; -template<> -struct BuildRtti { - static void build(Type::Builder builder) { builder.initPromise().initValue().setUnknown(); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { + builder.initPromise().initValue().setUnknown(); + } }; // Builtins #define DECLARE_BUILTIN_TYPE(T, V) \ -template<> \ -struct BuildRtti { \ - static void build(Type::Builder builder) { \ +template \ +struct BuildRtti { \ + static void build(Type::Builder builder, Builder& rtti) { \ builder.initBuiltin().setType(V); \ } \ }; @@ -310,25 +350,16 @@ FOR_EACH_BUILTIN_TYPE(DECLARE_BUILTIN_TYPE) #undef FOR_EACH_BUILTIN_TYPE #undef DECLARE_BUILTIN_TYPE -#define JSG_RTTI_DECLARE_CONFIGURATION_TYPE(T) \ - namespace workerd::jsg::rtti::impl { \ - template<> \ - struct BuildRtti { \ - static void build(Type::Builder builder) { \ - builder.initBuiltin().setType(BuiltinType::Type::FLAGS); \ - } \ - }; \ - } -// Use this at the global scope to declare a configuration type before invoking RTTI. E.g.: -// -// JSG_RTTI_DECLARE_CONFIGURATION_TYPE(workerd::CompatibilityFlags::Reader) -// -// TODO(cleanup): This should probably be done instead through a template parameter to -// `RttiBuilder` that gets passed down, but that's a deeper change. - -template -struct BuildRtti> { - static void build(Type::Builder builder) { +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { + builder.initBuiltin().setType(BuiltinType::Type::CONFIGURATION); + } +}; + +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { builder.initBuiltin().setType(BuiltinType::Type::JSG_TYPE_HANDLER); } }; @@ -336,37 +367,45 @@ struct BuildRtti> { // Functions -template -struct BuildRtti> { - static void build(Type::Builder builder) { +template +struct BuildRtti> { + static void build(Type::Builder builder, Builder& rtti) { auto fn = builder.initFunction(); using Traits = FunctionTraits; - BuildRtti::build(fn.initReturnType()); + BuildRtti::build(fn.initReturnType(), rtti); using Args = typename Traits::ArgsTuple; - TupleRttiBuilder::build(fn.initArgs(std::tuple_size_v)); + TupleRttiBuilder::build(fn.initArgs(std::tuple_size_v), rtti); } }; // C++ modifiers -template -struct BuildRtti { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; -template -struct BuildRtti { - static void build(Type::Builder builder) { BuildRtti::build(builder); } +template +struct BuildRtti { + static void build(Type::Builder builder, Builder& rtti) { + BuildRtti::build(builder, rtti); + } }; // Structs @@ -400,7 +439,7 @@ struct MemberCounter { template inline void registerPrototypeProperty() { ++count; } - + template inline void registerReadonlyInstanceProperty() { ++count; } @@ -421,18 +460,19 @@ struct MemberCounter { template struct MembersBuilder { - Configuration& configuration; Structure::Builder structure; capnp::List::Builder members; + Builder& rtti; int index = 0; - MembersBuilder(Configuration& configuration, Structure::Builder structure, - capnp::List::Builder members) - : configuration(configuration), structure(structure), members(members) { } + MembersBuilder(Structure::Builder structure, + capnp::List::Builder members, + Builder& rtti) + : structure(structure), members(members), rtti(rtti) { } template inline void registerInherit() { - BuildRtti::build(structure.initExtends()); + BuildRtti::build(structure.initExtends(), rtti); } template @@ -443,7 +483,7 @@ struct MembersBuilder { template inline void registerNestedType() { auto nested = members[index++].initNested(); - BuildRtti::build(nested, configuration); + BuildRtti::build(nested, rtti); } template @@ -451,7 +491,7 @@ struct MembersBuilder { auto prop = members[index++].initProperty(); prop.setName(name); using GetterTraits = FunctionTraits; - BuildRtti::build(prop.initType()); + BuildRtti::build(prop.initType(), rtti); } template @@ -460,7 +500,7 @@ struct MembersBuilder { prop.setName(name); prop.setReadonly(true); using GetterTraits = FunctionTraits; - BuildRtti::build(prop.initType()); + BuildRtti::build(prop.initType(), rtti); } template @@ -470,7 +510,7 @@ struct MembersBuilder { prop.setReadonly(readOnly); prop.setLazy(true); using GetterTraits = FunctionTraits; - BuildRtti::build(prop.initType()); + BuildRtti::build(prop.initType(), rtti); } template @@ -479,7 +519,7 @@ struct MembersBuilder { prop.setName(name); prop.setPrototype(true); using GetterTraits = FunctionTraits; - BuildRtti::build(prop.initType()); + BuildRtti::build(prop.initType(), rtti); } template @@ -489,7 +529,7 @@ struct MembersBuilder { prop.setPrototype(true); prop.setReadonly(true); using GetterTraits = FunctionTraits; - BuildRtti::build(prop.initType()); + BuildRtti::build(prop.initType(), rtti); } template @@ -497,14 +537,14 @@ struct MembersBuilder { auto constant = members[index++].initConstant(); constant.setName(name); constant.setValue(value); - // BuildRtti::build(constant.initType()); + // BuildRtti::build(constant.initType()); } template void registerStructProperty() { auto prop = members[index++].initProperty(); prop.setName(name); - BuildRtti::build(prop.initType()); + BuildRtti::build(prop.initType(), rtti); } template @@ -513,9 +553,9 @@ struct MembersBuilder { method.setName(name); using Traits = FunctionTraits; - BuildRtti::build(method.initReturnType()); + BuildRtti::build(method.initReturnType(), rtti); using Args = typename Traits::ArgsTuple; - TupleRttiBuilder::build(method.initArgs(std::tuple_size_v)); + TupleRttiBuilder::build(method.initArgs(std::tuple_size_v), rtti); } template @@ -525,9 +565,9 @@ struct MembersBuilder { method.setName(name); method.setStatic(true); using Traits = FunctionTraits; - BuildRtti::build(method.initReturnType()); + BuildRtti::build(method.initReturnType(), rtti); using Args = typename Traits::ArgsTuple; - TupleRttiBuilder::build(method.initArgs(std::tuple_size_v)); + TupleRttiBuilder::build(method.initArgs(std::tuple_size_v), rtti); } template @@ -552,20 +592,19 @@ struct HasConstructor : std::false_type {}; template struct HasConstructor : std::true_type { }; -template -struct BuildRtti::value>> { - using Configuration = DetectedOr; - - static void build(Type::Builder builder) { - builder.initStructure().setName(jsg::typeName(typeid(T))); +template +struct BuildRtti::value>> { + static void build(Type::Builder builder, Builder& rtti) { + auto name = jsg::typeName(typeid(T)); + builder.initStructure().setName(name); } - static void build(Structure::Builder builder, Configuration configuration) { + static void build(Structure::Builder builder, Builder& rtti) { builder.setName(jsg::typeName(typeid(T))); MemberCounter counter; if constexpr (isDetected()) { - T::template registerMembers(counter, configuration); + T::template registerMembers(counter, rtti.config); } else { T::template registerMembers(counter); } @@ -576,9 +615,9 @@ struct BuildRtti::value>> { } auto members = builder.initMembers(count); - MembersBuilder membersBuilder(configuration, builder, members); + MembersBuilder membersBuilder(builder, members, rtti); if constexpr (isDetected()) { - T::template registerMembers(membersBuilder, configuration); + T::template registerMembers(membersBuilder, rtti.config); } else { T::template registerMembers(membersBuilder); } @@ -587,7 +626,7 @@ struct BuildRtti::value>> { auto constructor = members[membersBuilder.index++].initConstructor(); using Traits = FunctionTraits; using Args = typename Traits::ArgsTuple; - TupleRttiBuilder::build(constructor.initArgs(std::tuple_size_v)); + TupleRttiBuilder::build(constructor.initArgs(std::tuple_size_v), rtti); } } };