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