z-schema 12.3.1 → 12.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/umd/ZSchema.js CHANGED
@@ -71,7 +71,7 @@
71
71
  function isInteger(value) {
72
72
  return typeof value === "number" && Number.isFinite(value) && value % 1 === 0;
73
73
  }
74
- const NON_SCHEMA_KEYWORDS_SET = new Set([
74
+ const NON_SCHEMA_KEYWORDS_SET = /* @__PURE__ */ new Set([
75
75
  "enum",
76
76
  "const",
77
77
  "default",
@@ -246,7 +246,8 @@
246
246
  }
247
247
  if (isObject(json1) && isObject(json2)) {
248
248
  const keys1 = sortedKeys(json1);
249
- if (!areEqual(keys1, sortedKeys(json2), options, _depth + 1)) return false;
249
+ const keys2 = sortedKeys(json2);
250
+ if (!areEqual(keys1, keys2, options, _depth + 1)) return false;
250
251
  len = keys1.length;
251
252
  for (i = 0; i < len; i++) if (!areEqual(json1[keys1[i]], json2[keys1[i]], options, _depth + 1)) return false;
252
253
  return true;
@@ -2444,6 +2445,94 @@
2444
2445
  })))(), 1);
2445
2446
  const IDN_SEPARATOR_REGEX = /[\u3002\uFF0E\uFF61]/g;
2446
2447
  const IDN_SEPARATOR_TEST_REGEX = /[\u3002\uFF0E\uFF61]/;
