uniqueItems.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const dataType_1 = require("../../compile/validate/dataType");
  4. const codegen_1 = require("../../compile/codegen");
  5. const equal = require("fast-deep-equal");
  6. const error = {
  7. message: ({ params: { i, j } }) => codegen_1.str `should NOT have duplicate items (items ## ${j} and ${i} are identical)`,
  8. params: ({ params: { i, j } }) => codegen_1._ `{i: ${i}, j: ${j}}`,
  9. };
  10. const def = {
  11. keyword: "uniqueItems",
  12. type: "array",
  13. schemaType: "boolean",
  14. $data: true,
  15. error,
  16. code(cxt) {
  17. const { gen, data, $data, schema, parentSchema, schemaCode, it } = cxt;
  18. if (!$data && !schema)
  19. return;
  20. const valid = gen.let("valid");
  21. const itemTypes = parentSchema.items ? dataType_1.getSchemaTypes(parentSchema.items) : [];
  22. cxt.block$data(valid, validateUniqueItems, codegen_1._ `${schemaCode} === false`);
  23. cxt.ok(valid);
  24. function validateUniqueItems() {
  25. const i = gen.let("i", codegen_1._ `${data}.length`);
  26. const j = gen.let("j");
  27. cxt.setParams({ i, j });
  28. gen.assign(valid, true);
  29. gen.if(codegen_1._ `${i} > 1`, () => (canOptimize() ? loopN : loopN2)(i, j));
  30. }
  31. function canOptimize() {
  32. return itemTypes.length > 0 && !itemTypes.some((t) => t === "object" || t === "array");
  33. }
  34. function loopN(i, j) {
  35. const item = gen.name("item");
  36. const wrongType = dataType_1.checkDataTypes(itemTypes, item, it.opts.strict, dataType_1.DataType.Wrong);
  37. const indices = gen.const("indices", codegen_1._ `{}`);
  38. gen.for(codegen_1._ `;${i}--;`, () => {
  39. gen.let(item, codegen_1._ `${data}[${i}]`);
  40. gen.if(wrongType, codegen_1._ `continue`);
  41. if (itemTypes.length > 1)
  42. gen.if(codegen_1._ `typeof ${item} == "string"`, codegen_1._ `${item} += "_"`);
  43. gen
  44. .if(codegen_1._ `typeof ${indices}[${item}] == "number"`, () => {
  45. gen.assign(j, codegen_1._ `${indices}[${item}]`);
  46. cxt.error();
  47. gen.assign(valid, false).break();
  48. })
  49. .code(codegen_1._ `${indices}[${item}] = ${i}`);
  50. });
  51. }
  52. function loopN2(i, j) {
  53. const eql = cxt.gen.scopeValue("func", {
  54. ref: equal,
  55. code: codegen_1._ `require("ajv/dist/compile/equal")`,
  56. });
  57. const outer = gen.name("outer");
  58. gen.label(outer).for(codegen_1._ `;${i}--;`, () => gen.for(codegen_1._ `${j} = ${i}; ${j}--;`, () => gen.if(codegen_1._ `${eql}(${data}[${i}], ${data}[${j}])`, () => {
  59. cxt.error();
  60. gen.assign(valid, false).break(outer);
  61. })));
  62. }
  63. },
  64. };
  65. exports.default = def;
  66. //# sourceMappingURL=uniqueItems.js.map