1 | 'use strict';
|
2 |
|
3 | const Assert = require('@hapi/hoek/lib/assert');
|
4 | const Clone = require('@hapi/hoek/lib/clone');
|
5 | const Ignore = require('@hapi/hoek/lib/ignore');
|
6 | const Reach = require('@hapi/hoek/lib/reach');
|
7 |
|
8 | const Common = require('./common');
|
9 | const Errors = require('./errors');
|
10 | const State = require('./state');
|
11 |
|
12 |
|
13 | const internals = {
|
14 | result: Symbol('result')
|
15 | };
|
16 |
|
17 |
|
18 | exports.entry = function (value, schema, prefs) {
|
19 |
|
20 | let settings = Common.defaults;
|
21 | if (prefs) {
|
22 | Assert(prefs.warnings === undefined, 'Cannot override warnings preference in synchronous validation');
|
23 | Assert(prefs.artifacts === undefined, 'Cannot override artifacts preference in synchronous validation');
|
24 | settings = Common.preferences(Common.defaults, prefs);
|
25 | }
|
26 |
|
27 | const result = internals.entry(value, schema, settings);
|
28 | Assert(!result.mainstay.externals.length, 'Schema with external rules must use validateAsync()');
|
29 | const outcome = { value: result.value };
|
30 |
|
31 | if (result.error) {
|
32 | outcome.error = result.error;
|
33 | }
|
34 |
|
35 | if (result.mainstay.warnings.length) {
|
36 | outcome.warning = Errors.details(result.mainstay.warnings);
|
37 | }
|
38 |
|
39 | if (result.mainstay.debug) {
|
40 | outcome.debug = result.mainstay.debug;
|
41 | }
|
42 |
|
43 | if (result.mainstay.artifacts) {
|
44 | outcome.artifacts = result.mainstay.artifacts;
|
45 | }
|
46 |
|
47 | return outcome;
|
48 | };
|
49 |
|
50 |
|
51 | exports.entryAsync = async function (value, schema, prefs) {
|
52 |
|
53 | let settings = Common.defaults;
|
54 | if (prefs) {
|
55 | settings = Common.preferences(Common.defaults, prefs);
|
56 | }
|
57 |
|
58 | const result = internals.entry(value, schema, settings);
|
59 | const mainstay = result.mainstay;
|
60 | if (result.error) {
|
61 | if (mainstay.debug) {
|
62 | result.error.debug = mainstay.debug;
|
63 | }
|
64 |
|
65 | throw result.error;
|
66 | }
|
67 |
|
68 | if (mainstay.externals.length) {
|
69 | let root = result.value;
|
70 | const errors = [];
|
71 | for (const external of mainstay.externals) {
|
72 | const path = external.state.path;
|
73 | const linked = external.schema.type === 'link' ? mainstay.links.get(external.schema) : null;
|
74 | let node = root;
|
75 | let key;
|
76 | let parent;
|
77 |
|
78 | const ancestors = path.length ? [root] : [];
|
79 | const original = path.length ? Reach(value, path) : value;
|
80 |
|
81 | if (path.length) {
|
82 | key = path[path.length - 1];
|
83 |
|
84 | let current = root;
|
85 | for (const segment of path.slice(0, -1)) {
|
86 | current = current[segment];
|
87 | ancestors.unshift(current);
|
88 | }
|
89 |
|
90 | parent = ancestors[0];
|
91 | node = parent[key];
|
92 | }
|
93 |
|
94 | try {
|
95 | const createError = (code, local) => (linked || external.schema).$_createError(code, node, local, external.state, settings);
|
96 | const output = await external.method(node, {
|
97 | schema: external.schema,
|
98 | linked,
|
99 | state: external.state,
|
100 | prefs,
|
101 | original,
|
102 | error: createError,
|
103 | errorsArray: internals.errorsArray,
|
104 | warn: (code, local) => mainstay.warnings.push((linked || external.schema).$_createError(code, node, local, external.state, settings)),
|
105 | message: (messages, local) => (linked || external.schema).$_createError('external', node, local, external.state, settings, { messages })
|
106 | });
|
107 |
|
108 | if (output === undefined ||
|
109 | output === node) {
|
110 |
|
111 | continue;
|
112 | }
|
113 |
|
114 | if (output instanceof Errors.Report) {
|
115 | mainstay.tracer.log(external.schema, external.state, 'rule', 'external', 'error');
|
116 | errors.push(output);
|
117 |
|
118 | if (settings.abortEarly) {
|
119 | break;
|
120 | }
|
121 |
|
122 | continue;
|
123 | }
|
124 |
|
125 | if (Array.isArray(output) &&
|
126 | output[Common.symbols.errors]) {
|
127 | mainstay.tracer.log(external.schema, external.state, 'rule', 'external', 'error');
|
128 | errors.push(...output);
|
129 |
|
130 | if (settings.abortEarly) {
|
131 | break;
|
132 | }
|
133 |
|
134 | continue;
|
135 | }
|
136 |
|
137 | if (parent) {
|
138 | mainstay.tracer.value(external.state, 'rule', node, output, 'external');
|
139 | parent[key] = output;
|
140 | }
|
141 | else {
|
142 | mainstay.tracer.value(external.state, 'rule', root, output, 'external');
|
143 | root = output;
|
144 | }
|
145 | }
|
146 | catch (err) {
|
147 | if (settings.errors.label) {
|
148 | err.message += ` (${(external.label)})`;
|
149 | }
|
150 |
|
151 | throw err;
|
152 | }
|
153 | }
|
154 |
|
155 | result.value = root;
|
156 |
|
157 | if (errors.length) {
|
158 | result.error = Errors.process(errors, value, settings);
|
159 |
|
160 | if (mainstay.debug) {
|
161 | result.error.debug = mainstay.debug;
|
162 | }
|
163 |
|
164 | throw result.error;
|
165 | }
|
166 | }
|
167 |
|
168 | if (!settings.warnings &&
|
169 | !settings.debug &&
|
170 | !settings.artifacts) {
|
171 |
|
172 | return result.value;
|
173 | }
|
174 |
|
175 | const outcome = { value: result.value };
|
176 | if (mainstay.warnings.length) {
|
177 | outcome.warning = Errors.details(mainstay.warnings);
|
178 | }
|
179 |
|
180 | if (mainstay.debug) {
|
181 | outcome.debug = mainstay.debug;
|
182 | }
|
183 |
|
184 | if (mainstay.artifacts) {
|
185 | outcome.artifacts = mainstay.artifacts;
|
186 | }
|
187 |
|
188 | return outcome;
|
189 | };
|
190 |
|
191 |
|
192 | internals.Mainstay = class {
|
193 |
|
194 | constructor(tracer, debug, links) {
|
195 |
|
196 | this.externals = [];
|
197 | this.warnings = [];
|
198 | this.tracer = tracer;
|
199 | this.debug = debug;
|
200 | this.links = links;
|
201 | this.shadow = null;
|
202 | this.artifacts = null;
|
203 |
|
204 | this._snapshots = [];
|
205 | }
|
206 |
|
207 | snapshot() {
|
208 |
|
209 | this._snapshots.push({
|
210 | externals: this.externals.slice(),
|
211 | warnings: this.warnings.slice()
|
212 | });
|
213 | }
|
214 |
|
215 | restore() {
|
216 |
|
217 | const snapshot = this._snapshots.pop();
|
218 | this.externals = snapshot.externals;
|
219 | this.warnings = snapshot.warnings;
|
220 | }
|
221 |
|
222 | commit() {
|
223 |
|
224 | this._snapshots.pop();
|
225 | }
|
226 | };
|
227 |
|
228 |
|
229 | internals.entry = function (value, schema, prefs) {
|
230 |
|
231 |
|
232 |
|
233 | const { tracer, cleanup } = internals.tracer(schema, prefs);
|
234 | const debug = prefs.debug ? [] : null;
|
235 | const links = schema._ids._schemaChain ? new Map() : null;
|
236 | const mainstay = new internals.Mainstay(tracer, debug, links);
|
237 | const schemas = schema._ids._schemaChain ? [{ schema }] : null;
|
238 | const state = new State([], [], { mainstay, schemas });
|
239 |
|
240 |
|
241 |
|
242 | const result = exports.validate(value, schema, state, prefs);
|
243 |
|
244 |
|
245 |
|
246 | if (cleanup) {
|
247 | schema.$_root.untrace();
|
248 | }
|
249 |
|
250 | const error = Errors.process(result.errors, value, prefs);
|
251 | return { value: result.value, error, mainstay };
|
252 | };
|
253 |
|
254 |
|
255 | internals.tracer = function (schema, prefs) {
|
256 |
|
257 | if (schema.$_root._tracer) {
|
258 | return { tracer: schema.$_root._tracer._register(schema) };
|
259 | }
|
260 |
|
261 | if (prefs.debug) {
|
262 | Assert(schema.$_root.trace, 'Debug mode not supported');
|
263 | return { tracer: schema.$_root.trace()._register(schema), cleanup: true };
|
264 | }
|
265 |
|
266 | return { tracer: internals.ignore };
|
267 | };
|
268 |
|
269 |
|
270 | exports.validate = function (value, schema, state, prefs, overrides = {}) {
|
271 |
|
272 | if (schema.$_terms.whens) {
|
273 | schema = schema._generate(value, state, prefs).schema;
|
274 | }
|
275 |
|
276 |
|
277 |
|
278 | if (schema._preferences) {
|
279 | prefs = internals.prefs(schema, prefs);
|
280 | }
|
281 |
|
282 |
|
283 |
|
284 | if (schema._cache &&
|
285 | prefs.cache) {
|
286 |
|
287 | const result = schema._cache.get(value);
|
288 | state.mainstay.tracer.debug(state, 'validate', 'cached', !!result);
|
289 | if (result) {
|
290 | return result;
|
291 | }
|
292 | }
|
293 |
|
294 |
|
295 |
|
296 | const createError = (code, local, localState) => schema.$_createError(code, value, local, localState || state, prefs);
|
297 | const helpers = {
|
298 | original: value,
|
299 | prefs,
|
300 | schema,
|
301 | state,
|
302 | error: createError,
|
303 | errorsArray: internals.errorsArray,
|
304 | warn: (code, local, localState) => state.mainstay.warnings.push(createError(code, local, localState)),
|
305 | message: (messages, local) => schema.$_createError('custom', value, local, state, prefs, { messages })
|
306 | };
|
307 |
|
308 |
|
309 |
|
310 | state.mainstay.tracer.entry(schema, state);
|
311 |
|
312 | const def = schema._definition;
|
313 | if (def.prepare &&
|
314 | value !== undefined &&
|
315 | prefs.convert) {
|
316 |
|
317 | const prepared = def.prepare(value, helpers);
|
318 | if (prepared) {
|
319 | state.mainstay.tracer.value(state, 'prepare', value, prepared.value);
|
320 | if (prepared.errors) {
|
321 | return internals.finalize(prepared.value, [].concat(prepared.errors), helpers);
|
322 | }
|
323 |
|
324 | value = prepared.value;
|
325 | }
|
326 | }
|
327 |
|
328 |
|
329 |
|
330 | if (def.coerce &&
|
331 | value !== undefined &&
|
332 | prefs.convert &&
|
333 | (!def.coerce.from || def.coerce.from.includes(typeof value))) {
|
334 |
|
335 | const coerced = def.coerce.method(value, helpers);
|
336 | if (coerced) {
|
337 | state.mainstay.tracer.value(state, 'coerced', value, coerced.value);
|
338 | if (coerced.errors) {
|
339 | return internals.finalize(coerced.value, [].concat(coerced.errors), helpers);
|
340 | }
|
341 |
|
342 | value = coerced.value;
|
343 | }
|
344 | }
|
345 |
|
346 |
|
347 |
|
348 | const empty = schema._flags.empty;
|
349 | if (empty &&
|
350 | empty.$_match(internals.trim(value, schema), state.nest(empty), Common.defaults)) {
|
351 |
|
352 | state.mainstay.tracer.value(state, 'empty', value, undefined);
|
353 | value = undefined;
|
354 | }
|
355 |
|
356 |
|
357 |
|
358 | const presence = overrides.presence || schema._flags.presence || (schema._flags._endedSwitch ? null : prefs.presence);
|
359 | if (value === undefined) {
|
360 | if (presence === 'forbidden') {
|
361 | return internals.finalize(value, null, helpers);
|
362 | }
|
363 |
|
364 | if (presence === 'required') {
|
365 | return internals.finalize(value, [schema.$_createError('any.required', value, null, state, prefs)], helpers);
|
366 | }
|
367 |
|
368 | if (presence === 'optional') {
|
369 | if (schema._flags.default !== Common.symbols.deepDefault) {
|
370 | return internals.finalize(value, null, helpers);
|
371 | }
|
372 |
|
373 | state.mainstay.tracer.value(state, 'default', value, {});
|
374 | value = {};
|
375 | }
|
376 | }
|
377 | else if (presence === 'forbidden') {
|
378 | return internals.finalize(value, [schema.$_createError('any.unknown', value, null, state, prefs)], helpers);
|
379 | }
|
380 |
|
381 |
|
382 |
|
383 | const errors = [];
|
384 |
|
385 | if (schema._valids) {
|
386 | const match = schema._valids.get(value, state, prefs, schema._flags.insensitive);
|
387 | if (match) {
|
388 | if (prefs.convert) {
|
389 | state.mainstay.tracer.value(state, 'valids', value, match.value);
|
390 | value = match.value;
|
391 | }
|
392 |
|
393 | state.mainstay.tracer.filter(schema, state, 'valid', match);
|
394 | return internals.finalize(value, null, helpers);
|
395 | }
|
396 |
|
397 | if (schema._flags.only) {
|
398 | const report = schema.$_createError('any.only', value, { valids: schema._valids.values({ display: true }) }, state, prefs);
|
399 | if (prefs.abortEarly) {
|
400 | return internals.finalize(value, [report], helpers);
|
401 | }
|
402 |
|
403 | errors.push(report);
|
404 | }
|
405 | }
|
406 |
|
407 |
|
408 |
|
409 | if (schema._invalids) {
|
410 | const match = schema._invalids.get(value, state, prefs, schema._flags.insensitive);
|
411 | if (match) {
|
412 | state.mainstay.tracer.filter(schema, state, 'invalid', match);
|
413 | const report = schema.$_createError('any.invalid', value, { invalids: schema._invalids.values({ display: true }) }, state, prefs);
|
414 | if (prefs.abortEarly) {
|
415 | return internals.finalize(value, [report], helpers);
|
416 | }
|
417 |
|
418 | errors.push(report);
|
419 | }
|
420 | }
|
421 |
|
422 |
|
423 |
|
424 | if (def.validate) {
|
425 | const base = def.validate(value, helpers);
|
426 | if (base) {
|
427 | state.mainstay.tracer.value(state, 'base', value, base.value);
|
428 | value = base.value;
|
429 |
|
430 | if (base.errors) {
|
431 | if (!Array.isArray(base.errors)) {
|
432 | errors.push(base.errors);
|
433 | return internals.finalize(value, errors, helpers);
|
434 | }
|
435 |
|
436 | if (base.errors.length) {
|
437 | errors.push(...base.errors);
|
438 | return internals.finalize(value, errors, helpers);
|
439 | }
|
440 | }
|
441 | }
|
442 | }
|
443 |
|
444 |
|
445 |
|
446 | if (!schema._rules.length) {
|
447 | return internals.finalize(value, errors, helpers);
|
448 | }
|
449 |
|
450 | return internals.rules(value, errors, helpers);
|
451 | };
|
452 |
|
453 |
|
454 | internals.rules = function (value, errors, helpers) {
|
455 |
|
456 | const { schema, state, prefs } = helpers;
|
457 |
|
458 | for (const rule of schema._rules) {
|
459 | const definition = schema._definition.rules[rule.method];
|
460 |
|
461 |
|
462 |
|
463 | if (definition.convert &&
|
464 | prefs.convert) {
|
465 |
|
466 | state.mainstay.tracer.log(schema, state, 'rule', rule.name, 'full');
|
467 | continue;
|
468 | }
|
469 |
|
470 |
|
471 |
|
472 | let ret;
|
473 | let args = rule.args;
|
474 | if (rule._resolve.length) {
|
475 | args = Object.assign({}, args);
|
476 | for (const key of rule._resolve) {
|
477 | const resolver = definition.argsByName.get(key);
|
478 |
|
479 | const resolved = args[key].resolve(value, state, prefs);
|
480 | const normalized = resolver.normalize ? resolver.normalize(resolved) : resolved;
|
481 |
|
482 | const invalid = Common.validateArg(normalized, null, resolver);
|
483 | if (invalid) {
|
484 | ret = schema.$_createError('any.ref', resolved, { arg: key, ref: args[key], reason: invalid }, state, prefs);
|
485 | break;
|
486 | }
|
487 |
|
488 | args[key] = normalized;
|
489 | }
|
490 | }
|
491 |
|
492 |
|
493 |
|
494 | ret = ret || definition.validate(value, helpers, args, rule);
|
495 |
|
496 | const result = internals.rule(ret, rule);
|
497 | if (result.errors) {
|
498 | state.mainstay.tracer.log(schema, state, 'rule', rule.name, 'error');
|
499 |
|
500 | if (rule.warn) {
|
501 | state.mainstay.warnings.push(...result.errors);
|
502 | continue;
|
503 | }
|
504 |
|
505 | if (prefs.abortEarly) {
|
506 | return internals.finalize(value, result.errors, helpers);
|
507 | }
|
508 |
|
509 | errors.push(...result.errors);
|
510 | }
|
511 | else {
|
512 | state.mainstay.tracer.log(schema, state, 'rule', rule.name, 'pass');
|
513 | state.mainstay.tracer.value(state, 'rule', value, result.value, rule.name);
|
514 | value = result.value;
|
515 | }
|
516 | }
|
517 |
|
518 | return internals.finalize(value, errors, helpers);
|
519 | };
|
520 |
|
521 |
|
522 | internals.rule = function (ret, rule) {
|
523 |
|
524 | if (ret instanceof Errors.Report) {
|
525 | internals.error(ret, rule);
|
526 | return { errors: [ret], value: null };
|
527 | }
|
528 |
|
529 | if (Array.isArray(ret) &&
|
530 | ret[Common.symbols.errors]) {
|
531 |
|
532 | ret.forEach((report) => internals.error(report, rule));
|
533 | return { errors: ret, value: null };
|
534 | }
|
535 |
|
536 | return { errors: null, value: ret };
|
537 | };
|
538 |
|
539 |
|
540 | internals.error = function (report, rule) {
|
541 |
|
542 | if (rule.message) {
|
543 | report._setTemplate(rule.message);
|
544 | }
|
545 |
|
546 | return report;
|
547 | };
|
548 |
|
549 |
|
550 | internals.finalize = function (value, errors, helpers) {
|
551 |
|
552 | errors = errors || [];
|
553 | const { schema, state, prefs } = helpers;
|
554 |
|
555 |
|
556 |
|
557 | if (errors.length) {
|
558 | const failover = internals.default('failover', undefined, errors, helpers);
|
559 | if (failover !== undefined) {
|
560 | state.mainstay.tracer.value(state, 'failover', value, failover);
|
561 | value = failover;
|
562 | errors = [];
|
563 | }
|
564 | }
|
565 |
|
566 |
|
567 |
|
568 | if (errors.length &&
|
569 | schema._flags.error) {
|
570 |
|
571 | if (typeof schema._flags.error === 'function') {
|
572 | errors = schema._flags.error(errors);
|
573 | if (!Array.isArray(errors)) {
|
574 | errors = [errors];
|
575 | }
|
576 |
|
577 | for (const error of errors) {
|
578 | Assert(error instanceof Error || error instanceof Errors.Report, 'error() must return an Error object');
|
579 | }
|
580 | }
|
581 | else {
|
582 | errors = [schema._flags.error];
|
583 | }
|
584 | }
|
585 |
|
586 |
|
587 |
|
588 | if (value === undefined) {
|
589 | const defaulted = internals.default('default', value, errors, helpers);
|
590 | state.mainstay.tracer.value(state, 'default', value, defaulted);
|
591 | value = defaulted;
|
592 | }
|
593 |
|
594 |
|
595 |
|
596 | if (schema._flags.cast &&
|
597 | value !== undefined) {
|
598 |
|
599 | const caster = schema._definition.cast[schema._flags.cast];
|
600 | if (caster.from(value)) {
|
601 | const casted = caster.to(value, helpers);
|
602 | state.mainstay.tracer.value(state, 'cast', value, casted, schema._flags.cast);
|
603 | value = casted;
|
604 | }
|
605 | }
|
606 |
|
607 |
|
608 |
|
609 | if (schema.$_terms.externals &&
|
610 | prefs.externals &&
|
611 | prefs._externals !== false) {
|
612 |
|
613 | for (const { method } of schema.$_terms.externals) {
|
614 | state.mainstay.externals.push({ method, schema, state, label: Errors.label(schema._flags, state, prefs) });
|
615 | }
|
616 | }
|
617 |
|
618 |
|
619 |
|
620 | const result = { value, errors: errors.length ? errors : null };
|
621 |
|
622 | if (schema._flags.result) {
|
623 | result.value = schema._flags.result === 'strip' ? undefined : helpers.original;
|
624 | state.mainstay.tracer.value(state, schema._flags.result, value, result.value);
|
625 | state.shadow(value, schema._flags.result);
|
626 | }
|
627 |
|
628 |
|
629 |
|
630 | if (schema._cache &&
|
631 | prefs.cache !== false &&
|
632 | !schema._refs.length) {
|
633 |
|
634 | schema._cache.set(helpers.original, result);
|
635 | }
|
636 |
|
637 |
|
638 |
|
639 | if (value !== undefined &&
|
640 | !result.errors &&
|
641 | schema._flags.artifact !== undefined) {
|
642 |
|
643 | state.mainstay.artifacts = state.mainstay.artifacts || new Map();
|
644 | if (!state.mainstay.artifacts.has(schema._flags.artifact)) {
|
645 | state.mainstay.artifacts.set(schema._flags.artifact, []);
|
646 | }
|
647 |
|
648 | state.mainstay.artifacts.get(schema._flags.artifact).push(state.path);
|
649 | }
|
650 |
|
651 | return result;
|
652 | };
|
653 |
|
654 |
|
655 | internals.prefs = function (schema, prefs) {
|
656 |
|
657 | const isDefaultOptions = prefs === Common.defaults;
|
658 | if (isDefaultOptions &&
|
659 | schema._preferences[Common.symbols.prefs]) {
|
660 |
|
661 | return schema._preferences[Common.symbols.prefs];
|
662 | }
|
663 |
|
664 | prefs = Common.preferences(prefs, schema._preferences);
|
665 | if (isDefaultOptions) {
|
666 | schema._preferences[Common.symbols.prefs] = prefs;
|
667 | }
|
668 |
|
669 | return prefs;
|
670 | };
|
671 |
|
672 |
|
673 | internals.default = function (flag, value, errors, helpers) {
|
674 |
|
675 | const { schema, state, prefs } = helpers;
|
676 | const source = schema._flags[flag];
|
677 | if (prefs.noDefaults ||
|
678 | source === undefined) {
|
679 |
|
680 | return value;
|
681 | }
|
682 |
|
683 | state.mainstay.tracer.log(schema, state, 'rule', flag, 'full');
|
684 |
|
685 | if (!source) {
|
686 | return source;
|
687 | }
|
688 |
|
689 | if (typeof source === 'function') {
|
690 | const args = source.length ? [Clone(state.ancestors[0]), helpers] : [];
|
691 |
|
692 | try {
|
693 | return source(...args);
|
694 | }
|
695 | catch (err) {
|
696 | errors.push(schema.$_createError(`any.${flag}`, null, { error: err }, state, prefs));
|
697 | return;
|
698 | }
|
699 | }
|
700 |
|
701 | if (typeof source !== 'object') {
|
702 | return source;
|
703 | }
|
704 |
|
705 | if (source[Common.symbols.literal]) {
|
706 | return source.literal;
|
707 | }
|
708 |
|
709 | if (Common.isResolvable(source)) {
|
710 | return source.resolve(value, state, prefs);
|
711 | }
|
712 |
|
713 | return Clone(source);
|
714 | };
|
715 |
|
716 |
|
717 | internals.trim = function (value, schema) {
|
718 |
|
719 | if (typeof value !== 'string') {
|
720 | return value;
|
721 | }
|
722 |
|
723 | const trim = schema.$_getRule('trim');
|
724 | if (!trim ||
|
725 | !trim.args.enabled) {
|
726 |
|
727 | return value;
|
728 | }
|
729 |
|
730 | return value.trim();
|
731 | };
|
732 |
|
733 |
|
734 | internals.ignore = {
|
735 | active: false,
|
736 | debug: Ignore,
|
737 | entry: Ignore,
|
738 | filter: Ignore,
|
739 | log: Ignore,
|
740 | resolve: Ignore,
|
741 | value: Ignore
|
742 | };
|
743 |
|
744 |
|
745 | internals.errorsArray = function () {
|
746 |
|
747 | const errors = [];
|
748 | errors[Common.symbols.errors] = true;
|
749 | return errors;
|
750 | };
|