Describe the bug
Adding a component to a prefab after it has been instantiated leaves the component invisible to instances — including instances created afterwards. The (IsA, base) table-graph edge appears to be cached and not invalidated when the base gains a component, so whether a new instance receives the component depends on whether its source table's IsA edge already existed. Regression in v4.1.0 (v4.0.5 is correct).
To Reproduce
#include "flecs.h"
#include <stdio.h>
int main(void) {
ecs_world_t *w = ecs_init();
ecs_entity_t C = ecs_component(w, {.entity=ecs_entity(w,{.name="C"}), .type={.size=4,.alignment=4}});
ecs_entity_t T = ecs_entity(w, {.name="Marker"});
ecs_entity_t P = ecs_new(w); ecs_add_id(w, P, EcsPrefab);
ecs_new_w_pair(w, EcsIsA, P); /* caches edge {} --(IsA,P)--> {(IsA,P)} */
ecs_add_id(w, P, C); /* prefab gains C AFTER that */
ecs_entity_t f1 = ecs_new_w_pair(w, EcsIsA, P); /* same source table {} */
printf("from empty table : has=%d owns=%d\n", ecs_has_id(w,f1,C), ecs_owns_id(w,f1,C));
ecs_entity_t f2 = ecs_new(w); ecs_add_id(w, f2, T);
ecs_add_pair(w, f2, EcsIsA, P); /* different source table */
printf("from {Marker} table : has=%d owns=%d\n", ecs_has_id(w,f2,C), ecs_owns_id(w,f2,C));
printf("prefab has C : %d\n", ecs_has_id(w,P,C));
}
Output on v4.1.6:
from empty table : has=0 owns=0
from {Marker} table : has=1 owns=1
prefab has C : 1
Expected behavior
from empty table : has=1 owns=0
from {Marker} table : has=1 owns=1
prefab has C : 1
Both instances should receive C (has=1), since both are created after the prefab gained it. On v4.0.4/v4.0.5 both instances see it. If mutating an instantiated prefab is no longer supported, it should throw as v4.1.6 already does for children of an instantiated prefab (Throw error when changing children of already instantiated prefab) rather than silently produce instances that differ by source table.
Additional context
- Checked on v4.0.4, v4.0.5, v4.1.0, v4.1.1, v4.1.6, change in behaviour starts from v4.1.0
- macOS arm64, clang, distr/flecs.{c,h} amalgamation, default build.
Describe the bug
Adding a component to a prefab after it has been instantiated leaves the component invisible to instances — including instances created afterwards. The (IsA, base) table-graph edge appears to be cached and not invalidated when the base gains a component, so whether a new instance receives the component depends on whether its source table's IsA edge already existed. Regression in v4.1.0 (v4.0.5 is correct).
To Reproduce
Output on v4.1.6:
from empty table : has=0 owns=0
from {Marker} table : has=1 owns=1
prefab has C : 1
Expected behavior
from empty table : has=1 owns=0
from {Marker} table : has=1 owns=1
prefab has C : 1
Both instances should receive C (has=1), since both are created after the prefab gained it. On v4.0.4/v4.0.5 both instances see it. If mutating an instantiated prefab is no longer supported, it should throw as v4.1.6 already does for children of an instantiated prefab (Throw error when changing children of already instantiated prefab) rather than silently produce instances that differ by source table.
Additional context