@yuneta/gobj-js 7.25.9 → 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 +85 -24
- package/dist/gobj-js.cjs.js +176 -72
- package/dist/gobj-js.cjs.js.map +1 -1
- package/dist/gobj-js.cjs.min.js +916 -862
- package/dist/gobj-js.cjs.min.js.map +1 -1
- package/dist/gobj-js.es.js +176 -72
- package/dist/gobj-js.es.js.map +1 -1
- package/dist/gobj-js.es.min.js +1032 -978
- package/dist/gobj-js.es.min.js.map +1 -1
- package/dist/gobj-js.iife.js +176 -72
- package/dist/gobj-js.iife.js.map +1 -1
- package/dist/gobj-js.iife.min.js +923 -869
- package/dist/gobj-js.iife.min.js.map +1 -1
- package/dist/gobj-js.umd.js +176 -72
- package/dist/gobj-js.umd.js.map +1 -1
- package/dist/gobj-js.umd.min.js +923 -869
- package/dist/gobj-js.umd.min.js.map +1 -1
- package/package.json +2 -2
package/dist/gobj-js.umd.js
CHANGED
|
@@ -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) {
|
|
@@ -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__) {
|
|
@@ -2580,7 +2599,16 @@
|
|
|
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;
|
|
@@ -3251,10 +3279,22 @@
|
|
|
3251
3279
|
f_warning = _console.warn;
|
|
3252
3280
|
}
|
|
3253
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
|
+
}
|
|
3254
3293
|
function format_log(format) {
|
|
3255
3294
|
const args = Array.prototype.slice.call(arguments);
|
|
3256
3295
|
let output = "";
|
|
3257
3296
|
if (typeof format === "string") {
|
|
3297
|
+
if (args.length === 1) return format;
|
|
3258
3298
|
let i = 1;
|
|
3259
3299
|
output = format.replace(/%[sdifoO]/g, (match) => {
|
|
3260
3300
|
const val = args[i++];
|
|
@@ -3264,17 +3304,17 @@
|
|
|
3264
3304
|
case "%i": return parseInt(val);
|
|
3265
3305
|
case "%f": return parseFloat(val);
|
|
3266
3306
|
case "%o":
|
|
3267
|
-
case "%O": return typeof val === "object" ?
|
|
3307
|
+
case "%O": return typeof val === "object" ? log_stringify(val) : String(val);
|
|
3268
3308
|
default: return match;
|
|
3269
3309
|
}
|
|
3270
3310
|
});
|
|
3271
|
-
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));
|
|
3272
3312
|
if (rest.length > 0) output += " " + rest.join(" ");
|
|
3273
|
-
} else output = args.map((arg) => typeof arg === "object" ?
|
|
3313
|
+
} else output = args.map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg)).join(" ");
|
|
3274
3314
|
return output;
|
|
3275
3315
|
}
|
|
3276
|
-
function log_error(format) {
|
|
3277
|
-
let msg = format_log(format);
|
|
3316
|
+
function log_error(format, ...args) {
|
|
3317
|
+
let msg = format_log(format, ...args);
|
|
3278
3318
|
let hora = current_timestamp();
|
|
3279
3319
|
if (f_error) {
|
|
3280
3320
|
if (f_error === _console.error) {
|
|
@@ -3286,8 +3326,8 @@
|
|
|
3286
3326
|
}
|
|
3287
3327
|
emit_log_callback("error", msg, hora);
|
|
3288
3328
|
}
|
|
3289
|
-
function log_warning(format) {
|
|
3290
|
-
let msg = format_log(format);
|
|
3329
|
+
function log_warning(format, ...args) {
|
|
3330
|
+
let msg = format_log(format, ...args);
|
|
3291
3331
|
let hora = current_timestamp();
|
|
3292
3332
|
if (f_warning) {
|
|
3293
3333
|
if (f_warning === _console.warn) {
|
|
@@ -3299,24 +3339,24 @@
|
|
|
3299
3339
|
}
|
|
3300
3340
|
emit_log_callback("warning", msg, hora);
|
|
3301
3341
|
}
|
|
3302
|
-
function log_info(format) {
|
|
3303
|
-
let msg = format_log(format);
|
|
3342
|
+
function log_info(format, ...args) {
|
|
3343
|
+
let msg = format_log(format, ...args);
|
|
3304
3344
|
let hora = current_timestamp();
|
|
3305
3345
|
if (f_info) {
|
|
3306
3346
|
if (console_wants("info", msg)) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
|
|
3307
3347
|
}
|
|
3308
3348
|
emit_log_callback("info", msg, hora);
|
|
3309
3349
|
}
|
|
3310
|
-
function log_debug(format) {
|
|
3311
|
-
let msg = format_log(format);
|
|
3350
|
+
function log_debug(format, ...args) {
|
|
3351
|
+
let msg = format_log(format, ...args);
|
|
3312
3352
|
let hora = current_timestamp();
|
|
3313
3353
|
if (f_debug) {
|
|
3314
3354
|
if (console_wants("debug", msg)) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
|
|
3315
3355
|
}
|
|
3316
3356
|
emit_log_callback("debug", msg, hora);
|
|
3317
3357
|
}
|
|
3318
|
-
function trace_msg(format) {
|
|
3319
|
-
let msg = format_log(format);
|
|
3358
|
+
function trace_msg(format, ...args) {
|
|
3359
|
+
let msg = format_log(format, ...args);
|
|
3320
3360
|
let hora = current_timestamp();
|
|
3321
3361
|
if (f_debug) {
|
|
3322
3362
|
if (console_wants("msg", msg)) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
|
|
@@ -3865,6 +3905,8 @@
|
|
|
3865
3905
|
if (is_number(jn_var1) || is_number(jn_var2)) {
|
|
3866
3906
|
let val1 = Number(jn_var1);
|
|
3867
3907
|
let val2 = Number(jn_var2);
|
|
3908
|
+
if (Number.isNaN(val1)) val1 = 0;
|
|
3909
|
+
if (Number.isNaN(val2)) val2 = 0;
|
|
3868
3910
|
if (val1 > val2) return 1;
|
|
3869
3911
|
else if (val1 < val2) return -1;
|
|
3870
3912
|
else return 0;
|
|
@@ -3932,6 +3974,28 @@
|
|
|
3932
3974
|
return false;
|
|
3933
3975
|
}
|
|
3934
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
|
+
/************************************************************
|
|
3935
3999
|
* The value at `path` (keys joined by a backtick), as the C
|
|
3936
4000
|
* kw_find_path() finds it: undefined when it is not there.
|
|
3937
4001
|
* A kw that is not a dict or a list is LOGGED ("kw must be list
|
|
@@ -3958,7 +4022,12 @@
|
|
|
3958
4022
|
}
|
|
3959
4023
|
let ss = path.split("`");
|
|
3960
4024
|
let len = ss.length;
|
|
3961
|
-
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;
|
|
3962
4031
|
kw = kw[ss[i]];
|
|
3963
4032
|
if (kw === void 0 || kw === null) {
|
|
3964
4033
|
if (verbose) log_error(`${prefix}path not found: '${path}'`);
|
|
@@ -4341,17 +4410,13 @@
|
|
|
4341
4410
|
return -1;
|
|
4342
4411
|
}
|
|
4343
4412
|
let ss = path.split("`");
|
|
4344
|
-
if (ss.length <= 1) {
|
|
4345
|
-
kw[path] = value;
|
|
4346
|
-
return 0;
|
|
4347
|
-
}
|
|
4348
4413
|
let len = ss.length;
|
|
4349
4414
|
for (let i = 0; i < len; i++) {
|
|
4350
4415
|
let key = ss[i];
|
|
4351
|
-
if (i === len - 1) kw
|
|
4416
|
+
if (i === len - 1) set_own_key(kw, key, value);
|
|
4352
4417
|
else {
|
|
4353
|
-
let seg = kw[key];
|
|
4354
|
-
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, {});
|
|
4355
4420
|
else if (!is_object(seg) && !is_array(seg)) {
|
|
4356
4421
|
log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_set_dict_value(): segment '${key}' is not a dict or a list: '${path}'`);
|
|
4357
4422
|
return -1;
|
|
@@ -4406,9 +4471,9 @@
|
|
|
4406
4471
|
if (!matched) break;
|
|
4407
4472
|
continue;
|
|
4408
4473
|
}
|
|
4409
|
-
let jn_record_value = kw_get_dict_value(0, kw, path, 0, 0);
|
|
4410
|
-
if (
|
|
4411
|
-
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) {
|
|
4412
4477
|
matched = false;
|
|
4413
4478
|
break;
|
|
4414
4479
|
}
|
|
@@ -4527,10 +4592,11 @@
|
|
|
4527
4592
|
***************************************************************************/
|
|
4528
4593
|
function kw_clone_by_not_keys(gobj, kw, keys, verbose) {
|
|
4529
4594
|
let kw_clone = {};
|
|
4595
|
+
if (!is_object(kw)) return kw_clone;
|
|
4530
4596
|
json_object_update(kw_clone, kw);
|
|
4531
4597
|
if (is_string(keys) && !empty_string(keys)) {
|
|
4532
4598
|
let key = keys;
|
|
4533
|
-
if (
|
|
4599
|
+
if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
|
|
4534
4600
|
else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
|
|
4535
4601
|
} else if (is_object(keys) && json_object_size(keys) > 0) {
|
|
4536
4602
|
for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
|
|
@@ -5490,9 +5556,15 @@
|
|
|
5490
5556
|
* will be 'data-i18n' attr
|
|
5491
5557
|
*
|
|
5492
5558
|
* content -> string | [createElement2() or parameters of createElement2]
|
|
5559
|
+
* | HTMLElement | SVGElement | Text
|
|
5493
5560
|
* if string begins with '<' then
|
|
5494
5561
|
* it will be converted to HTMLElement
|
|
5495
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)]
|
|
5496
5568
|
* if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
|
|
5497
5569
|
* it will be overridden with the translation
|
|
5498
5570
|
* content = translate(attrs['i18n']));
|
|
@@ -5931,7 +6003,7 @@
|
|
|
5931
6003
|
current[seg] = flat[key];
|
|
5932
6004
|
} else {
|
|
5933
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`);
|
|
5934
|
-
current
|
|
6006
|
+
set_own_key(current, seg, flat[key]);
|
|
5935
6007
|
}
|
|
5936
6008
|
break;
|
|
5937
6009
|
}
|
|
@@ -5944,10 +6016,10 @@
|
|
|
5944
6016
|
current[seg] = child;
|
|
5945
6017
|
}
|
|
5946
6018
|
} else {
|
|
5947
|
-
child = current[seg];
|
|
6019
|
+
child = is_prototype_segment(current, seg) ? void 0 : current[seg];
|
|
5948
6020
|
if (child === void 0) {
|
|
5949
6021
|
child = next_is_index ? [] : {};
|
|
5950
|
-
current
|
|
6022
|
+
set_own_key(current, seg, child);
|
|
5951
6023
|
}
|
|
5952
6024
|
}
|
|
5953
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`);
|
|
@@ -6710,6 +6782,7 @@
|
|
|
6710
6782
|
***************************************************************/
|
|
6711
6783
|
function mt_play(gobj) {
|
|
6712
6784
|
let default_service = gobj_default_service();
|
|
6785
|
+
if (!default_service) return 0;
|
|
6713
6786
|
if (!gobj_is_running(default_service)) gobj_start(default_service);
|
|
6714
6787
|
if (!gobj_is_playing(default_service)) gobj_play(default_service);
|
|
6715
6788
|
return 0;
|
|
@@ -6718,7 +6791,8 @@
|
|
|
6718
6791
|
* Framework Method: Pause
|
|
6719
6792
|
***************************************************************/
|
|
6720
6793
|
function mt_pause(gobj) {
|
|
6721
|
-
|
|
6794
|
+
let default_service = gobj_default_service();
|
|
6795
|
+
if (default_service && gobj_is_playing(default_service)) gobj_pause(default_service);
|
|
6722
6796
|
return 0;
|
|
6723
6797
|
}
|
|
6724
6798
|
/***************************************************************
|
|
@@ -6974,6 +7048,7 @@
|
|
|
6974
7048
|
function mt_create(gobj) {
|
|
6975
7049
|
let priv = gobj.priv;
|
|
6976
7050
|
priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), "C_TIMER", {}, gobj);
|
|
7051
|
+
priv.ws_seq = 0;
|
|
6977
7052
|
priv.url = gobj_read_str_attr(gobj, "url");
|
|
6978
7053
|
priv.remote_yuno_name = gobj_read_str_attr(gobj, "remote_yuno_name");
|
|
6979
7054
|
priv.remote_yuno_role = gobj_read_str_attr(gobj, "remote_yuno_role");
|
|
@@ -7008,6 +7083,16 @@
|
|
|
7008
7083
|
function mt_start(gobj) {
|
|
7009
7084
|
let priv = gobj.priv;
|
|
7010
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
|
+
}
|
|
7011
7096
|
priv.websocket = setup_websocket(gobj);
|
|
7012
7097
|
return 0;
|
|
7013
7098
|
}
|
|
@@ -7142,10 +7227,16 @@
|
|
|
7142
7227
|
log_error(`${gobj_short_name(gobj)}: Failed to initialize WebSocket.`);
|
|
7143
7228
|
return null;
|
|
7144
7229
|
}
|
|
7230
|
+
const ws_seq = ++gobj.priv.ws_seq;
|
|
7145
7231
|
websocket.onopen = () => {
|
|
7146
|
-
|
|
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);
|
|
7147
7237
|
};
|
|
7148
7238
|
websocket.onmessage = (e) => {
|
|
7239
|
+
if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
|
|
7149
7240
|
gobj_send_event(gobj, "EV_ON_MESSAGE", {
|
|
7150
7241
|
url,
|
|
7151
7242
|
data: e.data
|
|
@@ -7153,9 +7244,13 @@
|
|
|
7153
7244
|
};
|
|
7154
7245
|
websocket.onclose = (e) => {
|
|
7155
7246
|
if (gobj_is_destroying(gobj)) return;
|
|
7247
|
+
if (ws_seq !== gobj.priv.ws_seq) return;
|
|
7156
7248
|
if (!gobj_read_bool_attr(gobj_yuno(), "browser_beforeunload")) gobj_send_event(gobj, "EV_ON_CLOSE", {
|
|
7157
7249
|
url,
|
|
7158
|
-
|
|
7250
|
+
ws_seq,
|
|
7251
|
+
code: e.code,
|
|
7252
|
+
reason: e.reason,
|
|
7253
|
+
was_clean: e.wasClean
|
|
7159
7254
|
}, gobj);
|
|
7160
7255
|
else log_warning("Close websocket by unload page");
|
|
7161
7256
|
};
|
|
@@ -7176,7 +7271,7 @@
|
|
|
7176
7271
|
try {
|
|
7177
7272
|
websocket.close(code, reason);
|
|
7178
7273
|
} catch (e) {
|
|
7179
|
-
log_error(
|
|
7274
|
+
log_error(`${gobj_short_name(gobj)}: Error closing WebSocket: ${e.message}`);
|
|
7180
7275
|
}
|
|
7181
7276
|
}
|
|
7182
7277
|
/***************************************************************
|
|
@@ -7302,29 +7397,29 @@
|
|
|
7302
7397
|
try {
|
|
7303
7398
|
x = JSON.parse(data);
|
|
7304
7399
|
} catch (e) {
|
|
7305
|
-
|
|
7400
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event json: ${e}`);
|
|
7306
7401
|
return null;
|
|
7307
7402
|
}
|
|
7308
7403
|
if (!(x instanceof Object)) {
|
|
7309
|
-
|
|
7404
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: websocket data not a json object`);
|
|
7310
7405
|
return null;
|
|
7311
7406
|
}
|
|
7312
7407
|
let event = x["event"];
|
|
7313
7408
|
if (!event) {
|
|
7314
|
-
|
|
7409
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: no event`);
|
|
7315
7410
|
return null;
|
|
7316
7411
|
}
|
|
7317
7412
|
if (typeof event !== "string") {
|
|
7318
|
-
|
|
7413
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: event not a string`);
|
|
7319
7414
|
return null;
|
|
7320
7415
|
}
|
|
7321
7416
|
let kw = x["kw"];
|
|
7322
7417
|
if (!kw) {
|
|
7323
|
-
|
|
7418
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_kw: no kw`);
|
|
7324
7419
|
return null;
|
|
7325
7420
|
}
|
|
7326
7421
|
if (!(kw instanceof Object)) {
|
|
7327
|
-
|
|
7422
|
+
log_warning(`${gobj_short_name(gobj)}: parsing inter_event: kw not a json object`);
|
|
7328
7423
|
return null;
|
|
7329
7424
|
}
|
|
7330
7425
|
return {
|
|
@@ -7384,10 +7479,9 @@
|
|
|
7384
7479
|
***************************************************************/
|
|
7385
7480
|
function ac_on_close(gobj, event, kw, src) {
|
|
7386
7481
|
let priv = gobj.priv;
|
|
7387
|
-
let e = kw.e;
|
|
7388
7482
|
let url = kw.url;
|
|
7389
7483
|
set_remote_log_functions();
|
|
7390
|
-
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})`);
|
|
7391
7485
|
if (priv.websocket) {
|
|
7392
7486
|
priv.websocket.onopen = null;
|
|
7393
7487
|
priv.websocket.onmessage = null;
|
|
@@ -7404,15 +7498,15 @@
|
|
|
7404
7498
|
remote_yuno_service: priv.remote_yuno_service
|
|
7405
7499
|
});
|
|
7406
7500
|
} else {
|
|
7407
|
-
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})`);
|
|
7408
7502
|
gobj_publish_event(gobj, "EV_ON_OPEN_ERROR", {
|
|
7409
7503
|
url,
|
|
7410
7504
|
remote_yuno_name: priv.remote_yuno_name,
|
|
7411
7505
|
remote_yuno_role: priv.remote_yuno_role,
|
|
7412
7506
|
remote_yuno_service: priv.remote_yuno_service,
|
|
7413
|
-
code:
|
|
7414
|
-
reason:
|
|
7415
|
-
was_clean:
|
|
7507
|
+
code: kw.code,
|
|
7508
|
+
reason: kw.reason,
|
|
7509
|
+
was_clean: kw.was_clean
|
|
7416
7510
|
});
|
|
7417
7511
|
}
|
|
7418
7512
|
if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, next_retry(gobj));
|
|
@@ -7510,6 +7604,10 @@
|
|
|
7510
7604
|
function ac_on_message(gobj, event, kw, src) {
|
|
7511
7605
|
let url = gobj.priv.url;
|
|
7512
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
|
+
}
|
|
7513
7611
|
if (is_traffic_tracing(gobj)) {
|
|
7514
7612
|
let prefix = gobj_name(gobj_yuno()) + " <== " + url;
|
|
7515
7613
|
let size = kw.data.length;
|
|
@@ -7535,8 +7633,14 @@
|
|
|
7535
7633
|
return 0;
|
|
7536
7634
|
}
|
|
7537
7635
|
let iev_dst_service = kw_get_str(gobj, event_id, "dst_service", "");
|
|
7538
|
-
if (msg_type === "__subscribing__")
|
|
7539
|
-
|
|
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
|
+
}
|
|
7540
7644
|
if (gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
|
|
7541
7645
|
gobj_send_event(gobj, iev_event, iev_kw, gobj);
|
|
7542
7646
|
return 0;
|