@yuneta/gobj-js 7.25.4 → 7.25.6

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.
@@ -3031,7 +3031,7 @@ function gobj_stats(gobj, stats, kw, src) {
3031
3031
  *
3032
3032
  * Licence: MIT (http://www.opensource.org/licenses/mit-license)
3033
3033
  * Copyright (c) 2014,2024 Niyamaka.
3034
- * Copyright (c) 2025, ArtGins.
3034
+ * Copyright (c) 2025-2026, ArtGins.
3035
3035
  *********************************************************************************/
3036
3036
  var kw_flag_t = Object.freeze({
3037
3037
  KW_REQUIRED: 1,
@@ -3559,30 +3559,46 @@ function kw_has_key(kw, key) {
3559
3559
  return false;
3560
3560
  }
3561
3561
  /************************************************************
3562
- *
3562
+ * The value at `path` (keys joined by a backtick), as the C
3563
+ * kw_find_path() finds it: undefined when it is not there.
3564
+ * A kw that is not a dict or a list is LOGGED ("kw must be list
3565
+ * or dict") and answers undefined, as C answers NULL; so does a
3566
+ * segment in the middle of the path whose value is a scalar. A
3567
+ * middle segment that is absent or null answers undefined, logged
3568
+ * only when `verbose`. Before gobj-js 7.25.6 a bad kw answered 0,
3569
+ * which the typed readers took for a value found (kw_get_int() and
3570
+ * kw_get_real() answered 0 instead of the default, kw_get_str() and
3571
+ * kw_get_bool() logged a second line), the log named no path and
3572
+ * called gobj_short_name() on a null gobj ("gobj bad type"), and a
3573
+ * null middle segment threw a TypeError.
3563
3574
  ************************************************************/
3564
3575
  function kw_find_path(gobj, kw, path, verbose) {
3565
3576
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
3577
+ const prefix = gobj ? `${gobj_short_name(gobj)}: ` : "";
3566
3578
  if (!(is_object(kw) || is_array(kw))) {
3567
- log_error(`${gobj_short_name(gobj)}: kw must be list or dict`);
3568
- return 0;
3579
+ log_error(`${prefix}kw must be list or dict: '${String(path)}'`);
3580
+ return;
3569
3581
  }
3570
3582
  if (!is_string(path)) {
3571
- log_error(`${gobj_short_name(gobj)}: path must be a string: ${String(path)}`);
3572
- return 0;
3583
+ log_error(`${prefix}path must be a string: ${String(path)}`);
3584
+ return;
3573
3585
  }
3574
3586
  let ss = path.split("`");
3575
- if (ss.length <= 1) return kw[path];
3576
3587
  let len = ss.length;
3577
- for (let i = 0; i < len; i++) {
3578
- let key = ss[i];
3579
- kw = kw[key];
3580
- if (kw === void 0) {
3581
- if (verbose) log_error(`${gobj_short_name(gobj)}: path not found: ${String(path)}`);
3588
+ for (let i = 0; i < len - 1; i++) {
3589
+ kw = kw[ss[i]];
3590
+ if (kw === void 0 || kw === null) {
3591
+ if (verbose) log_error(`${prefix}path not found: '${path}'`);
3592
+ return;
3593
+ }
3594
+ if (!(is_object(kw) || is_array(kw))) {
3595
+ log_error(`${prefix}kw must be list or dict: '${path}'`);
3582
3596
  return;
3583
3597
  }
3584
3598
  }
3585
- return kw;
3599
+ let value = kw[ss[len - 1]];
3600
+ if (value === void 0 && verbose) log_error(`${prefix}path not found: '${path}'`);
3601
+ return value;
3586
3602
  }
3587
3603
  /************************************************************
3588
3604
  *
@@ -3607,10 +3623,13 @@ function kw_delete(gobj, kw, path) {
3607
3623
  * anything else gives the default back, LOGGED ("path MUST BE a
3608
3624
  * json boolean", required or not) -- unless KW_WILD_NUMBER asks
3609
3625
  * to read a number (0 is false), a string ("true"/"false" in any
3610
- * case, else its integer) or null (false); a list or a dict is
3611
- * then false, logged too. Before gobj-js 7.25.2 the value went
3612
- * through Boolean(), so "false" was TRUE; before 7.25.3 a value
3613
- * of the wrong type gave the default back in silence.
3626
+ * case, else its decimal integer as atoi() reads it: "0x1F" is 0,
3627
+ * so false) or null (false); a list or a dict is then false,
3628
+ * logged too. Before gobj-js 7.25.2 the value went through
3629
+ * Boolean(), so "false" was TRUE; before 7.25.3 a value of the
3630
+ * wrong type gave the default back in silence; before 7.25.5 the
3631
+ * string went through parseInt() with no base, which reads hex:
3632
+ * "0x1F" was TRUE.
3614
3633
  ************************************************************/
3615
3634
  function kw_get_bool(gobj, kw, path, default_value, flag) {
3616
3635
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
@@ -3620,7 +3639,7 @@ function kw_get_bool(gobj, kw, path, default_value, flag) {
3620
3639
  const extract = flag && flag & kw_flag_t.KW_EXTRACT;
3621
3640
  const wild = flag && flag & kw_flag_t.KW_WILD_NUMBER;
3622
3641
  if (b === void 0) {
3623
- if (create) {
3642
+ if (create && kw) {
3624
3643
  let v = Boolean(default_value);
3625
3644
  kw_set_dict_value(gobj, kw, path, v);
3626
3645
  return v;
@@ -3636,7 +3655,7 @@ function kw_get_bool(gobj, kw, path, default_value, flag) {
3636
3655
  else if (wild && is_string(b)) {
3637
3656
  if (b.toLowerCase() === "true") value = true;
3638
3657
  else if (b.toLowerCase() === "false") value = false;
3639
- else value = (parseInt(b) || 0) !== 0;
3658
+ else value = (parseInt(b, 10) || 0) !== 0;
3640
3659
  } else if (wild && b === null) value = false;
3641
3660
  else if (wild) {
3642
3661
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
@@ -3688,7 +3707,7 @@ function kw_get_int(gobj, kw, path, default_value, flag) {
3688
3707
  const extract = flag && flag & kw_flag_t.KW_EXTRACT;
3689
3708
  const wild = flag && flag & kw_flag_t.KW_WILD_NUMBER;
3690
3709
  if (v === void 0) {
3691
- if (create) {
3710
+ if (create && kw) {
3692
3711
  let v = parseInt(default_value);
3693
3712
  kw_set_dict_value(gobj, kw, path, v);
3694
3713
  return v;
@@ -3735,7 +3754,7 @@ function kw_get_real(gobj, kw, path, default_value, flag) {
3735
3754
  const extract = flag && flag & kw_flag_t.KW_EXTRACT;
3736
3755
  const wild = flag && flag & kw_flag_t.KW_WILD_NUMBER;
3737
3756
  if (v === void 0) {
3738
- if (create) {
3757
+ if (create && kw) {
3739
3758
  let v = Number(default_value);
3740
3759
  kw_set_dict_value(gobj, kw, path, v);
3741
3760
  return v;
@@ -3765,6 +3784,21 @@ function kw_get_real(gobj, kw, path, default_value, flag) {
3765
3784
  return value;
3766
3785
  }
3767
3786
  /************************************************************
3787
+ * TRUE when the last key of `path` is a key of its dict, whatever
3788
+ * its value: kw_find_path() answers undefined both for a key that
3789
+ * is not there and for one whose value is undefined.
3790
+ ************************************************************/
3791
+ function kw_path_holds_key(kw, path) {
3792
+ let ss = is_string(path) ? path.split("`") : [];
3793
+ let parent = kw;
3794
+ for (let i = 0; i < ss.length - 1; i++) {
3795
+ if (!(is_object(parent) || is_array(parent))) return false;
3796
+ parent = parent[ss[i]];
3797
+ }
3798
+ if (!(is_object(parent) || is_array(parent)) || ss.length === 0) return false;
3799
+ return Object.prototype.hasOwnProperty.call(parent, ss[ss.length - 1]);
3800
+ }
3801
+ /************************************************************
3768
3802
  * The default comes back AS GIVEN, as in the C kw_get_str()
3769
3803
  * (`const char *default_value`, where 0 is NULL). Turned into
3770
3804
  * a string, a default of 0 or null was "0" or "null", which is
@@ -3776,6 +3810,12 @@ function kw_get_real(gobj, kw, path, default_value, flag) {
3776
3810
  * C refuses to extract a string at all ("Cannot extract a
3777
3811
  * string": its answer would point into the freed json); a JS
3778
3812
  * string outlives the kw, so here it is taken out.
3813
+ * A value that is there and is not a string gives the default
3814
+ * back, LOGGED ("path MUST BE a json str", required or not), as
3815
+ * C does; a null value is the key saying "no string" and is not
3816
+ * logged, and KW_REQUIRED logs only a path that is not there at
3817
+ * all. Before gobj-js 7.25.5 a value of another type was logged
3818
+ * only with KW_REQUIRED, and then a null one too.
3779
3819
  ************************************************************/
3780
3820
  function kw_get_str(gobj, kw, path, default_value, flag) {
3781
3821
  if (gobj && !is_gobj(gobj)) log_error(`GObj bad instanceof`);
@@ -3784,19 +3824,19 @@ function kw_get_str(gobj, kw, path, default_value, flag) {
3784
3824
  const create = flag && flag & kw_flag_t.KW_CREATE;
3785
3825
  const extract = flag && flag & kw_flag_t.KW_EXTRACT;
3786
3826
  if (v === void 0) {
3787
- if (create) {
3827
+ if (create && kw) {
3788
3828
  kw_set_dict_value(gobj, kw, path, is_string(default_value) ? default_value : null);
3789
3829
  return default_value;
3790
- } else if (required) {
3830
+ } else if (required && !kw_path_holds_key(kw, path)) {
3791
3831
  log_error(`path not found: '${path}'`);
3792
3832
  trace_json(kw);
3793
3833
  }
3794
3834
  return default_value;
3795
3835
  }
3796
3836
  if (!is_string(v)) {
3797
- if (required) {
3798
- log_error(`${gobj_short_name(gobj)}: path value MUST BE a string: ${path}`);
3799
- trace_msg(kw);
3837
+ if (v !== null) {
3838
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json str: '${path}'`);
3839
+ trace_json(kw);
3800
3840
  }
3801
3841
  return default_value;
3802
3842
  }
@@ -3852,8 +3892,8 @@ function kw_get_dict(gobj, kw, path, default_value, flag) {
3852
3892
  }
3853
3893
  if (!is_object(v)) {
3854
3894
  if (required) {
3855
- log_error(`${gobj_short_name(gobj)}: path value MUST BE a dict: ${path}`);
3856
- trace_msg(kw);
3895
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json dict: '${path}'`);
3896
+ trace_json(kw);
3857
3897
  }
3858
3898
  return default_value;
3859
3899
  }
@@ -3910,8 +3950,8 @@ function kw_get_list(gobj, kw, path, default_value, flag) {
3910
3950
  }
3911
3951
  if (!is_array(v)) {
3912
3952
  if (required) {
3913
- log_error(`${gobj_short_name(gobj)}: path value MUST BE an array: ${path}`);
3914
- trace_msg(kw);
3953
+ log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json list: '${path}'`);
3954
+ trace_json(kw);
3915
3955
  }
3916
3956
  return default_value;
3917
3957
  }