@@ -204,14 +204,14 @@ Future<void> testAOT(
204204 );
205205
206206 // Ensure instance fields of classes are reported.
207- final baseClass =
208- objects[classnames.entries
209- . singleWhere ((e) => e.value == 'FieldTestBase' )
210- .key ];
211- final subClass =
212- objects[classnames.entries
213- . singleWhere ((e) => e.value == 'FieldTestSub' )
214- .key ];
207+ final baseClassId = classnames.entries
208+ . singleWhere ((e) => e.value == 'FieldTestBase' )
209+ .key;
210+ final baseClass = objects[baseClassId ];
211+ final subClassId = classnames.entries
212+ . singleWhere ((e) => e.value == 'FieldTestSub' )
213+ .key;
214+ final subClass = objects[subClassId ];
215215 final baseFieldIds = baseClass['fields' ];
216216 final baseFields = [for (final int id in baseFieldIds) objects[id]];
217217 final baseSlots = baseClass['instance_slots' ]
@@ -222,7 +222,7 @@ Future<void> testAOT(
222222 final subSlots = subClass['instance_slots' ];
223223
224224 // We have:
225- // class Base {
225+ // class FieldTestBase {
226226 // static int baseS0 = int.parse('1');
227227 // static int baseS1 = int.parse('2');
228228 // int base0;
@@ -233,12 +233,22 @@ Future<void> testAOT(
233233 // }
234234 //
235235 // This static field is never tree shaken.
236- expectField (baseFields[0 ], name: 'baseS0' , flags: ['static' ]);
237- expectField (baseFields[1 ], name: 'baseS1' , flags: ['static' ]);
236+ expectField (
237+ baseFields[0 ],
238+ name: 'baseS0' ,
239+ flags: ['static' ],
240+ ownerClass: baseClassId,
241+ );
242+ expectField (
243+ baseFields[1 ],
244+ name: 'baseS1' ,
245+ flags: ['static' ],
246+ ownerClass: baseClassId,
247+ );
238248
239249 // Neighboring static fields should always be one word away
240- final int staticFieldOffset0 = baseFields[0 ][" static_field_offset" ];
241- final int staticFieldOffset1 = baseFields[1 ][" static_field_offset" ];
250+ final int staticFieldOffset0 = baseFields[0 ][' static_field_offset' ];
251+ final int staticFieldOffset1 = baseFields[1 ][' static_field_offset' ];
242252 Expect .equals (staticFieldOffset1 - staticFieldOffset0, wordSize);
243253
244254 if (isProduct) {
@@ -277,25 +287,29 @@ Future<void> testAOT(
277287 expectField (
278288 baseFields[2 ],
279289 name: 'base0' ,
290+ ownerClass: baseClassId,
280291 isReference: false ,
281292 unboxedType: 'int' ,
282293 );
283294 expectField (
284295 baseFields[3 ],
285296 name: 'base1' ,
297+ ownerClass: baseClassId,
286298 isReference: false ,
287299 unboxedType: 'double' ,
288300 );
289- expectField (baseFields[4 ], name: 'base2' );
301+ expectField (baseFields[4 ], name: 'base2' , ownerClass : baseClassId );
290302 expectField (
291303 baseFields[5 ],
292304 name: 'base3' ,
305+ ownerClass: baseClassId,
293306 isReference: false ,
294307 unboxedType: 'Float32x4' ,
295308 );
296309 expectField (
297310 baseFields[6 ],
298311 name: 'base4' ,
312+ ownerClass: baseClassId,
299313 isReference: false ,
300314 unboxedType: 'Float64x2' ,
301315 );
@@ -336,13 +350,23 @@ Future<void> testAOT(
336350 );
337351 }
338352 // We have:
339- // class Sub <T> extends Base {
353+ // class FieldTestSub <T> extends FieldTestBase {
340354 // late int subL1 = int.parse('1');
341355 // late final double subL2 = double.parse('1.2');
342356 // }
343357 // These late instance fields are never tree shaken.
344- expectField (subFields[0 ], name: 'subL1' , flags: ['late' ]);
345- expectField (subFields[1 ], name: 'subL2' , flags: ['final' , 'late' ]);
358+ expectField (
359+ subFields[0 ],
360+ name: 'subL1' ,
361+ flags: ['late' ],
362+ ownerClass: subClassId,
363+ );
364+ expectField (
365+ subFields[1 ],
366+ name: 'subL2' ,
367+ flags: ['final' , 'late' ],
368+ ownerClass: subClassId,
369+ );
346370 expectTypeArgumentsSlot (
347371 subSlots[0 ],
348372 offsetReferences: 1 ,
@@ -399,6 +423,28 @@ Future<void> testAOT(
399423 }
400424 Expect .isTrue (totalGap < 500 );
401425 Expect .isTrue ((totalSize + totalGap - textSectionSize) < 500 );
426+
427+ // Ensure that functions correctly report their owners
428+ // `forceDrops` removes all Function objects, so we skip the test there
429+ if (! forceDrops) {
430+ final myBaseClass =
431+ objects[classnames.entries
432+ .singleWhere ((e) => e.value == 'MyBase' )
433+ .key];
434+ final mySubClass =
435+ objects[classnames.entries
436+ .singleWhere ((e) => e.value == 'MySub' )
437+ .key];
438+
439+ final functions = objects.where ((o) => o['type' ] == 'Function' ).toList ();
440+
441+ final fooFunc = functions.singleWhere ((o) => o['name' ] == 'MyBase.foo' );
442+
443+ final barFunc = functions.singleWhere ((o) => o['name' ] == 'MySub.bar' );
444+
445+ Expect .equals (fooFunc['owner_class' ], myBaseClass['id' ]);
446+ Expect .equals (barFunc['owner_class' ], mySubClass['id' ]);
447+ }
402448 });
403449}
404450
@@ -408,8 +454,12 @@ void expectField(
408454 List <String > flags = const [],
409455 bool isReference = true ,
410456 String ? unboxedType,
457+ int ? ownerClass,
411458}) {
412459 Expect .equals (name, fieldJson['name' ]);
460+ if (ownerClass != null ) {
461+ Expect .equals (ownerClass, fieldJson['owner_class' ]);
462+ }
413463 Expect .equals (isReference, fieldJson['is_reference' ]);
414464 Expect .listEquals (flags, fieldJson['flags' ]);
415465 if (unboxedType != null ) {
0 commit comments