"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.callRef = exports.getValidate = void 0; const ref_error_1 = require("../../compile/ref_error"); const code_1 = require("../code"); const codegen_1 = require("../../compile/codegen"); const names_1 = require("../../compile/names"); const compile_1 = require("../../compile"); const util_1 = require("../../compile/util"); const def = { keyword: "$ref", schemaType: "string", code(cxt) { const { gen, schema: $ref, it } = cxt; const { baseId, schemaEnv: env, validateName, opts, self } = it; const { root } = env; if (($ref === "#" || $ref === "#/") && baseId === root.baseId) return callRootRef(); const schOrEnv = compile_1.resolveRef.call(self, root, baseId, $ref); if (schOrEnv === undefined) throw new ref_error_1.default(baseId, $ref); if (schOrEnv instanceof compile_1.SchemaEnv) return callValidate(schOrEnv); return inlineRefSchema(schOrEnv); function callRootRef() { if (env === root) return callRef(cxt, validateName, env, env.$async); const rootName = gen.scopeValue("root", { ref: root }); return callRef(cxt, codegen_1._ `${rootName}.validate`, root, root.$async); } function callValidate(sch) { const v = getValidate(cxt, sch); callRef(cxt, v, sch, sch.$async); } function inlineRefSchema(sch) { const schName = gen.scopeValue("schema", opts.code.source === true ? { ref: sch, code: codegen_1.stringify(sch) } : { ref: sch }); const valid = gen.name("valid"); const schCxt = cxt.subschema({ schema: sch, dataTypes: [], schemaPath: codegen_1.nil, topSchemaRef: schName, errSchemaPath: $ref, }, valid); cxt.mergeEvaluated(schCxt); cxt.ok(valid); } }, }; function getValidate(cxt, sch) { const { gen } = cxt; return sch.validate ? gen.scopeValue("validate", { ref: sch.validate }) : codegen_1._ `${gen.scopeValue("wrapper", { ref: sch })}.validate`; } exports.getValidate = getValidate; function callRef(cxt, v, sch, $async) { const { gen, it } = cxt; const { allErrors, schemaEnv: env, opts } = it; const passCxt = opts.passContext ? names_1.default.this : codegen_1.nil; if ($async) callAsyncRef(); else callSyncRef(); function callAsyncRef() { if (!env.$async) throw new Error("async schema referenced by sync schema"); const valid = gen.let("valid"); gen.try(() => { gen.code(codegen_1._ `await ${code_1.callValidateCode(cxt, v, passCxt)}`); addEvaluatedFrom(v); // TODO will not work with async, it has to be returned with the result if (!allErrors) gen.assign(valid, true); }, (e) => { gen.if(codegen_1._ `!(${e} instanceof ${it.ValidationError})`, () => gen.throw(e)); addErrorsFrom(e); if (!allErrors) gen.assign(valid, false); }); cxt.ok(valid); } function callSyncRef() { cxt.result(code_1.callValidateCode(cxt, v, passCxt), () => addEvaluatedFrom(v), () => addErrorsFrom(v)); } function addErrorsFrom(source) { const errs = codegen_1._ `${source}.errors`; gen.assign(names_1.default.vErrors, codegen_1._ `${names_1.default.vErrors} === null ? ${errs} : ${names_1.default.vErrors}.concat(${errs})`); // TODO tagged gen.assign(names_1.default.errors, codegen_1._ `${names_1.default.vErrors}.length`); } function addEvaluatedFrom(source) { var _a; if (!it.opts.unevaluated) return; const schEvaluated = (_a = sch === null || sch === void 0 ? void 0 : sch.validate) === null || _a === void 0 ? void 0 : _a.evaluated; // TODO refactor if (it.props !== true) { if (schEvaluated && !schEvaluated.dynamicProps) { if (schEvaluated.props !== undefined) { it.props = util_1.mergeEvaluated.props(gen, schEvaluated.props, it.props); } } else { const props = gen.var("props", codegen_1._ `${source}.evaluated.props`); it.props = util_1.mergeEvaluated.props(gen, props, it.props, codegen_1.Name); } } if (it.items !== true) { if (schEvaluated && !schEvaluated.dynamicItems) { if (schEvaluated.items !== undefined) { it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items); } } else { const items = gen.var("items", codegen_1._ `${source}.evaluated.items`); it.items = util_1.mergeEvaluated.items(gen, items, it.items, codegen_1.Name); } } } } exports.callRef = callRef; exports.default = def; //# sourceMappingURL=ref.js.map