…, Map e Set
`[1,2].values().next()` falhava em COMPILAÇÃO — "no Registry entry for
`Array.next(0 args)`" — porque `values()`/`keys()`/`entries()` devolvem um array
materializado e `Array` não tem linha de Registry para `next`. `for-of` e spread
funcionavam (consomem array), mas o protocolo de iterador não existia.
Era a outra metade do padrão dos bundles (`[ generator(), [].values(), … ]`, #2038)
e o que impedia `368_iterator_protocol` (#2024) de rodar.
Duas peças:
1. O handle devolvido é REGISTRADO como iterador aberto na criação
(`open_vec_iterator`), o que o torna distinguível de um array comum em runtime
sem side-table nova — `GEN_CURSORS` já existia para o generator eager, e
`generator_next` já cursoriza `Entry::Vec`. Map/Set (stdlib `.ts`) devolvem seus
arrays através do `values()` de Array, herdando a marcação.
2. `.next()`/`.return()`/`.throw()` sobre receiver-array roteia ao despacho
dinâmico, que aceita `Entry::Vec` SOMENTE se marcado.
A distinção tem uma armadilha que derrubou uma tentativa anterior (registrada na
#2042): `generator_next` usa `or_insert(0)`, ou seja CRIA o cursor para qualquer
handle que receba — perguntar "tem cursor?" depois responde sim para um array
comum também. Por isso o predicado é `contains_key` puro, nunca inserindo: assim
continua sendo uma propriedade de COMO o handle foi criado, e `[1,2].next` segue
`undefined`.
O array continua materializado, então `for-of`, spread, `.join()` e `.length`
sobre o resultado seguem idênticos.
Testes: `claude-iterador-nativo-next.test.ts` (19) cobre Array/Map/Set,
independência de dois iteradores sobre o mesmo array, `take()` (a forma dos
bundles) e as não-regressões (`[1,2].next`→undefined, spread, for-of,
destructuring de entries, `.join()`, `.length`). Fixture cross-runtime
`claude-native-iterator-next.ts` — byte-idêntica a Node E Bun.
Suite: 2735/2736. A única falha — "window é o MESMO objeto entre scripts do
documento" — é PRÉ-EXISTENTE, verificada na main.
LIMITAÇÃO CONHECIDA, explícita: consumir parcialmente com `.next()` e DEPOIS
espalhar/iterar reinicia do zero —
const p = [10,20,30].values();
p.next(); // 10
[...p] // RTS: 10,20,30 · Node: 20,30
porque o front prova "é array" e emite index-walk a partir de 0, sem consultar o
cursor. Nenhum programa regride (essa composição não compilava antes), mas é uma
divergência real; corrigi-la exige o for-of/spread consultarem o cursor, o que
hoje é decidido estaticamente. Fica registrado na #2042.
Também permanece: `arr[Symbol.iterator]()` (a CHAMADA) — a leitura já devolve uma
função, mas a chamada roteia por `__rtsadp_idx_call`, que faz `ToString` da symbol
key (→ "[object Object]") em vez de ter a branch de symbol que
`__rtsadp_dyn_idx_get` já tem. Tentei e reverti: o retorno da função nativa é
re-interpretado como número na camada de invocação (o mesmo "i64 ⇒ número" do
#2042/#2044, agora em `fn_invoke_method`). Isso ainda trava a `zip` da
`368_iterator_protocol`.
Refs #2042, #2024, #2038
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017k43FcCXn8a1zqWfDmJAWr
O problema
[1,2].values().next()falhava em compilação:values()/keys()/entries()devolvem um array materializado, eArraynão tem linha de Registry paranext.for-ofe spread funcionavam (consomem array), mas o protocolo de iterador não existia — nem em Array, nem em Map/Set.Era a outra metade do padrão dos bundles (
[ generator(), [].values(), … ], #2038) e o que impedia368_iterator_protocol(#2024).A correção
1. O handle vira um iterador aberto na criação (
open_vec_iterator), o que o torna distinguível de um array comum em runtime — sem side-table nova:GEN_CURSORSjá existia para o generator eager, egenerator_nextjá cursorizaEntry::Vec. Map/Set (stdlib.ts) devolvem seus arrays através dovalues()de Array, herdando a marcação.2.
.next()/.return()/.throw()sobre receiver-array roteia ao despacho dinâmico, que aceitaEntry::Vecsomente se marcado.A armadilha que derrubou a tentativa anterior
generator_nextusaor_insert(0)— ele cria o cursor para qualquer handle que receba. Perguntar "tem cursor?" depois responde sim para um array comum também, e foi assim que a marcação por side-table falhou antes (registrado na #2042).Por isso o predicado é
contains_keypuro, nunca inserindo: continua sendo uma propriedade de como o handle foi criado.[1,2].nextsegueundefined.O array continua materializado, então
for-of, spread,.join()e.lengthsobre o resultado seguem idênticos.Validação
claude-iterador-nativo-next.test.ts— 19/19: Array/Map/Set, independência de dois iteradores sobre o mesmo array,take()(a forma dos bundles), mais as não-regressões ([1,2].next→undefined, spread, for-of, destructuring deentries(),.join(),.length).claude-native-iterator-next.ts— byte-idêntica a Node e Bun.read_before_commit.sh: sem violação.Limitação conhecida (explícita)
Consumir parcialmente com
.next()e depois espalhar/iterar reinicia do zero:O front prova "é array" e emite index-walk a partir de 0, sem consultar o cursor. Nenhum programa regride — essa composição não compilava antes —, mas é uma divergência real. Corrigi-la exige for-of/spread consultarem o cursor, hoje decidido estaticamente. Fica na #2042.
O que ainda falta
arr[Symbol.iterator]()(a chamada). A leitura já devolve uma função, mas a chamada roteia por__rtsadp_idx_call, que fazToStringda symbol key (→"[object Object]") em vez de ter a branch de symbol que__rtsadp_dyn_idx_getjá tem.Tentei e reverti: o retorno da função nativa é re-interpretado como número na camada de invocação — o mesmo
i64 ⇒ númerodo #2042/#2044, agora emfn_invoke_method. Ainda trava azipda368_iterator_protocol.Refs #2042, #2024, #2038
🤖 Generated with Claude Code