@yuneta/gobj-js 7.25.8 → 7.26.0
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 +102 -24
- package/dist/gobj-js.cjs.js +608 -132
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +1300 -1027
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +605 -133
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +1344 -1071
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +608 -132
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +1351 -1078
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +608 -132
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +1340 -1067
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +2 -2
package/dist/gobj-js.umd.js
CHANGED
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
return sprintf.apply(null, [fmt].concat(argv || []));
|
|
28
28
|
}
|
|
29
29
|
function sprintf_format(parse_tree, argv) {
|
|
30
|
-
var cursor = 1, tree_length = parse_tree.length, arg, output = "", i, k, ph, pad, pad_character, pad_length, is_positive, sign;
|
|
31
|
-
for (
|
|
30
|
+
var cursor = 1, tree_length = parse_tree.length, arg, output = "", i = 0, k, ph, pad, pad_character, pad_length, is_positive, sign;
|
|
31
|
+
for (; i < tree_length; i++) if (typeof parse_tree[i] === "string") output += parse_tree[i];
|
|
32
32
|
else if (typeof parse_tree[i] === "object") {
|
|
33
33
|
ph = parse_tree[i];
|
|
34
34
|
if (ph.keys) {
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
function build_command_response(gobj, result, comment, schema, data) {
|
|
162
162
|
return {
|
|
163
163
|
result,
|
|
164
|
-
comment: comment ||
|
|
164
|
+
comment: comment || "",
|
|
165
165
|
schema: schema || {},
|
|
166
166
|
data: data || []
|
|
167
167
|
};
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
var __global_stats_parser_fn__ = null;
|
|
216
216
|
var dl_global_event_types = [];
|
|
217
217
|
var _gclass_register = Object.create(null);
|
|
218
|
-
var __jn_services__ =
|
|
218
|
+
var __jn_services__ = Object.create(null);
|
|
219
219
|
var __yuno__ = null;
|
|
220
220
|
var __default_service__ = null;
|
|
221
221
|
var __inside__ = 0;
|
|
@@ -824,7 +824,8 @@
|
|
|
824
824
|
if (!is_object(jn_value)) jn_value = {};
|
|
825
825
|
break;
|
|
826
826
|
case data_type_t.DTP_JSON:
|
|
827
|
-
if (
|
|
827
|
+
if (svalue === "" || svalue === void 0) jn_value = null;
|
|
828
|
+
else if (is_string(svalue)) try {
|
|
828
829
|
jn_value = JSON.parse(svalue);
|
|
829
830
|
} catch (error) {
|
|
830
831
|
log_error(`JSON parse error: ${error.message}`);
|
|
@@ -859,11 +860,17 @@
|
|
|
859
860
|
break;
|
|
860
861
|
case data_type_t.DTP_INTEGER:
|
|
861
862
|
jn_value2 = parseInt(jn_value_);
|
|
862
|
-
if (isNaN(jn_value2))
|
|
863
|
+
if (isNaN(jn_value2)) {
|
|
864
|
+
log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
|
|
865
|
+
return -1;
|
|
866
|
+
}
|
|
863
867
|
break;
|
|
864
868
|
case data_type_t.DTP_REAL:
|
|
865
869
|
jn_value2 = Number(jn_value_);
|
|
866
|
-
if (isNaN(jn_value2))
|
|
870
|
+
if (isNaN(jn_value2)) {
|
|
871
|
+
log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
|
|
872
|
+
return -1;
|
|
873
|
+
}
|
|
867
874
|
break;
|
|
868
875
|
case data_type_t.DTP_LIST:
|
|
869
876
|
if (is_string(jn_value_)) try {
|
|
@@ -890,15 +897,11 @@
|
|
|
890
897
|
}
|
|
891
898
|
break;
|
|
892
899
|
case data_type_t.DTP_JSON:
|
|
900
|
+
jn_value2 = jn_value_;
|
|
893
901
|
if (is_string(jn_value_)) try {
|
|
894
902
|
jn_value2 = JSON.parse(jn_value_);
|
|
895
903
|
} catch (error) {
|
|
896
|
-
|
|
897
|
-
}
|
|
898
|
-
else jn_value2 = jn_value_;
|
|
899
|
-
if (!is_array(jn_value2) && !is_object(jn_value2)) {
|
|
900
|
-
log_error(`attr must be a json dict/list: ${it.name}`);
|
|
901
|
-
return -1;
|
|
904
|
+
jn_value2 = jn_value_;
|
|
902
905
|
}
|
|
903
906
|
break;
|
|
904
907
|
case data_type_t.DTP_POINTER: jn_value2 = jn_value_;
|
|
@@ -1203,6 +1206,10 @@
|
|
|
1203
1206
|
* find a service
|
|
1204
1207
|
************************************************************/
|
|
1205
1208
|
function gobj_find_service(service_name, verbose) {
|
|
1209
|
+
if (!is_string(service_name)) {
|
|
1210
|
+
log_error(`gobj_find_service(): service name must be a string: ${service_name}`);
|
|
1211
|
+
return null;
|
|
1212
|
+
}
|
|
1206
1213
|
service_name = service_name.toLowerCase();
|
|
1207
1214
|
let service_gobj = __jn_services__[service_name];
|
|
1208
1215
|
if (!service_gobj) {
|
|
@@ -1337,7 +1344,7 @@
|
|
|
1337
1344
|
let new_kw = kw;
|
|
1338
1345
|
if (json2sdata(hs, new_kw, -1, gobj.gclass.gclass_flag & gclass_flag_t.gcflag_ignore_unknown_attrs ? 0 : print_attr_not_found, gobj) < 0) {
|
|
1339
1346
|
log_error(`${gobj_short_name(gobj)} json2data() FAILED`);
|
|
1340
|
-
|
|
1347
|
+
trace_json_masked(new_kw);
|
|
1341
1348
|
}
|
|
1342
1349
|
}
|
|
1343
1350
|
/************************************************************
|
|
@@ -1360,9 +1367,10 @@
|
|
|
1360
1367
|
return null;
|
|
1361
1368
|
}
|
|
1362
1369
|
if (is_string(parent)) {
|
|
1363
|
-
|
|
1370
|
+
const parent_name = parent;
|
|
1371
|
+
parent = gobj_find_service(parent_name);
|
|
1364
1372
|
if (!parent) {
|
|
1365
|
-
log_warning(`parent service not found: ${
|
|
1373
|
+
log_warning(`parent service not found: ${parent_name}`);
|
|
1366
1374
|
return null;
|
|
1367
1375
|
}
|
|
1368
1376
|
}
|
|
@@ -1475,6 +1483,7 @@
|
|
|
1475
1483
|
parent.gclass.gmt.mt_child_removed(parent, gobj);
|
|
1476
1484
|
}
|
|
1477
1485
|
if (gobj.gobj_flag & gobj_flag_t.gobj_flag_service) _deregister_service(gobj);
|
|
1486
|
+
if (gobj === __default_service__) __default_service__ = null;
|
|
1478
1487
|
gobj_unsubscribe_list(gobj, gobj.dl_subscriptions, true);
|
|
1479
1488
|
gobj_unsubscribe_list(gobj, gobj.dl_subscribings, true);
|
|
1480
1489
|
if (parent) {
|
|
@@ -1820,7 +1829,7 @@
|
|
|
1820
1829
|
log_error(`gobj NULL of bad type`);
|
|
1821
1830
|
return null;
|
|
1822
1831
|
}
|
|
1823
|
-
if (gobj.bottom_gobj) log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);
|
|
1832
|
+
if (gobj.bottom_gobj && bottom_gobj) log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);
|
|
1824
1833
|
gobj.bottom_gobj = bottom_gobj;
|
|
1825
1834
|
}
|
|
1826
1835
|
/***************************************************************************
|
|
@@ -2235,7 +2244,7 @@
|
|
|
2235
2244
|
jn_attrs[key] = value;
|
|
2236
2245
|
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
|
|
2237
2246
|
if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
|
|
2238
|
-
if (gobj.mt_writing) gobj.mt_writing(gobj, key);
|
|
2247
|
+
if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
|
|
2239
2248
|
}
|
|
2240
2249
|
return 0;
|
|
2241
2250
|
}
|
|
@@ -2259,8 +2268,8 @@
|
|
|
2259
2268
|
if (!it.name) continue;
|
|
2260
2269
|
if (exclude_flag && it.flag & exclude_flag) continue;
|
|
2261
2270
|
if (include_flag === -1 || it.flag & include_flag) {
|
|
2262
|
-
|
|
2263
|
-
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] =
|
|
2271
|
+
set_default(gobj, gobj.jn_attrs, it);
|
|
2272
|
+
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
|
|
2264
2273
|
if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
|
|
2265
2274
|
}
|
|
2266
2275
|
}
|
|
@@ -2294,7 +2303,7 @@
|
|
|
2294
2303
|
let hs = gobj_hsdata2(gobj, name, false);
|
|
2295
2304
|
if (hs) {
|
|
2296
2305
|
hs[name] = parseBoolean(value);
|
|
2297
|
-
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] =
|
|
2306
|
+
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
|
|
2298
2307
|
if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
|
|
2299
2308
|
if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
|
|
2300
2309
|
}
|
|
@@ -2310,7 +2319,7 @@
|
|
|
2310
2319
|
let hs = gobj_hsdata2(gobj, name, false);
|
|
2311
2320
|
if (hs) {
|
|
2312
2321
|
hs[name] = parseInt(value);
|
|
2313
|
-
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] =
|
|
2322
|
+
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
|
|
2314
2323
|
if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
|
|
2315
2324
|
if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
|
|
2316
2325
|
}
|
|
@@ -2326,7 +2335,7 @@
|
|
|
2326
2335
|
let hs = gobj_hsdata2(gobj, name, false);
|
|
2327
2336
|
if (hs) {
|
|
2328
2337
|
hs[name] = String(value);
|
|
2329
|
-
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] =
|
|
2338
|
+
if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
|
|
2330
2339
|
if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
|
|
2331
2340
|
if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
|
|
2332
2341
|
}
|
|
@@ -2380,15 +2389,15 @@
|
|
|
2380
2389
|
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);
|
|
2381
2390
|
return -1;
|
|
2382
2391
|
}
|
|
2383
|
-
if (gobj.parent && gobj.parent.mt_child_removed) gobj.parent.mt_child_removed(gobj.parent, gobj);
|
|
2392
|
+
if (gobj.parent && gobj.parent.gclass.gmt.mt_child_removed) gobj.parent.gclass.gmt.mt_child_removed(gobj.parent, gobj);
|
|
2384
2393
|
if (gobj.parent) {
|
|
2385
2394
|
_remove_child(gobj.parent, gobj);
|
|
2386
2395
|
gobj.parent = null;
|
|
2387
2396
|
}
|
|
2388
2397
|
_add_child(parent, gobj);
|
|
2389
|
-
if (parent.mt_child_added) {
|
|
2398
|
+
if (parent.gclass.gmt.mt_child_added) {
|
|
2390
2399
|
if (__trace_gobj_create_delete__(gobj)) log_debug(sprintf("👦👦🔵 child_added(%s): %s", gobj_full_name(parent), gobj_short_name(gobj)));
|
|
2391
|
-
parent.mt_child_added(parent, gobj);
|
|
2400
|
+
parent.gclass.gmt.mt_child_added(parent, gobj);
|
|
2392
2401
|
}
|
|
2393
2402
|
return 0;
|
|
2394
2403
|
}
|
|
@@ -2500,9 +2509,19 @@
|
|
|
2500
2509
|
let snapshot = __dl_posted_events__;
|
|
2501
2510
|
__dl_posted_events__ = [];
|
|
2502
2511
|
let delivered = 0;
|
|
2503
|
-
for (let
|
|
2512
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
2513
|
+
const msg = snapshot[i];
|
|
2504
2514
|
if (msg.dst.obflag & (obflag_t.obflag_destroyed | obflag_t.obflag_destroying)) continue;
|
|
2505
|
-
|
|
2515
|
+
try {
|
|
2516
|
+
gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);
|
|
2517
|
+
} catch (e) {
|
|
2518
|
+
__dl_posted_events__ = snapshot.slice(i + 1).concat(__dl_posted_events__);
|
|
2519
|
+
if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
|
|
2520
|
+
__posted_events_scheduled__ = true;
|
|
2521
|
+
setTimeout(gobj_deliver_posted_events, 0);
|
|
2522
|
+
}
|
|
2523
|
+
throw e;
|
|
2524
|
+
}
|
|
2506
2525
|
delivered++;
|
|
2507
2526
|
}
|
|
2508
2527
|
if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
|
|
@@ -2552,7 +2571,7 @@
|
|
|
2552
2571
|
else trace_machine(sprintf("🔃 mach(%s%s), st: %s, ev: %s, from(%s%s)", !dst.running ? "!!" : "", gobj_short_name(dst), state.state_name, event ? event : "", src && !src.running ? "!!" : "", gobj_short_name(src)));
|
|
2553
2572
|
if (kw) {
|
|
2554
2573
|
if (__trace_gobj_ev_kw__(dst)) {
|
|
2555
|
-
if (json_object_size(kw))
|
|
2574
|
+
if (json_object_size(kw)) trace_json_masked(kw);
|
|
2556
2575
|
}
|
|
2557
2576
|
}
|
|
2558
2577
|
}
|
|
@@ -2572,7 +2591,7 @@
|
|
|
2572
2591
|
}
|
|
2573
2592
|
if (kw) {
|
|
2574
2593
|
if (__trace_gobj_ev_kw__(dst)) {
|
|
2575
|
-
if (json_object_size(kw))
|
|
2594
|
+
if (json_object_size(kw)) trace_json_masked(kw);
|
|
2576
2595
|
}
|
|
2577
2596
|
}
|
|
2578
2597
|
}
|
|
@@ -2580,15 +2599,40 @@
|
|
|
2580
2599
|
let ret = -1;
|
|
2581
2600
|
try {
|
|
2582
2601
|
if (event_action.action) ret = event_action.action(dst, event, kw, src);
|
|
2583
|
-
}
|
|
2602
|
+
} catch (e) {
|
|
2603
|
+
__inside__--;
|
|
2604
|
+
if (!(e && e.__gobj_logged__)) {
|
|
2605
|
+
log_error(`${gobj_short_name(dst)}: action of ${event} in ${dst.current_state.state_name} THREW: ${e && e.stack ? e.stack : e}`);
|
|
2606
|
+
try {
|
|
2607
|
+
e.__gobj_logged__ = true;
|
|
2608
|
+
} catch (e2) {}
|
|
2609
|
+
}
|
|
2610
|
+
throw e;
|
|
2611
|
+
}
|
|
2584
2612
|
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));
|
|
2585
2613
|
__inside__--;
|
|
2586
2614
|
return ret;
|
|
2587
2615
|
}
|
|
2588
2616
|
var subs_flag_t = Object.freeze({
|
|
2589
|
-
|
|
2590
|
-
|
|
2617
|
+
__rename_event_name__: 1,
|
|
2618
|
+
__hard_subscription__: 2,
|
|
2619
|
+
__own_event__: 4
|
|
2591
2620
|
});
|
|
2621
|
+
/***************************************************************************
|
|
2622
|
+
* The event type of `event_name` in any registered gclass, null if none.
|
|
2623
|
+
* The C kernel's gobj_find_event_type(): any case, gclasses only.
|
|
2624
|
+
***************************************************************************/
|
|
2625
|
+
function _find_event_type_in_gclasses(event_name) {
|
|
2626
|
+
let lower = String(event_name).toLowerCase();
|
|
2627
|
+
for (let gclass_name in _gclass_register) {
|
|
2628
|
+
let dl = _gclass_register[gclass_name].dl_events;
|
|
2629
|
+
for (let i = 0; i < dl.length; i++) {
|
|
2630
|
+
let event_type = dl[i];
|
|
2631
|
+
if (event_type.event_name && event_type.event_name.toLowerCase() === lower) return event_type;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
return null;
|
|
2635
|
+
}
|
|
2592
2636
|
var subscription_desc = [
|
|
2593
2637
|
SDATA(data_type_t.DTP_POINTER, "publisher", 0, null, "publisher gobj"),
|
|
2594
2638
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, null, "subscriber gobj"),
|
|
@@ -2621,6 +2665,21 @@
|
|
|
2621
2665
|
if (json_size(__config__) > 0) {
|
|
2622
2666
|
let kw_clone = json_deep_copy(__config__);
|
|
2623
2667
|
json_object_set_new(subs, "__config__", kw_clone);
|
|
2668
|
+
let renamed_event = kw_get_str(publisher, kw_clone, "__rename_event_name__", "");
|
|
2669
|
+
if (!empty_string(renamed_event)) {
|
|
2670
|
+
let event_type = _find_event_type_in_gclasses(renamed_event);
|
|
2671
|
+
if (event_type) {
|
|
2672
|
+
json_object_set_new(subs, "renamed_event", event_type.event_name);
|
|
2673
|
+
delete kw_clone.__rename_event_name__;
|
|
2674
|
+
subs_flag |= subs_flag_t.__rename_event_name__;
|
|
2675
|
+
let kw_global = kw_get_dict(publisher, subs, "__global__", null);
|
|
2676
|
+
if (!is_object(kw_global)) {
|
|
2677
|
+
kw_global = {};
|
|
2678
|
+
json_object_set_new(subs, "__global__", kw_global);
|
|
2679
|
+
}
|
|
2680
|
+
kw_global.__original_event_name__ = event;
|
|
2681
|
+
} else log_error(`${gobj_short_name(publisher)}: EVENT NOT FOUND (__rename_event_name__: ${renamed_event})`);
|
|
2682
|
+
}
|
|
2624
2683
|
if (kw_has_key(kw_clone, "__hard_subscription__")) {
|
|
2625
2684
|
let hard_subscription = kw_get_bool(publisher, kw_clone, "__hard_subscription__", false);
|
|
2626
2685
|
json_object_del(kw_clone, "__hard_subscription__");
|
|
@@ -2640,9 +2699,52 @@
|
|
|
2640
2699
|
return subs;
|
|
2641
2700
|
}
|
|
2642
2701
|
/***************************************************************************
|
|
2702
|
+
* The kw to find the subscriptions a (un)subscription `kw` names: `kw` as
|
|
2703
|
+
* _create_subscription() stores it, as the C kernel's
|
|
2704
|
+
* _subscription_match_kw(). The three `__config__` keys the framework
|
|
2705
|
+
* reads (__hard_subscription__, __own_event__, __rename_event_name__)
|
|
2706
|
+
* become the subs_flag and are taken out of the stored `__config__`, and
|
|
2707
|
+
* a renamed event adds `__original_event_name__` to the stored
|
|
2708
|
+
* `__global__`: with `kw` as it came, the same kw matched no subscription,
|
|
2709
|
+
* a repeat of it was made twice (the subscriber got each event twice) and
|
|
2710
|
+
* its withdrawal found nothing. A known renamed event is returned in
|
|
2711
|
+
* `renamed_event`, which _match_subscription() compares: a plain and a
|
|
2712
|
+
* renamed subscription, or two renames of one event, are two. A rename
|
|
2713
|
+
* that no gclass declares stays in the stored `__config__`, and in this
|
|
2714
|
+
* one. Up to gobj-js 7.25.8 the kw was compared as it came, and
|
|
2715
|
+
* `__rename_event_name__` always stayed in the stored `__config__`: a
|
|
2716
|
+
* plain kw with the rest of that __config__ found no repeat (two
|
|
2717
|
+
* subscriptions where C has one).
|
|
2718
|
+
* Return {kw, renamed_event}; renamed_event is "" when kw does not rename.
|
|
2719
|
+
***************************************************************************/
|
|
2720
|
+
function _subscription_match_kw(kw, event) {
|
|
2721
|
+
let __config__ = kw ? kw.__config__ : null;
|
|
2722
|
+
if (!is_object(__config__) || !kw_has_key(__config__, "__hard_subscription__") && !kw_has_key(__config__, "__own_event__") && !kw_has_key(__config__, "__rename_event_name__")) return {
|
|
2723
|
+
kw,
|
|
2724
|
+
renamed_event: ""
|
|
2725
|
+
};
|
|
2726
|
+
let kw_match = Object.assign({}, kw);
|
|
2727
|
+
let config_match = Object.assign({}, __config__);
|
|
2728
|
+
kw_match.__config__ = config_match;
|
|
2729
|
+
let renamed_event = "";
|
|
2730
|
+
let rename = config_match.__rename_event_name__;
|
|
2731
|
+
let event_type = typeof rename === "string" && !empty_string(rename) ? _find_event_type_in_gclasses(rename) : null;
|
|
2732
|
+
if (event_type) {
|
|
2733
|
+
renamed_event = event_type.event_name;
|
|
2734
|
+
delete config_match.__rename_event_name__;
|
|
2735
|
+
if (event && json_size(kw_match.__global__) > 0) kw_match.__global__ = Object.assign({}, kw_match.__global__, { __original_event_name__: event });
|
|
2736
|
+
}
|
|
2737
|
+
delete config_match.__hard_subscription__;
|
|
2738
|
+
delete config_match.__own_event__;
|
|
2739
|
+
return {
|
|
2740
|
+
kw: kw_match,
|
|
2741
|
+
renamed_event
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
/***************************************************************************
|
|
2643
2745
|
* Match subscription
|
|
2644
2746
|
***************************************************************************/
|
|
2645
|
-
function _match_subscription(subs, publisher, event, kw, subscriber) {
|
|
2747
|
+
function _match_subscription(subs, publisher, event, renamed_event, kw, subscriber) {
|
|
2646
2748
|
let __config__ = kw_get_dict(publisher, kw, "__config__", null);
|
|
2647
2749
|
let __global__ = kw_get_dict(publisher, kw, "__global__", null);
|
|
2648
2750
|
let __local__ = kw_get_dict(publisher, kw, "__local__", null);
|
|
@@ -2657,6 +2759,9 @@
|
|
|
2657
2759
|
if (event) {
|
|
2658
2760
|
if (event !== kw_get_str(null, subs, "event", "")) match = false;
|
|
2659
2761
|
}
|
|
2762
|
+
if (renamed_event) {
|
|
2763
|
+
if (renamed_event !== kw_get_str(null, subs, "renamed_event", "")) match = false;
|
|
2764
|
+
}
|
|
2660
2765
|
if (json_size(__config__) > 0) {
|
|
2661
2766
|
let kw_config = kw_get_dict(null, subs, "__config__", null);
|
|
2662
2767
|
if (json_size(kw_config) > 0) {
|
|
@@ -2691,26 +2796,29 @@
|
|
|
2691
2796
|
* kw (__config__, __global__, __local__, __filter__),
|
|
2692
2797
|
* subscriber
|
|
2693
2798
|
***************************************************************************/
|
|
2694
|
-
function _find_subscriptions(dl_subs, publisher, event, kw, subscriber) {
|
|
2799
|
+
function _find_subscriptions(dl_subs, publisher, event, renamed_event, kw, subscriber) {
|
|
2695
2800
|
let iter = [];
|
|
2696
2801
|
for (let i = 0; i < dl_subs.length; i++) {
|
|
2697
2802
|
let subs = dl_subs[i];
|
|
2698
|
-
if (_match_subscription(subs, publisher, event, kw, subscriber)) json_array_append(iter, subs);
|
|
2803
|
+
if (_match_subscription(subs, publisher, event, renamed_event, kw, subscriber)) json_array_append(iter, subs);
|
|
2699
2804
|
}
|
|
2700
2805
|
return iter;
|
|
2701
2806
|
}
|
|
2702
2807
|
/***************************************************************************
|
|
2703
|
-
* Find idx of subscription in dl_subs, -1 not found
|
|
2808
|
+
* Find idx of the subscription `subs` itself in dl_subs, -1 not found.
|
|
2809
|
+
* Up to gobj-js 7.25.8 it was the first entry whose fields matched `subs`:
|
|
2810
|
+
* a subscription already removed took a live one that matched it (a plain
|
|
2811
|
+
* one matches every other of its event and subscriber).
|
|
2704
2812
|
***************************************************************************/
|
|
2705
|
-
function _get_subs_idx(dl_subs,
|
|
2706
|
-
|
|
2707
|
-
let subs = dl_subs[i];
|
|
2708
|
-
if (_match_subscription(subs, publisher, event, kw, subscriber)) return i;
|
|
2709
|
-
}
|
|
2710
|
-
return -1;
|
|
2813
|
+
function _get_subs_idx(dl_subs, subs) {
|
|
2814
|
+
return dl_subs.indexOf(subs);
|
|
2711
2815
|
}
|
|
2712
2816
|
/***************************************************************************
|
|
2713
|
-
* Delete subscription in publisher and subscriber
|
|
2817
|
+
* Delete subscription in publisher and subscriber.
|
|
2818
|
+
* Return 0 removed, -1 a hard one kept (only `force` removes it), 1 it
|
|
2819
|
+
* was not there any more: already removed, as a stale reference is, or by
|
|
2820
|
+
* the mt_subscription_deleted() of an earlier entry of the same list. The
|
|
2821
|
+
* caller says which is an error. As in C.
|
|
2714
2822
|
***************************************************************************/
|
|
2715
2823
|
function _delete_subscription(gobj, subs, force, not_inform) {
|
|
2716
2824
|
let publisher = kw_get_pointer(gobj, subs, "publisher", null, kw_flag_t.KW_REQUIRED);
|
|
@@ -2719,7 +2827,12 @@
|
|
|
2719
2827
|
if (kw_get_int(gobj, subs, "subs_flag", null, kw_flag_t.KW_REQUIRED) & subs_flag_t.__hard_subscription__ ? 1 : 0) {
|
|
2720
2828
|
if (!force) return -1;
|
|
2721
2829
|
}
|
|
2722
|
-
|
|
2830
|
+
let tracea = __trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher);
|
|
2831
|
+
if (_get_subs_idx(publisher.dl_subscriptions, subs) < 0) {
|
|
2832
|
+
if (tracea) trace_machine(sprintf("💜💜👎 unsubscribing event '%s': publisher %s, subscriber'%s', ALREADY REMOVED", event ? event : "", gobj_short_name(publisher), gobj_short_name(subscriber)));
|
|
2833
|
+
return 1;
|
|
2834
|
+
}
|
|
2835
|
+
if (tracea) {
|
|
2723
2836
|
trace_machine(sprintf("💜💜👎 unsubscribing event '%s': publisher %s, subscriber'%s'", event ? event : "", gobj_short_name(publisher), gobj_short_name(subscriber)));
|
|
2724
2837
|
trace_json(subs);
|
|
2725
2838
|
}
|
|
@@ -2728,13 +2841,13 @@
|
|
|
2728
2841
|
if (publisher.gclass.gmt.mt_subscription_deleted) publisher.gclass.gmt.mt_subscription_deleted(publisher, subs);
|
|
2729
2842
|
}
|
|
2730
2843
|
}
|
|
2731
|
-
let idx = _get_subs_idx(publisher.dl_subscriptions,
|
|
2844
|
+
let idx = _get_subs_idx(publisher.dl_subscriptions, subs);
|
|
2732
2845
|
if (idx >= 0) json_array_remove(publisher.dl_subscriptions, idx);
|
|
2733
2846
|
else {
|
|
2734
2847
|
log_error(`${gobj_short_name(gobj)}: subscription in publisher not found`);
|
|
2735
2848
|
trace_json(subs);
|
|
2736
2849
|
}
|
|
2737
|
-
idx = _get_subs_idx(subscriber.dl_subscribings,
|
|
2850
|
+
idx = _get_subs_idx(subscriber.dl_subscribings, subs);
|
|
2738
2851
|
if (idx >= 0) json_array_remove(subscriber.dl_subscribings, idx);
|
|
2739
2852
|
else {
|
|
2740
2853
|
log_error(`${gobj_short_name(gobj)}: subscription in subscriber not found`);
|
|
@@ -2777,7 +2890,17 @@
|
|
|
2777
2890
|
}
|
|
2778
2891
|
}
|
|
2779
2892
|
} else event = "";
|
|
2780
|
-
let
|
|
2893
|
+
let match = _subscription_match_kw(kw, event);
|
|
2894
|
+
let dl_subs = _find_subscriptions(publisher.dl_subscriptions, publisher, event, match.renamed_event, match.kw, subscriber);
|
|
2895
|
+
let subs_hard = null;
|
|
2896
|
+
for (let i = 0; i < dl_subs.length; i++) if (kw_get_int(publisher, dl_subs[i], "subs_flag", 0, kw_flag_t.KW_REQUIRED) & subs_flag_t.__hard_subscription__) {
|
|
2897
|
+
subs_hard = dl_subs[i];
|
|
2898
|
+
break;
|
|
2899
|
+
}
|
|
2900
|
+
if (subs_hard) {
|
|
2901
|
+
log_warning(`${gobj_short_name(publisher)}: Hard subscription REPEATED, the one there is kept and returned (event: ${event}, subscriber: ${gobj_short_name(subscriber)})`);
|
|
2902
|
+
return subs_hard;
|
|
2903
|
+
}
|
|
2781
2904
|
if (json_array_size(dl_subs) > 0) {
|
|
2782
2905
|
log_error(`${gobj_short_name(publisher)}: ${json_array_size(dl_subs)} subscription(s) REPEATED, will be deleted and override`);
|
|
2783
2906
|
trace_json(dl_subs, "subscription REPEATED");
|
|
@@ -2792,7 +2915,7 @@
|
|
|
2792
2915
|
json_array_append(subscriber.dl_subscribings, subs);
|
|
2793
2916
|
if (__trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher)) {
|
|
2794
2917
|
trace_machine(sprintf("💜💜👍 subscribing event '%s', publisher '%s', subscriber %s", event ? event : "", gobj_short_name(publisher), gobj_short_name(subscriber)));
|
|
2795
|
-
if (kw && (__trace_gobj_ev_kw__(subscriber) || __trace_gobj_ev_kw__(publisher)))
|
|
2918
|
+
if (kw && (__trace_gobj_ev_kw__(subscriber) || __trace_gobj_ev_kw__(publisher))) trace_json_masked(kw);
|
|
2796
2919
|
}
|
|
2797
2920
|
if (publisher.gclass.gmt.mt_subscription_added) {
|
|
2798
2921
|
let result = publisher.gclass.gmt.mt_subscription_added(publisher, subs);
|
|
@@ -2834,16 +2957,22 @@
|
|
|
2834
2957
|
}
|
|
2835
2958
|
}
|
|
2836
2959
|
} else event = "";
|
|
2837
|
-
let
|
|
2960
|
+
let match = _subscription_match_kw(kw, event);
|
|
2961
|
+
let dl_subs = _find_subscriptions(publisher.dl_subscriptions, publisher, event, match.renamed_event, match.kw, subscriber);
|
|
2838
2962
|
let deleted = 0;
|
|
2963
|
+
let kept_hard = 0;
|
|
2964
|
+
let already_removed = 0;
|
|
2839
2965
|
for (let i = 0; i < dl_subs.length; i++) {
|
|
2840
2966
|
let subs = dl_subs[i];
|
|
2841
|
-
_delete_subscription(publisher, subs, false, false);
|
|
2842
|
-
deleted++;
|
|
2967
|
+
let ret = _delete_subscription(publisher, subs, false, false);
|
|
2968
|
+
if (ret === 0) deleted++;
|
|
2969
|
+
else if (ret < 0) kept_hard++;
|
|
2970
|
+
else already_removed++;
|
|
2843
2971
|
}
|
|
2844
|
-
if (
|
|
2972
|
+
if (kept_hard) log_warning(`${gobj_short_name(publisher)}: Hard subscription not removed, only gobj_unsubscribe_list() with force removes it (event: ${event}, hard: ${kept_hard})`);
|
|
2973
|
+
else if (!deleted && !already_removed) {
|
|
2845
2974
|
log_warning(`${gobj_short_name(publisher)}: No subscription found`);
|
|
2846
|
-
|
|
2975
|
+
trace_json_masked(kw, "No subscription found");
|
|
2847
2976
|
}
|
|
2848
2977
|
return 0;
|
|
2849
2978
|
}
|
|
@@ -2852,10 +2981,12 @@
|
|
|
2852
2981
|
***************************************************************************/
|
|
2853
2982
|
function gobj_unsubscribe_list(gobj, dl_subs, force) {
|
|
2854
2983
|
let dl = [...dl_subs];
|
|
2984
|
+
let already_removed = 0;
|
|
2855
2985
|
for (let i = 0; i < dl.length; i++) {
|
|
2856
2986
|
let subs = dl[i];
|
|
2857
|
-
_delete_subscription(gobj, subs, force, false)
|
|
2987
|
+
if (_delete_subscription(gobj, subs, force, false) > 0) already_removed++;
|
|
2858
2988
|
}
|
|
2989
|
+
if (already_removed) log_warning(`${gobj_short_name(gobj)}: Subscription(s) already removed, nothing to remove (count: ${already_removed})`);
|
|
2859
2990
|
return 0;
|
|
2860
2991
|
}
|
|
2861
2992
|
/***************************************************************************
|
|
@@ -2867,7 +2998,7 @@
|
|
|
2867
2998
|
***************************************************************************/
|
|
2868
2999
|
function gobj_find_subscriptions(publisher, event, kw, subscriber) {
|
|
2869
3000
|
if (kw == null) kw = {};
|
|
2870
|
-
return _find_subscriptions(publisher.dl_subscriptions, publisher, event, kw, subscriber);
|
|
3001
|
+
return _find_subscriptions(publisher.dl_subscriptions, publisher, event, null, kw, subscriber);
|
|
2871
3002
|
}
|
|
2872
3003
|
/***************************************************************************
|
|
2873
3004
|
*
|
|
@@ -2906,7 +3037,7 @@
|
|
|
2906
3037
|
* subscriber
|
|
2907
3038
|
***************************************************************************/
|
|
2908
3039
|
function gobj_find_subscribings(subscriber, event, kw, publisher) {
|
|
2909
|
-
return _find_subscriptions(subscriber.dl_subscribings, publisher, event, kw, subscriber);
|
|
3040
|
+
return _find_subscriptions(subscriber.dl_subscribings, publisher, event, null, kw, subscriber);
|
|
2910
3041
|
}
|
|
2911
3042
|
/***************************************************************************
|
|
2912
3043
|
* Return the sum of returns of gobj_send_event
|
|
@@ -2932,7 +3063,7 @@
|
|
|
2932
3063
|
if (tracea) {
|
|
2933
3064
|
if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔝 %s %s%s %s", event ? event : "", !publisher.running ? "!!" : "", gobj_short_name(publisher), publisher.current_state.state_name));
|
|
2934
3065
|
else trace_machine(sprintf("🔝🔝 mach(%s%s^%s), st: %s, ev: %s%s%s", !publisher.running ? "!!" : "", gobj_gclass_name(publisher), gobj_name(publisher), publisher.current_state.state_name, "", event ? event : "", ""));
|
|
2935
|
-
if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw))
|
|
3066
|
+
if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw)) trace_json_masked(kw);
|
|
2936
3067
|
}
|
|
2937
3068
|
if (publisher.gclass.gmt.mt_publish_event) {
|
|
2938
3069
|
let topublish = publisher.gclass.gmt.mt_publish_event(publisher, event, kw);
|
|
@@ -2957,6 +3088,8 @@
|
|
|
2957
3088
|
let __global__ = kw_get_dict(publisher, subs, "__global__", null, 0);
|
|
2958
3089
|
let __local__ = kw_get_dict(publisher, subs, "__local__", null, 0);
|
|
2959
3090
|
let __filter__ = kw_get_dict_value(publisher, subs, "__filter__", null, 0);
|
|
3091
|
+
let event_name = subs.renamed_event;
|
|
3092
|
+
if (empty_string(event_name)) event_name = event;
|
|
2960
3093
|
let topublish = 1;
|
|
2961
3094
|
if (publisher.gclass.gmt.mt_publication_filter) topublish = publisher.gclass.gmt.mt_publication_filter(publisher, event, kw, subscriber);
|
|
2962
3095
|
else if (json_size(__filter__) > 0) {
|
|
@@ -2980,11 +3113,11 @@
|
|
|
2980
3113
|
if (__config__) {}
|
|
2981
3114
|
if (json_size(__global__) > 0) json_object_update(kw2publish, json_deep_copy(__global__));
|
|
2982
3115
|
if (tracea) {
|
|
2983
|
-
if (__trace_machine_format__ === 1) trace_machine(sprintf("🔝🔄 %s (%s) %s%s", event ? event : "",
|
|
2984
|
-
else trace_machine(sprintf("🔝🔄 mach(%s%s), st: %s, ev: %s, from(%s%s)", !subscriber.running ? "!!" : "", gobj_short_name(subscriber), gobj_current_state(subscriber), event ? event : "", publisher && !publisher.running ? "!!" : "", gobj_short_name(publisher)));
|
|
2985
|
-
if (__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish))
|
|
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);
|
|
2986
3119
|
}
|
|
2987
|
-
let ret_ = gobj_send_event(subscriber,
|
|
3120
|
+
let ret_ = gobj_send_event(subscriber, event_name, kw2publish, publisher);
|
|
2988
3121
|
if (ret_ < 0 && subs_flag & subs_flag_t.__own_event__) {
|
|
2989
3122
|
sent_count = -1;
|
|
2990
3123
|
break;
|
|
@@ -3008,8 +3141,9 @@
|
|
|
3008
3141
|
return -1;
|
|
3009
3142
|
}
|
|
3010
3143
|
if (is_commands_tracing(gobj) || is_machine_tracing(gobj, null) && !is_machine_not_tracing(src, null)) {
|
|
3011
|
-
|
|
3012
|
-
|
|
3144
|
+
let command_shown = mask_secrets_inline(command);
|
|
3145
|
+
trace_machine(sprintf("🌀🌀 mach(%s%s), cmd: %s, src: %s", !gobj_is_running(gobj) ? "!!" : "", gobj_short_name(gobj), command_shown !== null ? command_shown : command, gobj_short_name(src)));
|
|
3146
|
+
if (__trace_gobj_ev_kw__(gobj)) trace_json_masked(kw);
|
|
3013
3147
|
}
|
|
3014
3148
|
if (gobj.gclass.gmt.mt_command_parser) return gobj.gclass.gmt.mt_command_parser(gobj, command, kw, src);
|
|
3015
3149
|
if (gobj.gclass.command_table) {
|
|
@@ -3145,10 +3279,22 @@
|
|
|
3145
3279
|
f_warning = _console.warn;
|
|
3146
3280
|
}
|
|
3147
3281
|
}
|
|
3282
|
+
/************************************************************
|
|
3283
|
+
* JSON.stringify for a log line: a circular object (a gobj,
|
|
3284
|
+
* a DOM node) must not make the log call itself throw.
|
|
3285
|
+
************************************************************/
|
|
3286
|
+
function log_stringify(v) {
|
|
3287
|
+
try {
|
|
3288
|
+
return JSON.stringify(v);
|
|
3289
|
+
} catch (e) {
|
|
3290
|
+
return String(v);
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3148
3293
|
function format_log(format) {
|
|
3149
3294
|
const args = Array.prototype.slice.call(arguments);
|
|
3150
3295
|
let output = "";
|
|
3151
3296
|
if (typeof format === "string") {
|
|
3297
|
+
if (args.length === 1) return format;
|
|
3152
3298
|
let i = 1;
|
|
3153
3299
|
output = format.replace(/%[sdifoO]/g, (match) => {
|
|
3154
3300
|
const val = args[i++];
|
|
@@ -3158,17 +3304,17 @@
|
|
|
3158
3304
|
case "%i": return parseInt(val);
|
|
3159
3305
|
case "%f": return parseFloat(val);
|
|
3160
3306
|
case "%o":
|
|
3161
|
-
case "%O": return typeof val === "object" ?
|
|
3307
|
+
case "%O": return typeof val === "object" ? log_stringify(val) : String(val);
|
|
3162
3308
|
default: return match;
|
|
3163
3309
|
}
|
|
3164
3310
|
});
|
|
3165
|
-
const rest = args.slice(i).map((arg) => typeof arg === "object" ?
|
|
3311
|
+
const rest = args.slice(i).map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg));
|
|
3166
3312
|
if (rest.length > 0) output += " " + rest.join(" ");
|
|
3167
|
-
} else output = args.map((arg) => typeof arg === "object" ?
|
|
3313
|
+
} else output = args.map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg)).join(" ");
|
|
3168
3314
|
return output;
|
|
3169
3315
|
}
|
|
3170
|
-
function log_error(format) {
|
|
3171
|
-
let msg = format_log(format);
|
|
3316
|
+
function log_error(format, ...args) {
|
|
3317
|
+
let msg = format_log(format, ...args);
|
|
3172
3318
|
let hora = current_timestamp();
|
|
3173
3319
|
if (f_error) {
|
|
3174
3320
|
if (f_error === _console.error) {
|
|
@@ -3180,8 +3326,8 @@
|
|
|
3180
3326
|
}
|
|
3181
3327
|
emit_log_callback("error", msg, hora);
|
|
3182
3328
|
}
|
|
3183
|
-
function log_warning(format) {
|
|
3184
|
-
let msg = format_log(format);
|
|
3329
|
+
function log_warning(format, ...args) {
|
|
3330
|
+
let msg = format_log(format, ...args);
|
|
3185
3331
|
let hora = current_timestamp();
|
|
3186
3332
|
if (f_warning) {
|
|
3187
3333
|
if (f_warning === _console.warn) {
|
|
@@ -3193,24 +3339,24 @@
|
|
|
3193
3339
|
}
|
|
3194
3340
|
emit_log_callback("warning", msg, hora);
|
|
3195
3341
|
}
|
|
3196
|
-
function log_info(format) {
|
|
3197
|
-
let msg = format_log(format);
|
|
3342
|
+
function log_info(format, ...args) {
|
|
3343
|
+
let msg = format_log(format, ...args);
|
|
3198
3344
|
let hora = current_timestamp();
|
|
3199
3345
|
if (f_info) {
|
|
3200
3346
|
if (console_wants("info", msg)) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
|
|
3201
3347
|
}
|
|
3202
3348
|
emit_log_callback("info", msg, hora);
|
|
3203
3349
|
}
|
|
3204
|
-
function log_debug(format) {
|
|
3205
|
-
let msg = format_log(format);
|
|
3350
|
+
function log_debug(format, ...args) {
|
|
3351
|
+
let msg = format_log(format, ...args);
|
|
3206
3352
|
let hora = current_timestamp();
|
|
3207
3353
|
if (f_debug) {
|
|
3208
3354
|
if (console_wants("debug", msg)) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
|
|
3209
3355
|
}
|
|
3210
3356
|
emit_log_callback("debug", msg, hora);
|
|
3211
3357
|
}
|
|
3212
|
-
function trace_msg(format) {
|
|
3213
|
-
let msg = format_log(format);
|
|
3358
|
+
function trace_msg(format, ...args) {
|
|
3359
|
+
let msg = format_log(format, ...args);
|
|
3214
3360
|
let hora = current_timestamp();
|
|
3215
3361
|
if (f_debug) {
|
|
3216
3362
|
if (console_wants("msg", msg)) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
|
|
@@ -3225,6 +3371,268 @@
|
|
|
3225
3371
|
emit_log_callback("json", jn, current_timestamp());
|
|
3226
3372
|
}
|
|
3227
3373
|
/************************************************************
|
|
3374
|
+
* The names of the secrets (is_secret_name()). The same lists
|
|
3375
|
+
* as the C kernel's helpers.c: a name that holds one of these
|
|
3376
|
+
* (any case) is a secret.
|
|
3377
|
+
************************************************************/
|
|
3378
|
+
var SECRET_NAME_PARTS = [
|
|
3379
|
+
"passw",
|
|
3380
|
+
"pwd",
|
|
3381
|
+
"passphrase",
|
|
3382
|
+
"secret",
|
|
3383
|
+
"token",
|
|
3384
|
+
"jwt",
|
|
3385
|
+
"bearer",
|
|
3386
|
+
"authorization",
|
|
3387
|
+
"cookie",
|
|
3388
|
+
"credential",
|
|
3389
|
+
"salt"
|
|
3390
|
+
];
|
|
3391
|
+
var SECRET_NAME_JOINED = [
|
|
3392
|
+
"apikey",
|
|
3393
|
+
"sessionid",
|
|
3394
|
+
"sessionkey",
|
|
3395
|
+
"authdata"
|
|
3396
|
+
];
|
|
3397
|
+
var NOT_SECRET_SEGMENTS = /* @__PURE__ */ new Set([
|
|
3398
|
+
"endpoint",
|
|
3399
|
+
"url",
|
|
3400
|
+
"uri",
|
|
3401
|
+
"domain",
|
|
3402
|
+
"path",
|
|
3403
|
+
"file",
|
|
3404
|
+
"public",
|
|
3405
|
+
"pub",
|
|
3406
|
+
"count",
|
|
3407
|
+
"counts",
|
|
3408
|
+
"type",
|
|
3409
|
+
"name",
|
|
3410
|
+
"len",
|
|
3411
|
+
"length",
|
|
3412
|
+
"size",
|
|
3413
|
+
"max",
|
|
3414
|
+
"min",
|
|
3415
|
+
"ttl",
|
|
3416
|
+
"timeout",
|
|
3417
|
+
"expiry",
|
|
3418
|
+
"expires",
|
|
3419
|
+
"mode"
|
|
3420
|
+
]);
|
|
3421
|
+
/************************************************************
|
|
3422
|
+
* TRUE if `name` is the name of a secret: a password, a token,
|
|
3423
|
+
* a key... Any case. As the C kernel's is_secret_name().
|
|
3424
|
+
************************************************************/
|
|
3425
|
+
function is_secret_name(name) {
|
|
3426
|
+
if (typeof name !== "string" || name.length < 3) return false;
|
|
3427
|
+
let lower = name.toLowerCase();
|
|
3428
|
+
let hit = false;
|
|
3429
|
+
for (const part of SECRET_NAME_PARTS) if (lower.indexOf(part) >= 0) {
|
|
3430
|
+
hit = true;
|
|
3431
|
+
break;
|
|
3432
|
+
}
|
|
3433
|
+
if (!hit) {
|
|
3434
|
+
let joined = lower.replace(/[_\-. \t]/g, "");
|
|
3435
|
+
for (const part of SECRET_NAME_JOINED) if (joined.indexOf(part) >= 0) {
|
|
3436
|
+
hit = true;
|
|
3437
|
+
break;
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
if (!hit) hit = lower.indexOf("priv") >= 0 && lower.indexOf("key") >= 0;
|
|
3441
|
+
if (!hit) return false;
|
|
3442
|
+
for (const segment of lower.split(/[_\-. \t]/)) if (NOT_SECRET_SEGMENTS.has(segment)) return false;
|
|
3443
|
+
return true;
|
|
3444
|
+
}
|
|
3445
|
+
/************************************************************
|
|
3446
|
+
* Where an unquoted secret value that begins at `p` ends: at
|
|
3447
|
+
* the end, at the quote that closes an outer quoted value, or
|
|
3448
|
+
* before the next "word=" -- a plain word after a blank is still
|
|
3449
|
+
* part of it ("password=correct horse battery", "password=
|
|
3450
|
+
* hunter2"). As the C kernel's inline_secret_value_end().
|
|
3451
|
+
************************************************************/
|
|
3452
|
+
function inline_secret_value_end(str, p, outer) {
|
|
3453
|
+
const blank = (c) => c === " " || c === " ";
|
|
3454
|
+
const closes_outer = (i) => outer && str[i] === outer && (i + 1 >= str.length || blank(str[i + 1]));
|
|
3455
|
+
let end = p;
|
|
3456
|
+
while (true) {
|
|
3457
|
+
while (end < str.length && !blank(str[end])) {
|
|
3458
|
+
if (closes_outer(end)) return end;
|
|
3459
|
+
end++;
|
|
3460
|
+
}
|
|
3461
|
+
if (end >= str.length) return end;
|
|
3462
|
+
let w = end;
|
|
3463
|
+
while (w < str.length && blank(str[w])) w++;
|
|
3464
|
+
if (w >= str.length || closes_outer(w)) return end;
|
|
3465
|
+
for (let e = w; e < str.length && !blank(str[e]) && !closes_outer(e); e++) if (str[e] === "=" && e > w) return end;
|
|
3466
|
+
end = w;
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
/************************************************************
|
|
3470
|
+
* A text (a command line) with the value of every "name=value"
|
|
3471
|
+
* whose name is a secret's written as "********", quoted or not
|
|
3472
|
+
* (and the "value" of a write-attr whose attribute names a
|
|
3473
|
+
* secret). The rest as it is. Return null when there was nothing
|
|
3474
|
+
* to mask. As the C kernel's mask_secrets_inline().
|
|
3475
|
+
************************************************************/
|
|
3476
|
+
var MASK_MAX_NAME = 128;
|
|
3477
|
+
var MASK_MAX_BYTES = 4194304;
|
|
3478
|
+
var MASK_TOO_LARGE = "<not shown: too large to mask>";
|
|
3479
|
+
function mask_secrets_inline(str) {
|
|
3480
|
+
if (typeof str !== "string" || str.indexOf("=") < 0) return null;
|
|
3481
|
+
if (str.length > MASK_MAX_BYTES) return MASK_TOO_LARGE;
|
|
3482
|
+
let value_is_secret = false;
|
|
3483
|
+
let re_attr = /(^|[ \t])attribute=["']?([^ \t"']*)/g;
|
|
3484
|
+
let m;
|
|
3485
|
+
while ((m = re_attr.exec(str)) !== null) if (is_secret_name(m[2].slice(-128))) value_is_secret = true;
|
|
3486
|
+
let parts = [];
|
|
3487
|
+
let copied = 0;
|
|
3488
|
+
let changed = false;
|
|
3489
|
+
let outer = "";
|
|
3490
|
+
let word = 0;
|
|
3491
|
+
let p = 0;
|
|
3492
|
+
const is_blank_or_end = (i) => i >= str.length || str[i] === " " || str[i] === " ";
|
|
3493
|
+
while (p < str.length) {
|
|
3494
|
+
let c = str[p];
|
|
3495
|
+
if (c === " " || c === " ") {
|
|
3496
|
+
p++;
|
|
3497
|
+
word = p;
|
|
3498
|
+
continue;
|
|
3499
|
+
}
|
|
3500
|
+
if (c === "\"" || c === "'") {
|
|
3501
|
+
if (!outer && (p === 0 || str[p - 1] === " " || str[p - 1] === " " || str[p - 1] === "=")) outer = c;
|
|
3502
|
+
else if (c === outer && is_blank_or_end(p + 1)) outer = "";
|
|
3503
|
+
}
|
|
3504
|
+
if (c !== "=") {
|
|
3505
|
+
p++;
|
|
3506
|
+
continue;
|
|
3507
|
+
}
|
|
3508
|
+
let name = str.substring(Math.max(word, p - MASK_MAX_NAME), p);
|
|
3509
|
+
word = p + 1;
|
|
3510
|
+
if (!(is_secret_name(name) || value_is_secret && name.toLowerCase() === "value")) {
|
|
3511
|
+
p++;
|
|
3512
|
+
continue;
|
|
3513
|
+
}
|
|
3514
|
+
p++;
|
|
3515
|
+
let quote = str[p] === "\"" || str[p] === "'" ? str[p] : "";
|
|
3516
|
+
let end;
|
|
3517
|
+
if (quote) {
|
|
3518
|
+
end = p + 1;
|
|
3519
|
+
while (end < str.length && str[end] !== quote) end++;
|
|
3520
|
+
if (str[end] === quote) end++;
|
|
3521
|
+
} else end = inline_secret_value_end(str, p, outer);
|
|
3522
|
+
if (end > p) {
|
|
3523
|
+
parts.push(str.substring(copied, p));
|
|
3524
|
+
parts.push("********");
|
|
3525
|
+
copied = end;
|
|
3526
|
+
changed = true;
|
|
3527
|
+
}
|
|
3528
|
+
p = end;
|
|
3529
|
+
word = p;
|
|
3530
|
+
}
|
|
3531
|
+
if (!changed) return null;
|
|
3532
|
+
parts.push(str.substring(copied));
|
|
3533
|
+
return parts.join("");
|
|
3534
|
+
}
|
|
3535
|
+
/************************************************************
|
|
3536
|
+
* A json as a log or a trace may show it: at any depth, the
|
|
3537
|
+
* value of a key with a secret's name is "********", whatever
|
|
3538
|
+
* its type (not an absent one, a null or an empty string); so is
|
|
3539
|
+
* the "value" of a dict whose "attribute" names a secret; and a
|
|
3540
|
+
* string is masked as mask_secrets_inline(). Return a masked
|
|
3541
|
+
* copy, or `jn` itself when there was nothing to mask. As the C
|
|
3542
|
+
* kernel's json_mask_secrets().
|
|
3543
|
+
*
|
|
3544
|
+
* Only JSON is walked: plain objects (their prototype is
|
|
3545
|
+
* Object.prototype or null) and arrays. Anything else -- a gobj,
|
|
3546
|
+
* a DOM node, a class instance, a typed array, a function -- is
|
|
3547
|
+
* passed as it is, never walked, as trace_json() always showed it
|
|
3548
|
+
* (a kw may carry a gobj: its parent and children make a cycle).
|
|
3549
|
+
* A plain object met twice is masked once, the same everywhere; a
|
|
3550
|
+
* cycle back to one is "<cycle>"; below MASK_MAX_DEPTH levels
|
|
3551
|
+
* (64, as in C) nothing is shown.
|
|
3552
|
+
* It never throws: a failure is the placeholder below.
|
|
3553
|
+
************************************************************/
|
|
3554
|
+
var MASK_MAX_DEPTH = 64;
|
|
3555
|
+
var MASK_FAILED = "<not shown: the masking failed>";
|
|
3556
|
+
function is_plain_object(value) {
|
|
3557
|
+
if (value === null || typeof value !== "object") return false;
|
|
3558
|
+
let proto = Object.getPrototypeOf(value);
|
|
3559
|
+
return proto === Object.prototype || proto === null;
|
|
3560
|
+
}
|
|
3561
|
+
var MASK_IN_PROGRESS = Symbol("mask-in-progress");
|
|
3562
|
+
function _json_mask_secrets(jn, memo, depth, budget) {
|
|
3563
|
+
if (typeof jn === "string") {
|
|
3564
|
+
if (jn.length > budget.left) {
|
|
3565
|
+
budget.left = 0;
|
|
3566
|
+
return MASK_TOO_LARGE;
|
|
3567
|
+
}
|
|
3568
|
+
budget.left -= jn.length;
|
|
3569
|
+
let masked = mask_secrets_inline(jn);
|
|
3570
|
+
return masked !== null ? masked : jn;
|
|
3571
|
+
}
|
|
3572
|
+
let is_array = Array.isArray(jn);
|
|
3573
|
+
if (!is_array && !is_plain_object(jn)) return jn;
|
|
3574
|
+
if (budget.left <= 0) return MASK_TOO_LARGE;
|
|
3575
|
+
if (memo.has(jn)) {
|
|
3576
|
+
let seen = memo.get(jn);
|
|
3577
|
+
return seen === MASK_IN_PROGRESS ? "<cycle>" : seen;
|
|
3578
|
+
}
|
|
3579
|
+
if (depth >= MASK_MAX_DEPTH) return "<deeper not shown>";
|
|
3580
|
+
budget.left -= 1;
|
|
3581
|
+
memo.set(jn, MASK_IN_PROGRESS);
|
|
3582
|
+
let changed = false;
|
|
3583
|
+
let truncated = false;
|
|
3584
|
+
let result;
|
|
3585
|
+
if (is_array) {
|
|
3586
|
+
result = [];
|
|
3587
|
+
for (let i = 0; i < jn.length; i++) {
|
|
3588
|
+
if (budget.left <= 0) {
|
|
3589
|
+
truncated = true;
|
|
3590
|
+
break;
|
|
3591
|
+
}
|
|
3592
|
+
budget.left -= 1;
|
|
3593
|
+
let shown = _json_mask_secrets(jn[i], memo, depth + 1, budget);
|
|
3594
|
+
if (shown !== jn[i]) changed = true;
|
|
3595
|
+
result.push(shown);
|
|
3596
|
+
}
|
|
3597
|
+
if (truncated) result.push(MASK_TOO_LARGE);
|
|
3598
|
+
} else {
|
|
3599
|
+
result = Object.create(Object.getPrototypeOf(jn));
|
|
3600
|
+
let value_is_secret = typeof jn.attribute === "string" && is_secret_name(jn.attribute.slice(-128));
|
|
3601
|
+
for (const key in jn) {
|
|
3602
|
+
if (!Object.prototype.hasOwnProperty.call(jn, key)) continue;
|
|
3603
|
+
if (budget.left <= 0) {
|
|
3604
|
+
truncated = true;
|
|
3605
|
+
break;
|
|
3606
|
+
}
|
|
3607
|
+
budget.left -= 1 + key.length;
|
|
3608
|
+
let value = jn[key];
|
|
3609
|
+
let shown;
|
|
3610
|
+
if ((is_secret_name(key.slice(-128)) || value_is_secret && key === "value") && value !== void 0 && value !== null && value !== "") shown = "********";
|
|
3611
|
+
else shown = _json_mask_secrets(value, memo, depth + 1, budget);
|
|
3612
|
+
if (shown !== value) changed = true;
|
|
3613
|
+
result[key] = shown;
|
|
3614
|
+
}
|
|
3615
|
+
if (truncated) result["<more>"] = MASK_TOO_LARGE;
|
|
3616
|
+
}
|
|
3617
|
+
if (!changed && !truncated) result = jn;
|
|
3618
|
+
memo.set(jn, result);
|
|
3619
|
+
return result;
|
|
3620
|
+
}
|
|
3621
|
+
function json_mask_secrets(jn) {
|
|
3622
|
+
try {
|
|
3623
|
+
return _json_mask_secrets(jn, /* @__PURE__ */ new WeakMap(), 0, { left: MASK_MAX_BYTES });
|
|
3624
|
+
} catch (e) {
|
|
3625
|
+
return MASK_FAILED;
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
/************************************************************
|
|
3629
|
+
* trace_json() of a json that can hold a credential: what
|
|
3630
|
+
* json_mask_secrets() masks is shown masked
|
|
3631
|
+
************************************************************/
|
|
3632
|
+
function trace_json_masked(jn, msg) {
|
|
3633
|
+
trace_json(json_mask_secrets(jn), msg);
|
|
3634
|
+
}
|
|
3635
|
+
/************************************************************
|
|
3228
3636
|
* Duplicate an object (new references)
|
|
3229
3637
|
* using the modern structuredClone (Deep copy of a single object)
|
|
3230
3638
|
************************************************************/
|
|
@@ -3497,6 +3905,8 @@
|
|
|
3497
3905
|
if (is_number(jn_var1) || is_number(jn_var2)) {
|
|
3498
3906
|
let val1 = Number(jn_var1);
|
|
3499
3907
|
let val2 = Number(jn_var2);
|
|
3908
|
+
if (Number.isNaN(val1)) val1 = 0;
|
|
3909
|
+
if (Number.isNaN(val2)) val2 = 0;
|
|
3500
3910
|
if (val1 > val2) return 1;
|
|
3501
3911
|
else if (val1 < val2) return -1;
|
|
3502
3912
|
else return 0;
|
|
@@ -3526,8 +3936,8 @@
|
|
|
3526
3936
|
***************************************************************************/
|
|
3527
3937
|
function is_metadata_key(key) {
|
|
3528
3938
|
if (!is_string(key)) return false;
|
|
3529
|
-
let i;
|
|
3530
|
-
for (
|
|
3939
|
+
let i = 0;
|
|
3940
|
+
for (; i < key.length; i++) {
|
|
3531
3941
|
if (key[i] !== "_") break;
|
|
3532
3942
|
if (i > 2) break;
|
|
3533
3943
|
}
|
|
@@ -3538,8 +3948,8 @@
|
|
|
3538
3948
|
***************************************************************************/
|
|
3539
3949
|
function is_private_key(key) {
|
|
3540
3950
|
if (!is_string(key)) return false;
|
|
3541
|
-
let i;
|
|
3542
|
-
for (
|
|
3951
|
+
let i = 0;
|
|
3952
|
+
for (; i < key.length; i++) {
|
|
3543
3953
|
if (key[i] !== "_") break;
|
|
3544
3954
|
if (i > 2) break;
|
|
3545
3955
|
}
|
|
@@ -3564,6 +3974,28 @@
|
|
|
3564
3974
|
return false;
|
|
3565
3975
|
}
|
|
3566
3976
|
/************************************************************
|
|
3977
|
+
* A key that reaches the prototype chain instead of the data:
|
|
3978
|
+
* "__proto__", "constructor" or "prototype" when the object
|
|
3979
|
+
* does not hold it as its OWN key. A walk through one of them
|
|
3980
|
+
* read, or WROTE, Object.prototype: the flat id
|
|
3981
|
+
* "__proto__`polluted" set a key on every object of the page.
|
|
3982
|
+
* In C they are keys like any other, so here too: read them
|
|
3983
|
+
* only as own keys, and write "__proto__" as an own key.
|
|
3984
|
+
************************************************************/
|
|
3985
|
+
function is_prototype_segment(obj, key) {
|
|
3986
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") return !Object.prototype.hasOwnProperty.call(obj, key);
|
|
3987
|
+
return false;
|
|
3988
|
+
}
|
|
3989
|
+
function set_own_key(obj, key, value) {
|
|
3990
|
+
if (key === "__proto__") Object.defineProperty(obj, key, {
|
|
3991
|
+
value,
|
|
3992
|
+
writable: true,
|
|
3993
|
+
enumerable: true,
|
|
3994
|
+
configurable: true
|
|
3995
|
+
});
|
|
3996
|
+
else obj[key] = value;
|
|
3997
|
+
}
|
|
3998
|
+
/************************************************************
|
|
3567
3999
|
* The value at `path` (keys joined by a backtick), as the C
|
|
3568
4000
|
* kw_find_path() finds it: undefined when it is not there.
|
|
3569
4001
|
* A kw that is not a dict or a list is LOGGED ("kw must be list
|
|
@@ -3590,7 +4022,12 @@
|
|
|
3590
4022
|
}
|
|
3591
4023
|
let ss = path.split("`");
|
|
3592
4024
|
let len = ss.length;
|
|
3593
|
-
for (let i = 0; i < len
|
|
4025
|
+
for (let i = 0; i < len; i++) {
|
|
4026
|
+
if (is_prototype_segment(kw, ss[i])) {
|
|
4027
|
+
if (verbose) log_error(`${prefix}path not found: '${path}'`);
|
|
4028
|
+
return;
|
|
4029
|
+
}
|
|
4030
|
+
if (i === len - 1) break;
|
|
3594
4031
|
kw = kw[ss[i]];
|
|
3595
4032
|
if (kw === void 0 || kw === null) {
|
|
3596
4033
|
if (verbose) log_error(`${prefix}path not found: '${path}'`);
|
|
@@ -3650,7 +4087,7 @@
|
|
|
3650
4087
|
return v;
|
|
3651
4088
|
} else if (required) {
|
|
3652
4089
|
log_error(`path not found: '${path}'`);
|
|
3653
|
-
|
|
4090
|
+
trace_json_masked(kw);
|
|
3654
4091
|
}
|
|
3655
4092
|
return Boolean(default_value);
|
|
3656
4093
|
}
|
|
@@ -3664,11 +4101,11 @@
|
|
|
3664
4101
|
} else if (wild && b === null) value = false;
|
|
3665
4102
|
else if (wild) {
|
|
3666
4103
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
|
|
3667
|
-
|
|
4104
|
+
trace_json_masked(kw);
|
|
3668
4105
|
return false;
|
|
3669
4106
|
} else {
|
|
3670
4107
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json boolean: '${path}'`);
|
|
3671
|
-
|
|
4108
|
+
trace_json_masked(kw);
|
|
3672
4109
|
return Boolean(default_value);
|
|
3673
4110
|
}
|
|
3674
4111
|
if (extract) kw_delete(gobj, kw, path);
|
|
@@ -3718,7 +4155,7 @@
|
|
|
3718
4155
|
return v;
|
|
3719
4156
|
} else if (required) {
|
|
3720
4157
|
log_error(`path not found: '${path}'`);
|
|
3721
|
-
|
|
4158
|
+
trace_json_masked(kw);
|
|
3722
4159
|
}
|
|
3723
4160
|
return parseInt(default_value);
|
|
3724
4161
|
}
|
|
@@ -3726,14 +4163,14 @@
|
|
|
3726
4163
|
if (is_number(v)) value = Math.trunc(v);
|
|
3727
4164
|
else if (!wild) {
|
|
3728
4165
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json integer: '${path}'`);
|
|
3729
|
-
|
|
4166
|
+
trace_json_masked(kw);
|
|
3730
4167
|
return parseInt(default_value);
|
|
3731
4168
|
} else if (is_boolean(v)) value = v ? 1 : 0;
|
|
3732
4169
|
else if (is_string(v)) value = strtoll_base0(v);
|
|
3733
4170
|
else if (v === null) value = 0;
|
|
3734
4171
|
else {
|
|
3735
4172
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
|
|
3736
|
-
|
|
4173
|
+
trace_json_masked(kw);
|
|
3737
4174
|
return 0;
|
|
3738
4175
|
}
|
|
3739
4176
|
if (extract) kw_delete(gobj, kw, path);
|
|
@@ -3765,7 +4202,7 @@
|
|
|
3765
4202
|
return v;
|
|
3766
4203
|
} else if (required) {
|
|
3767
4204
|
log_error(`path not found: '${path}'`);
|
|
3768
|
-
|
|
4205
|
+
trace_json_masked(kw);
|
|
3769
4206
|
}
|
|
3770
4207
|
return Number(default_value);
|
|
3771
4208
|
}
|
|
@@ -3773,7 +4210,7 @@
|
|
|
3773
4210
|
if (is_number(v)) value = v;
|
|
3774
4211
|
else if (!wild) {
|
|
3775
4212
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json real: '${path}'`);
|
|
3776
|
-
|
|
4213
|
+
trace_json_masked(kw);
|
|
3777
4214
|
return Number(default_value);
|
|
3778
4215
|
} else if (is_boolean(v)) value = v ? 1 : 0;
|
|
3779
4216
|
else if (is_string(v)) {
|
|
@@ -3782,7 +4219,7 @@
|
|
|
3782
4219
|
} else if (v === null) value = 0;
|
|
3783
4220
|
else {
|
|
3784
4221
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a simple json element: '${path}'`);
|
|
3785
|
-
|
|
4222
|
+
trace_json_masked(kw);
|
|
3786
4223
|
return 0;
|
|
3787
4224
|
}
|
|
3788
4225
|
if (extract) kw_delete(gobj, kw, path);
|
|
@@ -3834,14 +4271,14 @@
|
|
|
3834
4271
|
return default_value;
|
|
3835
4272
|
} else if (required && !kw_path_holds_key(kw, path)) {
|
|
3836
4273
|
log_error(`path not found: '${path}'`);
|
|
3837
|
-
|
|
4274
|
+
trace_json_masked(kw);
|
|
3838
4275
|
}
|
|
3839
4276
|
return default_value;
|
|
3840
4277
|
}
|
|
3841
4278
|
if (!is_string(v)) {
|
|
3842
4279
|
if (v !== null) {
|
|
3843
4280
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json str: '${path}'`);
|
|
3844
|
-
|
|
4281
|
+
trace_json_masked(kw);
|
|
3845
4282
|
}
|
|
3846
4283
|
return default_value;
|
|
3847
4284
|
}
|
|
@@ -3864,7 +4301,7 @@
|
|
|
3864
4301
|
return v;
|
|
3865
4302
|
} else if (required) {
|
|
3866
4303
|
log_error(`path not found: '${path}'`);
|
|
3867
|
-
|
|
4304
|
+
trace_json_masked(kw);
|
|
3868
4305
|
}
|
|
3869
4306
|
return default_value;
|
|
3870
4307
|
}
|
|
@@ -3891,14 +4328,14 @@
|
|
|
3891
4328
|
}
|
|
3892
4329
|
if (required) {
|
|
3893
4330
|
log_error(`path not found: '${path}'`);
|
|
3894
|
-
|
|
4331
|
+
trace_json_masked(kw);
|
|
3895
4332
|
}
|
|
3896
4333
|
return default_value;
|
|
3897
4334
|
}
|
|
3898
4335
|
if (!is_object(v)) {
|
|
3899
4336
|
if (required) {
|
|
3900
4337
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json dict: '${path}'`);
|
|
3901
|
-
|
|
4338
|
+
trace_json_masked(kw);
|
|
3902
4339
|
}
|
|
3903
4340
|
return default_value;
|
|
3904
4341
|
}
|
|
@@ -3921,7 +4358,7 @@
|
|
|
3921
4358
|
return v;
|
|
3922
4359
|
} else if (required) {
|
|
3923
4360
|
log_error(`path not found: '${path}'`);
|
|
3924
|
-
|
|
4361
|
+
trace_json_masked(kw);
|
|
3925
4362
|
}
|
|
3926
4363
|
return default_value;
|
|
3927
4364
|
}
|
|
@@ -3949,14 +4386,14 @@
|
|
|
3949
4386
|
}
|
|
3950
4387
|
if (required) {
|
|
3951
4388
|
log_error(`path not found: '${path}'`);
|
|
3952
|
-
|
|
4389
|
+
trace_json_masked(kw);
|
|
3953
4390
|
}
|
|
3954
4391
|
return default_value;
|
|
3955
4392
|
}
|
|
3956
4393
|
if (!is_array(v)) {
|
|
3957
4394
|
if (required) {
|
|
3958
4395
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}path MUST BE a json list: '${path}'`);
|
|
3959
|
-
|
|
4396
|
+
trace_json_masked(kw);
|
|
3960
4397
|
}
|
|
3961
4398
|
return default_value;
|
|
3962
4399
|
}
|
|
@@ -3973,17 +4410,13 @@
|
|
|
3973
4410
|
return -1;
|
|
3974
4411
|
}
|
|
3975
4412
|
let ss = path.split("`");
|
|
3976
|
-
if (ss.length <= 1) {
|
|
3977
|
-
kw[path] = value;
|
|
3978
|
-
return 0;
|
|
3979
|
-
}
|
|
3980
4413
|
let len = ss.length;
|
|
3981
4414
|
for (let i = 0; i < len; i++) {
|
|
3982
4415
|
let key = ss[i];
|
|
3983
|
-
if (i === len - 1) kw
|
|
4416
|
+
if (i === len - 1) set_own_key(kw, key, value);
|
|
3984
4417
|
else {
|
|
3985
|
-
let seg = kw[key];
|
|
3986
|
-
if (seg === void 0) kw
|
|
4418
|
+
let seg = is_prototype_segment(kw, key) ? void 0 : kw[key];
|
|
4419
|
+
if (seg === void 0) set_own_key(kw, key, {});
|
|
3987
4420
|
else if (!is_object(seg) && !is_array(seg)) {
|
|
3988
4421
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_set_dict_value(): segment '${key}' is not a dict or a list: '${path}'`);
|
|
3989
4422
|
return -1;
|
|
@@ -4038,9 +4471,9 @@
|
|
|
4038
4471
|
if (!matched) break;
|
|
4039
4472
|
continue;
|
|
4040
4473
|
}
|
|
4041
|
-
let jn_record_value = kw_get_dict_value(0, kw, path, 0, 0);
|
|
4042
|
-
if (
|
|
4043
|
-
if (
|
|
4474
|
+
let jn_record_value = kw_get_dict_value(0, kw, path, void 0, 0);
|
|
4475
|
+
if (jn_record_value === void 0) jn_record_value = json_object_get(kw, path);
|
|
4476
|
+
if (jn_record_value === void 0) {
|
|
4044
4477
|
matched = false;
|
|
4045
4478
|
break;
|
|
4046
4479
|
}
|
|
@@ -4159,10 +4592,11 @@
|
|
|
4159
4592
|
***************************************************************************/
|
|
4160
4593
|
function kw_clone_by_not_keys(gobj, kw, keys, verbose) {
|
|
4161
4594
|
let kw_clone = {};
|
|
4595
|
+
if (!is_object(kw)) return kw_clone;
|
|
4162
4596
|
json_object_update(kw_clone, kw);
|
|
4163
4597
|
if (is_string(keys) && !empty_string(keys)) {
|
|
4164
4598
|
let key = keys;
|
|
4165
|
-
if (
|
|
4599
|
+
if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
|
|
4166
4600
|
else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
|
|
4167
4601
|
} else if (is_object(keys) && json_object_size(keys) > 0) {
|
|
4168
4602
|
for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
|
|
@@ -5122,9 +5556,15 @@
|
|
|
5122
5556
|
* will be 'data-i18n' attr
|
|
5123
5557
|
*
|
|
5124
5558
|
* content -> string | [createElement2() or parameters of createElement2]
|
|
5559
|
+
* | HTMLElement | SVGElement | Text
|
|
5125
5560
|
* if string begins with '<' then
|
|
5126
5561
|
* it will be converted to HTMLElement
|
|
5127
5562
|
* content = createOneHtml(string)
|
|
5563
|
+
* ⚠️ So a string is MARKUP when it starts with '<': never
|
|
5564
|
+
* pass DATA (a value from a backend, a name a user typed)
|
|
5565
|
+
* as a bare string, or "<img src=x onerror=...>" runs.
|
|
5566
|
+
* Pass it as a Text node, which is always text:
|
|
5567
|
+
* ['span', {}, document.createTextNode(value)]
|
|
5128
5568
|
* if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
|
|
5129
5569
|
* it will be overridden with the translation
|
|
5130
5570
|
* content = translate(attrs['i18n']));
|
|
@@ -5563,7 +6003,7 @@
|
|
|
5563
6003
|
current[seg] = flat[key];
|
|
5564
6004
|
} else {
|
|
5565
6005
|
if (Object.prototype.hasOwnProperty.call(current, seg)) throw new Error(`flat2json: '${key}' is written twice, or once as a value and once as a container`);
|
|
5566
|
-
current
|
|
6006
|
+
set_own_key(current, seg, flat[key]);
|
|
5567
6007
|
}
|
|
5568
6008
|
break;
|
|
5569
6009
|
}
|
|
@@ -5576,10 +6016,10 @@
|
|
|
5576
6016
|
current[seg] = child;
|
|
5577
6017
|
}
|
|
5578
6018
|
} else {
|
|
5579
|
-
child = current[seg];
|
|
6019
|
+
child = is_prototype_segment(current, seg) ? void 0 : current[seg];
|
|
5580
6020
|
if (child === void 0) {
|
|
5581
6021
|
child = next_is_index ? [] : {};
|
|
5582
|
-
current
|
|
6022
|
+
set_own_key(current, seg, child);
|
|
5583
6023
|
}
|
|
5584
6024
|
}
|
|
5585
6025
|
if (child === null || typeof child !== "object") throw new Error(`flat2json: '${key}' walks through a value: the same id is a leaf and a container at once`);
|
|
@@ -6342,6 +6782,7 @@
|
|
|
6342
6782
|
***************************************************************/
|
|
6343
6783
|
function mt_play(gobj) {
|
|
6344
6784
|
let default_service = gobj_default_service();
|
|
6785
|
+
if (!default_service) return 0;
|
|
6345
6786
|
if (!gobj_is_running(default_service)) gobj_start(default_service);
|
|
6346
6787
|
if (!gobj_is_playing(default_service)) gobj_play(default_service);
|
|
6347
6788
|
return 0;
|
|
@@ -6350,7 +6791,8 @@
|
|
|
6350
6791
|
* Framework Method: Pause
|
|
6351
6792
|
***************************************************************/
|
|
6352
6793
|
function mt_pause(gobj) {
|
|
6353
|
-
|
|
6794
|
+
let default_service = gobj_default_service();
|
|
6795
|
+
if (default_service && gobj_is_playing(default_service)) gobj_pause(default_service);
|
|
6354
6796
|
return 0;
|
|
6355
6797
|
}
|
|
6356
6798
|
/***************************************************************
|
|
@@ -6606,6 +7048,7 @@
|
|
|
6606
7048
|
function mt_create(gobj) {
|
|
6607
7049
|
let priv = gobj.priv;
|
|
6608
7050
|
priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), "C_TIMER", {}, gobj);
|
|
7051
|
+
priv.ws_seq = 0;
|
|
6609
7052
|
priv.url = gobj_read_str_attr(gobj, "url");
|
|
6610
7053
|
priv.remote_yuno_name = gobj_read_str_attr(gobj, "remote_yuno_name");
|
|
6611
7054
|
priv.remote_yuno_role = gobj_read_str_attr(gobj, "remote_yuno_role");
|
|
@@ -6640,6 +7083,16 @@
|
|
|
6640
7083
|
function mt_start(gobj) {
|
|
6641
7084
|
let priv = gobj.priv;
|
|
6642
7085
|
priv.retry_ms = 0;
|
|
7086
|
+
if (gobj_current_state(gobj) !== "ST_DISCONNECTED") {
|
|
7087
|
+
gobj_send_event(gobj, "EV_ON_CLOSE", {
|
|
7088
|
+
url: priv.url,
|
|
7089
|
+
ws_seq: priv.ws_seq,
|
|
7090
|
+
code: 1e3,
|
|
7091
|
+
reason: "restarted",
|
|
7092
|
+
was_clean: true
|
|
7093
|
+
}, gobj);
|
|
7094
|
+
clear_timeout(priv.gobj_timer);
|
|
7095
|
+
}
|
|
6643
7096
|
priv.websocket = setup_websocket(gobj);
|
|
6644
7097
|
return 0;
|
|
6645
7098
|
}
|
|
@@ -6774,10 +7227,16 @@
|
|
|
6774
7227
|
log_error(`${gobj_short_name(gobj)}: Failed to initialize WebSocket.`);
|
|
6775
7228
|
return null;
|
|
6776
7229
|
}
|
|
7230
|
+
const ws_seq = ++gobj.priv.ws_seq;
|
|
6777
7231
|
websocket.onopen = () => {
|
|
6778
|
-
|
|
7232
|
+
if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
|
|
7233
|
+
gobj_send_event(gobj, "EV_ON_OPEN", {
|
|
7234
|
+
url,
|
|
7235
|
+
ws_seq
|
|
7236
|
+
}, gobj);
|
|
6779
7237
|
};
|
|
6780
7238
|
websocket.onmessage = (e) => {
|
|
7239
|
+
if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
|
|
6781
7240
|
gobj_send_event(gobj, "EV_ON_MESSAGE", {
|
|
6782
7241
|
url,
|
|
6783
7242
|
data: e.data
|
|
@@ -6785,9 +7244,13 @@
|
|
|
6785
7244
|
};
|
|
6786
7245
|
websocket.onclose = (e) => {
|
|
6787
7246
|
if (gobj_is_destroying(gobj)) return;
|
|
7247
|
+
if (ws_seq !== gobj.priv.ws_seq) return;
|
|
6788
7248
|
if (!gobj_read_bool_attr(gobj_yuno(), "browser_beforeunload")) gobj_send_event(gobj, "EV_ON_CLOSE", {
|
|
6789
7249
|
url,
|
|
6790
|
-
|
|
7250
|
+
ws_seq,
|
|
7251
|
+
code: e.code,
|
|
7252
|
+
reason: e.reason,
|
|
7253
|
+
was_clean: e.wasClean
|
|
6791
7254
|
}, gobj);
|
|
6792
7255
|
else log_warning("Close websocket by unload page");
|
|
6793
7256
|
};
|
|
@@ -6808,7 +7271,7 @@
|
|
|
6808
7271
|
try {
|
|
6809
7272
|
websocket.close(code, reason);
|
|
6810
7273
|
} catch (e) {
|
|
6811
|
-
log_error(
|
|
7274
|
+
log_error(`${gobj_short_name(gobj)}: Error closing WebSocket: ${e.message}`);
|
|
6812
7275
|
}
|
|
6813
7276
|
}
|
|
6814
7277
|
/***************************************************************
|
|
@@ -6818,7 +7281,7 @@
|
|
|
6818
7281
|
let hora = current_timestamp();
|
|
6819
7282
|
try {
|
|
6820
7283
|
log_debug("\n" + hora + " " + prefix + "\n");
|
|
6821
|
-
|
|
7284
|
+
trace_json_masked(iev);
|
|
6822
7285
|
} catch (e) {
|
|
6823
7286
|
log_debug("ERROR in trace_inter_event: " + e);
|
|
6824
7287
|
}
|
|
@@ -6934,29 +7397,29 @@
|
|
|
6934
7397
|
try {
|
|
6935
7398
|
x = JSON.parse(data);
|
|
6936
7399
|
} catch (e) {
|
|
6937
|
-
|
|
7400
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event json: ${e}`);
|
|
6938
7401
|
return null;
|
|
6939
7402
|
}
|
|
6940
7403
|
if (!(x instanceof Object)) {
|
|
6941
|
-
|
|
7404
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: websocket data not a json object`);
|
|
6942
7405
|
return null;
|
|
6943
7406
|
}
|
|
6944
7407
|
let event = x["event"];
|
|
6945
7408
|
if (!event) {
|
|
6946
|
-
|
|
7409
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: no event`);
|
|
6947
7410
|
return null;
|
|
6948
7411
|
}
|
|
6949
7412
|
if (typeof event !== "string") {
|
|
6950
|
-
|
|
7413
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: event not a string`);
|
|
6951
7414
|
return null;
|
|
6952
7415
|
}
|
|
6953
7416
|
let kw = x["kw"];
|
|
6954
7417
|
if (!kw) {
|
|
6955
|
-
|
|
7418
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_kw: no kw`);
|
|
6956
7419
|
return null;
|
|
6957
7420
|
}
|
|
6958
7421
|
if (!(kw instanceof Object)) {
|
|
6959
|
-
|
|
7422
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: kw not a json object`);
|
|
6960
7423
|
return null;
|
|
6961
7424
|
}
|
|
6962
7425
|
return {
|
|
@@ -7016,10 +7479,9 @@
|
|
|
7016
7479
|
***************************************************************/
|
|
7017
7480
|
function ac_on_close(gobj, event, kw, src) {
|
|
7018
7481
|
let priv = gobj.priv;
|
|
7019
|
-
let e = kw.e;
|
|
7020
7482
|
let url = kw.url;
|
|
7021
7483
|
set_remote_log_functions();
|
|
7022
|
-
log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${
|
|
7484
|
+
log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
|
|
7023
7485
|
if (priv.websocket) {
|
|
7024
7486
|
priv.websocket.onopen = null;
|
|
7025
7487
|
priv.websocket.onmessage = null;
|
|
@@ -7036,15 +7498,15 @@
|
|
|
7036
7498
|
remote_yuno_service: priv.remote_yuno_service
|
|
7037
7499
|
});
|
|
7038
7500
|
} else {
|
|
7039
|
-
log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${
|
|
7501
|
+
log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
|
|
7040
7502
|
gobj_publish_event(gobj, "EV_ON_OPEN_ERROR", {
|
|
7041
7503
|
url,
|
|
7042
7504
|
remote_yuno_name: priv.remote_yuno_name,
|
|
7043
7505
|
remote_yuno_role: priv.remote_yuno_role,
|
|
7044
7506
|
remote_yuno_service: priv.remote_yuno_service,
|
|
7045
|
-
code:
|
|
7046
|
-
reason:
|
|
7047
|
-
was_clean:
|
|
7507
|
+
code: kw.code,
|
|
7508
|
+
reason: kw.reason,
|
|
7509
|
+
was_clean: kw.was_clean
|
|
7048
7510
|
});
|
|
7049
7511
|
}
|
|
7050
7512
|
if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, next_retry(gobj));
|
|
@@ -7142,6 +7604,10 @@
|
|
|
7142
7604
|
function ac_on_message(gobj, event, kw, src) {
|
|
7143
7605
|
let url = gobj.priv.url;
|
|
7144
7606
|
let iev_msg = iev_create_from_json(gobj, kw.data);
|
|
7607
|
+
if (!iev_msg) {
|
|
7608
|
+
log_warning(`${gobj_short_name(gobj)}: frame dropped from ${url}: ${String(kw.data).substring(0, 256)}`);
|
|
7609
|
+
return -1;
|
|
7610
|
+
}
|
|
7145
7611
|
if (is_traffic_tracing(gobj)) {
|
|
7146
7612
|
let prefix = gobj_name(gobj_yuno()) + " <== " + url;
|
|
7147
7613
|
let size = kw.data.length;
|
|
@@ -7167,8 +7633,14 @@
|
|
|
7167
7633
|
return 0;
|
|
7168
7634
|
}
|
|
7169
7635
|
let iev_dst_service = kw_get_str(gobj, event_id, "dst_service", "");
|
|
7170
|
-
if (msg_type === "__subscribing__")
|
|
7171
|
-
|
|
7636
|
+
if (msg_type === "__subscribing__") {
|
|
7637
|
+
log_warning(`${gobj_short_name(gobj)}: subscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
|
|
7638
|
+
return -1;
|
|
7639
|
+
}
|
|
7640
|
+
if (msg_type === "__unsubscribing__") {
|
|
7641
|
+
log_warning(`${gobj_short_name(gobj)}: unsubscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
|
|
7642
|
+
return -1;
|
|
7643
|
+
}
|
|
7172
7644
|
if (gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
|
|
7173
7645
|
gobj_send_event(gobj, iev_event, iev_kw, gobj);
|
|
7174
7646
|
return 0;
|
|
@@ -7500,6 +7972,7 @@
|
|
|
7500
7972
|
exports.is_object = is_object;
|
|
7501
7973
|
exports.is_private_key = is_private_key;
|
|
7502
7974
|
exports.is_pure_number = is_pure_number;
|
|
7975
|
+
exports.is_secret_name = is_secret_name;
|
|
7503
7976
|
exports.is_string = is_string;
|
|
7504
7977
|
exports.jdb_delete = jdb_delete;
|
|
7505
7978
|
exports.jdb_get = jdb_get;
|
|
@@ -7515,6 +7988,7 @@
|
|
|
7515
7988
|
exports.json_array_size = json_array_size;
|
|
7516
7989
|
exports.json_deep_copy = json_deep_copy;
|
|
7517
7990
|
exports.json_is_identical = json_is_identical;
|
|
7991
|
+
exports.json_mask_secrets = json_mask_secrets;
|
|
7518
7992
|
exports.json_object_del = json_object_del;
|
|
7519
7993
|
exports.json_object_get = json_object_get;
|
|
7520
7994
|
exports.json_object_set = json_object_set;
|
|
@@ -7562,6 +8036,7 @@
|
|
|
7562
8036
|
exports.log_error = log_error;
|
|
7563
8037
|
exports.log_info = log_info;
|
|
7564
8038
|
exports.log_warning = log_warning;
|
|
8039
|
+
exports.mask_secrets_inline = mask_secrets_inline;
|
|
7565
8040
|
exports.msg_iev_get_msg_type = msg_iev_get_msg_type;
|
|
7566
8041
|
exports.msg_iev_get_stack = msg_iev_get_stack;
|
|
7567
8042
|
exports.msg_iev_push_stack = msg_iev_push_stack;
|
|
@@ -7595,6 +8070,7 @@
|
|
|
7595
8070
|
exports.template_get_field_desc = template_get_field_desc;
|
|
7596
8071
|
exports.timeTracker = timeTracker;
|
|
7597
8072
|
exports.trace_json = trace_json;
|
|
8073
|
+
exports.trace_json_masked = trace_json_masked;
|
|
7598
8074
|
exports.trace_level_t = trace_level_t;
|
|
7599
8075
|
exports.trace_msg = trace_msg;
|
|
7600
8076
|
exports.treedb_decoder_fkey = treedb_decoder_fkey;
|