@yuneta/gobj-js 7.26.27 → 7.26.28
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 +140 -49
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +755 -701
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +140 -49
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +292 -239
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +140 -49
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +742 -688
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +140 -49
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +742 -688
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/gobj-js.es.js
CHANGED
|
@@ -1948,6 +1948,31 @@ function gobj_destroy_children(gobj) {
|
|
|
1948
1948
|
}
|
|
1949
1949
|
}
|
|
1950
1950
|
/************************************************************
|
|
1951
|
+
* The SDF_REQUIRED attributes with no value, or null when there
|
|
1952
|
+
* is none: what is empty is asked type by type, as in C.
|
|
1953
|
+
************************************************************/
|
|
1954
|
+
function gobj_check_required_attrs(gobj) {
|
|
1955
|
+
const hs = gobj_hsdata(gobj);
|
|
1956
|
+
const missing = [];
|
|
1957
|
+
if (!is_array(gobj.gclass.attrs_table)) return null;
|
|
1958
|
+
for (const it of gobj.gclass.attrs_table) {
|
|
1959
|
+
if (!it.name || !(it.flag & sdata_flag_t.SDF_REQUIRED)) continue;
|
|
1960
|
+
const value = hs[it.name];
|
|
1961
|
+
switch (it.type) {
|
|
1962
|
+
case data_type_t.DTP_STRING:
|
|
1963
|
+
if (!is_string(value) || empty_string(value)) missing.push(it.name);
|
|
1964
|
+
break;
|
|
1965
|
+
case data_type_t.DTP_LIST:
|
|
1966
|
+
case data_type_t.DTP_DICT:
|
|
1967
|
+
case data_type_t.DTP_JSON:
|
|
1968
|
+
if (empty_json(value)) missing.push(it.name);
|
|
1969
|
+
break;
|
|
1970
|
+
case data_type_t.DTP_POINTER: if (!value) missing.push(it.name);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
return missing.length ? missing : null;
|
|
1974
|
+
}
|
|
1975
|
+
/************************************************************
|
|
1951
1976
|
*
|
|
1952
1977
|
************************************************************/
|
|
1953
1978
|
function gobj_start(gobj) {
|
|
@@ -1963,6 +1988,11 @@ function gobj_start(gobj) {
|
|
|
1963
1988
|
log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);
|
|
1964
1989
|
return -1;
|
|
1965
1990
|
}
|
|
1991
|
+
const required_attrs = gobj_check_required_attrs(gobj);
|
|
1992
|
+
if (required_attrs) {
|
|
1993
|
+
log_error(`${gobj_short_name(gobj)}: Cannot start without all required attributes: ` + JSON.stringify(required_attrs));
|
|
1994
|
+
return -1;
|
|
1995
|
+
}
|
|
1966
1996
|
if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏺ ⏺ start: %s", gobj_full_name(gobj)));
|
|
1967
1997
|
gobj.running = true;
|
|
1968
1998
|
let ret = 0;
|
|
@@ -2349,7 +2379,7 @@ function gobj_walk_gobj_children(gobj, walk_type, cb_walking, user_data, user_da
|
|
|
2349
2379
|
log_error(`gobj NULL, destroying, or bad type`);
|
|
2350
2380
|
return 0;
|
|
2351
2381
|
}
|
|
2352
|
-
return rc_walk_by_list(gobj
|
|
2382
|
+
return rc_walk_by_list(gobj, /* @__PURE__ */ new Set(), walk_type, cb_walking, user_data, user_data2);
|
|
2353
2383
|
}
|
|
2354
2384
|
/***************************************************************************
|
|
2355
2385
|
*
|
|
@@ -2359,7 +2389,7 @@ function gobj_walk_gobj_children_tree(gobj, walk_type, cb_walking, user_data, us
|
|
|
2359
2389
|
log_error(`gobj NULL, destroying, or bad type`);
|
|
2360
2390
|
return 0;
|
|
2361
2391
|
}
|
|
2362
|
-
return rc_walk_by_tree(gobj
|
|
2392
|
+
return rc_walk_by_tree(gobj, /* @__PURE__ */ new Set(), walk_type, cb_walking, user_data, user_data2);
|
|
2363
2393
|
}
|
|
2364
2394
|
/***************************************************************
|
|
2365
2395
|
* Walking
|
|
@@ -2386,18 +2416,33 @@ function walk_ret(ret) {
|
|
|
2386
2416
|
log_error(`walk callback must return a NUMBER (-1 stop, 0 descend, >0 skip children), got ${typeof ret}: taken as 0`);
|
|
2387
2417
|
return 0;
|
|
2388
2418
|
}
|
|
2389
|
-
|
|
2390
|
-
|
|
2419
|
+
/***************************************************************
|
|
2420
|
+
* Whether a walk steps over this gobj of the list of `owner`.
|
|
2421
|
+
*
|
|
2422
|
+
* Each list is walked over a COPY of it, because a callback may destroy
|
|
2423
|
+
* any gobj of the list, the current one included, or move one with
|
|
2424
|
+
* gobj_change_parent(). One it destroyed is stepped over, as the C walk
|
|
2425
|
+
* does; one it moved is no longer in this list, and is handed where the
|
|
2426
|
+
* walk finds it now (7.26.27 handed it here AND there); and a gobj is
|
|
2427
|
+
* never handed twice in one walk (`seen`), wherever it was moved.
|
|
2428
|
+
***************************************************************/
|
|
2429
|
+
function walk_steps_over(child, owner, seen) {
|
|
2430
|
+
return gobj_is_destroying(child) || child.parent !== owner || seen.has(child);
|
|
2431
|
+
}
|
|
2432
|
+
function rc_walk_by_list(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2433
|
+
let iter = [...owner.dl_children];
|
|
2391
2434
|
let child;
|
|
2392
2435
|
if (walk_type & walk_type_t.WALK_LAST2FIRST) for (let i = iter.length; i > 0; i--) {
|
|
2393
2436
|
child = iter[i - 1];
|
|
2394
|
-
if (
|
|
2437
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2438
|
+
seen.add(child);
|
|
2395
2439
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2396
2440
|
if (ret < 0) return ret;
|
|
2397
2441
|
}
|
|
2398
2442
|
else for (let i = 0; i < iter.length; i++) {
|
|
2399
2443
|
child = iter[i];
|
|
2400
|
-
if (
|
|
2444
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2445
|
+
seen.add(child);
|
|
2401
2446
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2402
2447
|
if (ret < 0) return ret;
|
|
2403
2448
|
}
|
|
@@ -2412,24 +2457,23 @@ function rc_walk_by_list(iter_, walk_type, cb_walking, user_data, user_data2) {
|
|
|
2412
2457
|
* or
|
|
2413
2458
|
* WALK_LAST2FIRST
|
|
2414
2459
|
***************************************************************/
|
|
2415
|
-
function rc_walk_by_level(
|
|
2416
|
-
let iter = [...
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
child
|
|
2422
|
-
|
|
2423
|
-
ret =
|
|
2460
|
+
function rc_walk_by_level(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2461
|
+
let iter = [...owner.dl_children];
|
|
2462
|
+
if (walk_type & walk_type_t.WALK_LAST2FIRST) iter.reverse();
|
|
2463
|
+
let handed = [];
|
|
2464
|
+
for (const child of iter) {
|
|
2465
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2466
|
+
seen.add(child);
|
|
2467
|
+
handed.push(child);
|
|
2468
|
+
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2424
2469
|
if (ret < 0) return ret;
|
|
2425
2470
|
}
|
|
2426
|
-
|
|
2427
|
-
child = iter[i];
|
|
2471
|
+
for (const child of handed) {
|
|
2428
2472
|
if (gobj_is_destroying(child)) continue;
|
|
2429
|
-
ret = rc_walk_by_level(child
|
|
2473
|
+
let ret = rc_walk_by_level(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2430
2474
|
if (ret < 0) return ret;
|
|
2431
2475
|
}
|
|
2432
|
-
return
|
|
2476
|
+
return 0;
|
|
2433
2477
|
}
|
|
2434
2478
|
/***************************************************************
|
|
2435
2479
|
* Walking
|
|
@@ -2446,27 +2490,29 @@ function rc_walk_by_level(iter_, walk_type, cb_walking, user_data, user_data2) {
|
|
|
2446
2490
|
* or
|
|
2447
2491
|
* WALK_LAST2FIRST
|
|
2448
2492
|
***************************************************************/
|
|
2449
|
-
function rc_walk_by_tree(
|
|
2450
|
-
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(
|
|
2451
|
-
let iter = [...
|
|
2493
|
+
function rc_walk_by_tree(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2494
|
+
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(owner, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2495
|
+
let iter = [...owner.dl_children];
|
|
2452
2496
|
let ret;
|
|
2453
2497
|
let child;
|
|
2454
2498
|
if (walk_type & walk_type_t.WALK_BOTTOM2TOP) for (let i = iter.length; i > 0; i--) {
|
|
2455
2499
|
child = iter[i - 1];
|
|
2456
|
-
if (
|
|
2457
|
-
ret = rc_walk_by_tree(child
|
|
2500
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2501
|
+
ret = rc_walk_by_tree(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2458
2502
|
if (ret < 0) return ret;
|
|
2459
2503
|
if (gobj_is_destroying(child)) continue;
|
|
2504
|
+
seen.add(child);
|
|
2460
2505
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2461
2506
|
if (ret < 0) return ret;
|
|
2462
2507
|
}
|
|
2463
2508
|
else for (let i = 0; i < iter.length; i++) {
|
|
2464
2509
|
child = iter[i];
|
|
2465
|
-
if (
|
|
2510
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2511
|
+
seen.add(child);
|
|
2466
2512
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2467
2513
|
if (ret < 0) return ret;
|
|
2468
2514
|
else if (ret === 0 && !gobj_is_destroying(child)) {
|
|
2469
|
-
ret = rc_walk_by_tree(child
|
|
2515
|
+
ret = rc_walk_by_tree(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2470
2516
|
if (ret < 0) return ret;
|
|
2471
2517
|
}
|
|
2472
2518
|
}
|
|
@@ -6099,7 +6145,10 @@ function warn_local_storage_once(key, msg) {
|
|
|
6099
6145
|
* for ever; a new corrupt entry is a new WARNING. Its text is never
|
|
6100
6146
|
* shown (JSON.parse() quotes it in its error, and an entry can hold a
|
|
6101
6147
|
* token). A store that cannot be read (blocked) is warned once per
|
|
6102
|
-
* key, and the default is NOT written there
|
|
6148
|
+
* key, and the default is NOT written there; one that cannot be
|
|
6149
|
+
* written (full) is warned once per key too: with `create` it was an
|
|
6150
|
+
* ERROR on every read, the default tried again each time. A key is
|
|
6151
|
+
* warned again after a read that goes well. Outside a browser: the
|
|
6103
6152
|
* default.
|
|
6104
6153
|
********************************************/
|
|
6105
6154
|
function kw_get_local_storage_value(key, default_value, create = false) {
|
|
@@ -6113,6 +6162,7 @@ function kw_get_local_storage_value(key, default_value, create = false) {
|
|
|
6113
6162
|
warn_local_storage_once(key, `${where} cannot be read (storage blocked?): the default is used`);
|
|
6114
6163
|
return default_value;
|
|
6115
6164
|
}
|
|
6165
|
+
let went_well = true;
|
|
6116
6166
|
let value = null;
|
|
6117
6167
|
if (text !== null) try {
|
|
6118
6168
|
value = JSON.parse(text);
|
|
@@ -6121,17 +6171,25 @@ function kw_get_local_storage_value(key, default_value, create = false) {
|
|
|
6121
6171
|
try {
|
|
6122
6172
|
store.removeItem(key);
|
|
6123
6173
|
log_warning(`${where} does not hold json: removed, the default is used`);
|
|
6124
|
-
local_storage_warned.delete(key);
|
|
6125
6174
|
} catch (e2) {
|
|
6175
|
+
went_well = false;
|
|
6126
6176
|
warn_local_storage_once(key, `${where} does not hold json and cannot be removed: the default is used`);
|
|
6127
6177
|
}
|
|
6128
|
-
text = void 0;
|
|
6129
6178
|
}
|
|
6130
|
-
if (text !== void 0) local_storage_warned.delete(key);
|
|
6131
6179
|
if (value === null) {
|
|
6132
|
-
|
|
6133
|
-
|
|
6180
|
+
value = default_value;
|
|
6181
|
+
if (create) {
|
|
6182
|
+
const default_text = json_text_of(default_value);
|
|
6183
|
+
if (default_text === void 0) log_error(`${where}: cannot write the default: a value with no json text`);
|
|
6184
|
+
else try {
|
|
6185
|
+
store.setItem(key, default_text);
|
|
6186
|
+
} catch (e) {
|
|
6187
|
+
went_well = false;
|
|
6188
|
+
warn_local_storage_once(key, `${where} cannot be written (storage full or blocked?): the default is used, not kept`);
|
|
6189
|
+
}
|
|
6190
|
+
}
|
|
6134
6191
|
}
|
|
6192
|
+
if (went_well) local_storage_warned.delete(key);
|
|
6135
6193
|
return value;
|
|
6136
6194
|
}
|
|
6137
6195
|
/********************************************
|
|
@@ -7371,29 +7429,62 @@ function index_in_list(list, elm) {
|
|
|
7371
7429
|
return -1;
|
|
7372
7430
|
}
|
|
7373
7431
|
/************************************************************
|
|
7432
|
+
* A new uuid v4 (RFC 9562).
|
|
7374
7433
|
*
|
|
7434
|
+
* crypto.randomUUID() exists only in a secure context, so a page
|
|
7435
|
+
* served over http without TLS has none; crypto.getRandomValues()
|
|
7436
|
+
* exists there too. With no crypto at all, Math.random(): not fit
|
|
7437
|
+
* for a secret, and a uuid that names a node is not one.
|
|
7375
7438
|
************************************************************/
|
|
7439
|
+
function new_uuid() {
|
|
7440
|
+
const c = typeof window !== "undefined" && window.crypto || globalThis.crypto;
|
|
7441
|
+
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
7442
|
+
const b = /* @__PURE__ */ new Uint8Array(16);
|
|
7443
|
+
if (c && typeof c.getRandomValues === "function") c.getRandomValues(b);
|
|
7444
|
+
else for (let i = 0; i < b.length; i++) b[i] = Math.floor(Math.random() * 256);
|
|
7445
|
+
b[6] = b[6] & 15 | 64;
|
|
7446
|
+
b[8] = b[8] & 63 | 128;
|
|
7447
|
+
const h = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
7448
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
|
|
7449
|
+
}
|
|
7450
|
+
/************************************************************
|
|
7451
|
+
* The uuid of this node: ONE for the life of the page.
|
|
7452
|
+
*
|
|
7453
|
+
* The one the store keeps ("host_uuid"), made and written there when
|
|
7454
|
+
* there is none. When the store cannot keep it (blocked, full, no
|
|
7455
|
+
* localStorage, outside a browser) the one this page made, warned
|
|
7456
|
+
* once. It goes in the node_uuid attribute of the yuno, the id of the
|
|
7457
|
+
* identity card and the `host` of every message the client sends, so
|
|
7458
|
+
* the first answer is kept and answered again: 7.26.27 made a new
|
|
7459
|
+
* uuid on every call when the store could not keep it, and answered
|
|
7460
|
+
* null without crypto.randomUUID().
|
|
7461
|
+
************************************************************/
|
|
7462
|
+
var uuid_of_this_page = null;
|
|
7376
7463
|
function node_uuid() {
|
|
7377
|
-
|
|
7464
|
+
if (uuid_of_this_page) return uuid_of_this_page;
|
|
7378
7465
|
const store = local_store();
|
|
7379
|
-
if (store) {
|
|
7466
|
+
if (!store) {
|
|
7467
|
+
uuid_of_this_page = new_uuid();
|
|
7468
|
+
return uuid_of_this_page;
|
|
7469
|
+
}
|
|
7470
|
+
let uuid = null;
|
|
7471
|
+
try {
|
|
7472
|
+
uuid = store.getItem("host_uuid");
|
|
7473
|
+
} catch (e) {
|
|
7474
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7475
|
+
uuid_of_this_page = new_uuid();
|
|
7476
|
+
return uuid_of_this_page;
|
|
7477
|
+
}
|
|
7478
|
+
if (!uuid) {
|
|
7479
|
+
uuid = new_uuid();
|
|
7380
7480
|
try {
|
|
7381
|
-
|
|
7481
|
+
store.setItem("host_uuid", uuid);
|
|
7382
7482
|
} catch (e) {
|
|
7383
|
-
uuid
|
|
7384
|
-
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7483
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be written (storage full or blocked?): a uuid of this page only");
|
|
7385
7484
|
}
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
store.setItem("host_uuid", uuid);
|
|
7390
|
-
} catch (e) {
|
|
7391
|
-
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be written (storage full or blocked?): a uuid of this page only");
|
|
7392
|
-
}
|
|
7393
|
-
}
|
|
7394
|
-
} else if (typeof globalThis !== "undefined" && globalThis.crypto?.randomUUID) uuid = globalThis.crypto.randomUUID();
|
|
7395
|
-
else uuid = "00000000-0000-0000-0000-000000000000";
|
|
7396
|
-
return uuid;
|
|
7485
|
+
}
|
|
7486
|
+
uuid_of_this_page = uuid;
|
|
7487
|
+
return uuid_of_this_page;
|
|
7397
7488
|
}
|
|
7398
7489
|
/************************************************************
|
|
7399
7490
|
* Build a cleaned name
|
|
@@ -8678,7 +8769,7 @@ var attrs_table = [
|
|
|
8678
8769
|
SDATA(data_type_t.DTP_STRING, "cert_pem", sdata_flag_t.SDF_PERSIST, "", "SSL server certification, PEM str format"),
|
|
8679
8770
|
SDATA(data_type_t.DTP_JSON, "extra_info", sdata_flag_t.SDF_RD, "{}", "dict data set by user, added to the identity card msg."),
|
|
8680
8771
|
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."),
|
|
8681
|
-
SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "
|
|
8772
|
+
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"),
|
|
8682
8773
|
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"),
|
|
8683
8774
|
SDATA(data_type_t.DTP_INTEGER, "timeout_idack", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
|
|
8684
8775
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, 0, "subscriber of output-events. If null then subscriber is the parent"),
|