| 125 | return new Promise((resolve, reject) => { |
| 126 | const started = Date.now(); |
| 127 | const tick = () => { |
| 128 | let v: T | undefined | null | false; |
| 129 | try { v = predicate(); } catch (e) { return reject(e); } |
| 130 | if (v) return resolve(v as T); |
| 131 | if (Date.now() - started > timeoutMs) { |
| 132 | // Name the wait: an async stack loses the await site, so an unlabeled |
| 133 | // timeout can't tell WHICH step flaked (the #662 test's recurring |
| 134 | // timeout was undiagnosable for exactly this reason). |
| 135 | return reject(new Error(`Timed out after ${timeoutMs}ms${label ? ` waiting for: ${label}` : ''}`)); |
| 136 | } |
| 137 | setTimeout(tick, pollMs); |
| 138 | }; |
| 139 | tick(); |
| 140 | }); |
| 141 | } |