2448
+ const XN_LABEL_REGEX = /^xn--/i;
2449
+ const DISALLOWED_CATEGORY_REGEX = /[\p{P}\p{S}\p{Z}\p{C}]/u;
2450
+ const DISALLOWED_CATEGORY_WHITELIST = /* @__PURE__ */ new Set([
2451
+ "-",
2452
+ "·",
2453
+ "͵",
2454
+ "׳",
2455
+ "״",
2456
+ "・",
2457
+ "۽",
2458
+ "۾",
2459
+ "་",
2460
+ "‌",
2461
+ "‍"
2462
+ ]);
2463
+ const isDisallowedCodePoint = (char) => DISALLOWED_CATEGORY_REGEX.test(char) && !DISALLOWED_CATEGORY_WHITELIST.has(char);
2464
+ const TRANSPARENT_MARK_REGEX = /\p{Mn}/u;
2465
+ const ARABIC_SCRIPT_REGEX = /\p{Script=Arabic}/u;
2466
+ const ARABIC_INDIC_DIGITS_REGEX = /[\u0660-\u0669\u06F0-\u06F9]/;
2467
+ const isArabicJoiningLetter = (char) => char !== void 0 && ARABIC_SCRIPT_REGEX.test(char) && !ARABIC_INDIC_DIGITS_REGEX.test(char);
2468
+ const hasZwnjJoiningContext = (label, idx) => {
2469
+ let before = idx - 1;
2470
+ while (before >= 0 && TRANSPARENT_MARK_REGEX.test(label[before])) before--;
2471
+ let after = idx + 1;
2472
+ while (after < label.length && TRANSPARENT_MARK_REGEX.test(label[after])) after++;
2473
+ return isArabicJoiningLetter(label[before]) && isArabicJoiningLetter(label[after]);
2474
+ };
2475
+ const BIDI_NSM_REGEX = /[\p{Mn}\p{Me}]/u;
2476
+ const BIDI_ARABIC_INDIC_DIGIT_REGEX = /[\u0660-\u0669]/;
2477
+ const BIDI_EXTENDED_ARABIC_INDIC_DIGIT_REGEX = /[\u06F0-\u06F9]/;
2478
+ const BIDI_HEBREW_SCRIPT_REGEX = /\p{Script=Hebrew}/u;
2479
+ const BIDI_AL_SCRIPT_REGEX = /[\p{Script=Arabic}\p{Script=Syriac}\p{Script=Thaana}]/u;
2480
+ const BIDI_ASCII_DIGIT_REGEX = /[0-9]/;
2481
+ const BIDI_LETTER_REGEX = /\p{L}/u;
2482
+ const classifyBidi = (char) => {
2483
+ if (BIDI_NSM_REGEX.test(char)) return "NSM";
2484
+ if (BIDI_ARABIC_INDIC_DIGIT_REGEX.test(char)) return "AN";
2485
+ if (BIDI_EXTENDED_ARABIC_INDIC_DIGIT_REGEX.test(char)) return "EN";
2486
+ if (BIDI_HEBREW_SCRIPT_REGEX.test(char)) return "R";
2487
+ if (BIDI_AL_SCRIPT_REGEX.test(char)) return "AL";
2488
+ if (BIDI_ASCII_DIGIT_REGEX.test(char)) return "EN";
2489
+ if (BIDI_LETTER_REGEX.test(char)) return "L";
2490
+ return "ON";
2491
+ };
2492
+ const isLabelBidiTriggering = (label) => {
2493
+ for (const char of label) {
2494
+ const bidiClass = classifyBidi(char);
2495
+ if (bidiClass === "R" || bidiClass === "AL" || bidiClass === "AN") return true;
2496
+ }
2497
+ return false;
2498
+ };
2499
+ const isLabelBidiRuleValid = (label) => {
2500
+ const classes = [];
2501
+ for (const char of label) classes.push(classifyBidi(char));
2502
+ if (classes.length === 0) return false;
2503
+ const first = classes[0];
2504
+ if (first !== "L" && first !== "R" && first !== "AL") return false;
2505
+ let lastIdx = classes.length - 1;
2506
+ while (lastIdx > 0 && classes[lastIdx] === "NSM") lastIdx--;
2507
+ const last = classes[lastIdx];
2508
+ if (first === "R" || first === "AL") {
2509
+ let hasEN = false;
2510
+ let hasAN = false;
2511
+ for (let i = 0; i < classes.length; i++) {
2512
+ const c = classes[i];
2513
+ if (c !== "R" && c !== "AL" && c !== "AN" && c !== "EN" && c !== "NSM" && c !== "ON") return false;
2514
+ if (c === "EN") hasEN = true;
2515
+ else if (c === "AN") hasAN = true;
2516
+ }
2517
+ if (hasEN && hasAN) return false;
2518
+ return last === "R" || last === "AL" || last === "EN" || last === "AN";
2519
+ }
2520
+ for (let i = 0; i < classes.length; i++) {
2521
+ const c = classes[i];
2522
+ if (c !== "L" && c !== "EN" && c !== "NSM" && c !== "ON") return false;
2523
+ }
2524
+ return last === "L" || last === "EN";
2525
+ };
2526
+ const isDomainBidiValid = (unicodeLabels) => {
2527
+ let isBidiDomain = false;
2528
+ for (let i = 0; i < unicodeLabels.length; i++) if (isLabelBidiTriggering(unicodeLabels[i])) {
2529
+ isBidiDomain = true;
2530
+ break;
2531
+ }
2532
+ if (!isBidiDomain) return true;
2533
+ for (let i = 0; i < unicodeLabels.length; i++) if (!isLabelBidiRuleValid(unicodeLabels[i])) return false;
2534
+ return true;
2535
+ };
2447
2536
  const splitHostnameLabels = (hostname) => {
2448
2537
  if (hostname.length === 0 || hostname.length > 255) return null;
2449
2538
  if (hostname.startsWith(".") || hostname.endsWith(".")) return null;
@@ -2459,7 +2548,7 @@
2459
2548
  const isHebrew = (char) => /\p{Script=Hebrew}/u.test(char);
2460
2549
  const hasCjkKanaOrHan = (input) => /[\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}]/u.test(input);
