@yuneta/gobj-js 7.26.20 → 7.26.22

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.
@@ -215,6 +215,13 @@ var __jn_services__ = Object.create(null);
215
215
  var __yuno__ = null;
216
216
  var __default_service__ = null;
217
217
  var __inside__ = 0;
218
+ var frame_kind_t = Object.freeze({
219
+ FRAME_ACTION: 0,
220
+ FRAME_PUBLICATION: 1,
221
+ FRAME_METHOD: 2,
222
+ FRAME_WATCH: 3
223
+ });
224
+ var __dispatch_top__ = null;
218
225
  /**************************************************************************
219
226
  * SData - Structured Data
220
227
  **************************************************************************/
@@ -228,7 +235,15 @@ var data_type_t = Object.freeze({
228
235
  DTP_JSON: 7,
229
236
  DTP_POINTER: 8
230
237
  });
238
+ var DTP_IS_STRING = (type) => type === data_type_t.DTP_STRING;
239
+ var DTP_IS_BOOLEAN = (type) => type === data_type_t.DTP_BOOLEAN;
240
+ var DTP_IS_INTEGER = (type) => type === data_type_t.DTP_INTEGER;
241
+ var DTP_IS_REAL = (type) => type === data_type_t.DTP_REAL;
242
+ var DTP_IS_LIST = (type) => type === data_type_t.DTP_LIST;
243
+ var DTP_IS_DICT = (type) => type === data_type_t.DTP_DICT;
244
+ var DTP_IS_JSON = (type) => type === data_type_t.DTP_JSON;
231
245
  data_type_t.DTP_POINTER;
