@yuneta/gobj-js 7.25.8 → 7.25.9

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.
@@ -27,8 +27,8 @@
27
27
  return sprintf.apply(null, [fmt].concat(argv || []));
28
28
  }
29
29
  function sprintf_format(parse_tree, argv) {
30
- var cursor = 1, tree_length = parse_tree.length, arg, output = "", i, k, ph, pad, pad_character, pad_length, is_positive, sign;
31
- for (i = 0; i < tree_length; i++) if (typeof parse_tree[i] === "string") output += parse_tree[i];
30
+ var cursor = 1, tree_length = parse_tree.length, arg, output = "", i = 0, k, ph, pad, pad_character, pad_length, is_positive, sign;
31
+ for (; i < tree_length; i++) if (typeof parse_tree[i] === "string") output += parse_tree[i];
32
32
  else if (typeof parse_tree[i] === "object") {
33
33
  ph = parse_tree[i];
34
34
  if (ph.keys) {
@@ -1337,7 +1337,7 @@
1337
1337
  let new_kw = kw;
1338
1338
  if (json2sdata(hs, new_kw, -1, gobj.gclass.gclass_flag & gclass_flag_t.gcflag_ignore_unknown_attrs ? 0 : print_attr_not_found, gobj) < 0) {
1339
1339
  log_error(`${gobj_short_name(gobj)} json2data() FAILED`);
1340
- trace_json(new_kw);
1340
+ trace_json_masked(new_kw);
1341
1341
  }
1342
1342
  }
1343
1343
  /************************************************************
@@ -2552,7 +2552,7 @@
2552
2552
  else trace_machine(sprintf("🔃 mach(%s%s), st: %s, ev: %s, from(%s%s)", !dst.running ? "!!" : "", gobj_short_name(dst), state.state_name, event ? event : "", src && !src.running ? "!!" : "", gobj_short_name(src)));
2553
2553
  if (kw) {
2554
2554
  if (__trace_gobj_ev_kw__(dst)) {
2555
- if (json_object_size(kw)) trace_json(kw);
2555
+ if (json_object_size(kw)) trace_json_masked(kw);
2556
2556
  }
2557
2557
  }
2558
2558
  }
@@ -2572,7 +2572,7 @@
2572
2572
  }
2573
2573
  if (kw) {
2574
2574
  if (__trace_gobj_ev_kw__(dst)) {
2575
- if (json_object_size(kw)) trace_json(kw);
2575
+ if (json_object_size(kw)) trace_json_masked(kw);
2576
2576
  }
2577
2577
  }
2578
2578
  }
@@ -2586,9 +2586,25 @@
2586
2586
  return ret;
2587
2587
  }
2588
2588
  var subs_flag_t = Object.freeze({
2589
- __hard_subscription__: 1,
2590
- __own_event__: 2
2589
+ __rename_event_name__: 1,
2590
+ __hard_subscription__: 2,
2591
+ __own_event__: 4
2591
2592
  });
2593
+ /***************************************************************************
2594
+ * The event type of `event_name` in any registered gclass, null if none.
2595
+ * The C kernel's gobj_find_event_type(): any case, gclasses only.
2596
+ ***************************************************************************/
2597
+ function _find_event_type_in_gclasses(event_name) {
2598
+ let lower = String(event_name).toLowerCase();
2599
+ for (let gclass_name in _gclass_register) {
2600
+ let dl = _gclass_register[gclass_name].dl_events;
2601
+ for (let i = 0; i < dl.length; i++) {
2602
+ let event_type = dl[i];
2603
+ if (event_type.event_name && event_type.event_name.toLowerCase() === lower) return event_type;
2604
+ }
2605
+ }
2606
+ return null;
2607
+ }
2592
2608
  var subscription_desc = [
2593
2609
  SDATA(data_type_t.DTP_POINTER, "publisher", 0, null, "publisher gobj"),
2594
2610
  SDATA(data_type_t.DTP_POINTER, "subscriber", 0, null, "subscriber gobj"),
@@ -2621,6 +2637,21 @@
2621
2637
  if (json_size(__config__) > 0) {
2622
2638
  let kw_clone = json_deep_copy(__config__);
2623
2639
  json_object_set_new(subs, "__config__", kw_clone);
2640
+ let renamed_event = kw_get_str(publisher, kw_clone, "__rename_event_name__", "");
2641
+ if (!empty_string(renamed_event)) {
2642
+ let event_type = _find_event_type_in_gclasses(renamed_event);
2643
+ if (event_type) {
2644
+ json_object_set_new(subs, "renamed_event", event_type.event_name);
2645
+ delete kw_clone.__rename_event_name__;
2646
+ subs_flag |= subs_flag_t.__rename_event_name__;
2647
+ let kw_global = kw_get_dict(publisher, subs, "__global__", null);
2648
+ if (!is_object(kw_global)) {
2649
+ kw_global = {};
2650
+ json_object_set_new(subs, "__global__", kw_global);
2651
+ }
2652
+ kw_global.__original_event_name__ = event;
2653
+ } else log_error(`${gobj_short_name(publisher)}: EVENT NOT FOUND (__rename_event_name__: ${renamed_event})`);
2654
+ }
2624
2655
  if (kw_has_key(kw_clone, "__hard_subscription__")) {
2625
2656
  let hard_subscription = kw_get_bool(publisher, kw_clone, "__hard_subscription__", false);
2626
2657
  json_object_del(kw_clone, "__hard_subscription__");
@@ -2640,9 +2671,52 @@
2640
2671
  return subs;
2641
2672
  }
2642
2673
  /***************************************************************************
2674
+ * The kw to find the subscriptions a (un)subscription `kw` names: `kw` as
2675
+ * _create_subscription() stores it, as the C kernel's
2676
+ * _subscription_match_kw(). The three `__config__` keys the framework
2677
+ * reads (__hard_subscription__, __own_event__, __rename_event_name__)
2678
+ * become the subs_flag and are taken out of the stored `__config__`, and
2679
+ * a renamed event adds `__original_event_name__` to the stored
2680
+ * `__global__`: with `kw` as it came, the same kw matched no subscription,
2681
+ * a repeat of it was made twice (the subscriber got each event twice) and
2682
+ * its withdrawal found nothing. A known renamed event is returned in
2683
+ * `renamed_event`, which _match_subscription() compares: a plain and a
2684
+ * renamed subscription, or two renames of one event, are two. A rename
2685
+ * that no gclass declares stays in the stored `__config__`, and in this
2686
+ * one. Up to gobj-js 7.25.8 the kw was compared as it came, and
2687
+ * `__rename_event_name__` always stayed in the stored `__config__`: a
2688
+ * plain kw with the rest of that __config__ found no repeat (two
2689
+ * subscriptions where C has one).
2690
+ * Return {kw, renamed_event}; renamed_event is "" when kw does not rename.
2691
+ ***************************************************************************/
2692
+ function _subscription_match_kw(kw, event) {
2693
+ let __config__ = kw ? kw.__config__ : null;
2694
+ if (!is_object(__config__) || !kw_has_key(__config__, "__hard_subscription__") && !kw_has_key(__config__, "__own_event__") && !kw_has_key(__config__, "__rename_event_name__")) return {
2695
+ kw,
2696
+ renamed_event: ""
2697
+ };
2698
+ let kw_match = Object.assign({}, kw);
2699
+ let config_match = Object.assign({}, __config__);
2700
+ kw_match.__config__ = config_match;
2701
+ let renamed_event = "";
2702
+ let rename = config_match.__rename_event_name__;
2703
+ let event_type = typeof rename === "string" && !empty_string(rename) ? _find_event_type_in_gclasses(rename) : null;
2704
+ if (event_type) {
2705
+ renamed_event = event_type.event_name;
2706
+ delete config_match.__rename_event_name__;
2707
+ if (event && json_size(kw_match.__global__) > 0) kw_match.__global__ = Object.assign({}, kw_match.__global__, { __original_event_name__: event });
2708
+ }
2709
+ delete config_match.__hard_subscription__;
2710
+ delete config_match.__own_event__;
2711
+ return {
2712
+ kw: kw_match,
2713
+ renamed_event
2714
+ };
2715
+ }
2716
+ /***************************************************************************
2643
2717
  * Match subscription
2644
2718
  ***************************************************************************/
2645
- function _match_subscription(subs, publisher, event, kw, subscriber) {
2719
+ function _match_subscription(subs, publisher, event, renamed_event, kw, subscriber) {
2646
2720
  let __config__ = kw_get_dict(publisher, kw, "__config__", null);
2647
2721
  let __global__ = kw_get_dict(publisher, kw, "__global__", null);
2648
2722
  let __local__ = kw_get_dict(publisher, kw, "__local__", null);
@@ -2657,6 +2731,9 @@
2657
2731
  if (event) {
2658
2732
  if (event !== kw_get_str(null, subs, "event", "")) match = false;
2659
2733
  }
2734
+ if (renamed_event) {
2735
+ if (renamed_event !== kw_get_str(null, subs, "renamed_event", "")) match = false;
2736
+ }
2660
2737
  if (json_size(__config__) > 0) {
2661
2738
  let kw_config = kw_get_dict(null, subs, "__config__", null);
2662
2739
  if (json_size(kw_config) > 0) {
@@ -2691,26 +2768,29 @@
2691
2768
  * kw (__config__, __global__, __local__, __filter__),
2692
2769
  * subscriber
2693
2770
  ***************************************************************************/
2694
- function _find_subscriptions(dl_subs, publisher, event, kw, subscriber) {
2771
+ function _find_subscriptions(dl_subs, publisher, event, renamed_event, kw, subscriber) {
2695
2772
  let iter = [];
2696
2773
  for (let i = 0; i < dl_subs.length; i++) {
2697
2774
  let subs = dl_subs[i];
2698
- if (_match_subscription(subs, publisher, event, kw, subscriber)) json_array_append(iter, subs);
2775
+ if (_match_subscription(subs, publisher, event, renamed_event, kw, subscriber)) json_array_append(iter, subs);
2699
2776
  }
2700
2777
  return iter;
2701
2778
  }
2702
2779
  /***************************************************************************
2703
- * Find idx of subscription in dl_subs, -1 not found
2780
+ * Find idx of the subscription `subs` itself in dl_subs, -1 not found.
2781
+ * Up to gobj-js 7.25.8 it was the first entry whose fields matched `subs`:
2782
+ * a subscription already removed took a live one that matched it (a plain
2783
+ * one matches every other of its event and subscriber).
2704
2784
  ***************************************************************************/
2705
- function _get_subs_idx(dl_subs, publisher, event, kw, subscriber) {
2706
- for (let i = 0; i < dl_subs.length; i++) {
2707
- let subs = dl_subs[i];
2708
- if (_match_subscription(subs, publisher, event, kw, subscriber)) return i;
2709
- }
2710
- return -1;
2785
+ function _get_subs_idx(dl_subs, subs) {
2786
+ return dl_subs.indexOf(subs);
2711
2787
  }
2712
2788
  /***************************************************************************
2713
- * Delete subscription in publisher and subscriber
2789
+ * Delete subscription in publisher and subscriber.
2790
+ * Return 0 removed, -1 a hard one kept (only `force` removes it), 1 it
2791
+ * was not there any more: already removed, as a stale reference is, or by
2792
+ * the mt_subscription_deleted() of an earlier entry of the same list. The
2793
+ * caller says which is an error. As in C.
2714
2794
  ***************************************************************************/
2715
2795
  function _delete_subscription(gobj, subs, force, not_inform) {
2716
2796
  let publisher = kw_get_pointer(gobj, subs, "publisher", null, kw_flag_t.KW_REQUIRED);
@@ -2719,7 +2799,12 @@
2719
2799
  if (kw_get_int(gobj, subs, "subs_flag", null, kw_flag_t.KW_REQUIRED) & subs_flag_t.__hard_subscription__ ? 1 : 0) {
2720
2800
  if (!force) return -1;
2721
2801
  }
2722
- if (__trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher)) {
2802
+ let tracea = __trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher);
2803
+ if (_get_subs_idx(publisher.dl_subscriptions, subs) < 0) {
2804
+ if (tracea) trace_machine(sprintf("💜💜👎 unsubscribing event '%s': publisher %s, subscriber'%s', ALREADY REMOVED", event ? event : "", gobj_short_name(publisher), gobj_short_name(subscriber)));
2805
+ return 1;
2806
+ }
2807
+ if (tracea) {
2723
2808
  trace_machine(sprintf("💜💜👎 unsubscribing event '%s': publisher %s, subscriber'%s'", event ? event : "", gobj_short_name(publisher), gobj_short_name(subscriber)));
2724
2809
  trace_json(subs);
2725
2810
  }
@@ -2728,13 +2813,13 @@
2728
2813
  if (publisher.gclass.gmt.mt_subscription_deleted) publisher.gclass.gmt.mt_subscription_deleted(publisher, subs);
2729
2814
  }
2730
2815
  }
2731
- let idx = _get_subs_idx(publisher.dl_subscriptions, publisher, event, subs, subscriber);
2816
+ let idx = _get_subs_idx(publisher.dl_subscriptions, subs);
2732
2817
  if (idx >= 0) json_array_remove(publisher.dl_subscriptions, idx);
2733
2818
  else {
2734
2819
  log_error(`${gobj_short_name(gobj)}: subscription in publisher not found`);
2735
2820
  trace_json(subs);
2736
2821
  }
2737
- idx = _get_subs_idx(subscriber.dl_subscribings, publisher, event, subs, subscriber);
2822
+ idx = _get_subs_idx(subscriber.dl_subscribings, subs);
2738
2823
  if (idx >= 0) json_array_remove(subscriber.dl_subscribings, idx);
2739
2824
  else {
2740
2825
  log_error(`${gobj_short_name(gobj)}: subscription in subscriber not found`);
@@ -2777,7 +2862,17 @@
2777
2862
  }
2778
2863
  }
2779
2864
  } else event = "";
2780
- let dl_subs = _find_subscriptions(publisher.dl_subscriptions, publisher, event, kw, subscriber);
2865
+ let match = _subscription_match_kw(kw, event);
2866
+ let dl_subs = _find_subscriptions(publisher.dl_subscriptions, publisher, event, match.renamed_event, match.kw, subscriber);
2867
+ let subs_hard = null;
2868
+ for (let i = 0; i < dl_subs.length; i++) if (kw_get_int(publisher, dl_subs[i], "subs_flag", 0, kw_flag_t.KW_REQUIRED) & subs_flag_t.__hard_subscription__) {
2869
+ subs_hard = dl_subs[i];
2870
+ break;
2871
+ }
2872
+ if (subs_hard) {
2873
+ log_warning(`${gobj_short_name(publisher)}: Hard subscription REPEATED, the one there is kept and returned (event: ${event}, subscriber: ${gobj_short_name(subscriber)})`);
2874
+ return subs_hard;
2875
+ }
2781
2876
  if (json_array_size(dl_subs) > 0) {
2782
2877
  log_error(`${gobj_short_name(publisher)}: ${json_array_size(dl_subs)} subscription(s) REPEATED, will be deleted and override`);
2783
2878
  trace_json(dl_subs, "subscription REPEATED");
@@ -2792,7 +2887,7 @@
2792
2887
  json_array_append(subscriber.dl_subscribings, subs);
2793
2888
  if (__trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher)) {
2794
2889
  trace_machine(sprintf("💜💜👍 subscribing event '%s', publisher '%s', subscriber %s", event ? event : "", gobj_short_name(publisher), gobj_short_name(subscriber)));
2795
- if (kw && (__trace_gobj_ev_kw__(subscriber) || __trace_gobj_ev_kw__(publisher))) trace_json(kw);
2890
+ if (kw && (__trace_gobj_ev_kw__(subscriber) || __trace_gobj_ev_kw__(publisher))) trace_json_masked(kw);
2796
2891
  }
2797
2892
  if (publisher.gclass.gmt.mt_subscription_added) {
2798
2893
  let result = publisher.gclass.gmt.mt_subscription_added(publisher, subs);
@@ -2834,16 +2929,22 @@
2834
2929
  }
2835
2930
  }
2836
2931
  } else event = "";
2837
- let dl_subs = _find_subscriptions(publisher.dl_subscriptions, publisher, event, kw, subscriber);
2932
+ let match = _subscription_match_kw(kw, event);
2933
+ let dl_subs = _find_subscriptions(publisher.dl_subscriptions, publisher, event, match.renamed_event, match.kw, subscriber);
2838
2934
  let deleted = 0;
2935
+ let kept_hard = 0;
2936
+ let already_removed = 0;
2839
2937
  for (let i = 0; i < dl_subs.length; i++) {
2840
2938
  let subs = dl_subs[i];
2841
- _delete_subscription(publisher, subs, false, false);
2842
- deleted++;
2939
+ let ret = _delete_subscription(publisher, subs, false, false);
2940
+ if (ret === 0) deleted++;
2941
+ else if (ret < 0) kept_hard++;
2942
+ else already_removed++;
2843
2943
  }
2844
- if (!deleted) {
2944
+ if (kept_hard) log_warning(`${gobj_short_name(publisher)}: Hard subscription not removed, only gobj_unsubscribe_list() with force removes it (event: ${event}, hard: ${kept_hard})`);
2945
+ else if (!deleted && !already_removed) {
2845
2946
  log_warning(`${gobj_short_name(publisher)}: No subscription found`);
2846
- trace_json(kw, "No subscription found");
2947
+ trace_json_masked(kw, "No subscription found");
2847
2948
  }
2848
2949
  return 0;
2849
2950
  }
@@ -2852,10 +2953,12 @@
2852
2953
  ***************************************************************************/
2853
2954
  function gobj_unsubscribe_list(gobj, dl_subs, force) {
2854
2955
  let dl = [...dl_subs];
2956
+ let already_removed = 0;
2855
2957
  for (let i = 0; i < dl.length; i++) {
2856
2958
  let subs = dl[i];
2857
- _delete_subscription(gobj, subs, force, false);
2959
+ if (_delete_subscription(gobj, subs, force, false) > 0) already_removed++;
2858
2960
  }
2961
+ if (already_removed) log_warning(`${gobj_short_name(gobj)}: Subscription(s) already removed, nothing to remove (count: ${already_removed})`);
2859
2962
  return 0;
2860
2963
  }
2861
2964
  /***************************************************************************
@@ -2867,7 +2970,7 @@
2867
2970
  ***************************************************************************/
2868
2971
  function gobj_find_subscriptions(publisher, event, kw, subscriber) {
2869
2972
  if (kw == null) kw = {};
2870
- return _find_subscriptions(publisher.dl_subscriptions, publisher, event, kw, subscriber);
2973
+ return _find_subscriptions(publisher.dl_subscriptions, publisher, event, null, kw, subscriber);
2871
2974
  }
2872
2975
  /***************************************************************************
2873
2976
  *
@@ -2906,7 +3009,7 @@
2906
3009
  * subscriber
2907
3010
  ***************************************************************************/
2908
3011
  function gobj_find_subscribings(subscriber, event, kw, publisher) {
2909
- return _find_subscriptions(subscriber.dl_subscribings, publisher, event, kw, subscriber);
3012
+ return _find_subscriptions(subscriber.dl_subscribings, publisher, event, null, kw, subscriber);
2910
3013
  }
2911
3014
  /***************************************************************************
2912
3015
  * Return the sum of returns of gobj_send_event
@@ -2932,7 +3035,7 @@
2932
3035
  if (tracea) {
2933
3036
  if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔝 %s %s%s %s", event ? event : "", !publisher.running ? "!!" : "", gobj_short_name(publisher), publisher.current_state.state_name));
2934
3037
  else trace_machine(sprintf("🔝🔝 mach(%s%s^%s), st: %s, ev: %s%s%s", !publisher.running ? "!!" : "", gobj_gclass_name(publisher), gobj_name(publisher), publisher.current_state.state_name, "", event ? event : "", ""));
2935
- if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw)) trace_json(kw);
3038
+ if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw)) trace_json_masked(kw);
2936
3039
  }
2937
3040
  if (publisher.gclass.gmt.mt_publish_event) {
2938
3041
  let topublish = publisher.gclass.gmt.mt_publish_event(publisher, event, kw);
@@ -2957,6 +3060,8 @@
2957
3060
  let __global__ = kw_get_dict(publisher, subs, "__global__", null, 0);
2958
3061
  let __local__ = kw_get_dict(publisher, subs, "__local__", null, 0);
2959
3062
  let __filter__ = kw_get_dict_value(publisher, subs, "__filter__", null, 0);
3063
+ let event_name = subs.renamed_event;
3064
+ if (empty_string(event_name)) event_name = event;
2960
3065
  let topublish = 1;
2961
3066
  if (publisher.gclass.gmt.mt_publication_filter) topublish = publisher.gclass.gmt.mt_publication_filter(publisher, event, kw, subscriber);
2962
3067
  else if (json_size(__filter__) > 0) {
@@ -2980,11 +3085,11 @@
2980
3085
  if (__config__) {}
2981
3086
  if (json_size(__global__) > 0) json_object_update(kw2publish, json_deep_copy(__global__));
2982
3087
  if (tracea) {
2983
- if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔄 %s (%s) %s%s", event ? event : "", event ? event : "", !subscriber.running ? "!!" : "", gobj_short_name(subscriber)));
2984
- else trace_machine(sprintf("🔝🔄 mach(%s%s), st: %s, ev: %s, from(%s%s)", !subscriber.running ? "!!" : "", gobj_short_name(subscriber), gobj_current_state(subscriber), event ? event : "", publisher && !publisher.running ? "!!" : "", gobj_short_name(publisher)));
2985
- if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish)) trace_json(kw2publish);
3088
+ if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔄 %s (%s) %s%s", event ? event : "", event_name ? event_name : "", !subscriber.running ? "!!" : "", gobj_short_name(subscriber)));
3089
+ else trace_machine(sprintf("🔝🔄 mach(%s%s), st: %s, ev: %s (%s), from(%s%s)", !subscriber.running ? "!!" : "", gobj_short_name(subscriber), gobj_current_state(subscriber), event ? event : "", event_name ? event_name : "", publisher && !publisher.running ? "!!" : "", gobj_short_name(publisher)));
3090
+ if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish)) trace_json_masked(kw2publish);
2986
3091
  }
2987
- let ret_ = gobj_send_event(subscriber, event, kw2publish, publisher);
3092
+ let ret_ = gobj_send_event(subscriber, event_name, kw2publish, publisher);
2988
3093
  if (ret_ < 0 && subs_flag & subs_flag_t.__own_event__) {
2989
3094
  sent_count = -1;
2990
3095
  break;
@@ -3008,8 +3113,9 @@
3008
3113
  return -1;
3009
3114
  }
3010
3115
  if (is_commands_tracing(gobj) || is_machine_tracing(gobj, null) && !is_machine_not_tracing(src, null)) {
3011
- trace_machine(sprintf("🌀🌀 mach(%s%s), cmd: %s, src: %s", !gobj_is_running(gobj) ? "!!" : "", gobj_short_name(gobj), command, gobj_short_name(src)));
3012
- if (__trace_gobj_ev_kw__(gobj)) trace_json(kw);
3116
+ let command_shown = mask_secrets_inline(command);
3117
+ trace_machine(sprintf("🌀🌀 mach(%s%s), cmd: %s, src: %s", !gobj_is_running(gobj) ? "!!" : "", gobj_short_name(gobj), command_shown !== null ? command_shown : command, gobj_short_name(src)));
3118
+ if (__trace_gobj_ev_kw__(gobj)) trace_json_masked(kw);
3013
3119
  }
3014
3120
  if (gobj.gclass.gmt.mt_command_parser) return gobj.gclass.gmt.mt_command_parser(gobj, command, kw, src);
3015
3121
  if (gobj.gclass.command_table) {
@@ -3225,6 +3331,268 @@
3225
3331
  emit_log_callback("json", jn, current_timestamp());
3226
3332
  }
3227
3333
  /************************************************************
3334
+ * The names of the secrets (is_secret_name()). The same lists
3335
+ * as the C kernel's helpers.c: a name that holds one of these
3336
+ * (any case) is a secret.
3337
+ ************************************************************/
3338
+ var SECRET_NAME_PARTS = [
3339
+ "passw",
3340
+ "pwd",
3341
+ "passphrase",
3342
+ "secret",
3343
+ "token",
3344
+ "jwt",
3345
+ "bearer",
3346
+ "authorization",
3347
+ "cookie",
3348
+ "credential",
3349
+ "salt"
3350
+ ];
3351
+ var SECRET_NAME_JOINED = [
3352
+ "apikey",
3353
+ "sessionid",
3354
+ "sessionkey",
3355
+ "authdata"
3356
+ ];
3357
+ var NOT_SECRET_SEGMENTS = /* @__PURE__ */ new Set([
3358
+ "endpoint",
3359
+ "url",
3360
+ "uri",
3361
+ "domain",
3362
+ "path",
3363
+ "file",
3364
+ "public",
3365
+ "pub",
3366
+ "count",
3367
+ "counts",
3368
+ "type",
3369
+ "name",
3370
+ "len",
3371
+ "length",
3372
+ "size",
3373
+ "max",
3374
+ "min",
3375
+ "ttl",
3376
+ "timeout",
3377
+ "expiry",
3378
+ "expires",
3379
+ "mode"
3380
+ ]);
3381
+ /************************************************************
3382
+ * TRUE if `name` is the name of a secret: a password, a token,
3383
+ * a key... Any case. As the C kernel's is_secret_name().
3384
+ ************************************************************/
3385
+ function is_secret_name(name) {
3386
+ if (typeof name !== "string" || name.length < 3) return false;
3387
+ let lower = name.toLowerCase();
3388
+ let hit = false;
3389
+ for (const part of SECRET_NAME_PARTS) if (lower.indexOf(part) >= 0) {
3390
+ hit = true;
3391
+ break;
3392
+ }
3393
+ if (!hit) {
3394
+ let joined = lower.replace(/[_\-. \t]/g, "");
3395
+ for (const part of SECRET_NAME_JOINED) if (joined.indexOf(part) >= 0) {
3396
+ hit = true;
3397
+ break;
3398
+ }
3399
+ }
3400
+ if (!hit) hit = lower.indexOf("priv") >= 0 && lower.indexOf("key") >= 0;
3401
+ if (!hit) return false;
3402
+ for (const segment of lower.split(/[_\-. \t]/)) if (NOT_SECRET_SEGMENTS.has(segment)) return false;
3403
+ return true;
3404
+ }
3405
+ /************************************************************
3406
+ * Where an unquoted secret value that begins at `p` ends: at
3407
+ * the end, at the quote that closes an outer quoted value, or
3408
+ * before the next "word=" -- a plain word after a blank is still
3409
+ * part of it ("password=correct horse battery", "password=
3410
+ * hunter2"). As the C kernel's inline_secret_value_end().
3411
+ ************************************************************/
3412
+ function inline_secret_value_end(str, p, outer) {
3413
+ const blank = (c) => c === " " || c === " ";
3414
+ const closes_outer = (i) => outer && str[i] === outer && (i + 1 >= str.length || blank(str[i + 1]));
3415
+ let end = p;
3416
+ while (true) {
3417
+ while (end < str.length && !blank(str[end])) {
3418
+ if (closes_outer(end)) return end;
3419
+ end++;
3420
+ }
3421
+ if (end >= str.length) return end;
3422
+ let w = end;
3423
+ while (w < str.length && blank(str[w])) w++;
3424
+ if (w >= str.length || closes_outer(w)) return end;
3425
+ for (let e = w; e < str.length && !blank(str[e]) && !closes_outer(e); e++) if (str[e] === "=" && e > w) return end;
3426
+ end = w;
3427
+ }
3428
+ }
3429
+ /************************************************************
3430
+ * A text (a command line) with the value of every "name=value"
3431
+ * whose name is a secret's written as "********", quoted or not
3432
+ * (and the "value" of a write-attr whose attribute names a
3433
+ * secret). The rest as it is. Return null when there was nothing
3434
+ * to mask. As the C kernel's mask_secrets_inline().
3435
+ ************************************************************/
3436
+ var MASK_MAX_NAME = 128;
3437
+ var MASK_MAX_BYTES = 4194304;
3438
+ var MASK_TOO_LARGE = "<not shown: too large to mask>";
3439
+ function mask_secrets_inline(str) {
3440
+ if (typeof str !== "string" || str.indexOf("=") < 0) return null;
3441
+ if (str.length > MASK_MAX_BYTES) return MASK_TOO_LARGE;
3442
+ let value_is_secret = false;
3443
+ let re_attr = /(^|[ \t])attribute=["']?([^ \t"']*)/g;
3444
+ let m;
3445
+ while ((m = re_attr.exec(str)) !== null) if (is_secret_name(m[2].slice(-128))) value_is_secret = true;
3446
+ let parts = [];
3447
+ let copied = 0;
3448
+ let changed = false;
3449
+ let outer = "";
3450
+ let word = 0;
3451
+ let p = 0;
3452
+ const is_blank_or_end = (i) => i >= str.length || str[i] === " " || str[i] === " ";
3453
+ while (p < str.length) {
3454
+ let c = str[p];
3455
+ if (c === " " || c === " ") {
3456
+ p++;
3457
+ word = p;
3458
+ continue;
3459
+ }
3460
+ if (c === "\"" || c === "'") {
3461
+ if (!outer && (p === 0 || str[p - 1] === " " || str[p - 1] === " " || str[p - 1] === "=")) outer = c;
3462
+ else if (c === outer && is_blank_or_end(p + 1)) outer = "";
3463
+ }
3464
+ if (c !== "=") {
3465
+ p++;
3466
+ continue;
3467
+ }
3468
+ let name = str.substring(Math.max(word, p - MASK_MAX_NAME), p);
3469
+ word = p + 1;
3470
+ if (!(is_secret_name(name) || value_is_secret && name.toLowerCase() === "value")) {
3471
+ p++;
3472
+ continue;
3473
+ }
3474
+ p++;
3475
+ let quote = str[p] === "\"" || str[p] === "'" ? str[p] : "";
3476
+ let end;
3477
+ if (quote) {
3478
+ end = p + 1;
3479
+ while (end < str.length && str[end] !== quote) end++;
3480
+ if (str[end] === quote) end++;
3481
+ } else end = inline_secret_value_end(str, p, outer);
3482
+ if (end > p) {
3483
+ parts.push(str.substring(copied, p));
3484
+ parts.push("********");
3485
+ copied = end;
3486
+ changed = true;
3487
+ }
3488
+ p = end;
3489
+ word = p;
3490
+ }
3491
+ if (!changed) return null;
3492
+ parts.push(str.substring(copied));
3493
+ return parts.join("");
3494
+ }
3495
+ /************************************************************
3496
+ * A json as a log or a trace may show it: at any depth, the
3497
+ * value of a key with a secret's name is "********", whatever
3498
+ * its type (not an absent one, a null or an empty string); so is
3499
+ * the "value" of a dict whose "attribute" names a secret; and a
3500
+ * string is masked as mask_secrets_inline(). Return a masked
3501
+ * copy, or `jn` itself when there was nothing to mask. As the C
3502
+ * kernel's json_mask_secrets().
3503
+ *
3504
+ * Only JSON is walked: plain objects (their prototype is
3505
+ * Object.prototype or null) and arrays. Anything else -- a gobj,
3506
+ * a DOM node, a class instance, a typed array, a function -- is
3507
+ * passed as it is, never walked, as trace_json() always showed it
3508
+ * (a kw may carry a gobj: its parent and children make a cycle).
3509
+ * A plain object met twice is masked once, the same everywhere; a
3510
+ * cycle back to one is "<cycle>"; below MASK_MAX_DEPTH levels
3511
+ * (64, as in C) nothing is shown.
3512
+ * It never throws: a failure is the placeholder below.
3513
+ ************************************************************/
3514
+ var MASK_MAX_DEPTH = 64;
3515
+ var MASK_FAILED = "<not shown: the masking failed>";
3516
+ function is_plain_object(value) {
3517
+ if (value === null || typeof value !== "object") return false;
3518
+ let proto = Object.getPrototypeOf(value);
3519
+ return proto === Object.prototype || proto === null;
3520
+ }
3521
+ var MASK_IN_PROGRESS = Symbol("mask-in-progress");
3522
+ function _json_mask_secrets(jn, memo, depth, budget) {
3523
+ if (typeof jn === "string") {
3524
+ if (jn.length > budget.left) {
3525
+ budget.left = 0;
3526
+ return MASK_TOO_LARGE;
3527
+ }
3528
+ budget.left -= jn.length;
3529
+ let masked = mask_secrets_inline(jn);
3530
+ return masked !== null ? masked : jn;
3531
+ }
3532
+ let is_array = Array.isArray(jn);
3533
+ if (!is_array && !is_plain_object(jn)) return jn;
3534
+ if (budget.left <= 0) return MASK_TOO_LARGE;
3535
+ if (memo.has(jn)) {
3536
+ let seen = memo.get(jn);
3537
+ return seen === MASK_IN_PROGRESS ? "<cycle>" : seen;
3538
+ }
3539
+ if (depth >= MASK_MAX_DEPTH) return "<deeper not shown>";
3540
+ budget.left -= 1;
3541
+ memo.set(jn, MASK_IN_PROGRESS);
3542
+ let changed = false;
3543
+ let truncated = false;
3544
+ let result;
3545
+ if (is_array) {
3546
+ result = [];
3547
+ for (let i = 0; i < jn.length; i++) {
3548
+ if (budget.left <= 0) {
3549
+ truncated = true;
3550
+ break;
3551
+ }
3552
+ budget.left -= 1;
3553
+ let shown = _json_mask_secrets(jn[i], memo, depth + 1, budget);
3554
+ if (shown !== jn[i]) changed = true;
3555
+ result.push(shown);
3556
+ }
3557
+ if (truncated) result.push(MASK_TOO_LARGE);
3558
+ } else {
3559
+ result = Object.create(Object.getPrototypeOf(jn));
3560
+ let value_is_secret = typeof jn.attribute === "string" && is_secret_name(jn.attribute.slice(-128));
3561
+ for (const key in jn) {
3562
+ if (!Object.prototype.hasOwnProperty.call(jn, key)) continue;
3563
+ if (budget.left <= 0) {
3564
+ truncated = true;
3565
+ break;
3566
+ }
3567
+ budget.left -= 1 + key.length;
3568
+ let value = jn[key];
3569
+ let shown;
3570
+ if ((is_secret_name(key.slice(-128)) || value_is_secret && key === "value") && value !== void 0 && value !== null && value !== "") shown = "********";
3571
+ else shown = _json_mask_secrets(value, memo, depth + 1, budget);
3572
+ if (shown !== value) changed = true;
3573
+ result[key] = shown;
3574
+ }
3575
+ if (truncated) result["<more>"] = MASK_TOO_LARGE;
3576
+ }
3577
+ if (!changed && !truncated) result = jn;
3578
+ memo.set(jn, result);
3579
+ return result;
3580
+ }
3581
+ function json_mask_secrets(jn) {
3582
+ try {
3583
+ return _json_mask_secrets(jn, /* @__PURE__ */ new WeakMap(), 0, { left: MASK_MAX_BYTES });
3584
+ } catch (e) {
3585
+ return MASK_FAILED;
3586
+ }
3587
+ }
3588
+ /************************************************************
3589
+ * trace_json() of a json that can hold a credential: what
3590
+ * json_mask_secrets() masks is shown masked
3591
+ ************************************************************/
3592
+ function trace_json_masked(jn, msg) {
3593
+ trace_json(json_mask_secrets(jn), msg);
3594
+ }
3595
+ /************************************************************
3228
3596
  * Duplicate an object (new references)
3229
3597
  * using the modern structuredClone (Deep copy of a single object)
3230
3598
  ************************************************************/
@@ -3526,8 +3894,8 @@
3526
3894
  ***************************************************************************/
3527
3895
  function is_metadata_key(key) {
3528
3896
  if (!is_string(key)) return false;
3529
- let i;
3530
- for (i = 0; i < key.length; i++) {
3897
+ let i = 0;
3898
+ for (; i < key.length; i++) {
3531
3899
  if (key[i] !== "_") break;
3532
3900
  if (i > 2) break;
3533
3901
  }
@@ -3538,8 +3906,8 @@
3538
3906
  ***************************************************************************/
3539
3907
  function is_private_key(key) {
3540
3908
  if (!is_string(key)) return false;
3541
- let i;
3542
- for (i = 0; i < key.length; i++) {
3909
+ let i = 0;
3910
+ for (; i < key.length; i++) {
3543
3911
  if (key[i] !== "_") break;
3544
3912
  if (i > 2) break;
3545
3913
  }
@@ -3650,7 +4018,7 @@
3650
4018
  return v;
3651
4019
  } else if (required) {
3652
4020
  log_error(`path not found: '${path}'`);
3653
- trace_json(kw);
4021
+ trace_json_masked(kw);
3654
4022
  }
3655
4023
  return Boolean(default_value);
3656
4024
  }
@@ -3664,11 +4032,11 @@
3664
4032
  } else if (wild && b === null) value = false;
3665
4033
  else if (wild) {
3666
4034
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
3667
- trace_json(kw);
4035
+ trace_json_masked(kw);
3668
4036
  return false;
3669
4037
  } else {
3670
4038
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json boolean: '${path}'`);
3671
- trace_json(kw);
4039
+ trace_json_masked(kw);
3672
4040
  return Boolean(default_value);
3673
4041
  }
3674
4042
  if (extract) kw_delete(gobj, kw, path);
@@ -3718,7 +4086,7 @@
3718
4086
  return v;
3719
4087
  } else if (required) {
3720
4088
  log_error(`path not found: '${path}'`);
3721
- trace_json(kw);
4089
+ trace_json_masked(kw);
3722
4090
  }
3723
4091
  return parseInt(default_value);
3724
4092
  }
@@ -3726,14 +4094,14 @@
3726
4094
  if (is_number(v)) value = Math.trunc(v);
3727
4095
  else if (!wild) {
3728
4096
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json integer: '${path}'`);
3729
- trace_json(kw);
4097
+ trace_json_masked(kw);
3730
4098
  return parseInt(default_value);
3731
4099
  } else if (is_boolean(v)) value = v ? 1 : 0;
3732
4100
  else if (is_string(v)) value = strtoll_base0(v);
3733
4101
  else if (v === null) value = 0;
3734
4102
  else {
3735
4103
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
3736
- trace_json(kw);
4104
+ trace_json_masked(kw);
3737
4105
  return 0;
3738
4106
  }
3739
4107
  if (extract) kw_delete(gobj, kw, path);
@@ -3765,7 +4133,7 @@
3765
4133
  return v;
3766
4134
  } else if (required) {
3767
4135
  log_error(`path not found: '${path}'`);
3768
- trace_json(kw);
4136
+ trace_json_masked(kw);
3769
4137
  }
3770
4138
  return Number(default_value);
3771
4139
  }
@@ -3773,7 +4141,7 @@
3773
4141
  if (is_number(v)) value = v;
3774
4142
  else if (!wild) {
3775
4143
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json real: '${path}'`);
3776
- trace_json(kw);
4144
+ trace_json_masked(kw);
3777
4145
  return Number(default_value);
3778
4146
  } else if (is_boolean(v)) value = v ? 1 : 0;
3779
4147
  else if (is_string(v)) {
@@ -3782,7 +4150,7 @@
3782
4150
  } else if (v === null) value = 0;
3783
4151
  else {
3784
4152
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
3785
- trace_json(kw);
4153
+ trace_json_masked(kw);
3786
4154
  return 0;
3787
4155
  }
3788
4156
  if (extract) kw_delete(gobj, kw, path);
@@ -3834,14 +4202,14 @@
3834
4202
  return default_value;
3835
4203
  } else if (required && !kw_path_holds_key(kw, path)) {
3836
4204
  log_error(`path not found: '${path}'`);
3837
- trace_json(kw);
4205
+ trace_json_masked(kw);
3838
4206
  }
3839
4207
  return default_value;
3840
4208
  }
3841
4209
  if (!is_string(v)) {
3842
4210
  if (v !== null) {
3843
4211
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json str: '${path}'`);
3844
- trace_json(kw);
4212
+ trace_json_masked(kw);
3845
4213
  }
3846
4214
  return default_value;
3847
4215
  }
@@ -3864,7 +4232,7 @@
3864
4232
  return v;
3865
4233
  } else if (required) {
3866
4234
  log_error(`path not found: '${path}'`);
3867
- trace_json(kw);
4235
+ trace_json_masked(kw);
3868
4236
  }
