fix: le resultat d-une commande de page suit la meme regle que tout le reste
Balayage execute sur les deux proxys apres le correctif precedent : aucun membre de la vue de collection ne rend plus la cible, mais une commande de page de l-enveloppe qui rendrait la collection la rendait BRUTE. `nextPage` est declare `() => void` et ne rend rien aujourd-hui, donc ce n-est pas un defaut vivant - c-est la meme justification jamais executee, sur l-autre proxy, et c-est exactement le motif qu-il fallait casser. Elle s-execute toujours ; seul son retour est tenu a la regle.
This commit is contained in:
@@ -500,12 +500,24 @@ export function makeReadFilteredShapeResult<R extends object>(result: R, caps: C
|
||||
"`useShapeQuery`.",
|
||||
);
|
||||
}
|
||||
// THE PAGE COMMANDS. They return `void` and yield nothing, so they forward, exactly
|
||||
// as `add`/`delete`/`clear` do on the collection view. What they load lands in the
|
||||
// raw collection, which is only ever read back through the filter above.
|
||||
// THE PAGE COMMANDS. They forward: what they load lands in the raw collection, which
|
||||
// is only ever read back through the filter above.
|
||||
//
|
||||
// Their RESULT is held to the same rule as everything else here, and that is the
|
||||
// lesson of the collection view rather than a worry about this one. `nextPage` is
|
||||
// declared `() => void` and the shipped hook assigns the subscription's own, so today
|
||||
// it yields nothing - but "it returns void" was the written, unexecuted ground on
|
||||
// which `add` was forwarded, and `Set.prototype.add` returns the collection. A page
|
||||
// command that ever hands something back gets the same answer as any other member:
|
||||
// a scalar passes, anything that could reach an item refuses.
|
||||
if (prop === "nextPage" || prop === "previousPage") {
|
||||
const fn = Reflect.get(target, prop, target);
|
||||
return typeof fn === "function" ? fn.bind(target) : fn;
|
||||
if (typeof fn !== "function") return fn;
|
||||
return (...args: unknown[]): unknown => {
|
||||
const out = (fn as (...a: unknown[]) => unknown).apply(target, args);
|
||||
if (cannotReachAnItem(out)) return out;
|
||||
throw refusalOf(prop, "the result envelope");
|
||||
};
|
||||
}
|
||||
return answerUnnamedMember(target, prop, "the result envelope");
|
||||
};
|
||||
|
||||
@@ -257,6 +257,29 @@ test("useShape: deleting reaches only what the view shows", async () => {
|
||||
expect([...(hook.raw() as Iterable<BaseType>)].map((o) => o["@graph"])).toEqual([hers]);
|
||||
});
|
||||
|
||||
// The page commands forward, and their RESULT is held to the same rule as every other
|
||||
// member. `nextPage` is declared `() => void` and yields nothing today, so this pins the
|
||||
// RULE rather than a live defect - which is the point: "it returns void" was the written,
|
||||
// never-executed ground on which `add` was forwarded, and `add` returns the collection.
|
||||
test("useShape: a page command that handed something back would be refused, not forwarded", async () => {
|
||||
const base = makeUseShapeHook({ paginated: true });
|
||||
const leaky: FakeShapeHook = {
|
||||
...base,
|
||||
hook: ((shapeType, conf) => ({
|
||||
...base.hook(shapeType, conf),
|
||||
nextPage: (): void => base.raw() as undefined,
|
||||
})) as UseShapeLike,
|
||||
};
|
||||
inject(leaky);
|
||||
const hers = await documentOf("alice");
|
||||
const his = await documentOf("bob");
|
||||
base.items.push(noteIn(hers, "a1"), noteIn(his, "b1"));
|
||||
|
||||
setCurrentUser("bob");
|
||||
const result: ShapeResult = useShape(NoteShape, EVERYTHING);
|
||||
expect(() => result.nextPage?.()).toThrow(/not filtered/i);
|
||||
});
|
||||
|
||||
// -- SAFE FOR A SHAPE NOBODY HAS SEEN --------------------------------------
|
||||
|
||||
/** What a later `@ng-org/orm` might hand back: the six members of `alpha.21` plus two
|
||||
|
||||
Reference in New Issue
Block a user