2461
2550
  const toUnicodeLabel = (label) => {
2462
- if (!/^xn--/i.test(label)) return label;
2551
+ if (!XN_LABEL_REGEX.test(label)) return label;
2463
2552
  try {
2464
2553
  return import_punycode.default.toUnicode(label.toLowerCase());
2465
2554
  } catch {
@@ -2468,7 +2557,7 @@
2468
2557
  };
2469
2558
  const isValidIdnUnicodeLabel = (label) => {
2470
2559
  if (label.startsWith("-") || label.endsWith("-")) return false;
2471
- if (label.length >= 4 && label[2] === "-" && label[3] === "-" && !/^xn--/i.test(label)) return false;
2560
+ if (label.length >= 4 && label[2] === "-" && label[3] === "-" && !XN_LABEL_REGEX.test(label)) return false;
2472
2561
  if (/^\p{M}/u.test(label)) return false;
2473
2562
  if (/[\u302E\u302F\u0640\u07FA]/u.test(label)) return false;
2474
2563
  for (let idx = 0; idx < label.length; idx++) {
@@ -2477,7 +2566,9 @@
2477
2566
  if (char === "͵" && (idx === label.length - 1 || !isGreek(label[idx + 1]))) return false;
2478
2567
  if ((char === "׳" || char === "״") && (idx === 0 || !isHebrew(label[idx - 1]))) return false;
2479
2568
  if (char === "‍" && (idx === 0 || label[idx - 1] !== "्")) return false;
2569
+ if (char === "‌" && (idx === 0 || label[idx - 1] !== "्" && !hasZwnjJoiningContext(label, idx))) return false;
2480
2570
  }
2571
+ for (const char of label) if (isDisallowedCodePoint(char)) return false;
2481
2572
  if (label.includes("・") && !hasCjkKanaOrHan(label.replaceAll("・", ""))) return false;
2482
2573
  const hasArabicIndic = /[\u0660-\u0669]/.test(label);
2483
2574
  const hasExtendedArabicIndic = /[\u06F0-\u06F9]/.test(label);
@@ -2492,7 +2583,7 @@
2492
2583
  for (let i = 0; i < labels.length; i++) {
2493
2584
  const label = labels[i];
2494
2585
  if (!isAsciiHostnameLabel(label)) return false;
2495
- if (/^xn--/i.test(label)) {
2586
+ if (XN_LABEL_REGEX.test(label)) {
2496
2587
  const unicodeLabel = toUnicodeLabel(label);
2497
2588
  if (unicodeLabel === null || !isValidIdnUnicodeLabel(unicodeLabel)) return false;
2498
2589
  }
@@ -2500,14 +2591,28 @@
2500
2591
  return true;
2501
2592
  };
2502
2593
  const isValidIdnHostname = (hostname) => {
2503
- const labels = splitHostnameLabels(hostname.replace(IDN_SEPARATOR_REGEX, "."));
2594
+ const normalizedHostname = hostname.replace(IDN_SEPARATOR_REGEX, ".");
2595
+ const labels = splitHostnameLabels(normalizedHostname);
2504
2596
  if (labels === null) return false;
2597
+ const unicodeLabels = [];
2598
+ let totalLength = labels.length - 1;
2505
2599
  for (let i = 0; i < labels.length; i++) {
2506
2600
  const label = labels[i];
2507
2601
  const unicodeLabel = toUnicodeLabel(label);
2508
2602
  if (unicodeLabel === null || !isValidIdnUnicodeLabel(unicodeLabel)) return false;
2603
+ let aLabel;
2604
+ try {
2605
+ aLabel = import_punycode.default.toASCII(unicodeLabel);
2606
+ } catch {
2607
+ return false;
2608
+ }
2609
+ if (XN_LABEL_REGEX.test(label) && aLabel.toLowerCase() !== label.toLowerCase()) return false;
2610
+ if (aLabel.length > 63) return false;
2611
+ totalLength += aLabel.length;
2612
+ unicodeLabels.push(unicodeLabel);
2509
2613
  }
2510
- return true;
2614
+ if (totalLength > 253) return false;
2615
+ return isDomainBidiValid(unicodeLabels);
2511
2616
  };
2512
2617
  //#endregion
2513
2618
  //#region src/utils/time.ts
@@ -2520,7 +2625,7 @@
2520
2625
  minute: normalizedUtcTotalMinutes % 60
2521
2626
  };
2522
2627
  };
2523
- const RFC3339_TIME_REGEX = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$/i;
2628
+ const RFC3339_TIME_REGEX = /^(?<hour>[0-9]{2}):(?<minute>[0-9]{2}):(?<second>[0-9]{2})(?<fraction>\.[0-9]+)?(?<offset>z|(?<offsetValue>[+-][0-9]{2}:[0-9]{2}))$/i;
2524
2629
  const parseRfc3339Time = (time) => {
2525
2630
  const matches = RFC3339_TIME_REGEX.exec(time);
2526
2631
  if (matches === null) return null;
@@ -2531,7 +2636,7 @@
2531
2636
  let utcHour = hour;
2532
2637
  let utcMinute = minute;
2533
2638
  if (matches[5].toLowerCase() !== "z") {
2534
- const offsetMatches = /^([+-])([0-9]{2}):([0-9]{2})$/.exec(matches[5]);
2639
+ const offsetMatches = /^(?<sign>[+-])(?<hour>[0-9]{2}):(?<minute>[0-9]{2})$/.exec(matches[5]);
2535
2640
  if (offsetMatches === null) return null;
2536
2641
  const offsetSign = offsetMatches[1];
2537
2642
  const offsetHour = Number.parseInt(offsetMatches[2], 10);
@@ -2554,7 +2659,7 @@
2554
2659
  //#region src/format-validators.ts
2555
2660
  const dateValidator = (date) => {
2556
2661
  if (typeof date !== "string") return true;
2557
- const matches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(date);
2662
+ const matches = /^(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})$/.exec(date);
2558
2663
  if (matches === null) return false;
2559
2664
  return isValidRfc3339Date(Number.parseInt(matches[1], 10), Number.parseInt(matches[2], 10), Number.parseInt(matches[3], 10));
2560
2665
  };
@@ -2565,7 +2670,7 @@
2565
2670
  if (tIdx === -1) return false;
2566
2671
  const datePart = dateTime.slice(0, tIdx);
2567
2672
  const timePart = dateTime.slice(tIdx + 1);
2568
- const dateMatches = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.exec(datePart);
2673
+ const dateMatches = /^(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})$/.exec(datePart);
2569
2674
  if (dateMatches === null) return false;
2570
2675
  if (!isValidRfc3339Date(Number.parseInt(dateMatches[1], 10), Number.parseInt(dateMatches[2], 10), Number.parseInt(dateMatches[3], 10))) return false;
2571
2676
  return parseRfc3339Time(timePart) !== null;
@@ -2576,7 +2681,7 @@
2576
2681
  require_tld: true,
2577
2682
  allow_ip_domain: true
2578
2683
  })) return true;
