@bobfrankston/iflow-direct 0.1.52 → 0.1.54
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 +25 -1
- package/package.json +3 -3
package/imap-native.js
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
* Existing callers are not affected.
|
|
8
8
|
*/
|
|
9
9
|
import * as proto from "./imap-protocol.js";
|
|
10
|
+
// Yield the event loop between buffer slices. Node has setImmediate (drains
|
|
11
|
+
// I/O + timers + IPC before resuming); browser / Android (BridgeTransport)
|
|
12
|
+
// runtimes don't, so fall back to a 0 ms timer. Reached via globalThis so this
|
|
13
|
+
// transport-agnostic package needs no node type dependency.
|
|
14
|
+
const yieldToEventLoop = typeof globalThis.setImmediate === "function"
|
|
15
|
+
? globalThis.setImmediate
|
|
16
|
+
: (cb) => { setTimeout(cb, 0); };
|
|
10
17
|
export class NativeImapClient {
|
|
11
18
|
transport;
|
|
12
19
|
transportFactory;
|
|
@@ -1208,7 +1215,7 @@ export class NativeImapClient {
|
|
|
1208
1215
|
const TIME_BUDGET_MS = 10;
|
|
1209
1216
|
while (true) {
|
|
1210
1217
|
if (performance.now() - t0 > TIME_BUDGET_MS) {
|
|
1211
|
-
|
|
1218
|
+
yieldToEventLoop(() => this.processBuffer());
|
|
1212
1219
|
return;
|
|
1213
1220
|
}
|
|
1214
1221
|
// Check for literal — `{N}` announces N octets of arbitrary data
|
|
@@ -1237,6 +1244,23 @@ export class NativeImapClient {
|
|
|
1237
1244
|
// decode happens once per literal, not once per chunk that
|
|
1238
1245
|
// arrives during the literal's transit.
|
|
1239
1246
|
let literal = this.utf8Decoder.decode(literalBytes);
|
|
1247
|
+
// DESYNC CAPTURE (Bob 2026-06-16, overnight debug). A BODY[]
|
|
1248
|
+
// literal whose content is itself an IMAP command tag means the
|
|
1249
|
+
// byte-buffer parser misaligned: the declared {N} didn't match
|
|
1250
|
+
// reality and we swallowed a later command's bytes. Dump the
|
|
1251
|
+
// declared size + the misaligned content + the raw bytes that
|
|
1252
|
+
// PRECEDED the literal, so the mechanism (how the {N} boundary
|
|
1253
|
+
// slipped) is finally visible. Cheap; only fires on the desync.
|
|
1254
|
+
if (this.pendingCommand.currentLiteralKey?.startsWith("BODY")
|
|
1255
|
+
&& /^[A-Za-z]+\d+\s+(SELECT|FETCH|UID|LOGIN|STATUS|EXAMINE|LIST|IDLE|NOOP|STORE|SEARCH|CAPABILITY|CLOSE|LOGOUT|APPEND|COPY|MOVE|EXPUNGE|CREATE|DELETE|RENAME|SUBSCRIBE|ENABLE|STARTTLS)\b/i.test(literal.slice(0, 80).replace(/^[\s*]+/, ""))) {
|
|
1256
|
+
const litStart = this.bufferOffset - neededBytes;
|
|
1257
|
+
const ctxStart = Math.max(0, litStart - 256);
|
|
1258
|
+
const ctx = this.buffer.subarray(ctxStart, litStart);
|
|
1259
|
+
const ascii = Array.from(ctx).map(b => (b >= 32 && b < 127) ? String.fromCharCode(b) : (b === 13 ? "\\r" : b === 10 ? "\\n" : ".")).join("");
|
|
1260
|
+
console.error(` [imap] DESYNC CAPTURE key=${this.pendingCommand.currentLiteralKey} declaredLiteral=${neededBytes}B bufferOffset=${this.bufferOffset} bufferLength=${this.bufferLength} litStart=${litStart}`);
|
|
1261
|
+
console.error(` [imap] DESYNC literal[0..200]=${JSON.stringify(literal.slice(0, 200))}`);
|
|
1262
|
+
console.error(` [imap] DESYNC preceding[${ctx.length}B]=${JSON.stringify(ascii)}`);
|
|
1263
|
+
}
|
|
1240
1264
|
// For non-BODY literals (e.g. display names in ENVELOPE), wrap in quotes
|
|
1241
1265
|
// so tokenizeParenList treats them as a single token
|
|
1242
1266
|
if (!this.pendingCommand.currentLiteralKey) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/iflow-direct",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.54",
|
|
4
4
|
"description": "Direct IMAP client — transport-agnostic, no Node.js dependencies, browser-ready",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.ts",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"author": "Bob Frankston",
|
|
20
20
|
"license": "ISC",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@bobfrankston/tcp-transport": "^0.1.
|
|
22
|
+
"@bobfrankston/tcp-transport": "^0.1.7"
|
|
23
23
|
},
|
|
24
24
|
"exports": {
|
|
25
25
|
".": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
".transformedSnapshot": {
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@bobfrankston/tcp-transport": "^0.1.
|
|
53
|
+
"@bobfrankston/tcp-transport": "^0.1.7"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|