From e277d00218667ebc9dcde898a1cadb9eea178792 Mon Sep 17 00:00:00 2001 From: Sam Verschueren Date: Fri, 11 Jan 2019 08:06:52 +0100 Subject: [PATCH] Only infer label when predicate fails - fixes #115 --- source/index.ts | 11 ++++++++--- source/lib/predicates/predicate.ts | 24 ++++++++++++++++-------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/source/index.ts b/source/index.ts index 024b4c0..bdcadc3 100644 --- a/source/index.ts +++ b/source/index.ts @@ -201,12 +201,15 @@ export interface Ow { any(...predicate: BasePredicate[]): AnyPredicate; } -const main = (value: T, labelOrPredicate: BasePredicate | string | undefined, predicate?: BasePredicate) => { +const main = (value: T, labelOrPredicate: BasePredicate | string | Function | undefined, predicate?: BasePredicate) => { let label: any = labelOrPredicate; let testPredicate: any = predicate; if (isPredicate(labelOrPredicate)) { - label = inferLabel(callsites()); + const stackFrames = callsites(); + + // Pass in a label function to only infer it when it fails + label = () => inferLabel(stackFrames); testPredicate = labelOrPredicate; } @@ -227,7 +230,9 @@ Object.defineProperties(main, { create: { value: (labelOrPredicate: BasePredicate | string | undefined, predicate?: BasePredicate) => (value: T) => { if (isPredicate(labelOrPredicate)) { - return main(value, inferLabel(callsites()), labelOrPredicate); + const stackFrames = callsites(); + + return main(value, () => inferLabel(stackFrames), labelOrPredicate); } return main(value, labelOrPredicate, predicate); diff --git a/source/lib/predicates/predicate.ts b/source/lib/predicates/predicate.ts index 2d1384b..0d31c46 100644 --- a/source/lib/predicates/predicate.ts +++ b/source/lib/predicates/predicate.ts @@ -55,18 +55,26 @@ export class Predicate implements BasePredicate { * @hidden */ // tslint:disable completed-docs - [testSymbol](value: T, main: Ow, label?: string) { - const label2 = label - ? `${this.type} \`${label}\`` - : this.type; - + [testSymbol](value: T, main: Ow, label?: string | Function) { for (const {validator, message} of this.context.validators) { const result = validator(value); - if (typeof result !== 'boolean' || !result) { - // TODO: Modify the stack output to show the original `ow()` call instead of this `throw` statement - throw new ArgumentError(message(value, label2, result), main); + if (result === true) { + continue; + } + + let label2 = label; + + if (typeof label === 'function') { + label2 = label(); } + + label2 = label2 + ? `${this.type} \`${label2}\`` + : this.type; + + // TODO: Modify the stack output to show the original `ow()` call instead of this `throw` statement + throw new ArgumentError(message(value, label2, result), main); } }