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