You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					92 lines
				
				2.8 KiB
			
		
		
			
		
	
	
					92 lines
				
				2.8 KiB
			| 
											3 years ago
										 | import type {CodeKeywordDefinition} from "../../types" | ||
|  | import type {KeywordCxt} from "../../compile/validate" | ||
|  | import {allSchemaProperties, usePattern} from "../code" | ||
|  | import {_, not, Name} from "../../compile/codegen" | ||
|  | import {alwaysValidSchema, checkStrictMode} from "../../compile/util" | ||
|  | import {evaluatedPropsToName, Type} from "../../compile/util" | ||
|  | import {AnySchema} from "../../types" | ||
|  | 
 | ||
|  | const def: CodeKeywordDefinition = { | ||
|  |   keyword: "patternProperties", | ||
|  |   type: "object", | ||
|  |   schemaType: "object", | ||
|  |   code(cxt: KeywordCxt) { | ||
|  |     const {gen, schema, data, parentSchema, it} = cxt | ||
|  |     const {opts} = it | ||
|  |     const patterns = allSchemaProperties(schema) | ||
|  |     const alwaysValidPatterns = patterns.filter((p) => | ||
|  |       alwaysValidSchema(it, schema[p] as AnySchema) | ||
|  |     ) | ||
|  | 
 | ||
|  |     if ( | ||
|  |       patterns.length === 0 || | ||
|  |       (alwaysValidPatterns.length === patterns.length && | ||
|  |         (!it.opts.unevaluated || it.props === true)) | ||
|  |     ) { | ||
|  |       return | ||
|  |     } | ||
|  | 
 | ||
|  |     const checkProperties = | ||
|  |       opts.strictSchema && !opts.allowMatchingProperties && parentSchema.properties | ||
|  |     const valid = gen.name("valid") | ||
|  |     if (it.props !== true && !(it.props instanceof Name)) { | ||
|  |       it.props = evaluatedPropsToName(gen, it.props) | ||
|  |     } | ||
|  |     const {props} = it | ||
|  |     validatePatternProperties() | ||
|  | 
 | ||
|  |     function validatePatternProperties(): void { | ||
|  |       for (const pat of patterns) { | ||
|  |         if (checkProperties) checkMatchingProperties(pat) | ||
|  |         if (it.allErrors) { | ||
|  |           validateProperties(pat) | ||
|  |         } else { | ||
|  |           gen.var(valid, true) // TODO var
 | ||
|  |           validateProperties(pat) | ||
|  |           gen.if(valid) | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     function checkMatchingProperties(pat: string): void { | ||
|  |       for (const prop in checkProperties) { | ||
|  |         if (new RegExp(pat).test(prop)) { | ||
|  |           checkStrictMode( | ||
|  |             it, | ||
|  |             `property ${prop} matches pattern ${pat} (use allowMatchingProperties)` | ||
|  |           ) | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     function validateProperties(pat: string): void { | ||
|  |       gen.forIn("key", data, (key) => { | ||
|  |         gen.if(_`${usePattern(cxt, pat)}.test(${key})`, () => { | ||
|  |           const alwaysValid = alwaysValidPatterns.includes(pat) | ||
|  |           if (!alwaysValid) { | ||
|  |             cxt.subschema( | ||
|  |               { | ||
|  |                 keyword: "patternProperties", | ||
|  |                 schemaProp: pat, | ||
|  |                 dataProp: key, | ||
|  |                 dataPropType: Type.Str, | ||
|  |               }, | ||
|  |               valid | ||
|  |             ) | ||
|  |           } | ||
|  | 
 | ||
|  |           if (it.opts.unevaluated && props !== true) { | ||
|  |             gen.assign(_`${props}[${key}]`, true) | ||
|  |           } else if (!alwaysValid && !it.allErrors) { | ||
|  |             // can short-circuit if `unevaluatedProperties` is not supported (opts.next === false)
 | ||
|  |             // or if all properties were evaluated (props === true)
 | ||
|  |             gen.if(not(valid), () => gen.break()) | ||
|  |           } | ||
|  |         }) | ||
|  |       }) | ||
|  |     } | ||
|  |   }, | ||
|  | } | ||
|  | 
 | ||
|  | export default def |