source: trip-planner-front/node_modules/ajv/lib/vocabularies/core/ref.ts

Last change on this file was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.3 KB
Line 
1import type {CodeKeywordDefinition, AnySchema} from "../../types"
2import type {KeywordCxt} from "../../compile/validate"
3import MissingRefError from "../../compile/ref_error"
4import {callValidateCode} from "../code"
5import {_, nil, stringify, Code, Name} from "../../compile/codegen"
6import N from "../../compile/names"
7import {SchemaEnv, resolveRef} from "../../compile"
8import {mergeEvaluated} from "../../compile/util"
9
10const def: CodeKeywordDefinition = {
11 keyword: "$ref",
12 schemaType: "string",
13 code(cxt: KeywordCxt): void {
14 const {gen, schema: $ref, it} = cxt
15 const {baseId, schemaEnv: env, validateName, opts, self} = it
16 const {root} = env
17 if (($ref === "#" || $ref === "#/") && baseId === root.baseId) return callRootRef()
18 const schOrEnv = resolveRef.call(self, root, baseId, $ref)
19 if (schOrEnv === undefined) throw new MissingRefError(baseId, $ref)
20 if (schOrEnv instanceof SchemaEnv) return callValidate(schOrEnv)
21 return inlineRefSchema(schOrEnv)
22
23 function callRootRef(): void {
24 if (env === root) return callRef(cxt, validateName, env, env.$async)
25 const rootName = gen.scopeValue("root", {ref: root})
26 return callRef(cxt, _`${rootName}.validate`, root, root.$async)
27 }
28
29 function callValidate(sch: SchemaEnv): void {
30 const v = getValidate(cxt, sch)
31 callRef(cxt, v, sch, sch.$async)
32 }
33
34 function inlineRefSchema(sch: AnySchema): void {
35 const schName = gen.scopeValue(
36 "schema",
37 opts.code.source === true ? {ref: sch, code: stringify(sch)} : {ref: sch}
38 )
39 const valid = gen.name("valid")
40 const schCxt = cxt.subschema(
41 {
42 schema: sch,
43 dataTypes: [],
44 schemaPath: nil,
45 topSchemaRef: schName,
46 errSchemaPath: $ref,
47 },
48 valid
49 )
50 cxt.mergeEvaluated(schCxt)
51 cxt.ok(valid)
52 }
53 },
54}
55
56export function getValidate(cxt: KeywordCxt, sch: SchemaEnv): Code {
57 const {gen} = cxt
58 return sch.validate
59 ? gen.scopeValue("validate", {ref: sch.validate})
60 : _`${gen.scopeValue("wrapper", {ref: sch})}.validate`
61}
62
63export function callRef(cxt: KeywordCxt, v: Code, sch?: SchemaEnv, $async?: boolean): void {
64 const {gen, it} = cxt
65 const {allErrors, schemaEnv: env, opts} = it
66 const passCxt = opts.passContext ? N.this : nil
67 if ($async) callAsyncRef()
68 else callSyncRef()
69
70 function callAsyncRef(): void {
71 if (!env.$async) throw new Error("async schema referenced by sync schema")
72 const valid = gen.let("valid")
73 gen.try(
74 () => {
75 gen.code(_`await ${callValidateCode(cxt, v, passCxt)}`)
76 addEvaluatedFrom(v) // TODO will not work with async, it has to be returned with the result
77 if (!allErrors) gen.assign(valid, true)
78 },
79 (e) => {
80 gen.if(_`!(${e} instanceof ${it.ValidationError as Name})`, () => gen.throw(e))
81 addErrorsFrom(e)
82 if (!allErrors) gen.assign(valid, false)
83 }
84 )
85 cxt.ok(valid)
86 }
87
88 function callSyncRef(): void {
89 cxt.result(
90 callValidateCode(cxt, v, passCxt),
91 () => addEvaluatedFrom(v),
92 () => addErrorsFrom(v)
93 )
94 }
95
96 function addErrorsFrom(source: Code): void {
97 const errs = _`${source}.errors`
98 gen.assign(N.vErrors, _`${N.vErrors} === null ? ${errs} : ${N.vErrors}.concat(${errs})`) // TODO tagged
99 gen.assign(N.errors, _`${N.vErrors}.length`)
100 }
101
102 function addEvaluatedFrom(source: Code): void {
103 if (!it.opts.unevaluated) return
104 const schEvaluated = sch?.validate?.evaluated
105 // TODO refactor
106 if (it.props !== true) {
107 if (schEvaluated && !schEvaluated.dynamicProps) {
108 if (schEvaluated.props !== undefined) {
109 it.props = mergeEvaluated.props(gen, schEvaluated.props, it.props)
110 }
111 } else {
112 const props = gen.var("props", _`${source}.evaluated.props`)
113 it.props = mergeEvaluated.props(gen, props, it.props, Name)
114 }
115 }
116 if (it.items !== true) {
117 if (schEvaluated && !schEvaluated.dynamicItems) {
118 if (schEvaluated.items !== undefined) {
119 it.items = mergeEvaluated.items(gen, schEvaluated.items, it.items)
120 }
121 } else {
122 const items = gen.var("items", _`${source}.evaluated.items`)
123 it.items = mergeEvaluated.items(gen, items, it.items, Name)
124 }
125 }
126 }
127}
128
129export default def
Note: See TracBrowser for help on using the repository browser.