@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/dist/gobj-js.umd.js
CHANGED
|
@@ -1952,6 +1952,31 @@
|
|
|
1952
1952
|
}
|
|
1953
1953
|
}
|
|
1954
1954
|
/************************************************************
|
|
1955
|
+
* The SDF_REQUIRED attributes with no value, or null when there
|
|
1956
|
+
* is none: what is empty is asked type by type, as in C.
|
|
1957
|
+
************************************************************/
|
|
1958
|
+
function gobj_check_required_attrs(gobj) {
|
|
1959
|
+
const hs = gobj_hsdata(gobj);
|
|
1960
|
+
const missing = [];
|
|
1961
|
+
if (!is_array(gobj.gclass.attrs_table)) return null;
|
|
1962
|
+
for (const it of gobj.gclass.attrs_table) {
|
|
1963
|
+
if (!it.name || !(it.flag & sdata_flag_t.SDF_REQUIRED)) continue;
|
|
1964
|
+
const value = hs[it.name];
|
|
1965
|
+
switch (it.type) {
|
|
1966
|
+
case data_type_t.DTP_STRING:
|
|
1967
|
+
if (!is_string(value) || empty_string(value)) missing.push(it.name);
|
|
1968
|
+
break;
|
|
1969
|
+
case data_type_t.DTP_LIST:
|
|
1970
|
+
case data_type_t.DTP_DICT:
|
|
1971
|
+
case data_type_t.DTP_JSON:
|
|
1972
|
+
if (empty_json(value)) missing.push(it.name);
|
|
1973
|
+
break;
|
|
1974
|
+
case data_type_t.DTP_POINTER: if (!value) missing.push(it.name);
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
return missing.length ? missing : null;
|
|
1978
|
+
}
|
|
1979
|
+
/************************************************************
|
|
1955
1980
|
*
|
|
1956
1981
|
************************************************************/
|
|
1957
1982
|
function gobj_start(gobj) {
|
|
@@ -1967,6 +1992,11 @@
|
|
|
1967
1992
|
log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);
|
|
1968
1993
|
return -1;
|
|
1969
1994
|
}
|
|
1995
|
+
const required_attrs = gobj_check_required_attrs(gobj);
|
|
1996
|
+
if (required_attrs) {
|
|
1997
|
+
log_error(`${gobj_short_name(gobj)}: Cannot start without all required attributes: ` + JSON.stringify(required_attrs));
|
|
1998
|
+
return -1;
|
|
1999
|
+
}
|
|
1970
2000
|
if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏺ ⏺ start: %s", gobj_full_name(gobj)));
|
|
1971
2001
|
gobj.running = true;
|
|
1972
2002
|
let ret = 0;
|
|
@@ -2124,7 +2154,8 @@
|
|
|
2124
2154
|
if (!gobj_is_running(gobj)) {
|
|
2125
2155
|
if (!(gobj.gclass.gclass_flag & gclass_flag_t.gcflag_required_start_to_play)) {
|
|
2126
2156
|
log_warning(`${gobj_short_name(gobj)}: GObj playing without previous start`);
|
|
2127
|
-
|
|
2157
|
+
if (start_destroys_it(gobj)) return -1;
|
|
2158
|
+
if (!gobj.running) return -1;
|
|
2128
2159
|
} else {
|
|
2129
2160
|
log_error(`${gobj_short_name(gobj)}: Cannot play, start not done`);
|
|
2130
2161
|
return -1;
|
|
@@ -2353,7 +2384,7 @@
|
|
|
2353
2384
|
log_error(`gobj NULL, destroying, or bad type`);
|
|
2354
2385
|
return 0;
|
|
2355
2386
|
}
|
|
2356
|
-
return rc_walk_by_list(gobj
|
|
2387
|
+
return rc_walk_by_list(gobj, /* @__PURE__ */ new Set(), walk_type, cb_walking, user_data, user_data2);
|
|
2357
2388
|
}
|
|
2358
2389
|
/***************************************************************************
|
|
2359
2390
|
*
|
|
@@ -2363,7 +2394,7 @@
|
|
|
2363
2394
|
log_error(`gobj NULL, destroying, or bad type`);
|
|
2364
2395
|
return 0;
|
|
2365
2396
|
}
|
|
2366
|
-
return rc_walk_by_tree(gobj
|
|
2397
|
+
return rc_walk_by_tree(gobj, /* @__PURE__ */ new Set(), walk_type, cb_walking, user_data, user_data2);
|
|
2367
2398
|
}
|
|
2368
2399
|
/***************************************************************
|
|
2369
2400
|
* Walking
|
|
@@ -2390,18 +2421,33 @@
|
|
|
2390
2421
|
log_error(`walk callback must return a NUMBER (-1 stop, 0 descend, >0 skip children), got ${typeof ret}: taken as 0`);
|
|
2391
2422
|
return 0;
|
|
2392
2423
|
}
|
|
2393
|
-
|
|
2394
|
-
|
|
2424
|
+
/***************************************************************
|
|
2425
|
+
* Whether a walk steps over this gobj of the list of `owner`.
|
|
2426
|
+
*
|
|
2427
|
+
* Each list is walked over a COPY of it, because a callback may destroy
|
|
2428
|
+
* any gobj of the list, the current one included, or move one with
|
|
2429
|
+
* gobj_change_parent(). One it destroyed is stepped over, as the C walk
|
|
2430
|
+
* does; one it moved is no longer in this list, and is handed where the
|
|
2431
|
+
* walk finds it now (7.26.27 handed it here AND there); and a gobj is
|
|
2432
|
+
* never handed twice in one walk (`seen`), wherever it was moved.
|
|
2433
|
+
***************************************************************/
|
|
2434
|
+
function walk_steps_over(child, owner, seen) {
|
|
2435
|
+
return gobj_is_destroying(child) || child.parent !== owner || seen.has(child);
|
|
2436
|
+
}
|
|
2437
|
+
function rc_walk_by_list(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2438
|
+
let iter = [...owner.dl_children];
|
|
2395
2439
|
let child;
|
|
2396
2440
|
if (walk_type & walk_type_t.WALK_LAST2FIRST) for (let i = iter.length; i > 0; i--) {
|
|
2397
2441
|
child = iter[i - 1];
|
|
2398
|
-
if (
|
|
2442
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2443
|
+
seen.add(child);
|
|
2399
2444
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2400
2445
|
if (ret < 0) return ret;
|
|
2401
2446
|
}
|
|
2402
2447
|
else for (let i = 0; i < iter.length; i++) {
|
|
2403
2448
|
child = iter[i];
|
|
2404
|
-
if (
|
|
2449
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2450
|
+
seen.add(child);
|
|
2405
2451
|
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2406
2452
|
if (ret < 0) return ret;
|
|
2407
2453
|
}
|
|
@@ -2416,24 +2462,23 @@
|
|
|
2416
2462
|
* or
|
|
2417
2463
|
* WALK_LAST2FIRST
|
|
2418
2464
|
***************************************************************/
|
|
2419
|
-
function rc_walk_by_level(
|
|
2420
|
-
let iter = [...
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
child
|
|
2426
|
-
|
|
2427
|
-
ret =
|
|
2465
|
+
function rc_walk_by_level(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2466
|
+
let iter = [...owner.dl_children];
|
|
2467
|
+
if (walk_type & walk_type_t.WALK_LAST2FIRST) iter.reverse();
|
|
2468
|
+
let handed = [];
|
|
2469
|
+
for (const child of iter) {
|
|
2470
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2471
|
+
seen.add(child);
|
|
2472
|
+
handed.push(child);
|
|
2473
|
+
let ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2428
2474
|
if (ret < 0) return ret;
|
|
2429
2475
|
}
|
|
2430
|
-
|
|
2431
|
-
child = iter[i];
|
|
2476
|
+
for (const child of handed) {
|
|
2432
2477
|
if (gobj_is_destroying(child)) continue;
|
|
2433
|
-
ret = rc_walk_by_level(child
|
|
2478
|
+
let ret = rc_walk_by_level(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2434
2479
|
if (ret < 0) return ret;
|
|
2435
2480
|
}
|
|
2436
|
-
return
|
|
2481
|
+
return 0;
|
|
2437
2482
|
}
|
|
2438
2483
|
/***************************************************************
|
|
2439
2484
|
* Walking
|
|
@@ -2450,27 +2495,29 @@
|
|
|
2450
2495
|
* or
|
|
2451
2496
|
* WALK_LAST2FIRST
|
|
2452
2497
|
***************************************************************/
|
|
2453
|
-
function rc_walk_by_tree(
|
|
2454
|
-
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(
|
|
2455
|
-
let iter = [...
|
|
2498
|
+
function rc_walk_by_tree(owner, seen, walk_type, cb_walking, user_data, user_data2) {
|
|
2499
|
+
if (walk_type & walk_type_t.WALK_BYLEVEL) return rc_walk_by_level(owner, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2500
|
+
let iter = [...owner.dl_children];
|
|
2456
2501
|
let ret;
|
|
2457
2502
|
let child;
|
|
2458
2503
|
if (walk_type & walk_type_t.WALK_BOTTOM2TOP) for (let i = iter.length; i > 0; i--) {
|
|
2459
2504
|
child = iter[i - 1];
|
|
2460
|
-
if (
|
|
2461
|
-
ret = rc_walk_by_tree(child
|
|
2505
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2506
|
+
ret = rc_walk_by_tree(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2462
2507
|
if (ret < 0) return ret;
|
|
2463
2508
|
if (gobj_is_destroying(child)) continue;
|
|
2509
|
+
seen.add(child);
|
|
2464
2510
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2465
2511
|
if (ret < 0) return ret;
|
|
2466
2512
|
}
|
|
2467
2513
|
else for (let i = 0; i < iter.length; i++) {
|
|
2468
2514
|
child = iter[i];
|
|
2469
|
-
if (
|
|
2515
|
+
if (walk_steps_over(child, owner, seen)) continue;
|
|
2516
|
+
seen.add(child);
|
|
2470
2517
|
ret = walk_ret(cb_walking(child, user_data, user_data2));
|
|
2471
2518
|
if (ret < 0) return ret;
|
|
2472
2519
|
else if (ret === 0 && !gobj_is_destroying(child)) {
|
|
2473
|
-
ret = rc_walk_by_tree(child
|
|
2520
|
+
ret = rc_walk_by_tree(child, seen, walk_type, cb_walking, user_data, user_data2);
|
|
2474
2521
|
if (ret < 0) return ret;
|
|
2475
2522
|
}
|
|
2476
2523
|
}
|
|
@@ -2933,12 +2980,20 @@
|
|
|
2933
2980
|
function gobj_change_parent(gobj, parent) {
|
|
2934
2981
|
if (gobj_is_destroying(gobj)) {
|
|
2935
2982
|
log_error("gobj NULL or DESTROYED");
|
|
2936
|
-
return
|
|
2983
|
+
return -1;
|
|
2937
2984
|
}
|
|
2938
2985
|
if (!(parent instanceof GObj)) {
|
|
2939
2986
|
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);
|
|
2940
2987
|
return -1;
|
|
2941
2988
|
}
|
|
2989
|
+
if (gobj_is_destroying(parent)) {
|
|
2990
|
+
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() parent NULL or DESTROYED`);
|
|
2991
|
+
return -1;
|
|
2992
|
+
}
|
|
2993
|
+
for (let p = parent; p; p = p.parent) if (p === gobj) {
|
|
2994
|
+
log_error(`${gobj_short_name(gobj)}: gobj_change_parent() a gobj cannot be its own ancestor: ${gobj_short_name(parent)}`);
|
|
2995
|
+
return -1;
|
|
2996
|
+
}
|
|
2942
2997
|
if (gobj.parent && gobj.parent.gclass.gmt.mt_child_removed) gobj.parent.gclass.gmt.mt_child_removed(gobj.parent, gobj);
|
|
2943
2998
|
if (gobj.parent) {
|
|
2944
2999
|
_remove_child(gobj.parent, gobj);
|
|
@@ -6103,7 +6158,10 @@
|
|
|
6103
6158
|
* for ever; a new corrupt entry is a new WARNING. Its text is never
|
|
6104
6159
|
* shown (JSON.parse() quotes it in its error, and an entry can hold a
|
|
6105
6160
|
* token). A store that cannot be read (blocked) is warned once per
|
|
6106
|
-
* key, and the default is NOT written there
|
|
6161
|
+
* key, and the default is NOT written there; one that cannot be
|
|
6162
|
+
* written (full) is warned once per key too: with `create` it was an
|
|
6163
|
+
* ERROR on every read, the default tried again each time. A key is
|
|
6164
|
+
* warned again after a read that goes well. Outside a browser: the
|
|
6107
6165
|
* default.
|
|
6108
6166
|
********************************************/
|
|
6109
6167
|
function kw_get_local_storage_value(key, default_value, create = false) {
|
|
@@ -6117,6 +6175,7 @@
|
|
|
6117
6175
|
warn_local_storage_once(key, `${where} cannot be read (storage blocked?): the default is used`);
|
|
6118
6176
|
return default_value;
|
|
6119
6177
|
}
|
|
6178
|
+
let went_well = true;
|
|
6120
6179
|
let value = null;
|
|
6121
6180
|
if (text !== null) try {
|
|
6122
6181
|
value = JSON.parse(text);
|
|
@@ -6125,17 +6184,25 @@
|
|
|
6125
6184
|
try {
|
|
6126
6185
|
store.removeItem(key);
|
|
6127
6186
|
log_warning(`${where} does not hold json: removed, the default is used`);
|
|
6128
|
-
local_storage_warned.delete(key);
|
|
6129
6187
|
} catch (e2) {
|
|
6188
|
+
went_well = false;
|
|
6130
6189
|
warn_local_storage_once(key, `${where} does not hold json and cannot be removed: the default is used`);
|
|
6131
6190
|
}
|
|
6132
|
-
text = void 0;
|
|
6133
6191
|
}
|
|
6134
|
-
if (text !== void 0) local_storage_warned.delete(key);
|
|
6135
6192
|
if (value === null) {
|
|
6136
|
-
|
|
6137
|
-
|
|
6193
|
+
value = default_value;
|
|
6194
|
+
if (create) {
|
|
6195
|
+
const default_text = json_text_of(default_value);
|
|
6196
|
+
if (default_text === void 0) log_error(`${where}: cannot write the default: a value with no json text`);
|
|
6197
|
+
else try {
|
|
6198
|
+
store.setItem(key, default_text);
|
|
6199
|
+
} catch (e) {
|
|
6200
|
+
went_well = false;
|
|
6201
|
+
warn_local_storage_once(key, `${where} cannot be written (storage full or blocked?): the default is used, not kept`);
|
|
6202
|
+
}
|
|
6203
|
+
}
|
|
6138
6204
|
}
|
|
6205
|
+
if (went_well) local_storage_warned.delete(key);
|
|
6139
6206
|
return value;
|
|
6140
6207
|
}
|
|
6141
6208
|
/********************************************
|
|
@@ -7375,29 +7442,68 @@
|
|
|
7375
7442
|
return -1;
|
|
7376
7443
|
}
|
|
7377
7444
|
/************************************************************
|
|
7445
|
+
* A new uuid v4 (RFC 9562).
|
|
7446
|
+
*
|
|
7447
|
+
* crypto.randomUUID() exists only in a secure context, so a page
|
|
7448
|
+
* served over http without TLS has none; crypto.getRandomValues()
|
|
7449
|
+
* exists there too. With no crypto at all, Math.random(): not fit
|
|
7450
|
+
* for a secret, and a uuid that names a node is not one.
|
|
7451
|
+
************************************************************/
|
|
7452
|
+
function new_uuid() {
|
|
7453
|
+
const c = typeof window !== "undefined" && window.crypto || globalThis.crypto;
|
|
7454
|
+
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
7455
|
+
const b = /* @__PURE__ */ new Uint8Array(16);
|
|
7456
|
+
if (c && typeof c.getRandomValues === "function") c.getRandomValues(b);
|
|
7457
|
+
else for (let i = 0; i < b.length; i++) b[i] = Math.floor(Math.random() * 256);
|
|
7458
|
+
b[6] = b[6] & 15 | 64;
|
|
7459
|
+
b[8] = b[8] & 63 | 128;
|
|
7460
|
+
const h = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
7461
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
|
|
7462
|
+
}
|
|
7463
|
+
/************************************************************
|
|
7464
|
+
* The uuid of this node: ONE for the life of the page.
|
|
7378
7465
|
*
|
|
7466
|
+
* The one the store keeps ("host_uuid"), made and written there when
|
|
7467
|
+
* there is none. When the store cannot keep it (blocked, full, no
|
|
7468
|
+
* localStorage, outside a browser) the one this page made, warned
|
|
7469
|
+
* once. It goes in the node_uuid attribute of the yuno, the id of the
|
|
7470
|
+
* identity card and the `host` of every message the client sends, so
|
|
7471
|
+
* the first answer is kept and answered again: 7.26.27 made a new
|
|
7472
|
+
* uuid on every call when the store could not keep it, and answered
|
|
7473
|
+
* null without crypto.randomUUID(). A stored value that is not a
|
|
7474
|
+
* uuid (a foreign or corrupt write) is replaced, with a WARNING.
|
|
7379
7475
|
************************************************************/
|
|
7476
|
+
var uuid_of_this_page = null;
|
|
7477
|
+
var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7380
7478
|
function node_uuid() {
|
|
7381
|
-
|
|
7479
|
+
if (uuid_of_this_page) return uuid_of_this_page;
|
|
7382
7480
|
const store = local_store();
|
|
7383
|
-
if (store) {
|
|
7481
|
+
if (!store) {
|
|
7482
|
+
uuid_of_this_page = new_uuid();
|
|
7483
|
+
return uuid_of_this_page;
|
|
7484
|
+
}
|
|
7485
|
+
let uuid = null;
|
|
7486
|
+
try {
|
|
7487
|
+
uuid = store.getItem("host_uuid");
|
|
7488
|
+
} catch (e) {
|
|
7489
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7490
|
+
uuid_of_this_page = new_uuid();
|
|
7491
|
+
return uuid_of_this_page;
|
|
7492
|
+
}
|
|
7493
|
+
if (uuid && !UUID_SHAPE.test(uuid)) {
|
|
7494
|
+
log_warning("node_uuid(): the stored host_uuid is not a uuid: a new one replaces it");
|
|
7495
|
+
uuid = null;
|
|
7496
|
+
}
|
|
7497
|
+
if (!uuid) {
|
|
7498
|
+
uuid = new_uuid();
|
|
7384
7499
|
try {
|
|
7385
|
-
|
|
7500
|
+
store.setItem("host_uuid", uuid);
|
|
7386
7501
|
} catch (e) {
|
|
7387
|
-
uuid
|
|
7388
|
-
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be read (storage blocked?): a uuid of this page only");
|
|
7389
|
-
}
|
|
7390
|
-
if (!uuid && window.crypto?.randomUUID) {
|
|
7391
|
-
uuid = window.crypto.randomUUID();
|
|
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
|
-
}
|
|
7502
|
+
warn_local_storage_once("host_uuid", "node_uuid(): localStorage cannot be written (storage full or blocked?): a uuid of this page only");
|
|
7397
7503
|
}
|
|
7398
|
-
}
|
|
7399
|
-
|
|
7400
|
-
return
|
|
7504
|
+
}
|
|
7505
|
+
uuid_of_this_page = uuid;
|
|
7506
|
+
return uuid_of_this_page;
|
|
7401
7507
|
}
|
|
7402
7508
|
/************************************************************
|
|
7403
7509
|
* Build a cleaned name
|
|
@@ -8682,7 +8788,7 @@
|
|
|
8682
8788
|
SDATA(data_type_t.DTP_STRING, "cert_pem", sdata_flag_t.SDF_PERSIST, "", "SSL server certification, PEM str format"),
|
|
8683
8789
|
SDATA(data_type_t.DTP_JSON, "extra_info", sdata_flag_t.SDF_RD, "{}", "dict data set by user, added to the identity card msg."),
|
|
8684
8790
|
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."),
|
|
8685
|
-
SDATA(data_type_t.DTP_INTEGER, "timeout_retry", sdata_flag_t.SDF_RD, "5000", "
|
|
8791
|
+
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"),
|
|
8686
8792
|
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"),
|
|
8687
8793
|
SDATA(data_type_t.DTP_INTEGER, "timeout_idack", sdata_flag_t.SDF_RD, "5000", "timeout waiting idAck"),
|
|
8688
8794
|
SDATA(data_type_t.DTP_POINTER, "subscriber", 0, 0, "subscriber of output-events. If null then subscriber is the parent"),
|