.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / table / node_modules / ajv / lib / vocabularies / code.ts
1 import type {AnySchema, SchemaMap} from "../types"
2 import type {SchemaCxt} from "../compile"
3 import type {KeywordCxt} from "../compile/validate"
4 import {CodeGen, _, and, or, not, nil, strConcat, getProperty, Code, Name} from "../compile/codegen"
5 import {alwaysValidSchema, Type} from "../compile/util"
6 import N from "../compile/names"
7
8 export function checkReportMissingProp(cxt: KeywordCxt, prop: string): void {
9   const {gen, data, it} = cxt
10   gen.if(noPropertyInData(gen, data, prop, it.opts.ownProperties), () => {
11     cxt.setParams({missingProperty: _`${prop}`}, true)
12     cxt.error()
13   })
14 }
15
16 export function checkMissingProp(
17   {gen, data, it: {opts}}: KeywordCxt,
18   properties: string[],
19   missing: Name
20 ): Code {
21   return or(
22     ...properties.map((prop) =>
23       and(noPropertyInData(gen, data, prop, opts.ownProperties), _`${missing} = ${prop}`)
24     )
25   )
26 }
27
28 export function reportMissingProp(cxt: KeywordCxt, missing: Name): void {
29   cxt.setParams({missingProperty: missing}, true)
30   cxt.error()
31 }
32
33 export function hasPropFunc(gen: CodeGen): Name {
34   return gen.scopeValue("func", {
35     // eslint-disable-next-line @typescript-eslint/unbound-method
36     ref: Object.prototype.hasOwnProperty,
37     code: _`Object.prototype.hasOwnProperty`,
38   })
39 }
40
41 export function isOwnProperty(gen: CodeGen, data: Name, property: Name | string): Code {
42   return _`${hasPropFunc(gen)}.call(${data}, ${property})`
43 }
44
45 export function propertyInData(
46   gen: CodeGen,
47   data: Name,
48   property: Name | string,
49   ownProperties?: boolean
50 ): Code {
51   const cond = _`${data}${getProperty(property)} !== undefined`
52   return ownProperties ? _`${cond} && ${isOwnProperty(gen, data, property)}` : cond
53 }
54
55 export function noPropertyInData(
56   gen: CodeGen,
57   data: Name,
58   property: Name | string,
59   ownProperties?: boolean
60 ): Code {
61   const cond = _`${data}${getProperty(property)} === undefined`
62   return ownProperties ? or(cond, not(isOwnProperty(gen, data, property))) : cond
63 }
64
65 export function allSchemaProperties(schemaMap?: SchemaMap): string[] {
66   return schemaMap ? Object.keys(schemaMap).filter((p) => p !== "__proto__") : []
67 }
68
69 export function schemaProperties(it: SchemaCxt, schemaMap: SchemaMap): string[] {
70   return allSchemaProperties(schemaMap).filter(
71     (p) => !alwaysValidSchema(it, schemaMap[p] as AnySchema)
72   )
73 }
74
75 export function callValidateCode(
76   {schemaCode, data, it: {gen, topSchemaRef, schemaPath, errorPath}, it}: KeywordCxt,
77   func: Code,
78   context: Code,
79   passSchema?: boolean
80 ): Code {
81   const dataAndSchema = passSchema ? _`${schemaCode}, ${data}, ${topSchemaRef}${schemaPath}` : data
82   const valCxt: [Name, Code | number][] = [
83     [N.instancePath, strConcat(N.instancePath, errorPath)],
84     [N.parentData, it.parentData],
85     [N.parentDataProperty, it.parentDataProperty],
86     [N.rootData, N.rootData],
87   ]
88   if (it.opts.dynamicRef) valCxt.push([N.dynamicAnchors, N.dynamicAnchors])
89   const args = _`${dataAndSchema}, ${gen.object(...valCxt)}`
90   return context !== nil ? _`${func}.call(${context}, ${args})` : _`${func}(${args})`
91 }
92
93 export function usePattern(gen: CodeGen, pattern: string): Name {
94   return gen.scopeValue("pattern", {
95     key: pattern,
96     ref: new RegExp(pattern, "u"),
97     code: _`new RegExp(${pattern}, "u")`,
98   })
99 }
100
101 export function validateArray(cxt: KeywordCxt): Name {
102   const {gen, data, keyword, it} = cxt
103   const valid = gen.name("valid")
104   if (it.allErrors) {
105     const validArr = gen.let("valid", true)
106     validateItems(() => gen.assign(validArr, false))
107     return validArr
108   }
109   gen.var(valid, true)
110   validateItems(() => gen.break())
111   return valid
112
113   function validateItems(notValid: () => void): void {
114     const len = gen.const("len", _`${data}.length`)
115     gen.forRange("i", 0, len, (i) => {
116       cxt.subschema(
117         {
118           keyword,
119           dataProp: i,
120           dataPropType: Type.Num,
121         },
122         valid
123       )
124       gen.if(not(valid), notValid)
125     })
126   }
127 }
128
129 export function validateUnion(cxt: KeywordCxt): void {
130   const {gen, schema, keyword, it} = cxt
131   /* istanbul ignore if */
132   if (!Array.isArray(schema)) throw new Error("ajv implementation error")
133   const alwaysValid = schema.some((sch: AnySchema) => alwaysValidSchema(it, sch))
134   if (alwaysValid && !it.opts.unevaluated) return
135
136   const valid = gen.let("valid", false)
137   const schValid = gen.name("_valid")
138
139   gen.block(() =>
140     schema.forEach((_sch: AnySchema, i: number) => {
141       const schCxt = cxt.subschema(
142         {
143           keyword,
144           schemaProp: i,
145           compositeRule: true,
146         },
147         schValid
148       )
149       gen.assign(valid, _`${valid} || ${schValid}`)
150       const merged = cxt.mergeValidEvaluated(schCxt, schValid)
151       // can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true)
152       // or if all properties and items were evaluated (it.props === true && it.items === true)
153       if (!merged) gen.if(not(valid))
154     })
155   )
156
157   cxt.result(
158     valid,
159     () => cxt.reset(),
160     () => cxt.error(true)
161   )
162 }