fix: le prototype et l-extensibilite sont des ecritures, elles aussi
Trouve en balayant le correctif de ce round plutot qu-en raisonnant dessus. `Object.setPrototypeOf(vue, ...)` remplacait le prototype de la VRAIE collection - apres quoi l-iterer leve pour toutes les identites, c-est le probleme de `clear` dans une autre tonalite - et `Object.preventExtensions`, par quoi `Object.freeze` commence, la rendait non extensible : une ecriture, et de surcroit la projection d-index de `ownKeys` n-est licite que tant que la cible est extensible.
This commit is contained in:
@@ -542,6 +542,19 @@ export function makeReadFilteredView<S extends object>(set: S, caps: CapRegistry
|
||||
defineProperty(_target, prop) {
|
||||
throw refusalOf(prop, "a write to the view itself");
|
||||
},
|
||||
// The two that reach the target without naming a property, found by sweeping this
|
||||
// file's own repair rather than by reasoning about it: `Object.setPrototypeOf(view, other)`
|
||||
// replaced the real collection's prototype - after which `[...collection]` throws for
|
||||
// EVERY identity, so it is the `clear` problem again in a different key - and
|
||||
// `Object.preventExtensions(view)` (which is what `Object.freeze` starts with) made
|
||||
// the target non-extensible, which both writes to it and breaks `ownKeys` below, whose
|
||||
// projection is only lawful while the target is extensible.
|
||||
setPrototypeOf() {
|
||||
throw refusalOf("the prototype", "a write to the view itself");
|
||||
},
|
||||
preventExtensions() {
|
||||
throw refusalOf("extensibility", "a write to the view itself");
|
||||
},
|
||||
ownKeys(target) {
|
||||
// A Set holds its items internally and owns no key naming one, so there is nothing
|
||||
// to project: `Object.keys` on it is already empty (measured). An array owns one key
|
||||
|
||||
@@ -366,6 +366,15 @@ test("a write to the view itself is refused, whatever the collection underneath
|
||||
view.length = 0;
|
||||
}).toThrow(/not filtered/i);
|
||||
expect(() => Object.defineProperty(view, "0", { value: { id: "SPY" } })).toThrow(/not filtered/i);
|
||||
// The two that reach the target without naming a property. Replacing the prototype
|
||||
// breaks iteration of the real collection for EVERY identity; `preventExtensions` -
|
||||
// which `Object.freeze` starts with - writes to it and unlawfully strands the index
|
||||
// projection. Both were found by sweeping this view's own repair.
|
||||
expect(() => Object.setPrototypeOf(view, { stolen: () => items })).toThrow(/not filtered/i);
|
||||
expect(() => Object.preventExtensions(view)).toThrow(/not filtered/i);
|
||||
expect(() => Object.freeze(view)).toThrow(/not filtered/i);
|
||||
// The plain array underneath accepted nothing, so the view is what stood in the way.
|
||||
expect(items.map((i) => i.id)).toEqual(["a", "p"]);
|
||||
expect(Object.getPrototypeOf(items)).toBe(Array.prototype);
|
||||
expect(Object.isExtensible(items)).toBe(true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user