|
22 | 22 | struct objc_slot *objc_get_slot(Class cls, SEL selector);
|
23 | 23 | #define CHECK_ARG(arg) if (0 == arg) { return 0; }
|
24 | 24 |
|
| 25 | +static inline void safe_remove_from_subclass_list(Class cls); |
| 26 | + |
25 | 27 | /**
|
26 | 28 | * Calls C++ destructors in the correct order.
|
27 | 29 | */
|
@@ -513,8 +515,44 @@ Class class_setSuperclass(Class cls, Class newSuper)
|
513 | 515 | CHECK_ARG(cls);
|
514 | 516 | CHECK_ARG(newSuper);
|
515 | 517 | if (Nil == cls) { return Nil; }
|
| 518 | + |
| 519 | + LOCK_RUNTIME_FOR_SCOPE(); |
| 520 | + |
| 521 | + safe_remove_from_subclass_list(cls); |
| 522 | + |
516 | 523 | Class oldSuper = cls->super_class;
|
517 | 524 | cls->super_class = newSuper;
|
| 525 | + |
| 526 | + // The super class's subclass list is used in certain method resolution scenarios. |
| 527 | + cls->sibling_class = cls->super_class->subclass_list; |
| 528 | + cls->super_class->subclass_list = cls; |
| 529 | + |
| 530 | + if (!class_isMetaClass(cls)) |
| 531 | + { |
| 532 | + // Update the metaclass's superclass. |
| 533 | + class_setSuperclass(cls->isa, newSuper->isa); |
| 534 | + } |
| 535 | + else |
| 536 | + { |
| 537 | + // newSuper is presumably a metaclass. Its isa will therefore be the appropriate root metaclass. |
| 538 | + cls->isa = newSuper->isa; |
| 539 | + } |
| 540 | + |
| 541 | + // Make sure the superclass is initialized if we're initialized. |
| 542 | + if (objc_test_class_flag(cls, objc_class_flag_initialized)) |
| 543 | + { |
| 544 | + objc_send_initialize(newSuper); |
| 545 | + // Update the class's dtable to reflect its new superclass's dtable. |
| 546 | + if (cls->dtable != uninstalled_dtable) |
| 547 | + { |
| 548 | + // we can't use objc_update_dtable_for_class here, as it doesn't take into account |
| 549 | + // superclasses. It only walks downward. |
| 550 | + free_dtable(cls->dtable); |
| 551 | + cls->dtable = uninstalled_dtable; |
| 552 | + cls->dtable = create_dtable_for_class(cls, uninstalled_dtable); |
| 553 | + } |
| 554 | + } |
| 555 | + |
518 | 556 | return oldSuper;
|
519 | 557 | }
|
520 | 558 |
|
|
0 commit comments