diff --git a/packages/polyfill/src/emulated-verifier/read-filter.ts b/packages/polyfill/src/emulated-verifier/read-filter.ts index efe855f..b3a7511 100644 --- a/packages/polyfill/src/emulated-verifier/read-filter.ts +++ b/packages/polyfill/src/emulated-verifier/read-filter.ts @@ -352,12 +352,16 @@ function filteredDescriptor( * cases leak is not a boundary. * * ── And `get` is not the only door ──────────────────────────────────────── - * Three traps answer the same question and all three have to give the same answer: + * Four traps answer the same question and all four have to give the same answer: * `get`, `getOwnPropertyDescriptor` (which `Object.keys`, a spread, `JSON.stringify` and * any console inspection go through, WITHOUT touching `get`) and, on the array form, * `has` and `ownKeys`. Each of them was forwarding to the target while `get` filtered. - * They are wired to one `read` function below rather than to three copies of the rule, - * because a boundary made of parallel switch statements is a boundary that drifts. + * `get` and `getOwnPropertyDescriptor` are wired to one `read` function below rather than + * to two copies of the rule; `has` and `ownKeys` answer positions rather than values, so + * they do not go through `read` but project from the same `kept` set it reads - which is + * what makes the four agree. Not one funnel, then, but one SOURCE: a boundary made of + * parallel switch statements is a boundary that drifts, and so is a header that claims a + * funnel it does not have. * * ── The default: DECIDED, or refused ───────────────────────────────────── * Every member this file serves is named below. Anything else refuses, whatever its type. @@ -574,7 +578,10 @@ export function makeReadFilteredView(set: S, caps: CapRegistry // three different ways: a mutation may not reach past what the view shows, and may not // hand back what the view hides. // - // ALL THREE ARE GATED ON `keep`, and that is the arbitration rather than an accident. + // ALL THREE ARE GATED, on the same question asked of the item, and that is the + // arbitration rather than an accident. `delete` and `clear` ask `keep` - may the + // holder READ this item - while `add` asks the stricter `writable`, because planting + // an item means naming a document the holder HOLDS, which reading one does not. // `delete` and `clear` were gated first and `add` was not, which made the rule above // true by coincidence: the ungated `add` MANUFACTURED the very state the other two // then handled partially - a holder can plant an item into a document it cannot read,