(doc, pathsToValidate, pathsToSkip, isNestedValidate)
| 2989 | */ |
| 2990 | |
| 2991 | function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate) { |
| 2992 | const doValidateOptions = {}; |
| 2993 | const schema = doc.$__schema; |
| 2994 | const schemaPaths = schema.paths; |
| 2995 | const activeStates = doc.$__.activePaths.states; |
| 2996 | |
| 2997 | // gh-16379: compute the modified-path set at most once and reuse it below, so |
| 2998 | // checking many required paths doesn't rebuild it per-path (O(required x modified)). |
| 2999 | let _modifiedPaths; |
| 3000 | const getModifiedPaths = () => (_modifiedPaths ??= doc.modifiedPaths()); |
| 3001 | |
| 3002 | // only validate required fields when necessary |
| 3003 | let paths = []; |
| 3004 | const requireStates = activeStates.require; |
| 3005 | if (requireStates != null) { |
| 3006 | let modifiedPaths = null; |
| 3007 | for (const path in requireStates) { |
| 3008 | // Evaluate function-valued `required` for every required path, before any |
| 3009 | // filtering, so `invalidate()` calls and `cachedRequired` entries stay |
| 3010 | // consistent no matter which paths end up validated. |
| 3011 | const type = Object.hasOwn(schemaPaths, path) ? schemaPaths[path] : schema.path(path); |
| 3012 | if (typeof type?.originalRequiredValue === 'function') { |
| 3013 | const cachedRequired = doc.$__.cachedRequired ?? (doc.$__.cachedRequired = {}); |
| 3014 | try { |
| 3015 | cachedRequired[path] = type.originalRequiredValue.call(doc, doc); |
| 3016 | } catch (err) { |
| 3017 | doc.invalidate(path, err); |
| 3018 | } |
| 3019 | } |
| 3020 | |
| 3021 | if (!doc.$__isSelected(path)) { |
| 3022 | if (modifiedPaths === null) { |
| 3023 | modifiedPaths = doc.modifiedPaths(); |
| 3024 | } |
| 3025 | if (!doc.$isModified(path, null, modifiedPaths)) { |
| 3026 | continue; |
| 3027 | } |
| 3028 | } |
| 3029 | if (path.charCodeAt(path.length - 1) === STAR_CHAR_CODE && path.endsWith('.$*')) { |
| 3030 | // Skip $* paths - they represent map schemas, not actual document paths |
| 3031 | continue; |
| 3032 | } |
| 3033 | const cachedRequired = doc.$__.cachedRequired; |
| 3034 | if (cachedRequired != null && path in cachedRequired) { |
| 3035 | if (cachedRequired[path]) { |
| 3036 | paths.push(path); |
| 3037 | } |
| 3038 | } else { |
| 3039 | paths.push(path); |
| 3040 | } |
| 3041 | } |
| 3042 | } |
| 3043 | |
| 3044 | for (let i = 0; i < STATES_TO_VALIDATE.length; ++i) { |
| 3045 | const statePaths = activeStates[STATES_TO_VALIDATE[i]]; |
| 3046 | if (statePaths == null) { |
| 3047 | continue; |
| 3048 | } |
no test coverage detected