Skip to content

Commit ee1b731

Browse files
tedeschiajquense
andauthoredJul 28, 2023
fix: performance improvement (#2043) (#2044)
* fix: performance improvement (#2043) * Update src/ValidationError.ts Co-authored-by: Jason Quense <monastic.panic@gmail.com> * Apply suggestions from code review Co-authored-by: Jason Quense <monastic.panic@gmail.com> * fix PR comments --------- Co-authored-by: Jason Quense <monastic.panic@gmail.com>
1 parent b4627a2 commit ee1b731

File tree

5 files changed

+51
-9
lines changed

5 files changed

+51
-9
lines changed
 

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const parsedUser = await userSchema.validate(
7373
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
7474
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
7575

76+
7677
- [Schema basics](#schema-basics)
7778
- [Parsing: Transforms](#parsing-transforms)
7879
- [Validation: Tests](#validation-tests)

‎src/ValidationError.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ let strReg = /\$\{\s*(\w+)\s*\}/g;
55

66
type Params = Record<string, unknown>;
77

8-
export default class ValidationError extends Error {
8+
export default class ValidationError implements Error {
9+
name: string;
10+
message: string;
11+
stack?: string | undefined;
912
value: any;
1013
path?: string;
1114
type?: string;
@@ -38,9 +41,8 @@ export default class ValidationError extends Error {
3841
value?: any,
3942
field?: string,
4043
type?: string,
44+
disableStack?: boolean,
4145
) {
42-
super();
43-
4446
this.name = 'ValidationError';
4547
this.value = value;
4648
this.path = field;
@@ -52,7 +54,8 @@ export default class ValidationError extends Error {
5254
toArray(errorOrErrors).forEach((err) => {
5355
if (ValidationError.isError(err)) {
5456
this.errors.push(...err.errors);
55-
this.inner = this.inner.concat(err.inner.length ? err.inner : err);
57+
const innerErrors = err.inner.length ? err.inner : [err];
58+
this.inner.push(...innerErrors);
5659
} else {
5760
this.errors.push(err);
5861
}
@@ -63,6 +66,7 @@ export default class ValidationError extends Error {
6366
? `${this.errors.length} errors occurred`
6467
: this.errors[0];
6568

66-
if (Error.captureStackTrace) Error.captureStackTrace(this, ValidationError);
69+
if (!disableStack && Error.captureStackTrace)
70+
Error.captureStackTrace(this, ValidationError);
6771
}
6872
}

‎src/schema.ts

+29-3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export type SchemaSpec<TDefault> = {
4343
strip?: boolean;
4444
strict?: boolean;
4545
recursive?: boolean;
46+
disableStackTrace?: boolean;
4647
label?: string | undefined;
4748
meta?: SchemaMetadata;
4849
};
@@ -191,6 +192,7 @@ export default abstract class Schema<
191192
strict: false,
192193
abortEarly: true,
193194
recursive: true,
195+
disableStackTrace: false,
194196
nullable: false,
195197
optional: true,
196198
coerce: true,
@@ -345,6 +347,8 @@ export default abstract class Schema<
345347
strict: options.strict ?? this.spec.strict,
346348
abortEarly: options.abortEarly ?? this.spec.abortEarly,
347349
recursive: options.recursive ?? this.spec.recursive,
350+
disableStackTrace:
351+
options.disableStackTrace ?? this.spec.disableStackTrace,
348352
};
349353
}
350354

@@ -499,7 +503,9 @@ export default abstract class Schema<
499503

500504
test(args!, panicOnce, function finishTestRun(err) {
501505
if (err) {
502-
nestedErrors = nestedErrors.concat(err);
506+
Array.isArray(err)
507+
? nestedErrors.push(...err)
508+
: nestedErrors.push(err);
503509
}
504510
if (--count <= 0) {
505511
nextOnce(nestedErrors);
@@ -553,6 +559,8 @@ export default abstract class Schema<
553559
options?: ValidateOptions<TContext>,
554560
): Promise<this['__outputType']> {
555561
let schema = this.resolve({ ...options, value });
562+
let disableStackTrace =
563+
options?.disableStackTrace ?? schema.spec.disableStackTrace;
556564

557565
return new Promise((resolve, reject) =>
558566
schema._validate(
@@ -563,7 +571,16 @@ export default abstract class Schema<
563571
reject(error);
564572
},
565573
(errors, validated) => {
566-
if (errors.length) reject(new ValidationError(errors!, validated));
574+
if (errors.length)
575+
reject(
576+
new ValidationError(
577+
errors!,
578+
validated,
579+
undefined,
580+
undefined,
581+
disableStackTrace,
582+
),
583+
);
567584
else resolve(validated as this['__outputType']);
568585
},
569586
),
@@ -576,6 +593,8 @@ export default abstract class Schema<
576593
): this['__outputType'] {
577594
let schema = this.resolve({ ...options, value });
578595
let result: any;
596+
let disableStackTrace =
597+
options?.disableStackTrace ?? schema.spec.disableStackTrace;
579598

580599
schema._validate(
581600
value,
@@ -585,7 +604,14 @@ export default abstract class Schema<
585604
throw error;
586605
},
587606
(errors, validated) => {
588-
if (errors.length) throw new ValidationError(errors!, value);
607+
if (errors.length)
608+
throw new ValidationError(
609+
errors!,
610+
value,
611+
undefined,
612+
undefined,
613+
disableStackTrace,
614+
);
589615
result = validated;
590616
},
591617
);

‎src/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export interface ValidateOptions<TContext = {}> {
6161
* When false validations will not descend into nested schema (relevant for objects or arrays). Default - true
6262
*/
6363
recursive?: boolean;
64+
/**
65+
* When true ValidationError instance won't include stack trace information. Default - false
66+
*/
67+
disableStackTrace?: boolean;
6468
/**
6569
* Any context needed for validating schema conditions (see: when())
6670
*/

‎src/util/createValidation.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type CreateErrorOptions = {
2222
message?: Message<any>;
2323
params?: ExtraParams;
2424
type?: string;
25+
disableStackTrace?: boolean;
2526
};
2627

2728
export type TestContext<TContext = {}> = {
@@ -79,7 +80,12 @@ export default function createValidation(config: {
7980
next: NextCallback,
8081
) {
8182
const { name, test, params, message, skipAbsent } = config;
82-
let { parent, context, abortEarly = schema.spec.abortEarly } = options;
83+
let {
84+
parent,
85+
context,
86+
abortEarly = schema.spec.abortEarly,
87+
disableStackTrace = schema.spec.disableStackTrace,
88+
} = options;
8389

8490
function resolve<T>(item: T | Reference<T>) {
8591
return Ref.isRef(item) ? item.getValue(value, parent, context) : item;
@@ -105,6 +111,7 @@ export default function createValidation(config: {
105111
value,
106112
nextParams.path,
107113
overrides.type || name,
114+
overrides.disableStackTrace ?? disableStackTrace,
108115
);
109116
error.params = nextParams;
110117
return error;

0 commit comments

Comments
 (0)
Please sign in to comment.