Repository: bevyengine/bevy
File: crates/bevy_ecs/src/observer/mod.rs (Rust)

Code before:
        world.add_observer(|mut trigger: On<EventWithData, A>| {
            trigger.event_mut().counter += 4;
        });

        let mut event = EventWithData { counter: 0 };
        let component_a = world.register_component::<A>();
        world.trigger_targets_ref(&mut event, component_a);
        assert_eq!(5, event.counter);
    }

    #[test]
    fn observer_multiple_listeners() {
        let mut world = World::new();
        world.init_resource::<Order>();

        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));

        world.spawn(A).flush();
        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
        // Our A entity plus our two observers
        assert_eq!(world.entity_count(), 3);
    }

    #[test]
    fn observer_multiple_events() {
        let mut world = World::new();
        world.init_resource::<Order>();
        let on_remove = Remove::register_event_key(&mut world);
        world.spawn(
            // SAFETY: Add and Remove are both unit types, so this is safe
            unsafe {
                Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
                    res.observed("add/remove");
                })
                .with_event_key(on_remove)
            },
        );

        let entity = world.spawn(A).id();
        world.despawn(entity);
        assert_eq!(
            vec!["add/remove", "add/remove"],
            world.resource::<Order>().0
        );
    }

    #[test]
    fn observer_multiple_components() {
        let mut world = World::new();
        world.init_resource::<Order>();

Review comment (performance):
Huh, it's unfortunate that we need `Allows<Internal>` in order to query `Observer`.  As a follow-up, we may want to consider expanding the rule for allowing filters to account for required components so that mentioning `Observer` disables the `Internal` filter.  I don't know whether it's possible to do that efficiently, though.  

Code after:
        });
        world.add_observer(|mut trigger: On<EventWithData, A>| {
            trigger.event_mut().counter += 4;
        });

        let mut event = EventWithData { counter: 0 };
        let component_a = world.register_component::<A>();
        world.trigger_targets_ref(&mut event, component_a);
        assert_eq!(5, event.counter);
    }

    #[test]
    fn observer_multiple_listeners() {
        let mut world = World::new();
        world.init_resource::<Order>();

        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));

        world.spawn(A).flush();
        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
        // we have one A entity and two observers
        assert_eq!(world.query::<&A>().query(&world).count(), 1);
        assert_eq!(
            world
                .query_filtered::<&Observer, Allows<Internal>>()
                .query(&world)
                .count(),
            2
        );
    }

    #[test]
    fn observer_multiple_events() {
        let mut world = World::new();
        world.init_resource::<Order>();
        let on_remove = Remove::register_event_key(&mut world);
        world.spawn(
            // SAFETY: Add and Remove are both unit types, so this is safe
            unsafe {
                Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
                    res.observed("add/remove");
                })
                .with_event_key(on_remove)
            },
        );

        let entity = world.spawn(A).id();
        world.despawn(entity);
        assert_eq!(
            vec!["add/remove", "add/remove"],