@bobfrankston/iflow-direct 0.1.47 → 0.1.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/imap-native.js CHANGED
@@ -467,19 +467,27 @@ export class NativeImapClient {
467
467
  items.push("BODY.PEEK[]");
468
468
  const tag = proto.nextTag();
469
469
  const streamed = [];
470
- const cb = onMessage
471
- ? (resp) => {
472
- if (resp.tag !== "*" || resp.type !== "FETCH")
473
- return;
474
- const parsed = this.parseFetchResponses([resp]);
475
- for (const msg of parsed) {
476
- streamed.push(msg);
470
+ // ALWAYS parse incrementally in the per-response callback — even
471
+ // when the caller passed no `onMessage`. The callback runs from
472
+ // processBuffer's 10 ms time-budgeted loop, so envelope parsing of a
473
+ // large FETCH (a sync-backfill chunk of 100+ messages) is sliced
474
+ // across event-loop turns. The old `onMessage ? stream : batch`
475
+ // path parsed every envelope in ONE synchronous block after the
476
+ // tagged OK — profiled 2026-05-15 as a ~30 s daemon wedge
477
+ // (tokenizeParenList ~40 % of CPU), starving every getMessage /
478
+ // move / delete IPC for the duration.
479
+ const cb = (resp) => {
480
+ if (resp.tag !== "*" || resp.type !== "FETCH")
481
+ return;
482
+ const parsed = this.parseFetchResponses([resp]);
483
+ for (const msg of parsed) {
484
+ streamed.push(msg);
485
+ if (onMessage)
477
486
  onMessage(msg);
478
- }
479
487
  }
480
- : undefined;
481
- const responses = await this.sendCommand(tag, proto.fetchCommand(tag, range, items), cb);
482
- return onMessage ? streamed : this.parseFetchResponses(responses);
488
+ };
489
+ await this.sendCommand(tag, proto.fetchCommand(tag, range, items), cb);
490
+ return streamed;
483
491
  }
484
492
  /**
485
493
  * Folder-scoped batch body fetch. Selects `folderPath`, issues a single
package/imap-protocol.js CHANGED
@@ -422,6 +422,16 @@ function tokenizeParenList(s) {
422
422
  let j = i;
423
423
  while (j < end && str[j] !== " " && str[j] !== ")" && str[j] !== "(")
424
424
  j++;
425
+ if (j === i) {
426
+ // str[i] is a stray ')' (or '(') that none of the branches
427
+ // above consumed — an unbalanced/malformed parenthesised
428
+ // list (Dovecot mis-parses some Outlook `From:` headers and
429
+ // emits exactly this). Without advancing, `i` is stuck and
430
+ // the while-loop spins FOREVER, pinning a CPU core and
431
+ // wedging the whole daemon event loop. Skip the stray char.
432
+ i++;
433
+ continue;
434
+ }
425
435
  tokens.push(str.substring(i, j));
426
436
  i = j;
427
437
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/iflow-direct",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "description": "Direct IMAP client — transport-agnostic, no Node.js dependencies, browser-ready",
5
5
  "main": "index.js",
6
6
  "types": "index.ts",