Skip to content

EventBus: emitting a wildcard literal double-fires handlers registered on the same literal name #1

Description

@razukc

Summary

When a handler is registered on an event name that contains * (e.g. *, user.*), EventBus stores it in wildcardHandlers rather than handlers. Emitting that exact same literal name then triggers both:

  1. the wildcard match (because * matches any event, including itself), and
  2. the exact-match wildcard entry,

so each registered handler fires twice. The same problem applies to any pattern literal — registering on "foo.*" and emitting "foo.*" double-fires.

Reproduction

```ts
import { Runtime } from 'writmint';

const rt = new Runtime();
const calls: number[] = [];
rt.registerPlugin({
name: 'p', version: '1.0.0',
setup: async (ctx) => {
ctx.events.on('', () => calls.push(1));
ctx.events.on('
', () => calls.push(2));
},
});
await rt.initialize();
rt.getContext().events.emit('*');
console.log(calls.length); // 4 — expected 2
```

Where

  • `src/event-bus.ts` — `emit` walks both `handlers` and `wildcardHandlers` and a literal-pattern handler matches both paths for its own name.
  • See `tests/property/event-delivery.property.test.ts` (top-of-file comment) — the property suite excludes `*` from generated event names to work around this.

Suggested fix

In `emit`, when iterating wildcard handlers, skip entries whose pattern equals the emitted event name and was already delivered via the exact-match path; or, equivalently, route a literal pattern (`isWildcard(pattern) && pattern === eventName`) through one path only.

Acceptance

  • The reproduction above prints `2`.
  • Remove the `.filter((s) => !s.includes('*'))` workaround on the `eventNameArb` generator in `tests/property/event-delivery.property.test.ts` and the suite stays green across many seeds.

Found

While running the prepublish gate for v0.1.0; fast-check counterexample `[2, "*"]` on seed `-1796970649`.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions