Conversation
| text: Parameters<Keyboard["type"]>[0], | ||
| options?: Parameters<Keyboard["type"]>[1], | ||
| ) => use((k) => k.type(text, options)), | ||
| up: (key: Parameters<Keyboard["up"]>[0]) => use((k) => k.up(key)), |
There was a problem hiding this comment.
useless change i think.
| Stream.callback<PageEvents[K]>((queue) => { | ||
| const handler = (value: PageEvents[K]) => | ||
| Queue.offerUnsafe(queue, value); | ||
| const closeHandler = () => Queue.endUnsafe(queue); |
There was a problem hiding this comment.
Ai says:
Yes, we absolutely need the queue because of a core architectural change in how Effect v4 handles asynchronous callbacks.
1. The v3 vs v4 API change
In Effect v3, eventStream used Stream.asyncPush, which provided an emit object. You had to call emit.single(value) to push a
value and emit.end() to close the stream:
// v3 (asyncPush)
Stream.asyncPush((emit) => {
context.on(event, emit.single);
context.once("close", emit.end);
})In Effect v4, Stream.asyncPush was deprecated and unified into Stream.callback. Its callback f no longer receives a custom
emit object; instead, it receives a standard Effect Queue (Queue.Queue<A, E | Cause.Done>):
// v4 (callback)
Stream.callback((queue) => { ... })2. Why did Effect make this change?
In v3, emit was an ad-hoc, proprietary object interface created specifically for async streams.
By changing this to a standard Queue in v4, Effect:
- Consolidated APIs: Unified the stream-callback protocol with the standard Queue primitive.
- Improved Customizability: Allows you to leverage standard Queue operations (such as capacity bounds, backpressure, custom
drop/slide strategies, and safety utilities) directly inside callbacks. - Optimized Performance: The underlying fiber runtime can pipe the Queue directly into channels under-the-hood without
wrapping it in an extra intermediate adapter.
3. How we interact with the Queue
To push event values onto the queue safely from the Playwright event-emitter context (which is synchronous/non-effectful), we
use Effect's fast, synchronous push APIs:
- Queue.offerUnsafe(queue, value): Instantly pushes an event down the stream without requiring an Effect context.
- Queue.endUnsafe(queue): Signals that the event stream is finished (e.g. when a page or browser context closes).
| Effect.flatten, | ||
| ); | ||
| const fileChooserOpt = yield* Fiber.join(fileChooserFiber); | ||
| const fileChooser = Option.getOrThrow(fileChooserOpt); |
There was a problem hiding this comment.
getOrThrow is not effecty
| browser.newContext(options).then(PlaywrightBrowserContext.make), | ||
| ), | ||
| (context) => context.close.pipe(Effect.ignoreLogged), | ||
| (context) => context.close.pipe(Effect.ignore), |
There was a problem hiding this comment.
ignoreLogged no longer a thing? investigate
No description provided.