@yuneta/gobj-js 7.26.26 → 7.26.27
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 +24 -6
- package/dist/gobj-js.cjs.js +140 -40
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +329 -273
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +140 -41
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +380 -324
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +140 -40
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +329 -273
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +140 -40
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +329 -273
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/gobj-js.umd.js
CHANGED
|
@@ -2395,11 +2395,13 @@
|
|
|
2395
2395
|
let child;
|
|
2396
2396
|
if (walk_type & walk_type_t.WALK_LAST2FIRST) for (let i = iter.length; i > 0; i--) {
|
|
2397
2397
|
child = iter[i - 1];
|
|
2398
|
+
if (gobj_is_destroying(child)) continue;
|
|
2398
2399
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2399
2400
|
if (ret < 0) return ret;
|
|
2400
2401
|
}
|
|
2401
2402
|
else for (let i = 0; i < iter.length; i++) {
|
|
2402
2403
|
child = iter[i];
|
|
2404
|
+
if (gobj_is_destroying(child)) continue;
|
|
2403
2405
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2404
2406
|
if (ret < 0) return ret;
|
|
2405
2407
|
}
|
|
@@ -2414,18 +2416,21 @@
|
|
|
2414
2416
|
* or
|
|
2415
2417
|
* WALK_LAST2FIRST
|
|
2416
2418
|
***************************************************************/
|
|
2417
|
-
function rc_walk_by_level(
|
|
2419
|
+
function rc_walk_by_level(iter_, walk_type, cb_walking, user_data, user_data2) {
|
|
2420
|
+
let iter = [...iter_];
|
|
2418
2421
|
let ret = rc_walk_by_list(iter, walk_type, cb_walking, user_data, user_data2);
|
|
2419
2422
|
if (ret < 0) return ret;
|
|
2420
2423
|
let child;
|
|
2421
2424
|
if (walk_type & walk_type_t.WALK_LAST2FIRST) for (let i = iter.length; i > 0; i--) {
|
|
2422
2425
|
child = iter[i - 1];
|
|
2423
|
-
|
|
2426
|
+
if (gobj_is_destroying(child)) continue;
|
|
2427
|
+
ret = rc_walk_by_level(child.dl_children, walk_type, cb_walking, user_data, user_data2);
|
|
2424
2428
|
if (ret < 0) return ret;
|
|
2425
2429
|
}
|
|
2426
2430
|
else for (let i = 0; i < iter.length; i++) {
|
|
2427
2431
|
child = iter[i];
|
|
2428
|
-
|
|
2432
|
+
if (gobj_is_destroying(child)) continue;
|
|
2433
|
+
ret = rc_walk_by_level(child.dl_children, walk_type, cb_walking, user_data, user_data2);
|
|
2429
2434
|
if (ret < 0) return ret;
|
|
2430
2435
|
}
|
|
2431
2436
|
return ret;
|
|
@@ -2445,23 +2450,27 @@
|
|
|
2445
2450
|
* or
|
|
2446
2451
|
* WALK_LAST2FIRST
|
|
2447
2452
|
***************************************************************/
|
|
2448
|
-
function rc_walk_by_tree(
|
|
2449
|
-
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(
|
|
2453
|
+
function rc_walk_by_tree(iter_, walk_type, cb_walking, user_data, user_data2) {
|
|
2454
|
+
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(iter_, walk_type, cb_walking, user_data, user_data2);
|
|
2455
|
+
let iter = [...iter_];
|
|
2450
2456
|
let ret;
|
|
2451
2457
|
let child;
|
|
2452
2458
|
if (walk_type & walk_type_t.WALK_BOTTOM2TOP) for (let i = iter.length; i > 0; i--) {
|
|
2453
2459
|
child = iter[i - 1];
|
|
2454
|
-
|
|
2460
|
+
if (gobj_is_destroying(child)) continue;
|
|
2461
|
+
ret = rc_walk_by_tree(child.dl_children, walk_type, cb_walking, user_data, user_data2);
|
|
2455
2462
|
if (ret < 0) return ret;
|
|
2463
|
+
if (gobj_is_destroying(child)) continue;
|
|
2456
2464
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2457
2465
|
if (ret < 0) return ret;
|
|
2458
2466
|
}
|
|
2459
2467
|
else for (let i = 0; i < iter.length; i++) {
|
|
2460
2468
|
child = iter[i];
|
|
2469
|
+
if (gobj_is_destroying(child)) continue;
|
|
2461
2470
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2462
2471
|
if (ret < 0) return ret;
|
|
2463
|
-
else if (ret === 0) {
|
|
2464
|
-
ret = rc_walk_by_tree(
|
|
2472
|
+
else if (ret === 0 && !gobj_is_destroying(child)) {
|
|
2473
|
+
ret = rc_walk_by_tree(child.dl_children, walk_type, cb_walking, user_data, user_data2);
|
|
2465
2474
|
if (ret < 0) return ret;
|
|
2466
2475
|
}
|
|
2467
2476
|
}
|
|
@@ -6046,40 +6055,83 @@
|
|
|
6046
6055
|
return kw_clone;
|
|
6047
6056
|
}
|
|
6048
6057
|
/********************************************
|
|
6058
|
+
* The browser's localStorage, or null when there is none (outside a
|
|
6059
|
+
* browser).
|
|
6060
|
+
*
|
|
6061
|
+
* With the site's data blocked (Chrome with cookies blocked, a sandboxed
|
|
6062
|
+
* iframe), READING the window.localStorage property already throws a
|
|
6063
|
+
* SecurityError, not only its getItem(): every app reads its locale at
|
|
6064
|
+
* start, so the app did not start. Such a store is answered as one whose
|
|
6065
|
+
* every call throws that error, so each helper fails as it fails for any
|
|
6066
|
+
* store that refuses it: a read gives the default, a write -1.
|
|
6067
|
+
********************************************/
|
|
6068
|
+
function local_store() {
|
|
6069
|
+
if (typeof window === "undefined") return null;
|
|
6070
|
+
let store;
|
|
6071
|
+
try {
|
|
6072
|
+
store = window.localStorage;
|
|
6073
|
+
} catch (e) {
|
|
6074
|
+
const refuse = () => {
|
|
6075
|
+
throw e;
|
|
6076
|
+
};
|
|
6077
|
+
return {
|
|
6078
|
+
getItem: refuse,
|
|
6079
|
+
setItem: refuse,
|
|
6080
|
+
removeItem: refuse
|
|
6081
|
+
};
|
|
6082
|
+
}
|
|
6083
|
+
return store || null;
|
|
6084
|
+
}
|
|
6085
|
+
/********************************************
|
|
6086
|
+
* A failure of the store that would repeat on every read is warned
|
|
6087
|
+
* once per key, until a read of the key goes well again.
|
|
6088
|
+
********************************************/
|
|
6089
|
+
var local_storage_warned = /* @__PURE__ */ new Set();
|
|
6090
|
+
function warn_local_storage_once(key, msg) {
|
|
6091
|
+
if (local_storage_warned.has(key)) return;
|
|
6092
|
+
local_storage_warned.add(key);
|
|
6093
|
+
log_warning(msg);
|
|
6094
|
+
}
|
|
6095
|
+
/********************************************
|
|
6049
6096
|
* Get a local attribute
|
|
6050
6097
|
*
|
|
6051
6098
|
* The json the entry holds, or `default_value` when there is none
|
|
6052
6099
|
* (written there too with `create`). A json null is no value, as
|
|
6053
6100
|
* json_absent() in C: the default. An entry that is not json (a
|
|
6054
|
-
* corrupt or foreign write) is
|
|
6101
|
+
* corrupt or foreign write) is a WARNING and is REMOVED, so the
|
|
6055
6102
|
* next read finds no entry: it used to console.warn on every read,
|
|
6056
|
-
* for ever
|
|
6057
|
-
* error, and an entry can hold a
|
|
6058
|
-
*
|
|
6103
|
+
* for ever; a new corrupt entry is a new WARNING. Its text is never
|
|
6104
|
+
* shown (JSON.parse() quotes it in its error, and an entry can hold a
|
|
6105
|
+
* token). A store that cannot be read (blocked) is warned once per
|
|
6106
|
+
* key, and the default is NOT written there. Outside a browser: the
|
|
6107
|
+
* default.
|
|
6059
6108
|
********************************************/
|
|
6060
|
-
var local_storage_warned = /* @__PURE__ */ new Set();
|
|
6061
|
-
function warn_local_storage_once(key, what) {
|
|
6062
|
-
if (local_storage_warned.has(key)) return;
|
|
6063
|
-
local_storage_warned.add(key);
|
|
6064
|
-
log_warning(`kw_get_local_storage_value(): localStorage key "${key}" ${what}`);
|
|
6065
|
-
}
|
|
6066
6109
|
function kw_get_local_storage_value(key, default_value, create = false) {
|
|
6067
|
-
|
|
6110
|
+
const store = local_store();
|
|
6111
|
+
if (!store) return default_value;
|
|
6112
|
+
const where = `kw_get_local_storage_value(): localStorage key "${key}"`;
|
|
6068
6113
|
let text;
|
|
6069
6114
|
try {
|
|
6070
|
-
text =
|
|
6115
|
+
text = store.getItem(key);
|
|
6071
6116
|
} catch (e) {
|
|
6072
|
-
warn_local_storage_once(key,
|
|
6117
|
+
warn_local_storage_once(key, `${where} cannot be read (storage blocked?): the default is used`);
|
|
6073
6118
|
return default_value;
|
|
6074
6119
|
}
|
|
6075
6120
|
let value = null;
|
|
6076
6121
|
if (text !== null) try {
|
|
6077
6122
|
value = JSON.parse(text);
|
|
6078
6123
|
} catch (e) {
|
|
6079
|
-
warn_local_storage_once(key, "does not hold json: removed, the default is used");
|
|
6080
|
-
kw_remove_local_storage_value(key);
|
|
6081
6124
|
value = null;
|
|
6125
|
+
try {
|
|
6126
|
+
store.removeItem(key);
|
|
6127
|
+
log_warning(`${where} does not hold json: removed, the default is used`);
|
|
6128
|
+
local_storage_warned.delete(key);
|
|
6129
|
+
} catch (e2) {
|
|
6130
|
+
warn_local_storage_once(key, `${where} does not hold json and cannot be removed: the default is used`);
|
|
6131
|
+
}
|
|
6132
|
+
text = void 0;
|
|
6082
6133
|
}
|
|
6134
|
+
if (text !== void 0) local_storage_warned.delete(key);
|
|
6083
6135
|
if (value === null) {
|
|
6084
6136
|
if (create) kw_set_local_storage_value(key, default_value);
|
|
6085
6137
|
return default_value;
|
|
@@ -6095,15 +6147,26 @@
|
|
|
6095
6147
|
* reported success on a store that had rejected the write: a full or blocked
|
|
6096
6148
|
* localStorage (quota, private mode) silently discarded the change while the
|
|
6097
6149
|
* UI showed it as saved.
|
|
6150
|
+
*
|
|
6151
|
+
* A value with no json text is refused with an ERROR, as a typed writer
|
|
6152
|
+
* refuses it (json_text_of()): a function was stored as the text
|
|
6153
|
+
* "undefined", and a NaN, a Date or a Map as a text that reads back as
|
|
6154
|
+
* another value. Checked in Node.js too, where there is no store.
|
|
6098
6155
|
********************************************/
|
|
6099
6156
|
function kw_set_local_storage_value(key, value) {
|
|
6100
|
-
if (
|
|
6101
|
-
|
|
6102
|
-
log_error(`kw_set_local_storage_value(): invalid key or value: key=${key}`);
|
|
6157
|
+
if (!key) {
|
|
6158
|
+
log_error(`kw_set_local_storage_value(): invalid key: key=${key}`);
|
|
6103
6159
|
return -1;
|
|
6104
6160
|
}
|
|
6161
|
+
const text = json_text_of(value);
|
|
6162
|
+
if (text === void 0) {
|
|
6163
|
+
log_error(`kw_set_local_storage_value(): cannot save "${key}": a value with no json text`);
|
|
6164
|
+
return -1;
|
|
6165
|
+
}
|
|
6166
|
+
const store = local_store();
|
|
6167
|
+
if (!store) return 0;
|
|
6105
6168
|
try {
|
|
6106
|
-
|
|
6169
|
+
store.setItem(key, text);
|
|
6107
6170
|
return 0;
|
|
6108
6171
|
} catch (e) {
|
|
6109
6172
|
log_error(`kw_set_local_storage_value(): cannot save "${key}" (storage full or blocked?): ${e && e.message ? e.message : e}`);
|
|
@@ -6114,15 +6177,16 @@
|
|
|
6114
6177
|
* Remove local attribute
|
|
6115
6178
|
********************************************/
|
|
6116
6179
|
function kw_remove_local_storage_value(key) {
|
|
6117
|
-
|
|
6180
|
+
const store = local_store();
|
|
6181
|
+
if (!store) return;
|
|
6118
6182
|
if (!key) {
|
|
6119
|
-
|
|
6183
|
+
log_error(`kw_remove_local_storage_value(): invalid key: key=${key}`);
|
|
6120
6184
|
return;
|
|
6121
6185
|
}
|
|
6122
6186
|
try {
|
|
6123
|
-
|
|
6187
|
+
store.removeItem(key);
|
|
6124
6188
|
} catch (e) {
|
|
6125
|
-
|
|
6189
|
+
log_warning(`kw_remove_local_storage_value(): cannot remove "${key}" (storage blocked?): ${e && e.message ? e.message : e}`);
|
|
6126
6190
|
}
|
|
6127
6191
|
}
|
|
6128
6192
|
/*************************************************************
|
|
@@ -7315,11 +7379,21 @@
|
|
|
7315
7379
|
************************************************************/
|
|
7316
7380
|
function node_uuid() {
|
|
7317
7381
|
let uuid = "";
|
|
7318
|
-
|
|
7319
|
-
|
|
7382
|
+
const store = local_store();
|
|
7383
|
+
if (store) {
|
|
7384
|
+
try {
|
|
7385
|
+
uuid = store.getItem("host_uuid");
|
|
7386
|
+
} catch (e) {
|
|
7387
|
+
uuid = null;
|
|
7388
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7389
|
+
}
|
|
7320
7390
|
if (!uuid && window.crypto?.randomUUID) {
|
|
7321
7391
|
uuid = window.crypto.randomUUID();
|
|
7322
|
-
|
|
7392
|
+
try {
|
|
7393
|
+
store.setItem("host_uuid", uuid);
|
|
7394
|
+
} catch (e) {
|
|
7395
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be written (storage full or blocked?): a uuid of this page only");
|
|
7396
|
+
}
|
|
7323
7397
|
}
|
|
7324
7398
|
} else if (typeof globalThis !== "undefined" && globalThis.crypto?.randomUUID) uuid = globalThis.crypto.randomUUID();
|
|
7325
7399
|
else uuid = "00000000-0000-0000-0000-000000000000";
|
|
@@ -8608,7 +8682,7 @@
|
|
|
8608
8682
|
SDATA(data_type_t.DTP_STRING, "cert_pem", sdata_flag_t.SDF_PERSIST, "", "SSL server certification, PEM str format"),
|
|
8609
8683
|
SDATA(data_type_t.DTP_JSON, "extra_info", sdata_flag_t.SDF_RD, "{}", "dict data set by user, added to the identity card msg."),
|
|
8610
8684
|
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."),
|
|
8611
|
-
SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "First reconnect delay (ms). It BACKS OFF from here, doubling up to timeout_retry_max, and resets when a session is reached"),
|
|
8685
|
+
SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "First reconnect delay (ms), at least 1000. It BACKS OFF from here, doubling up to timeout_retry_max, and resets when a session is reached"),
|
|
8612
8686
|
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"),
|
|
8613
8687
|
SDATA(data_type_t.DTP_INTEGER, "timeout_idack", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
|
|
8614
8688
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, 0, "subscriber of output-events. If null then subscriber is the parent"),
|
|
@@ -8633,7 +8707,8 @@
|
|
|
8633
8707
|
inside_on_open: false,
|
|
8634
8708
|
retry_ms: 0,
|
|
8635
8709
|
retry_ms_before_session: 0,
|
|
8636
|
-
session_since: 0
|
|
8710
|
+
session_since: 0,
|
|
8711
|
+
retry_floor_warned: false
|
|
8637
8712
|
};
|
|
8638
8713
|
var __gclass__ = null;
|
|
8639
8714
|
/******************************
|
|
@@ -8905,7 +8980,7 @@
|
|
|
8905
8980
|
function close_for_peer_fault(gobj, reason) {
|
|
8906
8981
|
let priv = gobj.priv;
|
|
8907
8982
|
if (gobj_current_state(gobj) === "ST_SESSION") {
|
|
8908
|
-
if (performance.now() - priv.session_since <
|
|
8983
|
+
if (performance.now() - priv.session_since < retry_bounds(gobj).max) priv.retry_ms = priv.retry_ms_before_session;
|
|
8909
8984
|
priv.retry_ms_before_session = 0;
|
|
8910
8985
|
}
|
|
8911
8986
|
close_websocket(gobj, CLOSE_PEER_FAULT, reason);
|
|
@@ -9177,6 +9252,32 @@
|
|
|
9177
9252
|
return 0;
|
|
9178
9253
|
}
|
|
9179
9254
|
/***************************************************************
|
|
9255
|
+
* The first delay of the backoff and its cap.
|
|
9256
|
+
*
|
|
9257
|
+
* A first delay below RETRY_FLOOR_MS is raised to it, with a WARNING
|
|
9258
|
+
* once: `timeout_retry` 0 never left 0 (0 doubled is 0), so a server
|
|
9259
|
+
* that closed before the ack was reconnected in a loop with no wait,
|
|
9260
|
+
* hundreds of connections a second.
|
|
9261
|
+
***************************************************************/
|
|
9262
|
+
var RETRY_FLOOR_MS = 1e3;
|
|
9263
|
+
function retry_bounds(gobj) {
|
|
9264
|
+
let priv = gobj.priv;
|
|
9265
|
+
let base = gobj_read_integer_attr(gobj, "timeout_retry");
|
|
9266
|
+
let max = gobj_read_integer_attr(gobj, "timeout_retry_max");
|
|
9267
|
+
if (!(base >= RETRY_FLOOR_MS)) {
|
|
9268
|
+
if (!priv.retry_floor_warned) {
|
|
9269
|
+
priv.retry_floor_warned = true;
|
|
9270
|
+
log_warning(`${gobj_short_name(gobj)}: timeout_retry ${base} ms is below ${RETRY_FLOOR_MS} ms: ${RETRY_FLOOR_MS} ms is used`);
|
|
9271
|
+
}
|
|
9272
|
+
base = RETRY_FLOOR_MS;
|
|
9273
|
+
}
|
|
9274
|
+
if (!(max >= base)) max = base;
|
|
9275
|
+
return {
|
|
9276
|
+
base,
|
|
9277
|
+
max
|
|
9278
|
+
};
|
|
9279
|
+
}
|
|
9280
|
+
/***************************************************************
|
|
9180
9281
|
* How long to wait before the next reconnect attempt.
|
|
9181
9282
|
*
|
|
9182
9283
|
* The delay used to be a constant (`timeout_retry`, 5s), for ever. A
|
|
@@ -9197,9 +9298,7 @@
|
|
|
9197
9298
|
***************************************************************/
|
|
9198
9299
|
function next_retry(gobj) {
|
|
9199
9300
|
let priv = gobj.priv;
|
|
9200
|
-
|
|
9201
|
-
let max = gobj_read_integer_attr(gobj, "timeout_retry_max");
|
|
9202
|
-
if (max < base) max = base;
|
|
9301
|
+
const { base, max } = retry_bounds(gobj);
|
|
9203
9302
|
priv.retry_ms = priv.retry_ms ? Math.min(priv.retry_ms * 2, max) : base;
|
|
9204
9303
|
let jitter = priv.retry_ms * .2;
|
|
9205
9304
|
let ms = priv.retry_ms - jitter + Math.random() * 2 * jitter;
|
|
@@ -9697,6 +9796,7 @@
|
|
|
9697
9796
|
exports.json_object_update_existing = json_object_update_existing;
|
|
9698
9797
|
exports.json_object_update_missing = json_object_update_missing;
|
|
9699
9798
|
exports.json_size = json_size;
|
|
9799
|
+
exports.json_text_of = json_text_of;
|
|
9700
9800
|
exports.jwt2json = jwt2json;
|
|
9701
9801
|
exports.jwtDecode = jwtDecode;
|
|
9702
9802
|
exports.kw_clone_by_keys = kw_clone_by_keys;
|