246
+ var DTP_IS_NUMBER = (type) => DTP_IS_INTEGER(type) || DTP_IS_REAL(type) || DTP_IS_BOOLEAN(type);
232
247
  var sdata_flag_t = Object.freeze({
233
248
  SDF_NOTACCESS: 1,
234
249
  SDF_RD: 2,
@@ -250,7 +265,8 @@ var sdata_flag_t = Object.freeze({
250
265
  SDF_AUTHZ_X: 131072,
251
266
  SDF_AUTHZ_P: 262144,
252
267
  SDF_AUTHZ_S: 524288,
253
- SDF_AUTHZ_RS: 1048576
268
+ SDF_AUTHZ_RS: 1048576,
269
+ SDF_SECRET: 2097152
254
270
  });
255
271
  sdata_flag_t.SDF_RD | sdata_flag_t.SDF_WR | sdata_flag_t.SDF_STATS | sdata_flag_t.SDF_PERSIST | sdata_flag_t.SDF_VOLATIL | sdata_flag_t.SDF_RSTATS | sdata_flag_t.SDF_PSTATS;
256
272
  sdata_flag_t.SDF_WR | sdata_flag_t.SDF_PERSIST;
@@ -838,6 +854,260 @@ function set_default(gobj, sdata, it) {
838
854
  return 0;
839
855
  }
840
856
  /***************************************************************************
857
+ * A value of a type, written as text or given as json, read as the C
858
+ * command parser reads a parameter (command_parser.c): the same grammar,
859
+ * the same refusals, so that a C client and a JS client read an attribute
860
+ * value the same way (json2item()). A refusal says why in a short phrase,
861
+ * never the value: it may be a secret.
862
+ ***************************************************************************/
863
+ var JSON_INTEGER_TEXT = /^-?(0|[1-9][0-9]*)$/;
864
+ var JSON_NUMBER_TEXT = /^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?$/;
865
+ var INT64_MIN = -(2n ** 63n);
866
+ var INT64_MAX = 2n ** 63n - 1n;
867
+ var REFUSED_TEXT = "a text that does not read as one";
868
+ function value_has_shape(type, value) {
869
+ if (DTP_IS_STRING(type)) return is_string(value);
870
+ if (DTP_IS_DICT(type)) return is_object(value);
871
+ if (DTP_IS_LIST(type)) return is_array(value);
872
+ if (DTP_IS_NUMBER(type)) return typeof value === "number" || typeof value === "boolean";
873
+ return true;
874
+ }
875
+ function shape_of_value(value) {
876
+ if (is_array(value)) return "an array";
877
+ if (is_object(value)) return "an object";
878
+ if (is_string(value)) return REFUSED_TEXT;
879
+ if (typeof value === "number") return Number.isInteger(value) ? "an integer" : "a real";
880
+ if (typeof value === "boolean") return "a boolean";
881
+ return "null";
882
+ }
883
+ function number_as_type(type, value) {
884
+ if (typeof value === "number" && !Number.isFinite(value)) return {
885
+ value: void 0,
886
+ refused: "a number out of its range"
887
+ };
888
+ if (DTP_IS_BOOLEAN(type)) return {
889
+ value: typeof value === "boolean" ? value : value !== 0,
890
+ refused: null
891
+ };
892
+ if (DTP_IS_REAL(type)) return {
893
+ value: typeof value === "boolean" ? value ? 1 : 0 : value,
894
+ refused: null
895
+ };
896
+ if (typeof value === "boolean") return {
897
+ value: value ? 1 : 0,
898
+ refused: null
899
+ };
900
+ if (!(value >= -0x8000000000000000 && value < 0x8000000000000000)) return {
901
+ value: void 0,
902
+ refused: "a number out of its range"
903
+ };
904
+ if (!Number.isInteger(value)) return {
905
+ value: void 0,
906
+ refused: "a real with decimals"
907
+ };
908
+ return {
909
+ value,
910
+ refused: null
911
+ };
912
+ }
913
+ function text2parameter(type, s, from_kw) {
914
+ if (!is_string(s)) s = "";
915
+ if (DTP_IS_STRING(type)) return {
916
+ value: s,
917
+ refused: null
918
+ };
919
+ if (DTP_IS_NUMBER(type)) {
920
+ if (s.length === 0) {
921
+ if (from_kw) return {
922
+ value: void 0,
923
+ refused: null
924
+ };
925
+ return {
926
+ value: DTP_IS_BOOLEAN(type) ? false : 0,
927
+ refused: null
928
+ };
929
+ }
930
+ if (DTP_IS_BOOLEAN(type)) {
931
+ const lower = s.toLowerCase();
932
+ if (lower === "true" || lower === "yes" || lower === "on") return {
933
+ value: true,
934
+ refused: null
935
+ };
936
+ if (lower === "false" || lower === "no" || lower === "off") return {
937
+ value: false,
938
+ refused: null
939
+ };
940
+ }
941
+ if (!(DTP_IS_REAL(type) ? JSON_NUMBER_TEXT : JSON_INTEGER_TEXT).test(s)) return {
942
+ value: void 0,
943
+ refused: REFUSED_TEXT
944
+ };
945
+ if (DTP_IS_REAL(type)) {
946
+ const d = Number(s);
947
+ if (!Number.isFinite(d)) return {
948
+ value: void 0,
949
+ refused: "a number out of its range"
950
+ };
951
+ return {
952
+ value: d,
953
+ refused: null
954
+ };
955
+ }
956
+ const n = BigInt(s);
957
+ if (n < INT64_MIN || n > INT64_MAX) return {
958
+ value: void 0,
959
+ refused: "a number out of its range"
960
+ };
961
+ if (DTP_IS_BOOLEAN(type)) return {
962
+ value: n !== 0n,
963
+ refused: null
964
+ };
965
+ return {
966
+ value: Number(n),
967
+ refused: null
968
+ };
969
+ }
970
+ if (DTP_IS_DICT(type) || DTP_IS_LIST(type)) {
971
+ let jn;
972
+ try {
973
+ jn = JSON.parse(s);
974
+ } catch (e) {
975
+ return {
976
+ value: void 0,
977
+ refused: REFUSED_TEXT
978
+ };
979
+ }
980
+ if (!value_has_shape(type, jn)) return {
981
+ value: void 0,
982
+ refused: REFUSED_TEXT
983
+ };
984
+ return {
985
+ value: jn,
986
+ refused: null
987
+ };
988
+ }
989
+ if (DTP_IS_JSON(type)) try {
990
+ return {
991
+ value: JSON.parse(s),
992
+ refused: null
993
+ };
994
+ } catch (e) {
995
+ const t = s.replace(/^[ \t]+/, "");
996
+ if (t.startsWith("{") || t.startsWith("[") || t.startsWith("\"")) return {
997
+ value: void 0,
998
+ refused: REFUSED_TEXT
999
+ };
1000
+ return {
1001
+ value: s,
1002
+ refused: null
1003
+ };
1004
+ }
1005
+ return {
1006
+ value: void 0,
1007
+ refused: REFUSED_TEXT
1008
+ };
1009
+ }
1010
+ /***************************************************************************
1011
+ * A value of `type` written as TEXT, read as the C parser reads a
1012
+ * parameter on the command line (command_parameter_from_text()): an empty
1013
+ * text is 0 or false. Return {value, refused}: `value` undefined when the
1014
+ * text does not read as one, `refused` saying why.
1015
+ ***************************************************************************/
1016
+ function command_parameter_from_text(type, text) {
1017
+ const r = text2parameter(type, text, false);
1018
+ if (r.value === void 0 && !r.refused) r.refused = REFUSED_TEXT;
1019
+ return r;
1020
+ }
1021
+ /***************************************************************************
1022
+ * A value of `type` given as JSON, read as the C parser reads a
1023
+ * parameter given in kw (command_parameter_from_json()): a string as
1024
+ * command_parameter_from_text() reads a text (a string with a NUL inside
1025
+ * refused), a number or a boolean as the EXACT type (an integer to a
1026
+ * DTP_REAL is its real, a boolean to a DTP_INTEGER 1 or 0, 2.7 to a
1027
+ * DTP_INTEGER refused), an object or a list of its shape as it is, any
1028
+ * other shape refused. Return {value, refused}: `value` undefined and
1029
+ * `refused` saying why, or `refused` null when there is NO value (a null,
1030
+ * undefined, or an empty text given to a number).
1031
+ ***************************************************************************/
1032
+ function command_parameter_from_json(type, value) {
1033
+ if (value === void 0 || value === null) {
1034
+ if (DTP_IS_JSON(type) && value === null) return {
1035
+ value: null,
1036
+ refused: null
1037
+ };
1038
+ return {
1039
+ value: void 0,
1040
+ refused: null
1041
+ };
1042
+ }
1043
+ const nul_inside = is_string(value) && value.indexOf("\0") >= 0;
1044
+ if (DTP_IS_JSON(type)) {
1045
+ if (!is_string(value) || nul_inside) return {
1046
+ value,
1047
+ refused: null
1048
+ };
1049
+ const r = text2parameter(type, value, true);
1050
+ return r.value === void 0 ? {
1051
+ value,
1052
+ refused: null
1053
+ } : r;
1054
+ }
1055
+ if (!(DTP_IS_STRING(type) || DTP_IS_DICT(type) || DTP_IS_LIST(type) || DTP_IS_NUMBER(type))) return {
1056
+ value,
1057
+ refused: null
1058
+ };
1059
+ if (nul_inside) return {
1060
+ value: void 0,
1061
+ refused: "a text with a NUL in it"
1062
+ };
1063
+ if (is_string(value) && !DTP_IS_STRING(type)) return text2parameter(type, value, true);
1064
+ if (!value_has_shape(type, value)) return {
1065
+ value: void 0,
1066
+ refused: shape_of_value(value)
1067
+ };
1068
+ if (DTP_IS_NUMBER(type)) return number_as_type(type, value);
1069
+ return {
1070
+ value,
1071
+ refused: null
1072
+ };
1073
+ }
1074
+ /***************************************************************************
1075
+ * A value json2item() refuses: the attr, its type and why, and the value
1076
+ * as a log may show it (a SDF_SECRET one never; any other masked, then
1077
+ * capped on a whole character, as in C)
1078
+ ***************************************************************************/
1079
+ var ATTR_VALUE_SHOWN = 64;
1080
+ var TYPES_READ = [
1081
+ data_type_t.DTP_BOOLEAN,
1082
+ data_type_t.DTP_INTEGER,
1083
+ data_type_t.DTP_REAL,
1084
+ data_type_t.DTP_LIST,
1085
+ data_type_t.DTP_DICT
1086
+ ];
1087
+ function log_attr_value_refused(gobj, it, value, refused) {
1088
+ const types = {
1089
+ [data_type_t.DTP_BOOLEAN]: "a boolean",
1090
+ [data_type_t.DTP_INTEGER]: "an integer",
1091
+ [data_type_t.DTP_REAL]: "a real",
1092
+ [data_type_t.DTP_LIST]: "a json array",
1093
+ [data_type_t.DTP_DICT]: "a json object"
1094
+ };
1095
+ let shown;
1096
+ if (it.flag & sdata_flag_t.SDF_SECRET) shown = "********";
1097
+ else {
1098
+ shown = is_string(value) ? value : String(JSON.stringify(value === void 0 ? null : value));
1099
+ const masked = mask_secrets_inline(shown);
1100
+ if (masked !== null) shown = masked;
1101
+ if (shown.length > ATTR_VALUE_SHOWN) {
1102
+ let n = ATTR_VALUE_SHOWN;
1103
+ const code = shown.charCodeAt(n);
1104
+ if (code >= 56320 && code <= 57343) n--;
1105
+ shown = shown.substring(0, n);
1106
+ }
1107
+ }
1108
+ log_error(`${gobj_short_name(gobj)}: Attribute value of the wrong type, not written: attr '${it.name}', type ${types[it.type] || "a value of its type"}, got ${refused || "no value (a null, or an empty text)"}, value '${shown}'`);
1109
+ }
1110
+ /***************************************************************************
841
1111
  * Set array values to sdata, from json or binary
842
1112
  ***************************************************************************/
843
1113
  function json2item(gobj, sdata, it, jn_value_) {
@@ -852,44 +1122,18 @@ function json2item(gobj, sdata, it, jn_value_) {
852
1122
  }
853
1123
  break;
854
1124
  case data_type_t.DTP_BOOLEAN:
855
- jn_value2 = parseBoolean(jn_value_);
856
- break;
857
1125
  case data_type_t.DTP_INTEGER:
858
- jn_value2 = parseInt(jn_value_);
859
- if (isNaN(jn_value2)) {
860
- log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
861
- return -1;
862
- }
863
- break;
864
1126
  case data_type_t.DTP_REAL:
865
- jn_value2 = Number(jn_value_);
866
- if (isNaN(jn_value2)) {
867
- log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
868
- return -1;
869
- }
870
- break;
871
1127
  case data_type_t.DTP_LIST:
872
- if (is_string(jn_value_)) try {
873
- jn_value2 = JSON.parse(jn_value_);
874
- } catch (error) {
875
- log_error(`JSON parse error: ${error.message}`);
876
- }
877
- else jn_value2 = jn_value_;
878
- if (!is_array(jn_value2)) {
879
- log_error(`attr must be an array: ${it.name}`);
880
- return -1;
881
- }
882
- break;
883
1128
  case data_type_t.DTP_DICT:
884
- if (is_string(jn_value_)) try {
885
- jn_value2 = JSON.parse(jn_value_);
886
- } catch (error) {
887
- log_error(`JSON parse error: ${error.message}`);
888
- }
889
- else jn_value2 = jn_value_;
890
- if (!is_object(jn_value2)) {
891
- log_error(`attr must be an object: ${it.name}`);
892
- return -1;
1129
+ {
1130
+ if (jn_value_ === void 0) return 0;
1131
+ const r = command_parameter_from_json(it.type, jn_value_);
1132
+ if (r.value === void 0) {
1133
+ log_attr_value_refused(gobj, it, jn_value_, r.refused);
1134
+ return -1;
1135
+ }
1136
+ jn_value2 = r.value;
893
1137
  }
894
1138
  break;
895
1139
  case data_type_t.DTP_JSON:
@@ -1464,6 +1708,8 @@ function gobj_destroy(gobj) {
1464
1708
  return;
1465
1709
  }
1466
1710
  if (gobj.__refs__ > 0) log_error(`${gobj_short_name(gobj)}: gobj DESTROYING with references: ${gobj.__refs__}`);
1711
+ if (!(gobj.parent && gobj_is_destroying(gobj.parent))) check_destroy_under_running_code(gobj);
1712
+ mark_dispatch_frames_destroyed(gobj);
1467
1713
  if (gobj.playing) {
1468
1714
  log_error(`Destroying a PLAYING gobj: ${gobj_full_name(gobj)}`);
1469
1715
  gobj_pause(gobj);
@@ -1528,10 +1774,44 @@ function gobj_start(gobj) {
1528
1774
  if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏺ ⏺ start: %s", gobj_full_name(gobj)));
1529
1775
  gobj.running = true;
1530
1776
  let ret = 0;
1531
- if (gobj.gclass.gmt.mt_start) ret = gobj.gclass.gmt.mt_start(gobj);
1777
+ if (gobj.gclass.gmt.mt_start) {
1778
+ const frame = push_dispatch_frame(gobj, "mt_start", frame_kind_t.FRAME_METHOD);
1779
+ try {
1780
+ ret = gobj.gclass.gmt.mt_start(gobj);
1781
+ } finally {
1782
+ pop_dispatch_frame(frame);
1783
+ }
1784
+ }
1532
1785
  return ret;
1533
1786
  }
1534
1787
  /***************************************************************************
1788
+ * Start a gobj in a walk of its tree, and say whether that destroyed it.
1789
+ *
1790
+ * A gclass may end itself in its own mt_start or mt_stop, and a walk of
1791
+ * the tree must not go down into the children of a gobj that is gone.
1792
+ ***************************************************************************/
1793
+ function start_destroys_it(gobj) {
1794
+ const frame = push_dispatch_frame(gobj, "gobj_start", frame_kind_t.FRAME_WATCH);
1795
+ try {
1796
+ gobj_start(gobj);
1797
+ } finally {
1798
+ pop_dispatch_frame(frame);
1799
+ }
1800
+ return frame.destroyed;
1801
+ }
1802
+ /***************************************************************************
1803
+ * Stop a gobj in a walk of its tree, and say whether that destroyed it.
1804
+ ***************************************************************************/
1805
+ function stop_destroys_it(gobj) {
1806
+ const frame = push_dispatch_frame(gobj, "gobj_stop", frame_kind_t.FRAME_WATCH);
1807
+ try {
1808
+ gobj_stop(gobj);
1809
+ } finally {
1810
+ pop_dispatch_frame(frame);
1811
+ }
1812
+ return frame.destroyed;
1813
+ }
1814
+ /***************************************************************************
1535
1815
  * Start all children of the gobj.
1536
1816
  ***************************************************************************/
1537
1817
  function cb_start_child(child, user_data, user_data2) {
@@ -1552,7 +1832,9 @@ function gobj_start_children(gobj) {
1552
1832
  function cb_start_child_tree(child, user_data, user_data2) {
1553
1833
  if (child.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start) return 1;
1554
1834
  if (gobj_is_disabled(child)) return 1;
1555
- if (!gobj_is_running(child)) gobj_start(child);
1835
+ if (!gobj_is_running(child)) {
1836
+ if (start_destroys_it(child)) return 1;
1837
+ }
1556
1838
  return 0;
1557
1839
  }
1558
1840
  function gobj_start_tree(gobj) {
@@ -1563,7 +1845,9 @@ function gobj_start_tree(gobj) {
1563
1845
  if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏺ ⏺ ⏺ ⏺ start_tree: %s", gobj_full_name(gobj)));
1564
1846
  if (gobj.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start) return 0;
1565
1847
  else if (gobj.disabled) return 0;
1566
- else if (!gobj.running) gobj_start(gobj);
1848
+ else if (!gobj.running) {
1849
+ if (start_destroys_it(gobj)) return 0;
1850
+ }
1567
1851
  return gobj_walk_gobj_children_tree(gobj, walk_type_t.WALK_TOP2BOTTOM, cb_start_child_tree, 0, 0);
1568
1852
  }
1569
1853
  /************************************************************
@@ -1585,14 +1869,23 @@ function gobj_stop(gobj) {
1585
1869
  if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏹ ⏹ stop: %s", gobj_full_name(gobj)));
1586
1870
  gobj.running = false;
1587
1871
  let ret = 0;
1588
- if (gobj.gclass.gmt.mt_stop) ret = gobj.gclass.gmt.mt_stop(gobj);
1872
+ if (gobj.gclass.gmt.mt_stop) {
1873
+ const frame = push_dispatch_frame(gobj, "mt_stop", frame_kind_t.FRAME_METHOD);
1874
+ try {
1875
+ ret = gobj.gclass.gmt.mt_stop(gobj);
1876
+ } finally {
1877
+ pop_dispatch_frame(frame);
1878
+ }
1879
+ }
1589
1880
  return ret;
1590
1881
  }
1591
1882
  /***************************************************************************
1592
1883
  * Stop all children of the gobj.
1593
1884
  ***************************************************************************/
1594
1885
  function cb_stop_child(child, user_data, user_data2) {
1595
- if (gobj_is_running(child)) gobj_stop(child);
1886
+ if (gobj_is_running(child)) {
1887
+ if (stop_destroys_it(child)) return 1;
1888
+ }
1596
1889
  return 0;
1597
1890
  }
1598
1891
  function gobj_stop_children(gobj) {
@@ -1611,7 +1904,9 @@ function gobj_stop_tree(gobj) {
1611
1904
  return -1;
1612
1905
  }
1613
1906
  if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏹ ⏹ ⏹ ⏹ stop_tree: %s", gobj_full_name(gobj)));
1614
- if (gobj_is_running(gobj)) gobj_stop(gobj);
1907
+ if (gobj_is_running(gobj)) {
1908
+ if (stop_destroys_it(gobj)) return 0;
1909
+ }
1615
1910
  return gobj_walk_gobj_children_tree(gobj, walk_type_t.WALK_TOP2BOTTOM, cb_stop_child, 0, 0);
1616
1911
  }
1617
1912
  /************************************************************
@@ -1643,8 +1938,13 @@ function gobj_play(gobj) {
1643
1938
  gobj.playing = true;
1644
1939
  let ret = 0;
1645
1940
  if (gobj.gclass.gmt.mt_play) {
1646
- ret = gobj.gclass.gmt.mt_play(gobj);
1647
- if (ret < 0 || ret === false) gobj.playing = false;
1941
+ const frame = push_dispatch_frame(gobj, "mt_play", frame_kind_t.FRAME_METHOD);
1942
+ try {
1943
+ ret = gobj.gclass.gmt.mt_play(gobj);
1944
+ } finally {
1945
+ pop_dispatch_frame(frame);
1946
+ }
1947
+ if ((ret < 0 || ret === false) && !frame.destroyed) gobj.playing = false;
1648
1948
  }
1649
1949
  return ret;
1650
1950
  }
@@ -1662,8 +1962,14 @@ function gobj_pause(gobj) {
1662
1962
  }
1663
1963
  if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏸ ⏸ pause: %s", gobj_full_name(gobj)));
1664
1964
  gobj.playing = false;
1665
- if (gobj.gclass.gmt.mt_pause) return gobj.gclass.gmt.mt_pause(gobj);
1666
- else return 0;
1965
+ if (gobj.gclass.gmt.mt_pause) {
1966
+ const frame = push_dispatch_frame(gobj, "mt_pause", frame_kind_t.FRAME_METHOD);
1967
+ try {
1968
+ return gobj.gclass.gmt.mt_pause(gobj);
1969
+ } finally {
1970
+ pop_dispatch_frame(frame);
1971
+ }
1972
+ } else return 0;
1667
1973
  }
1668
1974
  /************************************************************
1669
1975
  *
@@ -2216,14 +2522,7 @@ function gobj_write_attr(gobj, path, value, src) {
2216
2522
  if (ss.length <= 1) {
2217
2523
  let key = path;
2218
2524
  if (key in jn_attrs) {
2219
- if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) {
2220
- jn_attrs[key] = value;
2221
- if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, key)) gobj.priv[key] = value;
2222
- if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2223
- if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2224
- }
2225
- return 0;
2226
- }
2525
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) return write_attr_value(gobj, key, value);
2227
2526
  }
2228
2527
  log_error(sprintf("gobj_write_attr(%s): attr not found '%s'", gobj_short_name(gobj), key));
2229
2528
  return -1;
@@ -2239,14 +2538,7 @@ function gobj_write_attr(gobj, path, value, src) {
2239
2538
  }
2240
2539
  let jn_attrs = gobj.jn_attrs;
2241
2540
  if (key in jn_attrs) {
2242
- if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) {
2243
- jn_attrs[key] = value;
2244
- if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, key)) gobj.priv[key] = value;
2245
- if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2246
- if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2247
- }
2248
- return 0;
2249
- }
2541
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) return write_attr_value(gobj, key, value);
2250
2542
  }
2251
2543
  break;
2252
2544
  }
@@ -2254,6 +2546,49 @@ function gobj_write_attr(gobj, path, value, src) {
2254
2546
  return -1;
2255
2547
  }
2256
2548
  /***************************************************************************
2549
+ * The value written to the attr `key` of `gobj`, read as its type as the C
2550
+ * kernel reads it (json2item(): it writes priv and calls mt_writing too).
2551
+ * Up to 7.26.21 gobj_write_attr() wrote it raw.
2552
+ ***************************************************************************/
2553
+ function write_attr_value(gobj, key, value) {
2554
+ const it = gobj_attr_desc(gobj, key, false);
2555
+ if (!it) {
2556
+ log_error(sprintf("gobj_write_attr(%s): attr without description '%s'", gobj_short_name(gobj), key));
2557
+ return -1;
2558
+ }
2559
+ if (value === void 0 && TYPES_READ.includes(it.type)) {
2560
+ log_attr_value_refused(gobj, it, value, null);
2561
+ return -1;
2562
+ }
2563
+ return json2item(gobj, gobj.jn_attrs, it, value);
2564
+ }
2565
+ /***************************************************************************
2566
+ * The value a typed writer writes, read as ITS type by the grammar of
2567
+ * json2item() (a C writer takes its C type: a string is never read as a
2568
+ * number there). Return {value} or {refused} (logged): the attr keeps its
2569
+ * value. A string writer never refuses: null and undefined are "", any
2570
+ * other json its text, as a DTP_STRING attr reads them.
2571
+ ***************************************************************************/
2572
+ function typed_writer_value(gobj, name, type, value) {
2573
+ if (DTP_IS_STRING(type)) {
2574
+ if (value === null || value === void 0) return { value: "" };
2575
+ return { value: is_string(value) ? value : String(JSON.stringify(value)) };
2576
+ }
2577
+ const r = command_parameter_from_json(type, value);
2578
+ if (r.value === void 0) {
2579
+ let holder = gobj;
2580
+ while (holder && !gobj_has_attr(holder, name)) holder = holder.bottom_gobj;
2581
+ const it = holder ? gobj_attr_desc(holder, name, false) : null;
2582
+ log_attr_value_refused(gobj, {
2583
+ name,
2584
+ type,
2585
+ flag: it ? it.flag : 0
2586
+ }, value, r.refused);
2587
+ return { refused: true };
2588
+ }
2589
+ return { value: r.value };
2590
+ }
2591
+ /***************************************************************************
2257
2592
  * WRITE - high level
2258
2593
  ***************************************************************************/
2259
2594
  function sdata_write_default_values(gobj, include_flag, exclude_flag) {
@@ -2301,7 +2636,9 @@ function gobj_write_attrs(gobj, kw, include_flag, src) {
2301
2636
  function gobj_write_bool_attr(gobj, name, value) {
2302
2637
  let hs = gobj_hsdata2(gobj, name, false);
2303
2638
  if (hs) {
2304
- hs[name] = parseBoolean(value);
2639
+ const v = typed_writer_value(gobj, name, data_type_t.DTP_BOOLEAN, value);
2640
+ if (v.refused) return -1;
2641
+ hs[name] = v.value;
2305
2642
  if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2306
2643
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2307
2644
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
@@ -2317,7 +2654,9 @@ function gobj_write_bool_attr(gobj, name, value) {
2317
2654
  function gobj_write_integer_attr(gobj, name, value) {
2318
2655
  let hs = gobj_hsdata2(gobj, name, false);
2319
2656
  if (hs) {
2320
- hs[name] = parseInt(value);
2657
+ const v = typed_writer_value(gobj, name, data_type_t.DTP_INTEGER, value);
2658
+ if (v.refused) return -1;
2659
+ hs[name] = v.value;
2321
2660
  if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2322
2661
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2323
2662
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
@@ -2333,7 +2672,9 @@ function gobj_write_integer_attr(gobj, name, value) {
2333
2672
  function gobj_write_str_attr(gobj, name, value) {
2334
2673
  let hs = gobj_hsdata2(gobj, name, false);
2335
2674
  if (hs) {
2336
- hs[name] = String(value);
2675
+ const v = typed_writer_value(gobj, name, data_type_t.DTP_STRING, value);
2676
+ if (v.refused) return -1;
2677
+ hs[name] = v.value;
2337
2678
  if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2338
2679
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2339
2680
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
@@ -2543,6 +2884,84 @@ function purge_posted_events(gobj) {
2543
2884
  __dl_posted_events__ = __dl_posted_events__.filter((msg) => msg.dst !== gobj);
2544
2885
  }
2545
2886
  /************************************************************
2887
+ * A dispatch begins: its frame goes on top of the chain.
2888
+ * Every push is paired with a pop in a `finally`: an action
2889
+ * that throws must not leave its frame on the chain.
2890
+ ************************************************************/
2891
+ function push_dispatch_frame(gobj, event, kind) {
2892
+ const frame = {
2893
+ prev: __dispatch_top__,
2894
+ gobj,
2895
+ event,
2896
+ kind,
2897
+ destroyed: false
2898
+ };
2899
+ __dispatch_top__ = frame;
2900
+ return frame;
2901
+ }
2902
+ function pop_dispatch_frame(frame) {
2903
+ __dispatch_top__ = frame.prev;
2904
+ }
2905
+ /************************************************************
2906
+ * Every dispatch in progress of `gobj` learns that it is
2907
+ * destroyed. Only its own frames: each child destroyed with
2908
+ * it marks its own, in its own gobj_destroy().
2909
+ ************************************************************/
2910
+ function mark_dispatch_frames_destroyed(gobj) {
2911
+ for (let f = __dispatch_top__; f; f = f.prev) if (f.gobj === gobj) f.destroyed = true;
2912
+ }
2913
+ /************************************************************
2914
+ * Is the innermost live publication of `gobj` its EV_STOPPED?
2915
+ * Then the stop contract holds for it: that is the last thing
2916
+ * it does with itself.
2917
+ ************************************************************/
2918
+ function said_farewell(gobj) {
2919
+ for (let f = __dispatch_top__; f; f = f.prev) if (f.kind === frame_kind_t.FRAME_PUBLICATION && !f.destroyed && f.gobj === gobj) return f.event === "EV_STOPPED";
2920
+ return false;
2921
+ }
2922
+ /************************************************************
2923
+ * A gobj must not be destroyed under code that is still
2924
+ * running on it -- the C kernel's check, with its exemptions
2925
+ * and its fields, so both runtimes report the same defect the
2926
+ * same way.
2927
+ *
2928
+ * `gobj` is about to be destroyed, and with it its whole
2929
+ * subtree. Every live frame of a gobj of that subtree is code
2930
+ * that goes on when the destroy returns, on a gobj that is gone
2931
+ * (C_TIMER right after its EV_TIMEOUT). It is an ERROR, except
2932
+ * for:
2933
+ *
2934
+ * - the innermost frame: it is the code that destroys, and
2935
+ * knows it (a gobj that destroys itself in its own action);
2936
+ *
2937
+ * - the frames of a gobj whose innermost publication is
2938
+ * EV_STOPPED: the stop contract, its host destroys it there;
2939
+ *
2940
+ * - the watch frames, which run no gclass code of their own.
2941
+ *
2942
+ * The destroy goes on: this only says it, once. The fix is to
2943
+ * defer the destroy with gobj_post_event().
2944
+ ************************************************************/
2945
+ function check_destroy_under_running_code(gobj) {
2946
+ const top = __dispatch_top__;
2947
+ if (!top) return;
2948
+ for (let f = top.prev; f; f = f.prev) {
2949
+ if (f.destroyed || f.kind === frame_kind_t.FRAME_WATCH) continue;
2950
+ let in_tree = false;
2951
+ for (let p = f.gobj; p; p = p.parent) if (p === gobj) {
2952
+ in_tree = true;
2953
+ break;
2954
+ }
2955
+ if (!in_tree) continue;
2956
+ if (said_farewell(f.gobj)) continue;
2957
+ const destroyer = top.destroyed ? "(destroyed)" : gobj_full_name(top.gobj);
2958
+ const stack = String((/* @__PURE__ */ new Error()).stack || "").split("\n").slice(2).join("\n");
2959
+ if (f.kind === frame_kind_t.FRAME_PUBLICATION) log_error(`Destroying a gobj while its tree is publishing: destroying ${gobj_full_name(gobj)}, publisher ${gobj_full_name(f.gobj)}, event ${f.event || ""}, destroyer ${destroyer}, inner_event ${top.event || ""}. Defer it with gobj_post_event(): a subscriber must not destroy the tree of its publisher synchronously. stack:\n${stack}`);
2960
+ else log_error(`Destroying a gobj while one of its actions is still running: destroying ${gobj_full_name(gobj)}, running ${gobj_full_name(f.gobj)}, event ${f.event || ""}, destroyer ${destroyer}, inner_event ${top.event || ""}. Defer it with gobj_post_event(): an inner dispatch must not destroy a gobj that an outer one is running on. stack:\n${stack}`);
2961
+ return;
2962
+ }
2963
+ }
2964
+ /************************************************************
2546
2965
  * send_event
2547
2966
  ************************************************************/
2548
2967
  function gobj_send_event(dst, event, kw, src) {
@@ -2574,7 +2993,12 @@ function gobj_send_event(dst, event, kw, src) {
2574
2993
  }
2575
2994
  }
2576
2995
  }
2577
- return dst.gclass.gmt.mt_inject_event(dst, event, kw, src);
2996
+ const frame = push_dispatch_frame(dst, event, frame_kind_t.FRAME_ACTION);
2997
+ try {
2998
+ return dst.gclass.gmt.mt_inject_event(dst, event, kw, src);
2999
+ } finally {
3000
+ pop_dispatch_frame(frame);
3001
+ }
2578
3002
  }
2579
3003
  if (tracea) trace_machine(sprintf("📛 mach(%s%s^%s), st: %s, ev: %s, 📛📛ERROR Event NOT DEFINED in state📛📛, from(%s%s^%s)", !dst.running ? "!!" : "", gobj_gclass_name(dst), gobj_name(dst), state.state_name, event ? event : "", src && !src.running ? "!!" : "", gobj_gclass_name(src), gobj_name(src)));
2580
3004
  log_error(`📛📛 Event NOT DEFINED in state 📛📛: ${gobj_short_name(dst)}, ${state.state_name}, ${event}`);
@@ -2594,6 +3018,7 @@ function gobj_send_event(dst, event, kw, src) {
2594
3018
  }
2595
3019
  }
2596
3020
  }
3021
+ const frame = push_dispatch_frame(dst, event, frame_kind_t.FRAME_ACTION);
2597
3022
  if (event_action.next_state) gobj_change_state(dst, event_action.next_state);
2598
3023
  let ret = -1;
2599
3024
  try {
@@ -2607,8 +3032,10 @@ function gobj_send_event(dst, event, kw, src) {
2607
3032
  } catch (e2) {}
2608
3033
  }
2609
3034
  throw e;
3035
+ } finally {
3036
+ pop_dispatch_frame(frame);
2610
3037
  }
2611
- if (tracea && __trace_machine_format__ !== 1 && !(dst.obflag & obflag_t.obflag_destroyed)) trace_machine(sprintf("<- mach(%s%s^%s), st: %s, ev: %s, ret: %d", !dst.running ? "!!" : "", gobj_gclass_name(dst), gobj_name(dst), dst.current_state.state_name, event ? event : "", is_number(ret) ? ret : 0));
3038
+ if (tracea && __trace_machine_format__ !== 1 && !frame.destroyed) trace_machine(sprintf("<- mach(%s%s^%s), st: %s, ev: %s, ret: %d", !dst.running ? "!!" : "", gobj_gclass_name(dst), gobj_name(dst), dst.current_state.state_name, event ? event : "", is_number(ret) ? ret : 0));
2612
3039
  __inside__--;
2613
3040
  return ret;
2614
3041
  }
@@ -3071,62 +3498,67 @@ function gobj_publish_event(publisher, event, kw) {
3071
3498
  let dl_subs = [...publisher.dl_subscriptions];
3072
3499
  let sent_count = 0;
3073
3500
  let ret = 0;
3074
- for (let idx = 0; idx < dl_subs.length; idx++) {
3075
- let subs = dl_subs[idx];
3076
- if (publisher.gclass.gmt.mt_publication_pre_filter) {
3077
- let topublish = publisher.gclass.gmt.mt_publication_pre_filter(publisher, subs, event, kw);
3078
- if (topublish < 0) break;
3079
- else if (!topublish) continue;
3080
- }
3081
- let subscriber = kw_get_pointer(publisher, subs, "subscriber", null, kw_flag_t.KW_REQUIRED);
3082
- if (!(subscriber && !gobj_is_destroying(subscriber))) continue;
3083
- let subs_flag = kw_get_int(publisher, subs, "subs_flag", 0, kw_flag_t.KW_REQUIRED);
3084
- let event_ = kw_get_str(publisher, subs, "event", "", kw_flag_t.KW_REQUIRED);
3085
- if (empty_string(event_) || strcasecmp(event_, event) === 0) {
3086
- let __config__ = kw_get_dict(publisher, subs, "__config__", null, 0);
3087
- let __global__ = kw_get_dict(publisher, subs, "__global__", null, 0);
3088
- let __local__ = kw_get_dict(publisher, subs, "__local__", null, 0);
3089
- let __filter__ = kw_get_dict_value(publisher, subs, "__filter__", null, 0);
3090
- let event_name = subs.renamed_event;
3091
- if (empty_string(event_name)) event_name = event;
3092
- let topublish = 1;
3093
- if (publisher.gclass.gmt.mt_publication_filter) topublish = publisher.gclass.gmt.mt_publication_filter(publisher, event, kw, subscriber);
3094
- else if (json_size(__filter__) > 0) {
3095
- topublish = kw_match_simple(kw, __filter__) ? 1 : 0;
3501
+ const frame = push_dispatch_frame(publisher, event, frame_kind_t.FRAME_PUBLICATION);
3502
+ try {
3503
+ for (let idx = 0; idx < dl_subs.length; idx++) {
3504
+ let subs = dl_subs[idx];
3505
+ if (publisher.gclass.gmt.mt_publication_pre_filter) {
3506
+ let topublish = publisher.gclass.gmt.mt_publication_pre_filter(publisher, subs, event, kw);
3507
+ if (topublish < 0) break;
3508
+ else if (!topublish) continue;
3509
+ }
3510
+ let subscriber = kw_get_pointer(publisher, subs, "subscriber", null, kw_flag_t.KW_REQUIRED);
3511
+ if (!(subscriber && !gobj_is_destroying(subscriber))) continue;
3512
+ let subs_flag = kw_get_int(publisher, subs, "subs_flag", 0, kw_flag_t.KW_REQUIRED);
3513
+ let event_ = kw_get_str(publisher, subs, "event", "", kw_flag_t.KW_REQUIRED);
3514
+ if (empty_string(event_) || strcasecmp(event_, event) === 0) {
3515
+ let __config__ = kw_get_dict(publisher, subs, "__config__", null, 0);
3516
+ let __global__ = kw_get_dict(publisher, subs, "__global__", null, 0);
3517
+ let __local__ = kw_get_dict(publisher, subs, "__local__", null, 0);
3518
+ let __filter__ = kw_get_dict_value(publisher, subs, "__filter__", null, 0);
3519
+ let event_name = subs.renamed_event;
3520
+ if (empty_string(event_name)) event_name = event;
3521
+ let topublish = 1;
3522
+ if (publisher.gclass.gmt.mt_publication_filter) topublish = publisher.gclass.gmt.mt_publication_filter(publisher, event, kw, subscriber);
3523
+ else if (json_size(__filter__) > 0) {
3524
+ topublish = kw_match_simple(kw, __filter__) ? 1 : 0;
3525
+ if (tracea) {
3526
+ trace_machine(sprintf("💜💜🔄%s publishing with filter, event '%s', subscriber'%s', publisher %s", topublish ? "👍" : "👎", event ? event : "", gobj_short_name(subscriber), gobj_short_name(publisher)));
3527
+ trace_json(__filter__);
3528
+ }
3529
+ }
3530
+ if (topublish < 0) break;
3531
+ else if (!topublish) continue;
3532
+ let ev_ = gobj_event_type(subscriber, event, true);
3533
+ if (ev_) {
3534
+ if (ev_.event_flag & event_flag_t.EVF_SYSTEM_EVENT) {
3535
+ if (!gobj_has_event(subscriber, ev_.event_name, 0)) continue;
3536
+ }
3537
+ }
3538
+ let kw2publish = kw;
3539
+ if (json_size(__local__) > 0 || json_size(__global__) > 0) kw2publish = json_object_update({}, kw);
3540
+ if (json_size(__local__) > 0) kw_pop(kw2publish, __local__);
3541
+ if (__config__) {}
3542
+ if (json_size(__global__) > 0) json_object_update(kw2publish, json_deep_copy(__global__));
3096
3543
  if (tracea) {
3097
- trace_machine(sprintf("💜💜🔄%s publishing with filter, event '%s', subscriber'%s', publisher %s", topublish ? "👍" : "👎", event ? event : "", gobj_short_name(subscriber), gobj_short_name(publisher)));
3098
- trace_json(__filter__);
3544
+ if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔄 %s (%s) %s%s", event ? event : "", event_name ? event_name : "", !subscriber.running ? "!!" : "", gobj_short_name(subscriber)));
3545
+ 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)));
3546
+ if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish)) trace_json_masked(kw2publish);
3099
3547
  }
3100
- }
3101
- if (topublish < 0) break;
3102
- else if (!topublish) continue;
3103
- let ev_ = gobj_event_type(subscriber, event, true);
3104
- if (ev_) {
3105
- if (ev_.event_flag & event_flag_t.EVF_SYSTEM_EVENT) {
3106
- if (!gobj_has_event(subscriber, ev_.event_name, 0)) continue;
3548
+ let ret_ = gobj_send_event(subscriber, event_name, kw2publish, publisher);
3549
+ if (ret_ < 0 && subs_flag & subs_flag_t.__own_event__) {
3550
+ sent_count = -1;
3551
+ break;
3107
3552
  }
3553
+ ret += ret_;
3554
+ sent_count++;
3555
+ if (frame.destroyed || gobj_is_destroying(publisher)) break;
3108
3556
  }
3109
- let kw2publish = kw;
3110
- if (json_size(__local__) > 0 || json_size(__global__) > 0) kw2publish = json_object_update({}, kw);
3111
- if (json_size(__local__) > 0) kw_pop(kw2publish, __local__);
3112
- if (__config__) {}
3113
- if (json_size(__global__) > 0) json_object_update(kw2publish, json_deep_copy(__global__));
3114
- if (tracea) {
3115
- if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔄 %s (%s) %s%s", event ? event : "", event_name ? event_name : "", !subscriber.running ? "!!" : "", gobj_short_name(subscriber)));
3116
- 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)));
3117
- if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish)) trace_json_masked(kw2publish);
3118
- }
3119
- let ret_ = gobj_send_event(subscriber, event_name, kw2publish, publisher);
3120
- if (ret_ < 0 && subs_flag & subs_flag_t.__own_event__) {
3121
- sent_count = -1;
3122
- break;
3123
- }
3124
- ret += ret_;
3125
- sent_count++;
3126
- if (gobj_is_destroying(publisher)) break;
3127
3557
  }
3558
+ } finally {
3559
+ pop_dispatch_frame(frame);
3128
3560
  }
3129
- if (!sent_count) {
3561
+ if (!sent_count && !frame.destroyed) {
3130
3562
  if (!ev || !(ev.event_flag & event_flag_t.EVF_NO_WARN_SUBS)) log_warning(`${gobj_short_name(publisher)}: Publish event WITHOUT subscribers, ev ${event}`);
3131
3563
  }
3132
3564
  return ret;
@@ -3435,12 +3867,12 @@ var SECRET_NAME_JOINED = [
3435
3867
  "sessionkey",
3436
3868
  "authdata"
3437
3869
  ];
3438
- var SECRET_NAME_SEGMENTS = /* @__PURE__ */ new Set([
3870
+ var SECRET_NAME_SEGMENTS = [
3439
3871
  "pass",
3440
3872
  "pin",
3441
3873
  "otp"
3442
- ]);
3443
- var NOT_SECRET_SEGMENTS = /* @__PURE__ */ new Set([
3874
+ ];
3875
+ var NOT_SECRET_SEGMENTS = [
3444
3876
  "endpoint",
3445
3877
  "url",
3446
3878
  "uri",
@@ -3463,36 +3895,130 @@ var NOT_SECRET_SEGMENTS = /* @__PURE__ */ new Set([
3463
3895
  "expiry",
3464
3896
  "expires",
3465
3897
  "mode"
3466
- ]);
3898
+ ];
3899
+ function words_by_letter(list) {
3900
+ const by_letter = new Array(128).fill(null);
3901
+ for (const word of list) {
3902
+ const c = word.charCodeAt(0);
3903
+ if (!by_letter[c]) by_letter[c] = [];
3904
+ by_letter[c].push(word);
3905
+ }
3906
+ return by_letter;
3907
+ }
3908
+ var SECRET_PARTS_BY_LETTER = words_by_letter(SECRET_NAME_PARTS);
3909
+ var SECRET_JOINED_BY_LETTER = words_by_letter(SECRET_NAME_JOINED);
3910
+ var SECRET_SEGMENTS_BY_LETTER = words_by_letter(SECRET_NAME_SEGMENTS);
3911
+ var NOT_SECRET_BY_LETTER = words_by_letter(NOT_SECRET_SEGMENTS);
3912
+ function ascii_lower_code(code) {
3913
+ return code >= 65 && code <= 90 ? code + 32 : code;
3914
+ }
3915
+ function is_name_joiner_code(code) {
3916
+ return code === 95 || code === 45 || code === 46 || code === 32 || code === 9;
3917
+ }
3918
+ function name_segment_in(str, from, to, by_letter) {
3919
+ const n = to - from;
3920
+ if (n === 0) return false;
3921
+ const c0 = ascii_lower_code(str.charCodeAt(from));
3922
+ const words = c0 < 128 ? by_letter[c0] : null;
3923
+ if (!words) return false;
3924
+ for (let w = 0; w < words.length; w++) {
3925
+ const word = words[w];
3926
+ if (word.length !== n) continue;
3927
+ let i = 1;
3928
+ while (i < n && ascii_lower_code(str.charCodeAt(from + i)) === word.charCodeAt(i)) i++;
3929
+ if (i === n) return true;
3930
+ }
3931
+ return false;
3932
+ }
3933
+ function name_part_at(str, to, i, part, joined) {
3934
+ let j = i;
3935
+ let k = 0;
3936
+ while (k < part.length) {
3937
+ if (j >= to) return false;
3938
+ const code = str.charCodeAt(j);
3939
+ if (joined && k > 0 && is_name_joiner_code(code)) {
3940
+ j++;
3941
+ continue;
3942
+ }
3943
+ if (ascii_lower_code(code) !== part.charCodeAt(k)) return false;
3944
+ j++;
3945
+ k++;
3946
+ }
3947
+ return true;
3948
+ }
3949
+ function secret_name_check(str, from, to, about_wins, by_segments) {
3950
+ if (to - from < 3) return false;
3951
+ if (about_wins) {
3952
+ let seg = from;
3953
+ for (let i = from; i <= to; i++) {
3954
+ if (i < to && !is_name_joiner_code(str.charCodeAt(i))) continue;
3955
+ if (name_segment_in(str, seg, i, NOT_SECRET_BY_LETTER)) return false;
3956
+ seg = i + 1;
3957
+ }
3958
+ }
3959
+ if (by_segments) {
3960
+ let seg = from;
3961
+ for (let i = from; i <= to; i++) {
3962
+ if (i < to && is_ascii_alnum_code(str.charCodeAt(i))) continue;
3963
+ if (name_segment_in(str, seg, i, SECRET_SEGMENTS_BY_LETTER)) return true;
3964
+ seg = i + 1;
3965
+ }
3966
+ }
3967
+ let has_priv = false;
3968
+ let has_key = false;
3969
+ for (let i = from; i < to; i++) {
3970
+ const c = ascii_lower_code(str.charCodeAt(i));
3971
+ if (c >= 128) continue;
3972
+ const parts = SECRET_PARTS_BY_LETTER[c];
3973
+ for (let k = 0; parts && k < parts.length; k++) if (name_part_at(str, to, i, parts[k], false)) return true;
3974
+ const joined = SECRET_JOINED_BY_LETTER[c];
3975
+ for (let k = 0; joined && k < joined.length; k++) if (name_part_at(str, to, i, joined[k], true)) return true;
3976
+ if (c === 112 && !has_priv) has_priv = name_part_at(str, to, i, "priv", false);
3977
+ else if (c === 107 && !has_key) has_key = name_part_at(str, to, i, "key", false);
3978
+ }
3979
+ return has_priv && has_key;
3980
+ }
3467
3981
  /************************************************************
3468
3982
  * TRUE if `name` is the name of a secret: a password, a token,
3469
3983
  * a key... Any case. As the C kernel's is_secret_name().
3470
3984
  ************************************************************/
3471
3985
  function is_secret_name(name) {
3472
- if (typeof name !== "string" || name.length < 3) return false;
3473
- let lower = name.toLowerCase();
3474
- let hit = false;
3475
- for (const segment of lower.split(/[^a-z0-9]+/)) if (SECRET_NAME_SEGMENTS.has(segment)) {
3476
- hit = true;
3477
- break;
3478
- }
3479
- if (!hit) {
3480
- for (const part of SECRET_NAME_PARTS) if (lower.indexOf(part) >= 0) {
3481
- hit = true;
3482
- break;
3986
+ if (typeof name !== "string") return false;
3987
+ return secret_name_check(name, 0, name.length, true, true);
3988
+ }
3989
+ var NAMES_NOW = 0;
3990
+ var NAMES_7_26_9 = 1;
3991
+ function is_secret_name_tail(str, from, to, names) {
3992
+ const by_segments = names === NAMES_NOW;
3993
+ if ((to - from) * 3 <= MASK_MAX_NAME) return secret_name_check(str, from, to, true, by_segments);
3994
+ let bytes = 0;
3995
+ let i = to;
3996
+ let partial = false;
3997
+ while (i > from) {
3998
+ const code = str.charCodeAt(i - 1);
3999
+ let n = 3;
4000
+ let units = 1;
4001
+ if (code < 128) n = 1;
4002
+ else if (code < 2048) n = 2;
4003
+ else if (code >= 56320 && code <= 57343 && i - 2 >= from) {
4004
+ const high = str.charCodeAt(i - 2);
4005
+ if (high >= 55296 && high <= 56319) {
4006
+ n = 4;
4007
+ units = 2;
4008
+ }
3483
4009
  }
3484
- }
3485
- if (!hit) {
3486
- let joined = lower.replace(/[_\-. \t]/g, "");
3487
- for (const part of SECRET_NAME_JOINED) if (joined.indexOf(part) >= 0) {
3488
- hit = true;
4010
+ if (bytes + n > MASK_MAX_NAME) {
4011
+ partial = bytes < MASK_MAX_NAME;
3489
4012
  break;
3490
4013
  }
4014
+ bytes += n;
4015
+ i -= units;
3491
4016
  }
3492
- if (!hit) hit = lower.indexOf("priv") >= 0 && lower.indexOf("key") >= 0;
3493
- if (!hit) return false;
3494
- for (const segment of lower.split(/[_\-. \t]/)) if (NOT_SECRET_SEGMENTS.has(segment)) return false;
3495
- return true;
4017
+ if (partial) {
4018
+ const name = "€" + str.substring(i, to);
4019
+ return secret_name_check(name, 0, name.length, true, by_segments);
4020
+ }
4021
+ return secret_name_check(str, i, to, true, by_segments);
3496
4022
  }
3497
4023
  /************************************************************
3498
4024
  * Where an unquoted secret value that begins at `p` ends: at
@@ -3520,77 +4046,255 @@ function inline_secret_value_end(str, p, outer) {
3520
4046
  }
3521
4047
  /************************************************************
3522
4048
  * A credential by its SHAPE, whatever names it -- the C kernel's
3523
- * jwt_len() / bearer_token_len(), the shapes the agent's audit
3524
- * record redacts:
3525
- * - a JWT: "eyJ" (the base64url of '{"') at the start of a
3526
- * word, and three parts of base64url joined by '.'; the dots
3527
- * at the end of the run are not its own (a JWT ends a
3528
- * sentence: "... eyJ.eyJ.sig.");
3529
- * - the token after "Bearer " (any case, a word of its own).
3530
- ************************************************************/
4049
+ * jwt_len() / scheme_credential(), the shapes the agent's audit
4050
+ * record redacts, and the schemes of an HTTP Authorization:
4051
+ * - a JWT or a JWE: "eyJ" (the base64url of '{"') at the start
4052
+ * of a word, base64url, and a '.' of its own after it -- three
4053
+ * parts joined by '.' (a JWS), five (a JWE), or fewer when a cap
4054
+ * cut it; the dots at the end of the run are not its own (a JWT
4055
+ * ends a sentence: "... eyJ.eyJ.sig."), so a run whose only
4056
+ * dots end it is a header and no JWT ("eyJhIjoxfQ.");
4057
+ * - the credential after the scheme word "Bearer" or "Basic"
4058
+ * (any case, a word of its own): scheme_credential().
4059
+ ************************************************************/
4060
+ var MASK_TOKEN_MIN = 8;
4061
+ var MASK_PROSE_MAX = 24;
3531
4062
  function is_ascii_alnum_code(code) {
3532
4063
  return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
3533
4064
  }
4065
+ function is_ascii_letter_code(code) {
4066
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122;
4067
+ }
4068
+ function is_ascii_upper_code(code) {
4069
+ return code >= 65 && code <= 90;
4070
+ }
3534
4071
  function is_base64url_code(code) {
3535
4072
  return is_ascii_alnum_code(code) || code === 45 || code === 95;
3536
4073
  }
4074
+ function ascii_case_equal(str, p, word) {
4075
+ if (str.length - p < word.length) return false;
4076
+ for (let i = 0; i < word.length; i++) {
4077
+ let code = str.charCodeAt(p + i);
4078
+ if (code >= 65 && code <= 90) code += 32;
4079
+ if (code !== word.charCodeAt(i)) return false;
4080
+ }
4081
+ return true;
4082
+ }
3537
4083
  function jwt_len(str, p) {
3538
4084
  if (str.length - p < 3 || str[p] !== "e" || str[p + 1] !== "y" || str[p + 2] !== "J") return 0;
3539
4085
  if (p > 0 && (is_base64url_code(str.charCodeAt(p - 1)) || str[p - 1] === ".")) return 0;
3540
4086
  let e = p;
3541
- let dots = 0;
4087
+ let dotted = false;
3542
4088
  while (e < str.length && (is_base64url_code(str.charCodeAt(e)) || str[e] === ".")) {
3543
- if (str[e] === ".") dots++;
4089
+ if (e > p && str[e] !== "." && str[e - 1] === ".") dotted = true;
3544
4090
  e++;
3545
4091
  }
3546
- while (str[e - 1] === ".") {
3547
- e--;
3548
- dots--;
4092
+ if (!dotted) return 0;
4093
+ while (str[e - 1] === ".") e--;
4094
+ return e - p;
4095
+ }
4096
+ function scheme_word_len(str, p) {
4097
+ if (p > 0 && is_ascii_alnum_code(str.charCodeAt(p - 1))) return 0;
4098
+ for (const scheme of ["bearer", "basic"]) {
4099
+ const n = scheme.length;
4100
+ if (str.length - p > n && ascii_case_equal(str, p, scheme) && (str[p + n] === " " || str[p + n] === " ")) return n;
4101
+ }
4102
+ return 0;
4103
+ }
4104
+ function code_points(str, w, n) {
4105
+ let count = 0;
4106
+ for (let i = w; i < w + n; i++) {
4107
+ const code = str.charCodeAt(i);
4108
+ if (code < 56320 || code > 57343) count++;
4109
+ }
4110
+ return count;
4111
+ }
4112
+ function is_prose_word(str, w, n) {
4113
+ if (n === 0 || n >= MASK_PROSE_MAX) return false;
4114
+ let i = w;
4115
+ const end = w + n;
4116
+ while (true) {
4117
+ let r = i;
4118
+ let upper_rest = true;
4119
+ let lower_rest = true;
4120
+ while (r < end && is_ascii_letter_code(str.charCodeAt(r))) {
4121
+ if (r > i) {
4122
+ if (is_ascii_upper_code(str.charCodeAt(r))) lower_rest = false;
4123
+ else upper_rest = false;
4124
+ }
4125
+ r++;
4126
+ }
4127
+ if (r === i) return false;
4128
+ if (!lower_rest && !(upper_rest && is_ascii_upper_code(str.charCodeAt(i)))) return false;
4129
+ if (r === end) return true;
4130
+ if (str[r] !== "-" && str[r] !== "." && str[r] !== "/" || r + 1 === end) return false;
4131
+ i = r + 1;
4132
+ }
4133
+ }
4134
+ function base64_digit(code) {
4135
+ if (code >= 65 && code <= 90) return code - 65;
4136
+ if (code >= 97 && code <= 122) return code - 97 + 26;
4137
+ if (code >= 48 && code <= 57) return code - 48 + 52;
4138
+ if (code === 43) return 62;
4139
+ if (code === 47) return 63;
4140
+ return -1;
4141
+ }
4142
+ function is_basic_credential(str, w, n) {
4143
+ let bits = 0;
4144
+ let n_bits = 0;
4145
+ for (let i = 0; i < n; i++) {
4146
+ const v = base64_digit(str.charCodeAt(w + i));
4147
+ if (v < 0) return false;
4148
+ bits = (bits << 6 | v) & 16383;
4149
+ n_bits += 6;
4150
+ if (n_bits >= 8) {
4151
+ n_bits -= 8;
4152
+ if ((bits >> n_bits & 255) === 58) return true;
4153
+ }
3549
4154
  }
3550
- return dots === 2 ? e - p : 0;
4155
+ return false;
3551
4156
  }
3552
- var BEARER_STOPS = " \r\n'\",;}]\0";
3553
- function bearer_token(str, p) {
3554
- const word_len = 6;
3555
- if (str.length - p <= word_len || str.slice(p, p + word_len).toLowerCase() !== "bearer") return [0, 0];
3556
- if (p > 0 && is_ascii_alnum_code(str.charCodeAt(p - 1))) return [0, 0];
3557
- let t = p + word_len;
3558
- if (str[t] !== " " && str[t] !== " ") return [0, 0];
4157
+ var SCHEME_WORD_STOPS = " \r\n\"',;}]\0";
4158
+ function scheme_credential(str, p) {
4159
+ const n = scheme_word_len(str, p);
4160
+ if (!n) return [0, 0];
4161
+ const scheme = n === 5 ? "basic" : "bearer";
4162
+ let context = false;
4163
+ let t = p + n;
3559
4164
  while (t < str.length && (str[t] === " " || str[t] === " ")) t++;
4165
+ if (t < str.length && scheme_word_len(str, t) === n && ascii_case_equal(str, t, scheme)) {
4166
+ t += n;
4167
+ context = true;
4168
+ while (t < str.length && (str[t] === " " || str[t] === " ")) t++;
4169
+ }
4170
+ if (t >= str.length) return [0, 0];
4171
+ if (str[t] === "\"" || str[t] === "'") {
4172
+ let q = t + 1;
4173
+ while (q < str.length && str[q] !== str[t] && str[q] !== " " && str[q] !== " " && str[q] !== "\r" && str[q] !== "\n" && str[q] !== "\0") q++;
4174
+ if (q < str.length && str[q] === str[t] && q > t + 1) return [t - p, q + 1 - t];
4175
+ return [0, 0];
4176
+ }
3560
4177
  let e = t;
3561
- while (e < str.length && BEARER_STOPS.indexOf(str[e]) < 0) e++;
4178
+ while (e < str.length && SCHEME_WORD_STOPS.indexOf(str[e]) < 0) e++;
4179
+ if (e === t) return [0, 0];
4180
+ if (!context) {
4181
+ let w_end = e;
4182
+ while (w_end > t && str[w_end - 1] === ".") w_end--;
4183
+ const len = w_end - t;
4184
+ if (len === 0 || is_prose_word(str, t, len)) return [0, 0];
4185
+ if (n === 5) {
4186
+ if (!is_basic_credential(str, t, len)) return [0, 0];
4187
+ } else if (code_points(str, t, len) < MASK_TOKEN_MIN) return [0, 0];
4188
+ }
3562
4189
  return [t - p, e - t];
3563
4190
  }
3564
- /************************************************************
3565
- * A text (a command line) with the value of every "name=value"
3566
- * whose name is a secret's written as "********", quoted or not
3567
- * (and the "value" of a write-attr whose attribute names a
3568
- * secret); and a JWT or the token after "Bearer ", wherever they
3569
- * are, whatever names them. The rest as it is. Return null when
3570
- * there was nothing to mask. As the C kernel's
3571
- * mask_secrets_inline().
3572
- ************************************************************/
4191
+ function shape_len(str, p) {
4192
+ const c = str[p];
4193
+ if (c === "e") return [0, jwt_len(str, p)];
4194
+ if (c === "b" || c === "B") return scheme_credential(str, p);
4195
+ return [0, 0];
4196
+ }
4197
+ function shape_len_js_7_26_20(str, p) {
4198
+ const c = str[p];
4199
+ if (c === "e") {
4200
+ if (str.length - p < 3 || str[p + 1] !== "y" || str[p + 2] !== "J") return [0, 0];
4201
+ if (p > 0 && (is_base64url_code(str.charCodeAt(p - 1)) || str[p - 1] === ".")) return [0, 0];
4202
+ let e = p;
4203
+ let dots = 0;
4204
+ while (e < str.length && (is_base64url_code(str.charCodeAt(e)) || str[e] === ".")) {
4205
+ if (str[e] === ".") dots++;
4206
+ e++;
4207
+ }
4208
+ while (str[e - 1] === ".") {
4209
+ e--;
4210
+ dots--;
4211
+ }
4212
+ return dots === 2 ? [0, e - p] : [0, 0];
4213
+ }
4214
+ if (c === "b" || c === "B") {
4215
+ if (str.length - p <= 6 || !ascii_case_equal(str, p, "bearer")) return [0, 0];
4216
+ if (p > 0 && is_ascii_alnum_code(str.charCodeAt(p - 1))) return [0, 0];
4217
+ let t = p + 6;
4218
+ if (str[t] !== " " && str[t] !== " ") return [0, 0];
4219
+ while (t < str.length && (str[t] === " " || str[t] === " ")) t++;
4220
+ let e = t;
4221
+ while (e < str.length && " \r\n'\",;}]\0".indexOf(str[e]) < 0) e++;
4222
+ return [t - p, e - t];
4223
+ }
4224
+ return [0, 0];
4225
+ }
4226
+ var COLON_VALUE_STOPS = " \r\n,;&)]}<>\"'\0";
4227
+ function colon_value_end(str, v) {
4228
+ if (v >= str.length) return v;
4229
+ const c = str[v];
4230
+ if (c === "\"" || c === "'") {
4231
+ let e = v + 1;
4232
+ while (e < str.length && str[e] !== c) {
4233
+ if (str[e] === "\\" && e + 1 < str.length) e++;
4234
+ e++;
4235
+ }
4236
+ return e < str.length ? e + 1 : str.length;
4237
+ }
4238
+ if (c === "{" || c === "[") {
4239
+ let depth = 0;
4240
+ let in_string = false;
4241
+ for (let e = v; e < str.length; e++) if (in_string) {
4242
+ if (str[e] === "\\" && e + 1 < str.length) e++;
4243
+ else if (str[e] === "\"") in_string = false;
4244
+ } else if (str[e] === "\"") in_string = true;
4245
+ else if (str[e] === "{" || str[e] === "[") depth++;
4246
+ else if (str[e] === "}" || str[e] === "]") {
4247
+ depth--;
4248
+ if (depth === 0) return e + 1;
4249
+ }
4250
+ return str.length;
4251
+ }
4252
+ if (c === "\\") {
4253
+ let q = v;
4254
+ while (q < str.length && str[q] === "\\") q++;
4255
+ if (q < str.length && (str[q] === "\"" || str[q] === "'")) {
4256
+ const level = q - v;
4257
+ let run = 0;
4258
+ for (let e = q + 1; e < str.length; e++) {
4259
+ if (str[e] === "\\") {
4260
+ run++;
4261
+ continue;
4262
+ }
4263
+ if (str[e] === str[q] && run === level) return e + 1;
4264
+ run = 0;
4265
+ }
4266
+ return str.length;
4267
+ }
4268
+ }
4269
+ let e = v;
4270
+ const n = scheme_word_len(str, v);
4271
+ if (n) {
4272
+ e = v + n;
4273
+ while (e < str.length && (str[e] === " " || str[e] === " ")) e++;
4274
+ if (e < str.length && (str[e] === "\"" || str[e] === "'")) return colon_value_end(str, e);
4275
+ }
4276
+ while (e < str.length && COLON_VALUE_STOPS.indexOf(str[e]) < 0) e++;
4277
+ return e;
4278
+ }
3573
4279
  var MASK_MAX_NAME = 128;
3574
4280
  var MASK_MAX_BYTES = 4194304;
3575
4281
  var MASK_TOO_LARGE = "<not shown: too large to mask>";
3576
- function mask_secrets_inline(str) {
3577
- if (typeof str !== "string") return null;
3578
- if (str.indexOf("=") < 0 && str.indexOf("eyJ") < 0 && !/bearer/i.test(str)) return null;
3579
- if (str.length > MASK_MAX_BYTES) return MASK_TOO_LARGE;
3580
- let value_is_secret = false;
3581
- let re_attr = /(^|[ \t])attribute=["']?([^ \t"']*)/g;
3582
- let m;
3583
- while ((m = re_attr.exec(str)) !== null) if (is_secret_name(m[2].slice(-128))) value_is_secret = true;
3584
- let parts = [];
3585
- let copied = 0;
3586
- let changed = false;
4282
+ function mark_range(marks, from, to) {
4283
+ for (let i = from; i < to; i++) marks[i] = 1;
4284
+ }
4285
+ var READ_NOW = 0;
4286
+ var READ_AS_GOBJ_JS_7_26_20 = 1;
4287
+ var READ_AS_7_26_9 = 2;
4288
+ function mark_params(str, value_is_secret, reading, marks, judged) {
4289
+ const names = reading === READ_AS_7_26_9 ? NAMES_7_26_9 : NAMES_NOW;
4290
+ let not_7_26_9 = false;
4291
+ const is_blank_or_end = (i) => i >= str.length || str[i] === " " || str[i] === " " || str[i] === "\0";
3587
4292
  let outer = "";
3588
4293
  let word = 0;
3589
4294
  let p = 0;
3590
- const is_blank_or_end = (i) => i >= str.length || str[i] === " " || str[i] === " ";
3591
4295
  while (p < str.length) {
3592
- let c = str[p];
3593
- if (c === " " || c === " ") {
4296
+ const c = str[p];
4297
+ if (c === " " || c === " " || c === "\0") {
3594
4298
  p++;
3595
4299
  word = p;
3596
4300
  continue;
@@ -3599,48 +4303,205 @@ function mask_secrets_inline(str) {
3599
4303
  if (!outer && (p === 0 || str[p - 1] === " " || str[p - 1] === " " || str[p - 1] === "=")) outer = c;
3600
4304
  else if (c === outer && is_blank_or_end(p + 1)) outer = "";
3601
4305
  }
3602
- let shape = c === "e" ? jwt_len(str, p) : 0;
3603
- let token_offset = 0;
3604
- if (c === "b" || c === "B") [token_offset, shape] = bearer_token(str, p);
3605
- if (shape) {
3606
- parts.push(str.substring(copied, p + token_offset));
3607
- parts.push("********");
3608
- p += token_offset + shape;
3609
- copied = p;
3610
- changed = true;
3611
- word = p;
3612
- continue;
4306
+ if (reading === READ_AS_GOBJ_JS_7_26_20 && (c === "e" || c === "b" || c === "B")) {
4307
+ const [offset, n] = shape_len_js_7_26_20(str, p);
4308
+ if (n) {
4309
+ p += offset + n;
4310
+ word = p;
4311
+ continue;
4312
+ }
3613
4313
  }
3614
4314
  if (c !== "=") {
3615
4315
  p++;
3616
4316
  continue;
3617
4317
  }
3618
- let name = str.substring(Math.max(word, p - MASK_MAX_NAME), p);
4318
+ const name_from = word;
3619
4319
  word = p + 1;
3620
- if (!(is_secret_name(name) || value_is_secret && name.toLowerCase() === "value")) {
4320
+ const secret = is_secret_name_tail(str, name_from, p, names);
4321
+ if (secret && names === NAMES_NOW && !is_secret_name_tail(str, name_from, p, NAMES_7_26_9)) not_7_26_9 = true;
4322
+ if (!(secret || value_is_secret && p - name_from === 5 && ascii_case_equal(str, name_from, "value"))) {
4323
+ if (judged && query_name_from(str, p) === name_from) judged[p] = 1;
3621
4324
  p++;
3622
4325
  continue;
3623
4326
  }
3624
4327
  p++;
3625
- let quote = str[p] === "\"" || str[p] === "'" ? str[p] : "";
3626
4328
  let end;
4329
+ const quote = p < str.length && (str[p] === "\"" || str[p] === "'") ? str[p] : "";
3627
4330
  if (quote) {
3628
4331
  end = p + 1;
3629
- while (end < str.length && str[end] !== quote) end++;
3630
- if (str[end] === quote) end++;
4332
+ while (end < str.length && str[end] !== quote && str[end] !== "\0") end++;
4333
+ if (end < str.length && str[end] === quote) end++;
3631
4334
  } else end = inline_secret_value_end(str, p, outer);
3632
- if (end > p) {
3633
- parts.push(str.substring(copied, p));
4335
+ mark_range(marks, p, end);
4336
+ p = end;
4337
+ word = p;
4338
+ }
4339
+ return not_7_26_9;
4340
+ }
4341
+ function has_shape_js_7_26_20(str) {
4342
+ for (let p = 0; p < str.length; p++) {
4343
+ const code = str.charCodeAt(p);
4344
+ if ((code === 101 || code === 98 || code === 66) && shape_len_js_7_26_20(str, p)[1]) return true;
4345
+ }
4346
+ return false;
4347
+ }
4348
+ function stop_table(chars) {
4349
+ const table = /* @__PURE__ */ new Uint8Array(128);
4350
+ for (const c of chars + "\r\n\0") table[c.charCodeAt(0)] = 1;
4351
+ return table;
4352
+ }
4353
+ var PARAM_VALUE_STOPS = stop_table("&; ,\"'<>");
4354
+ var QUOTE_STOPS = {
4355
+ "\"": stop_table("\""),
4356
+ "'": stop_table("'")
4357
+ };
4358
+ function mark_run(str, p, stops, marks) {
4359
+ let e = p;
4360
+ while (e < str.length) {
4361
+ const code = str.charCodeAt(e);
4362
+ if (code < 128 && stops[code]) break;
4363
+ e++;
4364
+ }
4365
+ mark_range(marks, p, e);
4366
+ return e;
4367
+ }
4368
+ function mark_scheme_value(str, v, stops, marks) {
4369
+ const n = scheme_word_len(str, v);
4370
+ if (!n) return -1;
4371
+ let w = v + n;
4372
+ while (w < str.length && (str[w] === " " || str[w] === " ")) w++;
4373
+ mark_range(marks, v, w);
4374
+ if (w < str.length && (str[w] === "\"" || str[w] === "'")) {
4375
+ const e = colon_value_end(str, w);
4376
+ mark_range(marks, w, e);
4377
+ return e;
4378
+ }
4379
+ return mark_run(str, w, stops, marks);
4380
+ }
4381
+ function is_name_char_code(code) {
4382
+ return is_ascii_alnum_code(code) || code === 95 || code === 45 || code === 46;
4383
+ }
4384
+ function query_name_from(str, eq) {
4385
+ let n = eq;
4386
+ while (n > 0 && eq - n < MASK_MAX_NAME && is_name_char_code(str.charCodeAt(n - 1))) n--;
4387
+ return n;
4388
+ }
4389
+ function mark_query_params(str, marks, judged) {
4390
+ let frontier = 0;
4391
+ for (let p = 1; p < str.length; p++) {
4392
+ if (p < frontier) {
4393
+ p = frontier - 1;
4394
+ continue;
4395
+ }
4396
+ if (str.charCodeAt(p) !== 61) continue;
4397
+ if (judged[p]) continue;
4398
+ const n = query_name_from(str, p);
4399
+ if (n === p || !secret_name_check(str, n, p, true, true)) continue;
4400
+ const v = p + 1;
4401
+ if (v < str.length && (str[v] === "\"" || str[v] === "'")) frontier = mark_run(str, v + 1, QUOTE_STOPS[str[v]], marks);
4402
+ else {
4403
+ mark_scheme_value(str, v, PARAM_VALUE_STOPS, marks);
4404
+ frontier = mark_run(str, v, PARAM_VALUE_STOPS, marks);
4405
+ }
4406
+ }
4407
+ }
4408
+ function mark_shapes(str, marks) {
4409
+ for (let p = 0; p < str.length; p++) {
4410
+ const code = str.charCodeAt(p);
4411
+ if (code !== 101 && code !== 98 && code !== 66) continue;
4412
+ const [offset, n] = shape_len(str, p);
4413
+ if (n) mark_range(marks, p + offset, p + offset + n);
4414
+ }
4415
+ }
4416
+ function mark_labels(str, marks) {
4417
+ let word = 0;
4418
+ let p = 0;
4419
+ while (p < str.length) {
4420
+ const code = str.charCodeAt(p);
4421
+ if (code === 32 || code === 9 || code === 0 || code === 61) {
4422
+ p++;
4423
+ word = p;
4424
+ continue;
4425
+ }
4426
+ if (code !== 58) {
4427
+ p++;
4428
+ continue;
4429
+ }
4430
+ if (!is_secret_name_tail(str, word, p, NAMES_NOW)) {
4431
+ p++;
4432
+ word = p;
4433
+ continue;
4434
+ }
4435
+ let v = p + 1;
4436
+ while (v < str.length && (str[v] === " " || str[v] === " ")) v++;
4437
+ const e = colon_value_end(str, v);
4438
+ mark_range(marks, v, e);
4439
+ const n_scheme = scheme_word_len(str, v);
4440
+ if (n_scheme) p = v + n_scheme;
4441
+ else p = e > v ? e : p + 1;
4442
+ word = p;
4443
+ }
4444
+ }
4445
+ function inline_value_is_secret(str, names) {
4446
+ let p = str.indexOf("attribute=");
4447
+ while (p >= 0) {
4448
+ if (p === 0 || str[p - 1] === " " || str[p - 1] === " ") {
4449
+ let v = p + 10;
4450
+ if (v < str.length && (str[v] === "\"" || str[v] === "'")) v++;
4451
+ let e = v;
4452
+ while (e < str.length && " \"'\0".indexOf(str[e]) < 0) e++;
4453
+ if (is_secret_name_tail(str, v, e, names)) return true;
4454
+ }
4455
+ p = str.indexOf("attribute=", p + 1);
4456
+ }
4457
+ return false;
4458
+ }
4459
+ function mark_inline_secrets(str, marks) {
4460
+ const value_is_secret = inline_value_is_secret(str, NAMES_NOW);
4461
+ const value_is_secret_7_26_9 = inline_value_is_secret(str, NAMES_7_26_9);
4462
+ const judged = new Uint8Array(str.length);
4463
+ if (mark_params(str, value_is_secret, READ_NOW, marks, judged) || value_is_secret !== value_is_secret_7_26_9) mark_params(str, value_is_secret_7_26_9, READ_AS_7_26_9, marks, null);
4464
+ if (has_shape_js_7_26_20(str)) mark_params(str, value_is_secret, READ_AS_GOBJ_JS_7_26_20, marks, null);
4465
+ mark_query_params(str, marks, judged);
4466
+ mark_shapes(str, marks);
4467
+ mark_labels(str, marks);
4468
+ }
4469
+ /************************************************************
4470
+ * A text (a command line) with the secrets that can be told
4471
+ * written as "********" (each run of them as one), the rest as it
4472
+ * is: the value of every "name=value" whose name is a secret's,
4473
+ * quoted or not (and the "value" of a write-attr whose attribute
4474
+ * names a secret) -- the name is the word before the '=', and also
4475
+ * the run of name characters before it, as in a query string; the
4476
+ * same for a "name: value", its name in quotes or not (a json, a
4477
+ * header, a label: "password": x, Authorization: Basic x, bearer:
4478
+ * tok); and a JWT or the credential after "Bearer " or "Basic ",
4479
+ * wherever they are, whatever names them. Each rule judges the text
4480
+ * as it came. Return null when there was nothing to mask. As the C
4481
+ * kernel's mask_secrets_inline().
4482
+ ************************************************************/
4483
+ function mask_secrets_inline(str) {
4484
+ if (typeof str !== "string") return null;
4485
+ if (str.indexOf("=") < 0 && str.indexOf(":") < 0 && str.indexOf("eyJ") < 0 && !/bearer|basic/i.test(str)) return null;
4486
+ if (str.length > MASK_MAX_BYTES) return MASK_TOO_LARGE;
4487
+ const marks = new Uint8Array(str.length);
4488
+ mark_inline_secrets(str, marks);
4489
+ let parts = [];
4490
+ let changed = false;
4491
+ let i = 0;
4492
+ while (i < str.length) {
4493
+ let j = i;
4494
+ if (marks[i]) {
4495
+ while (j < str.length && marks[j]) j++;
3634
4496
  parts.push("********");
3635
- copied = end;
3636
4497
  changed = true;
4498
+ } else {
4499
+ while (j < str.length && !marks[j]) j++;
4500
+ parts.push(str.substring(i, j));
3637
4501
  }
3638
- p = end;
3639
- word = p;
4502
+ i = j;
3640
4503
  }
3641
- if (!changed) return null;
3642
- parts.push(str.substring(copied));
3643
- return parts.join("");
4504
+ return changed ? parts.join("") : null;
3644
4505
  }
3645
4506
  /************************************************************
3646
4507
  * A json as a log or a trace may show it: at any depth, the
@@ -3708,7 +4569,12 @@ function _json_mask_secrets(jn, memo, depth, budget) {
3708
4569
  if (truncated) result.push(MASK_TOO_LARGE);
3709
4570
  } else {
3710
4571
  result = Object.create(Object.getPrototypeOf(jn));
3711
- let value_is_secret = typeof jn.attribute === "string" && is_secret_name(jn.attribute.slice(-128));
4572
+ let value_is_secret = false;
4573
+ if (typeof jn.attribute === "string") {
4574
+ let nul = jn.attribute.indexOf("\0");
4575
+ let attribute = nul >= 0 ? jn.attribute.substring(0, nul) : jn.attribute;
4576
+ value_is_secret = is_secret_name_tail(attribute, 0, attribute.length, NAMES_NOW);
4577
+ }
3712
4578
  for (const key in jn) {
3713
4579
  if (!Object.prototype.hasOwnProperty.call(jn, key)) continue;
3714
4580
  if (budget.left <= 0) {
@@ -3718,7 +4584,7 @@ function _json_mask_secrets(jn, memo, depth, budget) {
3718
4584
  budget.left -= 1 + key.length;
3719
4585
  let value = jn[key];
3720
4586
  let shown;
3721
- if ((is_secret_name(key.slice(-128)) || value_is_secret && key === "value") && value !== void 0 && value !== null && value !== "") shown = "********";
4587
+ if ((is_secret_name_tail(key, 0, key.length, NAMES_NOW) || value_is_secret && key === "value") && value !== void 0 && value !== null && value !== "") shown = "********";
3722
4588
  else shown = _json_mask_secrets(value, memo, depth + 1, budget);
3723
4589
  if (shown !== value) changed = true;
3724
4590
  set_own_key(result, key, shown);
@@ -6867,8 +7733,12 @@ var __gclass__$2 = null;
6867
7733
  ***************************************************************/
6868
7734
  function mt_create$2(gobj) {
6869
7735
  let priv = gobj.priv;
6870
- const subscriber = gobj_read_pointer_attr(gobj, "subscriber");
7736
+ let subscriber = gobj_read_pointer_attr(gobj, "subscriber");
6871
7737
  if (subscriber) gobj_subscribe_event(gobj, null, {}, subscriber);
7738
+ else if (gobj_is_pure_child(gobj)) {
7739
+ subscriber = gobj_parent(gobj);
7740
+ gobj_subscribe_event(gobj, null, {}, subscriber);
7741
+ }
6872
7742
  priv.periodic = gobj_read_bool_attr(gobj, "periodic");
6873
7743
  priv.msec = gobj_read_integer_attr(gobj, "msec");
6874
7744
  }
@@ -6925,8 +7795,7 @@ function ac_timeout$1(gobj, event, kw, src) {
6925
7795
  gobj_send_event(gobj, "EV_TIMEOUT", {}, gobj);
6926
7796
  }, priv.msec);
6927
7797
  else priv.timer_id = -1;
6928
- if (gobj_is_pure_child(gobj)) gobj_send_event(gobj_parent(gobj), ev, {}, gobj);
6929
- else gobj_publish_event(gobj, ev, {});
7798
+ gobj_publish_event(gobj, ev, {});
6930
7799
  if (!priv.periodic && priv.timer_id === -1) {
6931
7800
  if (gobj_is_running(gobj)) gobj_stop(gobj);
6932
7801
  }
@@ -6973,6 +7842,15 @@ function register_c_timer() {
6973
7842
  * Helpers
6974
7843
  ***************************/
6975
7844
  /***************************************************************************
7845
+ * A number of milliseconds as the integer `msec` holds it: C takes an
7846
+ * integer, and a time computed in JS can carry a float error (0.3 * 1000
7847
+ * is 300.00000000000006, which an integer attr refuses). Anything that is
7848
+ * not a number goes as it is, to be refused loudly by the attr.
7849
+ ***************************************************************************/
7850
+ function whole_msec(msec) {
7851
+ return typeof msec === "number" && Number.isFinite(msec) ? Math.round(msec) : msec;
7852
+ }
7853
+ /***************************************************************************
6976
7854
  * Set timeout
6977
7855
  ***************************************************************************/
6978
7856
  function set_timeout(gobj, msec) {
@@ -6985,7 +7863,7 @@ function set_timeout(gobj, msec) {
6985
7863
  return -1;
6986
7864
  }
6987
7865
  gobj_write_bool_attr(gobj, "periodic", false);
6988
- gobj_write_integer_attr(gobj, "msec", msec);
7866
+ gobj_write_integer_attr(gobj, "msec", whole_msec(msec));
6989
7867
  }
6990
7868
  /***************************************************************************
6991
7869
  * Set periodic timeout
@@ -7000,7 +7878,7 @@ function set_timeout_periodic(gobj, msec) {
7000
7878
  return -1;
7001
7879
  }
7002
7880
  gobj_write_bool_attr(gobj, "periodic", true);
7003
- gobj_write_integer_attr(gobj, "msec", msec);
7881
+ gobj_write_integer_attr(gobj, "msec", whole_msec(msec));
7004
7882
  }
7005
7883
  /***************************************************************************
7006
7884
  * Clear timeout
@@ -7387,8 +8265,12 @@ function mt_create(gobj) {
7387
8265
  gobj_write_str_attr(gobj, "wanted_yuno_name", priv.remote_yuno_name);
7388
8266
  gobj_write_str_attr(gobj, "wanted_yuno_role", priv.remote_yuno_role);
7389
8267
  gobj_write_str_attr(gobj, "wanted_yuno_service", priv.remote_yuno_service);
7390
- const subscriber = gobj_read_pointer_attr(gobj, "subscriber");
8268
+ let subscriber = gobj_read_pointer_attr(gobj, "subscriber");
7391
8269
  if (subscriber) gobj_subscribe_event(gobj, null, {}, subscriber);
8270
+ else if (gobj_is_pure_child(gobj)) {
8271
+ subscriber = gobj_parent(gobj);
8272
+ gobj_subscribe_event(gobj, null, {}, subscriber);
8273
+ }
7392
8274
  }
7393
8275
  /***************************************************************
7394
8276
  * Framework Method: Writing
@@ -7613,6 +8495,27 @@ function close_websocket(gobj, code = 1e3, reason = "") {
7613
8495
  }
7614
8496
  }
7615
8497
  /***************************************************************
8498
+ * A text of the server -- a frame, the name of an event, of a
8499
+ * service, of a role -- as a log shows it: masked, then capped on a
8500
+ * whole character (capped first, a credential the cap cut would
8501
+ * show its first characters). As the C kernel shows the name of an
8502
+ * event that is not public (mask_secrets_inline_capped()).
8503
+ ***************************************************************/
8504
+ var PEER_NAME_SHOWN = 64;
8505
+ var PEER_FRAME_SHOWN = 256;
8506
+ function peer_text_shown(text, max) {
8507
+ let s = String(text);
8508
+ let masked = mask_secrets_inline(s);
8509
+ if (masked !== null) s = masked;
8510
+ if (s.length > max) {
8511
+ let n = max;
8512
+ let code = s.charCodeAt(n);
8513
+ if (code >= 56320 && code <= 57343) n--;
8514
+ s = s.substring(0, n);
8515
+ }
8516
+ return s;
8517
+ }
8518
+ /***************************************************************
7616
8519
  * Trace intra event
7617
8520
  ***************************************************************/
7618
8521
  function trace_inter_event(gobj, prefix, iev) {
@@ -7735,7 +8638,8 @@ function iev_create_from_json(gobj, data) {
7735
8638
  try {
7736
8639
  x = JSON.parse(data);
7737
8640
  } catch (e) {
7738
- log_warning(`${gobj_short_name(gobj)}: parsing inter_event json: ${e}`);
8641
+ let at = /position (\d+)/.exec(String(e && e.message));
8642
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event json: frame is not json${at ? ", at position " + at[1] : ""}, ${String(data).length} characters`);
7739
8643
  return null;
7740
8644
  }
7741
8645
  if (!(x instanceof Object)) {
@@ -7820,7 +8724,7 @@ function ac_on_close(gobj, event, kw, src) {
7820
8724
  let url = kw.url;
7821
8725
  if (kw.ws_seq !== void 0 && kw.ws_seq !== priv.ws_seq) return 0;
7822
8726
  set_remote_log_functions();
7823
- log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
8727
+ log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${peer_text_shown(kw.reason, PEER_FRAME_SHOWN)}", Clean: ${kw.was_clean})`);
7824
8728
  if (priv.websocket) {
7825
8729
  priv.websocket.onopen = null;
7826
8730
  priv.websocket.onmessage = null;
@@ -7905,7 +8809,7 @@ function ac_identity_card_ack(gobj, event, kw, src) {
7905
8809
  let services_roles = kw_get_dict_value(gobj, kw, "services_roles", {});
7906
8810
  if (result < 0) {
7907
8811
  close_websocket(gobj);
7908
- let kw_nak = {
8812
+ gobj_publish_event(gobj, "EV_ON_ID_NAK", {
7909
8813
  "url": gobj_read_str_attr(gobj, "url"),
7910
8814
  "result": result,
7911
8815
  "comment": comment,
@@ -7913,24 +8817,20 @@ function ac_identity_card_ack(gobj, event, kw, src) {
7913
8817
  "remote_yuno_name": src_yuno,
7914
8818
  "remote_yuno_role": src_role,
7915
8819
  "remote_yuno_service": src_service
7916
- };
7917
- if (gobj_is_pure_child(gobj)) gobj_send_event(gobj_parent(gobj), "EV_ON_ID_NAK", kw_nak, gobj);
7918
- else gobj_publish_event(gobj, "EV_ON_ID_NAK", kw_nak);
8820
+ });
7919
8821
  } else {
7920
8822
  gobj_change_state(gobj, "ST_SESSION");
7921
8823
  priv.inside_on_open = true;
7922
8824
  priv.retry_ms = 0;
7923
8825
  if (!priv.inform_on_close) {
7924
8826
  priv.inform_on_close = true;
7925
- let kw_on_open = {
8827
+ gobj_publish_event(gobj, "EV_ON_OPEN", {
7926
8828
  "username": username_,
7927
8829
  "remote_yuno_name": src_yuno,
7928
8830
  "remote_yuno_role": src_role,
7929
8831
  "remote_yuno_service": src_service,
7930
8832
  "services_roles": services_roles
7931
- };
7932
- if (gobj_is_pure_child(gobj)) gobj_send_event(gobj_parent(gobj), "EV_ON_OPEN", kw_on_open, gobj);
7933
- else gobj_publish_event(gobj, "EV_ON_OPEN", kw_on_open);
8833
+ });
7934
8834
  }
7935
8835
  priv.inside_on_open = false;
7936
8836
  resend_subscriptions(gobj);
@@ -7944,7 +8844,7 @@ function ac_on_message(gobj, event, kw, src) {
7944
8844
  let url = gobj.priv.url;
7945
8845
  let iev_msg = iev_create_from_json(gobj, kw.data);
7946
8846
  if (!iev_msg) {
7947
- log_warning(`${gobj_short_name(gobj)}: frame dropped from ${url}: ${String(kw.data).substring(0, 256)}`);
8847
+ log_warning(`${gobj_short_name(gobj)}: frame dropped from ${url}: ${peer_text_shown(kw.data, PEER_FRAME_SHOWN)}`);
7948
8848
  return -1;
7949
8849
  }
7950
8850
  if (is_traffic_tracing(gobj)) {
@@ -7959,7 +8859,7 @@ function ac_on_message(gobj, event, kw, src) {
7959
8859
  if (gobj_current_state(gobj) !== "ST_SESSION") {
7960
8860
  if (gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
7961
8861
  if (!(gobj_send_event(gobj, iev_event, iev_kw, gobj) < 0)) return 0;
7962
- } else log_error(`${gobj_short_name(gobj)}: event UNKNOWN in not-session state ${iev_event}`);
8862
+ } else log_error(`${gobj_short_name(gobj)}: event UNKNOWN in not-session state ${peer_text_shown(iev_event, PEER_NAME_SHOWN)}`);
7963
8863
  close_websocket(gobj);
7964
8864
  return -1;
7965
8865
  }
@@ -7968,16 +8868,16 @@ function ac_on_message(gobj, event, kw, src) {
7968
8868
  let event_id = msg_iev_get_stack(gobj, iev_kw, IEVENT_STACK_ID);
7969
8869
  let iev_dst_role = kw_get_str(gobj, event_id, "dst_role", "");
7970
8870
  if (iev_dst_role.toLowerCase() !== gobj_yuno_role().toLowerCase()) {
7971
- log_error(`"It's not my role, dst_role: ${iev_dst_role}, my_role: ${gobj_yuno_role()}`);
8871
+ log_error(`"It's not my role, dst_role: ${peer_text_shown(iev_dst_role, PEER_NAME_SHOWN)}, my_role: ${gobj_yuno_role()}`);
7972
8872
  return 0;
7973
8873
  }
7974
8874
  let iev_dst_service = kw_get_str(gobj, event_id, "dst_service", "");
7975
8875
  if (msg_type === "__subscribing__") {
7976
- log_warning(`${gobj_short_name(gobj)}: subscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
8876
+ log_warning(`${gobj_short_name(gobj)}: subscription event ignored, I'm client (service: ${peer_text_shown(iev_dst_service, PEER_NAME_SHOWN)}, event: ${peer_text_shown(iev_event, PEER_NAME_SHOWN)})`);
7977
8877
  return -1;
7978
8878
  }
7979
8879
  if (msg_type === "__unsubscribing__") {
7980
- log_warning(`${gobj_short_name(gobj)}: unsubscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
8880
+ log_warning(`${gobj_short_name(gobj)}: unsubscription event ignored, I'm client (service: ${peer_text_shown(iev_dst_service, PEER_NAME_SHOWN)}, event: ${peer_text_shown(iev_event, PEER_NAME_SHOWN)})`);
7981
8881
  return -1;
7982
8882
  }
7983
8883
  if (gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
@@ -7987,18 +8887,17 @@ function ac_on_message(gobj, event, kw, src) {
7987
8887
  if (!empty_string(iev_dst_service)) {
7988
8888
  let gobj_service = gobj_find_service(iev_dst_service, false);
7989
8889
  if (!gobj_service) {
7990
- log_warning(`${gobj_short_name(gobj)}: event for a service that is gone, DROPPED: service '${iev_dst_service}', ev '${iev_event}'`);
8890
+ log_warning(`${gobj_short_name(gobj)}: event for a service that is gone, DROPPED: service '${peer_text_shown(iev_dst_service, PEER_NAME_SHOWN)}', ev '${peer_text_shown(iev_event, PEER_NAME_SHOWN)}'`);
7991
8891
  return 0;
7992
8892
  }
7993
8893
  if (!gobj_has_event(gobj_service, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
7994
- log_error(`${gobj_short_name(gobj)}: Service found but no event or not public, service '${gobj_short_name(gobj_service)}', ev '${iev_event}'`);
8894
+ log_error(`${gobj_short_name(gobj)}: Service found but no event or not public, service '${gobj_short_name(gobj_service)}', ev '${peer_text_shown(iev_event, PEER_NAME_SHOWN)}'`);
7995
8895
  return -1;
7996
8896
  }
7997
8897
  gobj_send_event(gobj_service, iev_event, iev_kw, gobj);
7998
8898
  return 0;
7999
8899
  }
8000
- if (gobj_is_pure_child(gobj)) gobj_send_event(gobj_parent(gobj), iev_event, iev_kw, gobj);
8001
- else gobj_publish_event(gobj, iev_event, iev_kw);
8900
+ gobj_publish_event(gobj, iev_event, iev_kw);
8002
8901
  return 0;
8003
8902
  }
8004
8903
  /***************************************************************************
@@ -8137,6 +9036,6 @@ function register_c_ievent_cli() {
8137
9036
  return create_gclass(GCLASS_NAME);
8138
9037
  }
8139
9038
  //#endregion
8140
- export { GObj, SDATA, SDATAAUTHZ, SDATACM, SDATACM2, SDATADF, SDATAPM, SDATAPM0, SDATA_END, SDataDesc, YUNETA_VERSION, __yuno__, build_command_response, build_path, build_stats_response, clean_name, clear_timeout, cmp_two_simple_json, command_parser, createElement2, createOneHtml, create_json_record, create_template_record, current_timestamp, data_type_t, db_list_persistent_attrs, db_load_persistent_attrs, db_remove_persistent_attrs, db_save_persistent_attrs, debounce, delete_from_list, duplicate_objects, empty_json, empty_string, escapeHtml, event_flag_t, flat2json, flat_apply, flat_diff, flat_key_join, flat_key_split, gclass_add_ev_action, gclass_add_event_type, gclass_add_state, gclass_check_fsm, gclass_create, gclass_event_type, gclass_find_by_name, gclass_flag_t, gclass_unregister, getPositionRelativeToBody, get_function_name, get_now, gobj_bottom_gobj, gobj_change_parent, gobj_change_state, gobj_command, gobj_create, gobj_create2, gobj_create_default_service, gobj_create_pure_child, gobj_create_service, gobj_create_volatil, gobj_create_yuno, gobj_current_state, gobj_default_service, gobj_deliver_posted_events, gobj_destroy, gobj_find_child, gobj_find_gobj, gobj_find_service, gobj_find_subscribings, gobj_find_subscriptions, gobj_flag_t, gobj_full_name, gobj_gclass_name, gobj_get_gclass_trace_level, gobj_get_gclass_trace_level2, gobj_get_gclass_trace_no_level, gobj_get_global_trace_level, gobj_get_global_trace_no_level, gobj_global_trace_level, gobj_global_trace_no_level, gobj_has_attr, gobj_has_event, gobj_has_output_event, gobj_hsdata, gobj_is_destroying, gobj_is_playing, gobj_is_pure_child, gobj_is_running, gobj_is_service, gobj_is_volatil, gobj_list_persistent_attrs, gobj_list_subscriptions, gobj_load_persistent_attrs, gobj_match_children, gobj_match_children_tree, gobj_match_gobj, gobj_name, gobj_parent, gobj_pause, gobj_play, gobj_post_event, gobj_posted_events_size, gobj_publish_event, gobj_read_attr, gobj_read_attrs, gobj_read_bool_attr, gobj_read_integer_attr, gobj_read_pointer_attr, gobj_read_str_attr, gobj_remove_persistent_attrs, gobj_repr_global_trace_levels, gobj_reset_volatil_attrs, gobj_save_persistent_attrs, gobj_search_path, gobj_send_event, gobj_services, gobj_set_bottom_gobj, gobj_set_deep_trace, gobj_set_gclass_no_trace, gobj_set_gclass_trace, gobj_set_global_no_trace, gobj_set_global_no_trace2, gobj_set_global_trace, gobj_set_global_trace2, gobj_set_gobj_no_trace, gobj_set_gobj_trace, gobj_set_trace_machine_format, gobj_short_name, gobj_start, gobj_start_children, gobj_start_tree, gobj_start_up, gobj_stats, gobj_stop, gobj_stop_children, gobj_stop_tree, gobj_subscribe_event, gobj_trace_level, gobj_trace_machine_format, gobj_trace_no_level, gobj_unsubscribe_event, gobj_unsubscribe_list, gobj_walk_gobj_children, gobj_walk_gobj_children_tree, gobj_write_attr, gobj_write_attrs, gobj_write_bool_attr, gobj_write_integer_attr, gobj_write_str_attr, gobj_yuno, gobj_yuno_id, gobj_yuno_name, gobj_yuno_role, html_markup, id_index_in_obj_list, index_in_list, is_array, is_boolean, is_date, is_function, is_gobj, is_html_markup, is_metadata_key, is_null, is_number, is_object, is_private_key, is_pure_number, is_secret_name, is_string, jdb_delete, jdb_get, jdb_get_by_idx, jdb_get_topic, jdb_init, jdb_update, json2flat, json_array_append, json_array_append_new, json_array_extend, json_array_remove, json_array_size, json_deep_copy, json_is_identical, json_mask_secrets, json_object_del, json_object_get, json_object_set, json_object_set_new, json_object_size, json_object_update, json_object_update_existing, json_object_update_missing, json_size, jwt2json, jwtDecode, kw_clone_by_keys, kw_clone_by_not_keys, kw_collect, kw_delete, kw_find_json_in_list, kw_find_path, kw_flag_t, kw_get_bool, kw_get_dict, kw_get_dict_value, kw_get_int, kw_get_list, kw_get_local_storage_value, kw_get_pointer, kw_get_real, kw_get_str, kw_has_key, kw_match_simple, kw_pop, kw_remove_local_storage_value, kw_select, kw_set_dict_value, kw_set_local_storage_value, kw_set_subdict_value, kwid_collect, kwid_find_one_record, kwid_get_ids, kwid_match_id, kwid_new_dict, kwid_new_list, list2options, load_json_file, log_debug, log_error, log_info, log_warning, mask_secrets_inline, msg_iev_get_msg_type, msg_iev_get_stack, msg_iev_push_stack, msg_iev_read_key, msg_iev_set_msg_type, msg_iev_write_key, node_uuid, parseBoolean, parseSVG, refresh_language, register_c_ievent_cli, register_c_timer, register_c_yuno, safeSrc, sdata_flag_t, send_http_json_post, set_console_log_enabled, set_console_log_filter, set_log_callback, set_remote_log_functions, set_strings_are_text, set_timeout, set_timeout_periodic, sprintf, stats_parser, str_in_list, strcasecmp, strcmp, strings_are_text, strncmp, strs_in_list, strstr, template_get_field_desc, timeTracker, trace_json, trace_json_masked, trace_level_t, trace_msg, treedb_decoder_fkey, treedb_decoder_hook, treedb_encoder_fkey, treedb_get_field_desc, treedb_hook_data_size, vsprintf, walk_type_t };
9039
+ export { GObj, SDATA, SDATAAUTHZ, SDATACM, SDATACM2, SDATADF, SDATAPM, SDATAPM0, SDATA_END, SDataDesc, YUNETA_VERSION, __yuno__, build_command_response, build_path, build_stats_response, clean_name, clear_timeout, cmp_two_simple_json, command_parameter_from_json, command_parameter_from_text, command_parser, createElement2, createOneHtml, create_json_record, create_template_record, current_timestamp, data_type_t, db_list_persistent_attrs, db_load_persistent_attrs, db_remove_persistent_attrs, db_save_persistent_attrs, debounce, delete_from_list, duplicate_objects, empty_json, empty_string, escapeHtml, event_flag_t, flat2json, flat_apply, flat_diff, flat_key_join, flat_key_split, gclass_add_ev_action, gclass_add_event_type, gclass_add_state, gclass_check_fsm, gclass_create, gclass_event_type, gclass_find_by_name, gclass_flag_t, gclass_unregister, getPositionRelativeToBody, get_function_name, get_now, gobj_bottom_gobj, gobj_change_parent, gobj_change_state, gobj_command, gobj_create, gobj_create2, gobj_create_default_service, gobj_create_pure_child, gobj_create_service, gobj_create_volatil, gobj_create_yuno, gobj_current_state, gobj_default_service, gobj_deliver_posted_events, gobj_destroy, gobj_find_child, gobj_find_gobj, gobj_find_service, gobj_find_subscribings, gobj_find_subscriptions, gobj_flag_t, gobj_full_name, gobj_gclass_name, gobj_get_gclass_trace_level, gobj_get_gclass_trace_level2, gobj_get_gclass_trace_no_level, gobj_get_global_trace_level, gobj_get_global_trace_no_level, gobj_global_trace_level, gobj_global_trace_no_level, gobj_has_attr, gobj_has_event, gobj_has_output_event, gobj_hsdata, gobj_is_destroying, gobj_is_playing, gobj_is_pure_child, gobj_is_running, gobj_is_service, gobj_is_volatil, gobj_list_persistent_attrs, gobj_list_subscriptions, gobj_load_persistent_attrs, gobj_match_children, gobj_match_children_tree, gobj_match_gobj, gobj_name, gobj_parent, gobj_pause, gobj_play, gobj_post_event, gobj_posted_events_size, gobj_publish_event, gobj_read_attr, gobj_read_attrs, gobj_read_bool_attr, gobj_read_integer_attr, gobj_read_pointer_attr, gobj_read_str_attr, gobj_remove_persistent_attrs, gobj_repr_global_trace_levels, gobj_reset_volatil_attrs, gobj_save_persistent_attrs, gobj_search_path, gobj_send_event, gobj_services, gobj_set_bottom_gobj, gobj_set_deep_trace, gobj_set_gclass_no_trace, gobj_set_gclass_trace, gobj_set_global_no_trace, gobj_set_global_no_trace2, gobj_set_global_trace, gobj_set_global_trace2, gobj_set_gobj_no_trace, gobj_set_gobj_trace, gobj_set_trace_machine_format, gobj_short_name, gobj_start, gobj_start_children, gobj_start_tree, gobj_start_up, gobj_stats, gobj_stop, gobj_stop_children, gobj_stop_tree, gobj_subscribe_event, gobj_trace_level, gobj_trace_machine_format, gobj_trace_no_level, gobj_unsubscribe_event, gobj_unsubscribe_list, gobj_walk_gobj_children, gobj_walk_gobj_children_tree, gobj_write_attr, gobj_write_attrs, gobj_write_bool_attr, gobj_write_integer_attr, gobj_write_str_attr, gobj_yuno, gobj_yuno_id, gobj_yuno_name, gobj_yuno_role, html_markup, id_index_in_obj_list, index_in_list, is_array, is_boolean, is_date, is_function, is_gobj, is_html_markup, is_metadata_key, is_null, is_number, is_object, is_private_key, is_pure_number, is_secret_name, is_string, jdb_delete, jdb_get, jdb_get_by_idx, jdb_get_topic, jdb_init, jdb_update, json2flat, json_array_append, json_array_append_new, json_array_extend, json_array_remove, json_array_size, json_deep_copy, json_is_identical, json_mask_secrets, json_object_del, json_object_get, json_object_set, json_object_set_new, json_object_size, json_object_update, json_object_update_existing, json_object_update_missing, json_size, jwt2json, jwtDecode, kw_clone_by_keys, kw_clone_by_not_keys, kw_collect, kw_delete, kw_find_json_in_list, kw_find_path, kw_flag_t, kw_get_bool, kw_get_dict, kw_get_dict_value, kw_get_int, kw_get_list, kw_get_local_storage_value, kw_get_pointer, kw_get_real, kw_get_str, kw_has_key, kw_match_simple, kw_pop, kw_remove_local_storage_value, kw_select, kw_set_dict_value, kw_set_local_storage_value, kw_set_subdict_value, kwid_collect, kwid_find_one_record, kwid_get_ids, kwid_match_id, kwid_new_dict, kwid_new_list, list2options, load_json_file, log_debug, log_error, log_info, log_warning, mask_secrets_inline, msg_iev_get_msg_type, msg_iev_get_stack, msg_iev_push_stack, msg_iev_read_key, msg_iev_set_msg_type, msg_iev_write_key, node_uuid, parseBoolean, parseSVG, refresh_language, register_c_ievent_cli, register_c_timer, register_c_yuno, safeSrc, sdata_flag_t, send_http_json_post, set_console_log_enabled, set_console_log_filter, set_log_callback, set_remote_log_functions, set_strings_are_text, set_timeout, set_timeout_periodic, sprintf, stats_parser, str_in_list, strcasecmp, strcmp, strings_are_text, strncmp, strs_in_list, strstr, template_get_field_desc, timeTracker, trace_json, trace_json_masked, trace_level_t, trace_msg, treedb_decoder_fkey, treedb_decoder_hook, treedb_encoder_fkey, treedb_get_field_desc, treedb_hook_data_size, vsprintf, walk_type_t };
8141
9040
 
8142
9041
  //# sourceMappingURL=gobj-js.es.js.map