3869
4237
  return default_value;
3870
4238
  }
@@ -3891,14 +4259,14 @@
3891
4259
  }
3892
4260
  if (required) {
3893
4261
  log_error(`path not found: '${path}'`);
3894
- trace_json(kw);
4262
+ trace_json_masked(kw);
3895
4263
  }
3896
4264
  return default_value;
3897
4265
  }
3898
4266
  if (!is_object(v)) {
3899
4267
  if (required) {
3900
4268
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json dict: '${path}'`);
3901
- trace_json(kw);
4269
+ trace_json_masked(kw);
3902
4270
  }
3903
4271
  return default_value;
3904
4272
  }
@@ -3921,7 +4289,7 @@
3921
4289
  return v;
3922
4290
  } else if (required) {
3923
4291
  log_error(`path not found: '${path}'`);
3924
- trace_json(kw);
4292
+ trace_json_masked(kw);
3925
4293
  }
3926
4294
  return default_value;
3927
4295
  }
@@ -3949,14 +4317,14 @@
3949
4317
  }
3950
4318
  if (required) {
3951
4319
  log_error(`path not found: '${path}'`);
3952
- trace_json(kw);
4320
+ trace_json_masked(kw);
3953
4321
  }
3954
4322
  return default_value;
3955
4323
  }
3956
4324
  if (!is_array(v)) {
3957
4325
  if (required) {
3958
4326
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json list: '${path}'`);
3959
- trace_json(kw);
4327
+ trace_json_masked(kw);
3960
4328
  }
