| 1489 | } |
| 1490 | |
| 1491 | class ArrayCursor implements IterableIterator<any> { |
| 1492 | private index = 0; |
| 1493 | private len: number; |
| 1494 | private start: number; |
| 1495 | |
| 1496 | // Optimization 1: Cache views locally to avoid 'this.buffer' lookups in the hot loop |
| 1497 | private u32: Uint32Array; |
| 1498 | private f64: Float64Array; |
| 1499 | |
| 1500 | constructor(private buffer: SharedJsonBufferImpl<any>, ptr: number) { |
| 1501 | buffer.resolvePtr(ptr); |
| 1502 | this.len = buffer.scratchLen; |
| 1503 | this.start = buffer.scratchStart; |
| 1504 | this.u32 = buffer.u32; |
| 1505 | this.f64 = buffer.f64; |
| 1506 | |
| 1507 | // Direct check: Type Array is 6 |
| 1508 | if (this.u32[buffer.scratchPtr >> 2] !== 6) { |
| 1509 | throw new Error("Iterator must be used on an Array"); |
| 1510 | } |
| 1511 | } |
| 1512 | |
| 1513 | [Symbol.iterator]() { |
| 1514 | return this; |
| 1515 | } |
| 1516 | |
| 1517 | next(): IteratorResult<any> { |
| 1518 | // Bounds check |
| 1519 | if (this.index >= this.len) { |
| 1520 | return { done: true, value: undefined }; |
| 1521 | } |
| 1522 | |
| 1523 | // Optimization 2: Bitwise shift for *8. |
| 1524 | // Calculate offset: start + (index * 8) |
| 1525 | const offset = this.start + (this.index++ << 3); |
| 1526 | |
| 1527 | // Direct memory read |
| 1528 | const type = this.u32[offset >> 2]!; |
| 1529 | |
| 1530 | // Optimization 3: Inline Primitive Handling (Zero Allocation Path) |
| 1531 | // TYPE_NUMBER (3) is the most common primitive, check it first. |
| 1532 | if (type === 3) { |
| 1533 | const payload = this.u32[(offset + 4) >> 2]!; |
| 1534 | return { done: false, value: this.f64[payload >> 3] }; |
| 1535 | } |
| 1536 | |
| 1537 | // TYPE_NULL (0), TYPE_TRUE (1), TYPE_FALSE (2) |
| 1538 | if (type <= 2) { |
| 1539 | // Nested ternary is faster than switch for 3 values |
| 1540 | const val = type === 1 ? true : (type === 2 ? false : null); |
| 1541 | return { done: false, value: val }; |
| 1542 | } |
| 1543 | |
| 1544 | // Fallback: Objects (5, 6) & Strings (4) |
| 1545 | // We MUST delegate to readSlot here to get the correct Proxy or String. |
| 1546 | // This maintains correctness (distinct objects) while isolating the cost |
| 1547 | // only to complex types. |
| 1548 | return { done: false, value: this.buffer.readSlot(offset) }; |
nothing calls this directly
no outgoing calls
no test coverage detected