2579
- const ipv6Literal = /^(.+)@\[IPv6:([^\]]+)\]$/i.exec(email);
2684
+ const ipv6Literal = /^(?<localPart>.+)@\[IPv6:(?<address>[^\]]+)\]$/i.exec(email);
2580
2685
  if (!ipv6Literal) return false;
2581
2686
  const localPart = ipv6Literal[1];
2582
2687
  const addressPart = ipv6Literal[2];
@@ -2596,7 +2701,7 @@
2596
2701
  if (ipv6.includes("%")) return false;
2597
2702
  return import_isIP.default.default(ipv6, 6);
2598
2703
  };
2599
- const INVALID_REGEX_ESCAPES = new Set(["a"]);
2704
+ const INVALID_REGEX_ESCAPES = /* @__PURE__ */ new Set(["a"]);
2600
2705
  const regexValidator = (input) => {
2601
2706
  if (typeof input !== "string") return true;
2602
2707
  for (let idx = 0; idx < input.length; idx++) {
@@ -2649,7 +2754,7 @@
2649
2754
  if (typeof uri !== "string") return true;
2650
2755
  if (/[^\u0000-\u007F]/.test(uri)) return false;
2651
2756
  if (!hasValidPercentEncoding(uri)) return false;
2652
- const match = /^([a-zA-Z][a-zA-Z0-9+.-]*):\/\/([^/?#]*)/.exec(uri);
2757
+ const match = /^(?<scheme>[a-zA-Z][a-zA-Z0-9+.-]*):\/\/(?<authority>[^/?#]*)/.exec(uri);
2653
2758
  if (match) {
2654
2759
  const authority = match[2];
2655
2760
  const atIndex = authority.indexOf("@");
@@ -2673,11 +2778,11 @@
2673
2778
  const uriReferenceValidator = (uri) => {
2674
2779
  if (typeof uri !== "string") return true;
2675
2780
  if (/[^\u0000-\u007F]/.test(uri)) return false;
2676
- return /^([a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/.test(uri);
2781
+ return /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/.test(uri);
2677
2782
  };
2678
2783
  const uriTemplateValidator = (uri) => {
2679
2784
  if (typeof uri !== "string") return true;
2680
- if (!/^([a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^`| ]*$/.test(uri)) return false;
2785
+ if (!/^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^`| ]*$/.test(uri)) return false;
2681
2786
  let inExpression = false;
2682
2787
  for (let idx = 0; idx < uri.length; idx++) {
2683
2788
  const ch = uri[idx];
@@ -2709,7 +2814,7 @@
2709
2814
  };
2710
2815
  const relativeJsonPointerValidator = (pointer) => {
2711
2816
  if (typeof pointer !== "string") return true;
2712
- const match = /^(0|[1-9]\d*)(.*)$/.exec(pointer);
2817
+ const match = /^(?<int>0|[1-9]\d*)(?<suffix>.*)$/.exec(pointer);
2713
2818
  if (!match) return false;
2714
2819
  const suffix = match[2];
2715
2820
  if (suffix === "" || suffix === "#") return true;
@@ -2723,9 +2828,19 @@
2723
2828
  if (typeof time !== "string") return true;
2724
2829
  return parseRfc3339Time(time) !== null;
2725
2830
  };
2831
+ const LONE_SURROGATE_REGEX = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]/;
2832
+ const QUOTED_LOCAL_PART_REGEX = /^"(?:[^"\\]|\\.)*"$/u;
2833
+ const UNQUOTED_LOCAL_PART_REGEX = /^[^\s@]+$/u;
2834
+ const isValidIdnEmailLocalPart = (localPart) => {
2835
+ if (localPart.length === 0 || LONE_SURROGATE_REGEX.test(localPart)) return false;
2836
+ if (localPart.length >= 2 && localPart.startsWith("\"") && localPart.endsWith("\"")) return QUOTED_LOCAL_PART_REGEX.test(localPart);
2837
+ return UNQUOTED_LOCAL_PART_REGEX.test(localPart);
2838
+ };
2726
2839
  const idnEmailValidator = (email) => {
2727
2840
  if (typeof email !== "string") return true;
2728
- return /^[^\s@]+@[^\s@]+$/.test(email);
2841
+ const atIdx = email.lastIndexOf("@");
2842
+ if (atIdx <= 0 || atIdx === email.length - 1) return false;
2843
+ return isValidIdnEmailLocalPart(email.slice(0, atIdx)) && isValidIdnHostname(email.slice(atIdx + 1));
2729
2844
  };
2730
2845
  const idnHostnameValidator = (hostname) => {
2731
2846
  if (typeof hostname !== "string") return true;
@@ -2743,7 +2858,7 @@
2743
2858
  };
2744
2859
  const iriReferenceValidator = (iriReference) => {
2745
2860
  if (typeof iriReference !== "string") return true;
2746
- return /^([a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/u.test(iriReference);
2861
+ return /^(?:[a-zA-Z][a-zA-Z0-9+.-]*:)?[^"\\<>^{}^`| ]*$/u.test(iriReference);
2747
2862
  };
2748
2863
  const inbuiltValidators = {
2749
2864
  date: dateValidator,
@@ -3778,7 +3893,7 @@
3778
3893
  const VOCAB_VALIDATION_2020_12 = "https://json-schema.org/draft/2020-12/vocab/validation";
3779
3894
  const VOCAB_FORMAT_2019_09 = "https://json-schema.org/draft/2019-09/vocab/format";
3780
3895
  const VOCAB_FORMAT_ASSERTION_2020_12 = "https://json-schema.org/draft/2020-12/vocab/format-assertion";
3781
- const VALIDATION_VOCAB_KEYWORDS = new Set([
3896
+ const VALIDATION_VOCAB_KEYWORDS = /* @__PURE__ */ new Set([
3782
3897
  "type",
3783
3898
  "multipleOf",
3784
3899
  "maximum",
@@ -3809,7 +3924,9 @@
3809
3924
  const metaSchema = currentSchemaMeta || rootSchemaMeta;
3810
3925
  if (!metaSchema || typeof metaSchema !== "object" || !isObject(metaSchema.$vocabulary)) return true;
3811
3926
  const vocabulary = metaSchema.$vocabulary;
3812
- if (Object.hasOwn(vocabulary, VOCAB_VALIDATION_2019_09) || Object.hasOwn(vocabulary, VOCAB_VALIDATION_2020_12)) return vocabulary[VOCAB_VALIDATION_2019_09] || vocabulary[VOCAB_VALIDATION_2020_12];
3927
+ const has2019 = Object.hasOwn(vocabulary, VOCAB_VALIDATION_2019_09);
3928
+ const has2020 = Object.hasOwn(vocabulary, VOCAB_VALIDATION_2020_12);
3929
+ if (has2019 || has2020) return vocabulary[VOCAB_VALIDATION_2019_09] || vocabulary[VOCAB_VALIDATION_2020_12];
3813
3930
  return false;
3814
3931
  };
3815
3932
  /**
@@ -4245,11 +4362,11 @@
4245
4362
  if (result instanceof Promise) {
4246
4363
  const promiseResult = result;
4247
4364
  report.addAsyncTaskWithPath(async (callback) => {
4365
+ let resolved = false;
4248
4366
  try {
4249
- callback(await promiseResult);
4250
- } catch {
4251
- callback(false);
4252
- }
4367
+ resolved = await promiseResult;
4368
+ } catch {}
4369
+ callback(resolved);
4253
4370
  }, [], (resolvedResult) => {
4254
4371
  if (resolvedResult !== true) report.addError("INVALID_FORMAT", [schema.format, JSON.stringify(json)], void 0, schema, "format");
4255
4372
  });
@@ -4742,7 +4859,8 @@
4742
4859
  }
4743
4860
  }
4744
4861
  if (deferredUnevaluatedKeys.length > 0 && !(report.errors.length > 0 && ctx.options.breakOnFirstError)) for (let i = 0; i < deferredUnevaluatedKeys.length; i++) {
4745
- const validator = JsonValidators[deferredUnevaluatedKeys[i]];
4862
+ const key = deferredUnevaluatedKeys[i];
4863
+ const validator = JsonValidators[key];
4746
4864
  if (validator) {
4747
4865
  validator(ctx, report, schema, json);
4748
4866
  if (report.errors.length && ctx.options.breakOnFirstError) break;
@@ -4769,7 +4887,7 @@
4769
4887
  }
4770
4888
  //#endregion
4771
4889
  //#region src/schema-compiler.ts
4772
- const UNSAFE_TARGETS = new Set([
4890
+ const UNSAFE_TARGETS = /* @__PURE__ */ new Set([
4773
4891
  Object.prototype,
4774
4892
  Function.prototype,
4775
4893
  Array.prototype
@@ -4851,7 +4969,10 @@
4851
4969
  }
4852
4970
  }
4853
4971
  id.absoluteParent = absoluteParent;
4854
- if (id.absoluteParent) id.absoluteUri = resolveSchemaScopeId(id.absoluteParent.absoluteUri || id.absoluteParent.id, schemaNode, id.id);
4972
+ if (id.absoluteParent) {
4973
+ const parentUri = id.absoluteParent.absoluteUri || id.absoluteParent.id;
4974
+ id.absoluteUri = resolveSchemaScopeId(parentUri, schemaNode, id.id);
4975
+ }
4855
4976
  }
4856
4977
  ids.push(id);
4857
4978
  scope.push(id);
@@ -4935,7 +5056,8 @@
4935
5056
  for (const item of ids) if (item.absoluteUri) {
4936
5057
  this.validator.scache.cacheSchemaByUri(item.absoluteUri, item.obj);
4937
5058
  if (item.type === "relative" && item.absoluteParent && isSimpleIdentifier(item.id)) {
4938
- const altAbsoluteUri = resolveReference(item.absoluteParent.absoluteUri || item.absoluteParent.id, item.id);
5059
+ const parentUri = item.absoluteParent.absoluteUri || item.absoluteParent.id;
5060
+ const altAbsoluteUri = resolveReference(parentUri, item.id);
4939
5061
  this.validator.scache.cacheSchemaByUri(altAbsoluteUri, item.obj);
4940
5062
  }
4941
5063
  } else if (item.type === "root") this.validator.scache.cacheSchemaByUri(item.id, item.obj);