@@ -147,6 +147,25 @@ const Func* lookupWithDefaultValuesFunc(const Class* cls) {
147147 return func;
148148}
149149
150+ const StaticString s_clearTerseFields (" clearTerseFields" );
151+
152+ const Func* lookupClearTerseFieldsFunc (const Class* cls) {
153+ auto const func = cls->lookupMethod (s_clearTerseFields.get ());
154+ if (func == nullptr ) {
155+ thrift_error (
156+ folly::sformat (" Method {}::clearTerseFields() not found" , cls->name ()),
157+ ERR_INVALID_DATA
158+ );
159+ }
160+ if (func->isStatic ()) {
161+ thrift_error (
162+ folly::sformat (" Method {}::clearTerseFields() is static" , cls->name ()),
163+ ERR_INVALID_DATA
164+ );
165+ }
166+ return func;
167+ }
168+
150169StructSpec compileSpec (const Array& spec, const Class* cls) {
151170 // A union field also writes to a property named __type. If one exists, we
152171 // need to also verify that it accepts integer values. We only need to do
@@ -197,10 +216,13 @@ StructSpec compileSpec(const Array& spec, const Class* cls) {
197216
198217 // We can precompute the cls::withDefaultValues() func pointer only if the
199218 // underlying class cannot change.
200- auto const func = cls != nullptr && cls->isPersistent ()
219+ auto const withDefaultValuesFunc = cls != nullptr && cls->isPersistent ()
201220 ? lookupWithDefaultValuesFunc (cls) : nullptr ;
202221
203- return StructSpec{HPHP::FixedVector (std::move (temp)), func};
222+ auto const clearTerseFieldsFunc = cls != nullptr && cls->isPersistent ()
223+ ? lookupClearTerseFieldsFunc (cls) : nullptr ;
224+
225+ return StructSpec{HPHP::FixedVector (std::move (temp)), withDefaultValuesFunc, clearTerseFieldsFunc};
204226}
205227
206228} // namespace
@@ -303,7 +325,9 @@ Object StructSpec::newObject(Class* cls) const {
303325
304326 auto obj = g_context->invokeFuncFew (
305327 func, cls, 0 , nullptr , RuntimeCoeffects::pure (), false /* dynamic */ );
306- if (tvIsObject (obj)) return Object::attach (obj.m_data .pobj );
328+ if (tvIsObject (obj)) {
329+ return Object::attach (obj.m_data .pobj );
330+ }
307331
308332 SCOPE_EXIT { tvDecRefGen (obj); };
309333 thrift_error (
@@ -315,4 +339,11 @@ Object StructSpec::newObject(Class* cls) const {
315339 );
316340}
317341
342+ void StructSpec::clearTerseFields (Class* cls, const Object& obj) const {
343+ auto const func = clearTerseFieldsFunc != nullptr
344+ ? clearTerseFieldsFunc : lookupClearTerseFieldsFunc (cls);
345+ g_context->invokeFuncFew (
346+ func, obj.get (), 0 , nullptr , RuntimeCoeffects::write_props ());
347+ }
348+
318349}
0 commit comments