3961
4329
  return default_value;
3962
4330
  }
@@ -6818,7 +7186,7 @@
6818
7186
  let hora = current_timestamp();
6819
7187
  try {
6820
7188
  log_debug("\n" + hora + " " + prefix + "\n");
6821
- trace_json(iev);
7189
+ trace_json_masked(iev);
6822
7190
  } catch (e) {
6823
7191
  log_debug("ERROR in trace_inter_event: " + e);
6824
7192
  }
@@ -7500,6 +7868,7 @@
7500
7868
  exports.is_object = is_object;
7501
7869
  exports.is_private_key = is_private_key;
7502
7870
  exports.is_pure_number = is_pure_number;
7871
+ exports.is_secret_name = is_secret_name;
7503
7872
  exports.is_string = is_string;
7504
7873
  exports.jdb_delete = jdb_delete;
7505
7874
  exports.jdb_get = jdb_get;
@@ -7515,6 +7884,7 @@
7515
7884
  exports.json_array_size = json_array_size;
7516
7885
  exports.json_deep_copy = json_deep_copy;
7517
7886
  exports.json_is_identical = json_is_identical;
7887
+ exports.json_mask_secrets = json_mask_secrets;
7518
7888
  exports.json_object_del = json_object_del;
7519
7889
  exports.json_object_get = json_object_get;
7520
7890
  exports.json_object_set = json_object_set;
@@ -7562,6 +7932,7 @@
7562
7932
  exports.log_error = log_error;
7563
7933
  exports.log_info = log_info;
7564
7934
  exports.log_warning = log_warning;
7935
+ exports.mask_secrets_inline = mask_secrets_inline;
7565
7936
  exports.msg_iev_get_msg_type = msg_iev_get_msg_type;
7566
7937
  exports.msg_iev_get_stack = msg_iev_get_stack;
7567
7938
  exports.msg_iev_push_stack = msg_iev_push_stack;
@@ -7595,6 +7966,7 @@
7595
7966
  exports.template_get_field_desc = template_get_field_desc;
7596
7967
  exports.timeTracker = timeTracker;
7597
7968
  exports.trace_json = trace_json;
7969
+ exports.trace_json_masked = trace_json_masked;
7598
7970
  exports.trace_level_t = trace_level_t;
7599
7971
  exports.trace_msg = trace_msg;
7600
7972
  exports.treedb_decoder_fkey = treedb_decoder_fkey;