@yuneta/gobj-js 7.26.27 → 7.26.29
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 +15 -3
- package/dist/gobj-js.cjs.js +157 -51
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +826 -767
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +157 -51
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +1480 -1422
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +157 -51
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +825 -766
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +157 -51
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +825 -766
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -460,7 +460,10 @@ gobj_create_volatil(name, gclass_name, attrs, parent)
|
|
|
460
460
|
gobj_create_pure_child(name, gclass_name, attrs, parent)
|
|
461
461
|
|
|
462
462
|
// Start / Stop
|
|
463
|
-
gobj_start(gobj) // calls mt_start
|
|
463
|
+
gobj_start(gobj) // calls mt_start; -1 with an ERROR if a
|
|
464
|
+
// SDF_REQUIRED attr is empty, as in C
|
|
465
|
+
// (BREAKING in 7.26.28: "" string, empty_json()
|
|
466
|
+
// list/dict/json, null pointer)
|
|
464
467
|
gobj_stop(gobj) // calls mt_stop
|
|
465
468
|
gobj_start_children(gobj)
|
|
466
469
|
gobj_stop_children(gobj)
|
|
@@ -599,6 +602,9 @@ gobj_search_path(gobj, path)
|
|
|
599
602
|
|
|
600
603
|
gobj_walk_gobj_children(gobj, walk_type, cb_walking, user_data, user_data2)
|
|
601
604
|
gobj_walk_gobj_children_tree(gobj, walk_type, cb_walking, user_data, user_data2)
|
|
605
|
+
// A callback may destroy or move (gobj_change_parent()) any gobj: a
|
|
606
|
+
// destroyed one is never handed, a moved one is handed where the walk
|
|
607
|
+
// finds it now, and no gobj is handed twice in one walk (7.26.28).
|
|
602
608
|
```
|
|
603
609
|
|
|
604
610
|
### Persistence
|
|
@@ -740,11 +746,16 @@ kw_remove_local_storage_value(key)
|
|
|
740
746
|
// kw_set_local_storage_value("k", () => 1) → -1
|
|
741
747
|
// kw_set_local_storage_value("k", {w: NaN}) → -1 (it was {"w":null})
|
|
742
748
|
// kw_set_local_storage_value("k", [1, , 3]) → -1 (a hole: [1,null,3])
|
|
749
|
+
// A full store (read, not written) with `create`: the default, warned
|
|
750
|
+
// once per key (7.26.28: an ERROR on every read).
|
|
743
751
|
|
|
744
752
|
// Misc utilities
|
|
745
753
|
current_timestamp() // ISO string
|
|
746
754
|
get_now() // Date object
|
|
747
|
-
node_uuid() //
|
|
755
|
+
node_uuid() // uuid of this browser, the SAME for the
|
|
756
|
+
// life of the page (kept in localStorage
|
|
757
|
+
// "host_uuid"; a page uuid if the store
|
|
758
|
+
// cannot keep it; never null: 7.26.28)
|
|
748
759
|
parseBoolean(v) // coerce to boolean
|
|
749
760
|
empty_string(s) // true if null/undefined/""
|
|
750
761
|
str_in_list(list, str, ci) // case-insensitive optional
|
|
@@ -1106,7 +1117,8 @@ count as reached: the backoff goes on from where it was (7.26.25), so a server
|
|
|
1106
1117
|
that breaks every session is not reconnected at the first delay for ever -- unless
|
|
1107
1118
|
the session outlived `timeout_retry_max`: a session that long was served, and its
|
|
1108
1119
|
fault starts the backoff over, as a clean end does (7.26.26). For the old fixed-interval behaviour set `timeout_retry_max` equal to
|
|
1109
|
-
`timeout_retry`. The first delay is **at least 1000 ms** (7.26.27
|
|
1120
|
+
`timeout_retry`. The BASE of the first delay is **at least 1000 ms** (7.26.27;
|
|
1121
|
+
the ±20% jitter puts the first delay itself between 800 and 1200 ms): a lower
|
|
1110
1122
|
`timeout_retry` is raised to 1000 with one WARNING, because 0 never doubled
|
|
1111
1123
|
away from 0 and a server that closes before the ack was reconnected in a loop
|
|
1112
1124
|
with no wait, hundreds of times a second.
|
package/dist/gobj-js.cjs.js
CHANGED
|
@@ -1949,6 +1949,31 @@ function gobj_destroy_children(gobj) {
|
|
|
1949
1949
|
}
|
|
1950
1950
|
}
|
|
1951
1951
|
/************************************************************
|
|
1952
|
+
* The SDF_REQUIRED attributes with no value, or null when there
|
|
1953
|
+
* is none: what is empty is asked type by type, as in C.
|
|
1954
|
+
************************************************************/
|
|
1955
|
+
function gobj_check_required_attrs(gobj) {
|
|
1956
|
+
const hs = gobj_hsdata(gobj);
|
|
1957
|
+
const missing = [];
|
|
1958
|
+
if (!is_array(gobj.gclass.attrs_table)) return null;
|
|
1959
|
+
for (const it of gobj.gclass.attrs_table) {
|
|
1960
|
+
if (!it.name || !(it.flag & sdata_flag_t.SDF_REQUIRED)) continue;
|
|
1961
|
+
const value = hs[it.name];
|
|
1962
|
+
switch (it.type) {
|
|
1963
|
+
case data_type_t.DTP_STRING:
|
|
1964
|
+
if (!is_string(value) || empty_string(value)) missing.push(it.name);
|
|
1965
|
+
break;
|
|
1966
|
+
case data_type_t.DTP_LIST:
|
|
1967
|
+
case data_type_t.DTP_DICT:
|
|
1968
|
+
case data_type_t.DTP_JSON:
|
|
1969
|
+
if (empty_json(value)) missing.push(it.name);
|
|
1970
|
+
break;
|
|
1971
|
+
case data_type_t.DTP_POINTER: if (!value) missing.push(it.name);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
return missing.length ? missing : null;
|
|
1975
|
+
}
|
|
1976
|
+
/************************************************************
|
|
1952
1977
|
*
|
|
1953
1978
|
************************************************************/
|
|
1954
1979
|
function gobj_start(gobj) {
|
|
@@ -1964,6 +1989,11 @@ function gobj_start(gobj) {
|
|
|
1964
1989
|
log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);
|
|
1965
1990
|
return -1;
|
|
1966
1991
|
}
|
|
1992
|
+
const required_attrs = gobj_check_required_attrs(gobj);
|
|
1993
|
+
if (required_attrs) {
|
|
1994
|
+
log_error(`${gobj_short_name(gobj)}: Cannot start without all required attributes: ` + JSON.stringify(required_attrs));
|
|
1995
|
+
return -1;
|
|
1996
|
+
}
|
|
1967
1997
|
if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏺ ⏺ start: %s", gobj_full_name(gobj)));
|
|
1968
1998
|
gobj.running = true;
|
|
1969
1999
|
let ret = 0;
|
|
@@ -2121,7 +2151,8 @@ function gobj_play(gobj) {
|
|
|
2121
2151
|
if (!gobj_is_running(gobj)) {
|
|
2122
2152
|
if (!(gobj.gclass.gclass_flag & gclass_flag_t.gcflag_required_start_to_play)) {
|
|
2123
2153
|
log_warning(`${gobj_short_name(gobj)}: GObj playing without previous start`);
|
|
2124
|
-
|
|
2154
|
+
if (start_destroys_it(gobj)) return -1;
|
|
2155
|
+
if (!gobj.running) return -1;
|
|
2125
2156
|
} else {
|
|
2126
2157
|
log_error(`${gobj_short_name(gobj)}: Cannot play, start not done`);
|
|
2127
2158
|
return -1;
|
|
@@ -2350,7 +2381,7 @@ function gobj_walk_gobj_children(gobj, walk_type, cb_walking, user_data, user_da
|
|
|
2350
2381
|
log_error(`gobj NULL, destroying, or bad type`);
|
|
2351
2382
|
return 0;
|
|
2352
2383
|
}
|
|
2353
|
-
return rc_walk_by_list(gobj
|
|
2384
|
+
return rc_walk_by_list(gobj, /* @__PURE__ */ new Set(), walk_type, cb_walking, user_data, user_data2);
|
|
2354
2385
|
}
|
|
2355
2386
|
/***************************************************************************
|
|
2356
2387
|
*
|
|
@@ -2360,7 +2391,7 @@ function gobj_walk_gobj_children_tree(gobj, walk_type, cb_walking, user_data, us
|
|
|
2360
2391
|
log_error(`gobj NULL, destroying, or bad type`);
|
|
2361
2392
|
return 0;
|
|
2362
2393
|
}
|
|
2363
|
-
return rc_walk_by_tree(gobj
|
|
2394
|
+
return rc_walk_by_tree(gobj, /* @__PURE__ */ new Set(), walk_type, cb_walking, user_data, user_data2);
|
|
2364
2395
|
}
|
|
2365
2396
|
/***************************************************************
|
|
2366
2397
|
* Walking
|
|
@@ -2387,18 +2418,33 @@ function walk_ret(ret) {
|
|
|
2387
2418
|
log_error(`walk callback must return a NUMBER (-1 stop, 0 descend, >0 skip children), got ${typeof ret}: taken as 0`);
|
|
2388
2419
|
return 0;
|
|
2389
2420
|
}
|
|
2390
|
-
|
|
2391
|
-
|
|
2421
|
+
/***************************************************************
|
|
2422
|
+
* Whether a walk steps over this gobj of the list of `owner`.
|
|
2423
|
+
*
|
|
2424
|
+
* Each list is walked over a COPY of it, because a callback may destroy
|
|
2425
|
+
* any gobj of the list, the current one included, or move one with
|
|
2426
|
+
* gobj_change_parent(). One it destroyed is stepped over, as the C walk
|
|
2427
|
+
* does; one it moved is no longer in this list, and is handed where the
|
|
2428
|
+
* walk finds it now (7.26.27 handed it here AND there); and a gobj is
|
|
2429
|
+
* never handed twice in one walk (`seen`), wherever it was moved.
|
|
2430
|
+
***************************************************************/
|
|
2431
|
+
function walk_steps_over(child, owner, seen) {
|
|
2432
|
+
return gobj_is_destroying(child) || child.parent !== owner || seen.has(child);
|
|
2433
|
+
}
|
|
2434
|
+
function rc_walk_by_list(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2435
|
+
let iter = [...owner.dl_children];
|
|
2392
2436
|
let child;
|
|
2393
2437
|
if (walk_type & walk_type_t.WALK_LAST2FIRST) for (let i = iter.length; i > 0; i--) {
|
|
2394
2438
|
child = iter[i - 1];
|
|
2395
|
-
if (
|
|
2439
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2440
|
+
seen.add(child);
|
|
2396
2441
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2397
2442
|
if (ret < 0) return ret;
|
|
2398
2443
|
}
|
|
2399
2444
|
else for (let i = 0; i < iter.length; i++) {
|
|
2400
2445
|
child = iter[i];
|
|
2401
|
-
if (
|
|
2446
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2447
|
+
seen.add(child);
|
|
2402
2448
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2403
2449
|
if (ret < 0) return ret;
|
|
2404
2450
|
}
|
|
@@ -2413,24 +2459,23 @@ function rc_walk_by_list(iter_, walk_type, cb_walking, user_data, user_data2) {
|
|
|
2413
2459
|
* or
|
|
2414
2460
|
* WALK_LAST2FIRST
|
|
2415
2461
|
***************************************************************/
|
|
2416
|
-
function rc_walk_by_level(
|
|
2417
|
-
let iter = [...
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
child
|
|
2423
|
-
|
|
2424
|
-
ret =
|
|
2462
|
+
function rc_walk_by_level(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2463
|
+
let iter = [...owner.dl_children];
|
|
2464
|
+
if (walk_type & walk_type_t.WALK_LAST2FIRST) iter.reverse();
|
|
2465
|
+
let handed = [];
|
|
2466
|
+
for (const child of iter) {
|
|
2467
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2468
|
+
seen.add(child);
|
|
2469
|
+
handed.push(child);
|
|
2470
|
+
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2425
2471
|
if (ret < 0) return ret;
|
|
2426
2472
|
}
|
|
2427
|
-
|
|
2428
|
-
child = iter[i];
|
|
2473
|
+
for (const child of handed) {
|
|
2429
2474
|
if (gobj_is_destroying(child)) continue;
|
|
2430
|
-
ret = rc_walk_by_level(child
|
|
2475
|
+
let ret = rc_walk_by_level(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2431
2476
|
if (ret < 0) return ret;
|
|
2432
2477
|
}
|
|
2433
|
-
return
|
|
2478
|
+
return 0;
|
|
2434
2479
|
}
|
|
2435
2480
|
/***************************************************************
|
|
2436
2481
|
* Walking
|
|
@@ -2447,27 +2492,29 @@ function rc_walk_by_level(iter_, walk_type, cb_walking, user_data, user_data2) {
|
|
|
2447
2492
|
* or
|
|
2448
2493
|
* WALK_LAST2FIRST
|
|
2449
2494
|
***************************************************************/
|
|
2450
|
-
function rc_walk_by_tree(
|
|
2451
|
-
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(
|
|
2452
|
-
let iter = [...
|
|
2495
|
+
function rc_walk_by_tree(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2496
|
+
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(owner, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2497
|
+
let iter = [...owner.dl_children];
|
|
2453
2498
|
let ret;
|
|
2454
2499
|
let child;
|
|
2455
2500
|
if (walk_type & walk_type_t.WALK_BOTTOM2TOP) for (let i = iter.length; i > 0; i--) {
|
|
2456
2501
|
child = iter[i - 1];
|
|
2457
|
-
if (
|
|
2458
|
-
ret = rc_walk_by_tree(child
|
|
2502
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2503
|
+
ret = rc_walk_by_tree(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2459
2504
|
if (ret < 0) return ret;
|
|
2460
2505
|
if (gobj_is_destroying(child)) continue;
|
|
2506
|
+
seen.add(child);
|
|
2461
2507
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2462
2508
|
if (ret < 0) return ret;
|
|
2463
2509
|
}
|
|
2464
2510
|
else for (let i = 0; i < iter.length; i++) {
|
|
2465
2511
|
child = iter[i];
|
|
2466
|
-
if (
|
|
2512
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2513
|
+
seen.add(child);
|
|
2467
2514
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2468
2515
|
if (ret < 0) return ret;
|
|
2469
2516
|
else if (ret === 0 && !gobj_is_destroying(child)) {
|
|
2470
|
-
ret = rc_walk_by_tree(child
|
|
2517
|
+
ret = rc_walk_by_tree(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2471
2518
|
if (ret < 0) return ret;
|
|
2472
2519
|
}
|
|
2473
2520
|
}
|
|
@@ -2930,12 +2977,20 @@ function gobj_current_state(gobj) {
|
|
|
2930
2977
|
function gobj_change_parent(gobj, parent) {
|
|
2931
2978
|
if (gobj_is_destroying(gobj)) {
|
|
2932
2979
|
log_error("gobj NULL or DESTROYED");
|
|
2933
|
-
return
|
|
2980
|
+
return -1;
|
|
2934
2981
|
}
|
|
2935
2982
|
if (!(parent instanceof GObj)) {
|
|
2936
2983
|
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);
|
|
2937
2984
|
return -1;
|
|
2938
2985
|
}
|
|
2986
|
+
if (gobj_is_destroying(parent)) {
|
|
2987
|
+
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() parent NULL or DESTROYED`);
|
|
2988
|
+
return -1;
|
|
2989
|
+
}
|
|
2990
|
+
for (let p = parent; p; p = p.parent) if (p === gobj) {
|
|
2991
|
+
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() a gobj cannot be its own ancestor: ${gobj_short_name(parent)}`);
|
|
2992
|
+
return -1;
|
|
2993
|
+
}
|
|
2939
2994
|
if (gobj.parent && gobj.parent.gclass.gmt.mt_child_removed) gobj.parent.gclass.gmt.mt_child_removed(gobj.parent, gobj);
|
|
2940
2995
|
if (gobj.parent) {
|
|
2941
2996
|
_remove_child(gobj.parent, gobj);
|
|
@@ -6100,7 +6155,10 @@ function warn_local_storage_once(key, msg) {
|
|
|
6100
6155
|
* for ever; a new corrupt entry is a new WARNING. Its text is never
|
|
6101
6156
|
* shown (JSON.parse() quotes it in its error, and an entry can hold a
|
|
6102
6157
|
* token). A store that cannot be read (blocked) is warned once per
|
|
6103
|
-
* key, and the default is NOT written there
|
|
6158
|
+
* key, and the default is NOT written there; one that cannot be
|
|
6159
|
+
* written (full) is warned once per key too: with `create` it was an
|
|
6160
|
+
* ERROR on every read, the default tried again each time. A key is
|
|
6161
|
+
* warned again after a read that goes well. Outside a browser: the
|
|
6104
6162
|
* default.
|
|
6105
6163
|
********************************************/
|
|
6106
6164
|
function kw_get_local_storage_value(key, default_value, create = false) {
|
|
@@ -6114,6 +6172,7 @@ function kw_get_local_storage_value(key, default_value, create = false) {
|
|
|
6114
6172
|
warn_local_storage_once(key, `${where} cannot be read (storage blocked?): the default is used`);
|
|
6115
6173
|
return default_value;
|
|
6116
6174
|
}
|
|
6175
|
+
let went_well = true;
|
|
6117
6176
|
let value = null;
|
|
6118
6177
|
if (text !== null) try {
|
|
6119
6178
|
value = JSON.parse(text);
|
|
@@ -6122,17 +6181,25 @@ function kw_get_local_storage_value(key, default_value, create = false) {
|
|
|
6122
6181
|
try {
|
|
6123
6182
|
store.removeItem(key);
|
|
6124
6183
|
log_warning(`${where} does not hold json: removed, the default is used`);
|
|
6125
|
-
local_storage_warned.delete(key);
|
|
6126
6184
|
} catch (e2) {
|
|
6185
|
+
went_well = false;
|
|
6127
6186
|
warn_local_storage_once(key, `${where} does not hold json and cannot be removed: the default is used`);
|
|
6128
6187
|
}
|
|
6129
|
-
text = void 0;
|
|
6130
6188
|
}
|
|
6131
|
-
if (text !== void 0) local_storage_warned.delete(key);
|
|
6132
6189
|
if (value === null) {
|
|
6133
|
-
|
|
6134
|
-
|
|
6190
|
+
value = default_value;
|
|
6191
|
+
if (create) {
|
|
6192
|
+
const default_text = json_text_of(default_value);
|
|
6193
|
+
if (default_text === void 0) log_error(`${where}: cannot write the default: a value with no json text`);
|
|
6194
|
+
else try {
|
|
6195
|
+
store.setItem(key, default_text);
|
|
6196
|
+
} catch (e) {
|
|
6197
|
+
went_well = false;
|
|
6198
|
+
warn_local_storage_once(key, `${where} cannot be written (storage full or blocked?): the default is used, not kept`);
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
6135
6201
|
}
|
|
6202
|
+
if (went_well) local_storage_warned.delete(key);
|
|
6136
6203
|
return value;
|
|
6137
6204
|
}
|
|
6138
6205
|
/********************************************
|
|
@@ -7372,29 +7439,68 @@ function index_in_list(list, elm) {
|
|
|
7372
7439
|
return -1;
|
|
7373
7440
|
}
|
|
7374
7441
|
/************************************************************
|
|
7442
|
+
* A new uuid v4 (RFC 9562).
|
|
7443
|
+
*
|
|
7444
|
+
* crypto.randomUUID() exists only in a secure context, so a page
|
|
7445
|
+
* served over http without TLS has none; crypto.getRandomValues()
|
|
7446
|
+
* exists there too. With no crypto at all, Math.random(): not fit
|
|
7447
|
+
* for a secret, and a uuid that names a node is not one.
|
|
7448
|
+
************************************************************/
|
|
7449
|
+
function new_uuid() {
|
|
7450
|
+
const c = typeof window !== "undefined" && window.crypto || globalThis.crypto;
|
|
7451
|
+
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
7452
|
+
const b = /* @__PURE__ */ new Uint8Array(16);
|
|
7453
|
+
if (c && typeof c.getRandomValues === "function") c.getRandomValues(b);
|
|
7454
|
+
else for (let i = 0; i < b.length; i++) b[i] = Math.floor(Math.random() * 256);
|
|
7455
|
+
b[6] = b[6] & 15 | 64;
|
|
7456
|
+
b[8] = b[8] & 63 | 128;
|
|
7457
|
+
const h = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
7458
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
|
|
7459
|
+
}
|
|
7460
|
+
/************************************************************
|
|
7461
|
+
* The uuid of this node: ONE for the life of the page.
|
|
7375
7462
|
*
|
|
7463
|
+
* The one the store keeps ("host_uuid"), made and written there when
|
|
7464
|
+
* there is none. When the store cannot keep it (blocked, full, no
|
|
7465
|
+
* localStorage, outside a browser) the one this page made, warned
|
|
7466
|
+
* once. It goes in the node_uuid attribute of the yuno, the id of the
|
|
7467
|
+
* identity card and the `host` of every message the client sends, so
|
|
7468
|
+
* the first answer is kept and answered again: 7.26.27 made a new
|
|
7469
|
+
* uuid on every call when the store could not keep it, and answered
|
|
7470
|
+
* null without crypto.randomUUID(). A stored value that is not a
|
|
7471
|
+
* uuid (a foreign or corrupt write) is replaced, with a WARNING.
|
|
7376
7472
|
************************************************************/
|
|
7473
|
+
var uuid_of_this_page = null;
|
|
7474
|
+
var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7377
7475
|
function node_uuid() {
|
|
7378
|
-
|
|
7476
|
+
if (uuid_of_this_page) return uuid_of_this_page;
|
|
7379
7477
|
const store = local_store();
|
|
7380
|
-
if (store) {
|
|
7478
|
+
if (!store) {
|
|
7479
|
+
uuid_of_this_page = new_uuid();
|
|
7480
|
+
return uuid_of_this_page;
|
|
7481
|
+
}
|
|
7482
|
+
let uuid = null;
|
|
7483
|
+
try {
|
|
7484
|
+
uuid = store.getItem("host_uuid");
|
|
7485
|
+
} catch (e) {
|
|
7486
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7487
|
+
uuid_of_this_page = new_uuid();
|
|
7488
|
+
return uuid_of_this_page;
|
|
7489
|
+
}
|
|
7490
|
+
if (uuid && !UUID_SHAPE.test(uuid)) {
|
|
7491
|
+
log_warning("node_uuid(): the stored host_uuid is not a uuid: a new one replaces it");
|
|
7492
|
+
uuid = null;
|
|
7493
|
+
}
|
|
7494
|
+
if (!uuid) {
|
|
7495
|
+
uuid = new_uuid();
|
|
7381
7496
|
try {
|
|
7382
|
-
|
|
7497
|
+
store.setItem("host_uuid", uuid);
|
|
7383
7498
|
} catch (e) {
|
|
7384
|
-
uuid
|
|
7385
|
-
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7386
|
-
}
|
|
7387
|
-
if (!uuid && window.crypto?.randomUUID) {
|
|
7388
|
-
uuid = window.crypto.randomUUID();
|
|
7389
|
-
try {
|
|
7390
|
-
store.setItem("host_uuid", uuid);
|
|
7391
|
-
} catch (e) {
|
|
7392
|
-
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be written (storage full or blocked?): a uuid of this page only");
|
|
7393
|
-
}
|
|
7499
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be written (storage full or blocked?): a uuid of this page only");
|
|
7394
7500
|
}
|
|
7395
|
-
}
|
|
7396
|
-
|
|
7397
|
-
return
|
|
7501
|
+
}
|
|
7502
|
+
uuid_of_this_page = uuid;
|
|
7503
|
+
return uuid_of_this_page;
|
|
7398
7504
|
}
|
|
7399
7505
|
/************************************************************
|
|
7400
7506
|
* Build a cleaned name
|
|
@@ -8679,7 +8785,7 @@ var attrs_table = [
|
|
|
8679
8785
|
SDATA(data_type_t.DTP_STRING, "cert_pem", sdata_flag_t.SDF_PERSIST, "", "SSL server certification, PEM str format"),
|
|
8680
8786
|
SDATA(data_type_t.DTP_JSON, "extra_info", sdata_flag_t.SDF_RD, "{}", "dict data set by user, added to the identity card msg."),
|
|
8681
8787
|
SDATA(data_type_t.DTP_LIST, "required_services", sdata_flag_t.SDF_RD, "[]", "Services this LINK requires (identity card). Empty = the yuno's `required_services`, as before. A yuno with several links to DIFFERENT backends must set it per link: the yuno-wide list is the union, so every backend is told the service names of all the others."),
|
|
8682
|
-
SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "
|
|
8788
|
+
SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "Base of the first reconnect delay (ms, ±20% jitter), at least 1000. It BACKS OFF from here, doubling up to timeout_retry_max, and resets when a session is reached"),
|
|
8683
8789
|
SDATA(data_type_t.DTP_INTEGER, "timeout_retry_max", sdata_flag_t.SDF_RD, "60000", "Cap of the reconnect backoff (ms). Set it equal to timeout_retry for the old fixed-interval behaviour"),
|
|
8684
8790
|
SDATA(data_type_t.DTP_INTEGER, "timeout_idack", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
|
|
8685
8791
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, 0, "subscriber of output-events. If null then subscriber is the parent"),
|