@yuneta/gobj-js 7.25.9 → 7.26.1

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.
@@ -159,7 +159,7 @@ var gobjJs = (function(exports) {
159
159
  function build_command_response(gobj, result, comment, schema, data) {
160
160
  return {
161
161
  result,
162
- comment: comment || {},
162
+ comment: comment || "",
163
163
  schema: schema || {},
164
164
  data: data || []
165
165
  };
@@ -213,7 +213,7 @@ var gobjJs = (function(exports) {
213
213
  var __global_stats_parser_fn__ = null;
214
214
  var dl_global_event_types = [];
215
215
  var _gclass_register = Object.create(null);
216
- var __jn_services__ = {};
216
+ var __jn_services__ = Object.create(null);
217
217
  var __yuno__ = null;
218
218
  var __default_service__ = null;
219
219
  var __inside__ = 0;
@@ -822,7 +822,8 @@ var gobjJs = (function(exports) {
822
822
  if (!is_object(jn_value)) jn_value = {};
823
823
  break;
824
824
  case data_type_t.DTP_JSON:
825
- if (is_string(svalue)) try {
825
+ if (svalue === "" || svalue === void 0) jn_value = null;
826
+ else if (is_string(svalue)) try {
826
827
  jn_value = JSON.parse(svalue);
827
828
  } catch (error) {
828
829
  log_error(`JSON parse error: ${error.message}`);
@@ -857,11 +858,17 @@ var gobjJs = (function(exports) {
857
858
  break;
858
859
  case data_type_t.DTP_INTEGER:
859
860
  jn_value2 = parseInt(jn_value_);
860
- if (isNaN(jn_value2)) log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
861
+ if (isNaN(jn_value2)) {
862
+ log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
863
+ return -1;
864
+ }
861
865
  break;
862
866
  case data_type_t.DTP_REAL:
863
867
  jn_value2 = Number(jn_value_);
864
- if (isNaN(jn_value2)) log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
868
+ if (isNaN(jn_value2)) {
869
+ log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);
870
+ return -1;
871
+ }
865
872
  break;
866
873
  case data_type_t.DTP_LIST:
867
874
  if (is_string(jn_value_)) try {
@@ -888,15 +895,14 @@ var gobjJs = (function(exports) {
888
895
  }
889
896
  break;
890
897
  case data_type_t.DTP_JSON:
891
- if (is_string(jn_value_)) try {
892
- jn_value2 = JSON.parse(jn_value_);
893
- } catch (error) {
894
- log_error(`JSON parse error: ${error.message}`);
895
- }
896
- else jn_value2 = jn_value_;
897
- if (!is_array(jn_value2) && !is_object(jn_value2)) {
898
- log_error(`attr must be a json dict/list: ${it.name}`);
899
- return -1;
898
+ jn_value2 = jn_value_;
899
+ if (is_string(jn_value_)) {
900
+ const t = jn_value_.trim();
901
+ if (t.startsWith("{") || t.startsWith("[")) try {
902
+ jn_value2 = JSON.parse(t);
903
+ } catch (error) {
904
+ jn_value2 = jn_value_;
905
+ }
900
906
  }
901
907
  break;
902
908
  case data_type_t.DTP_POINTER: jn_value2 = jn_value_;
@@ -1201,6 +1207,10 @@ var gobjJs = (function(exports) {
1201
1207
  * find a service
1202
1208
  ************************************************************/
1203
1209
  function gobj_find_service(service_name, verbose) {
1210
+ if (!is_string(service_name)) {
1211
+ log_error(`gobj_find_service(): service name must be a string: ${service_name}`);
1212
+ return null;
1213
+ }
1204
1214
  service_name = service_name.toLowerCase();
1205
1215
  let service_gobj = __jn_services__[service_name];
1206
1216
  if (!service_gobj) {
@@ -1358,9 +1368,10 @@ var gobjJs = (function(exports) {
1358
1368
  return null;
1359
1369
  }
1360
1370
  if (is_string(parent)) {
1361
- parent = gobj_find_service(parent);
1371
+ const parent_name = parent;
1372
+ parent = gobj_find_service(parent_name);
1362
1373
  if (!parent) {
1363
- log_warning(`parent service not found: ${parent}`);
1374
+ log_warning(`parent service not found: ${parent_name}`);
1364
1375
  return null;
1365
1376
  }
1366
1377
  }
@@ -1473,6 +1484,7 @@ var gobjJs = (function(exports) {
1473
1484
  parent.gclass.gmt.mt_child_removed(parent, gobj);
1474
1485
  }
1475
1486
  if (gobj.gobj_flag & gobj_flag_t.gobj_flag_service) _deregister_service(gobj);
1487
+ if (gobj === __default_service__) __default_service__ = null;
1476
1488
  gobj_unsubscribe_list(gobj, gobj.dl_subscriptions, true);
1477
1489
  gobj_unsubscribe_list(gobj, gobj.dl_subscribings, true);
1478
1490
  if (parent) {
@@ -1818,7 +1830,7 @@ var gobjJs = (function(exports) {
1818
1830
  log_error(`gobj NULL of bad type`);
1819
1831
  return null;
1820
1832
  }
1821
- if (gobj.bottom_gobj) log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);
1833
+ if (gobj.bottom_gobj && bottom_gobj) log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);
1822
1834
  gobj.bottom_gobj = bottom_gobj;
1823
1835
  }
1824
1836
  /***************************************************************************
@@ -2233,7 +2245,7 @@ var gobjJs = (function(exports) {
2233
2245
  jn_attrs[key] = value;
2234
2246
  if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
2235
2247
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2236
- if (gobj.mt_writing) gobj.mt_writing(gobj, key);
2248
+ if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2237
2249
  }
2238
2250
  return 0;
2239
2251
  }
@@ -2257,8 +2269,8 @@ var gobjJs = (function(exports) {
2257
2269
  if (!it.name) continue;
2258
2270
  if (exclude_flag && it.flag & exclude_flag) continue;
2259
2271
  if (include_flag === -1 || it.flag & include_flag) {
2260
- const value = set_default(gobj, gobj.jn_attrs, it);
2261
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = value;
2272
+ set_default(gobj, gobj.jn_attrs, it);
2273
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
2262
2274
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
2263
2275
  }
2264
2276
  }
@@ -2292,7 +2304,7 @@ var gobjJs = (function(exports) {
2292
2304
  let hs = gobj_hsdata2(gobj, name, false);
2293
2305
  if (hs) {
2294
2306
  hs[name] = parseBoolean(value);
2295
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = value;
2307
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2296
2308
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2297
2309
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2298
2310
  }
@@ -2308,7 +2320,7 @@ var gobjJs = (function(exports) {
2308
2320
  let hs = gobj_hsdata2(gobj, name, false);
2309
2321
  if (hs) {
2310
2322
  hs[name] = parseInt(value);
2311
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = value;
2323
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2312
2324
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2313
2325
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2314
2326
  }
@@ -2324,7 +2336,7 @@ var gobjJs = (function(exports) {
2324
2336
  let hs = gobj_hsdata2(gobj, name, false);
2325
2337
  if (hs) {
2326
2338
  hs[name] = String(value);
2327
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = value;
2339
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2328
2340
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2329
2341
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2330
2342
  }
@@ -2378,15 +2390,15 @@ var gobjJs = (function(exports) {
2378
2390
  log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);
2379
2391
  return -1;
2380
2392
  }
2381
- if (gobj.parent && gobj.parent.mt_child_removed) gobj.parent.mt_child_removed(gobj.parent, gobj);
2393
+ if (gobj.parent && gobj.parent.gclass.gmt.mt_child_removed) gobj.parent.gclass.gmt.mt_child_removed(gobj.parent, gobj);
2382
2394
  if (gobj.parent) {
2383
2395
  _remove_child(gobj.parent, gobj);
2384
2396
  gobj.parent = null;
2385
2397
  }
2386
2398
  _add_child(parent, gobj);
2387
- if (parent.mt_child_added) {
2399
+ if (parent.gclass.gmt.mt_child_added) {
2388
2400
  if (__trace_gobj_create_delete__(gobj)) log_debug(sprintf("👦👦🔵 child_added(%s): %s", gobj_full_name(parent), gobj_short_name(gobj)));
2389
- parent.mt_child_added(parent, gobj);
2401
+ parent.gclass.gmt.mt_child_added(parent, gobj);
2390
2402
  }
2391
2403
  return 0;
2392
2404
  }
@@ -2498,9 +2510,19 @@ var gobjJs = (function(exports) {
2498
2510
  let snapshot = __dl_posted_events__;
2499
2511
  __dl_posted_events__ = [];
2500
2512
  let delivered = 0;
2501
- for (let msg of snapshot) {
2513
+ for (let i = 0; i < snapshot.length; i++) {
2514
+ const msg = snapshot[i];
2502
2515
  if (msg.dst.obflag & (obflag_t.obflag_destroyed | obflag_t.obflag_destroying)) continue;
2503
- gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);
2516
+ try {
2517
+ gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);
2518
+ } catch (e) {
2519
+ __dl_posted_events__ = snapshot.slice(i + 1).concat(__dl_posted_events__);
2520
+ if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
2521
+ __posted_events_scheduled__ = true;
2522
+ setTimeout(gobj_deliver_posted_events, 0);
2523
+ }
2524
+ throw e;
2525
+ }
2504
2526
  delivered++;
2505
2527
  }
2506
2528
  if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
@@ -2578,7 +2600,16 @@ var gobjJs = (function(exports) {
2578
2600
  let ret = -1;
2579
2601
  try {
2580
2602
  if (event_action.action) ret = event_action.action(dst, event, kw, src);
2581
- } finally {}
2603
+ } catch (e) {
2604
+ __inside__--;
2605
+ if (!(e && e.__gobj_logged__)) {
2606
+ log_error(`${gobj_short_name(dst)}: action of ${event} in ${state.state_name} THREW: ${e && e.stack ? e.stack : e}`);
2607
+ try {
2608
+ e.__gobj_logged__ = true;
2609
+ } catch (e2) {}
2610
+ }
2611
+ throw e;
2612
+ }
2582
2613
  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));
2583
2614
  __inside__--;
2584
2615
  return ret;
@@ -3249,10 +3280,22 @@ var gobjJs = (function(exports) {
3249
3280
  f_warning = _console.warn;
3250
3281
  }
3251
3282
  }
3283
+ /************************************************************
3284
+ * JSON.stringify for a log line: a circular object (a gobj,
3285
+ * a DOM node) must not make the log call itself throw.
3286
+ ************************************************************/
3287
+ function log_stringify(v) {
3288
+ try {
3289
+ return JSON.stringify(v);
3290
+ } catch (e) {
3291
+ return String(v);
3292
+ }
3293
+ }
3252
3294
  function format_log(format) {
3253
3295
  const args = Array.prototype.slice.call(arguments);
3254
3296
  let output = "";
3255
3297
  if (typeof format === "string") {
3298
+ if (args.length === 1) return format;
3256
3299
  let i = 1;
3257
3300
  output = format.replace(/%[sdifoO]/g, (match) => {
3258
3301
  const val = args[i++];
@@ -3262,17 +3305,17 @@ var gobjJs = (function(exports) {
3262
3305
  case "%i": return parseInt(val);
3263
3306
  case "%f": return parseFloat(val);
3264
3307
  case "%o":
3265
- case "%O": return typeof val === "object" ? JSON.stringify(val) : String(val);
3308
+ case "%O": return typeof val === "object" ? log_stringify(val) : String(val);
3266
3309
  default: return match;
3267
3310
  }
3268
3311
  });
3269
- const rest = args.slice(i).map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg));
3312
+ const rest = args.slice(i).map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg));
3270
3313
  if (rest.length > 0) output += " " + rest.join(" ");
3271
- } else output = args.map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg)).join(" ");
3314
+ } else output = args.map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg)).join(" ");
3272
3315
  return output;
3273
3316
  }
3274
- function log_error(format) {
3275
- let msg = format_log(format);
3317
+ function log_error(format, ...args) {
3318
+ let msg = format_log(format, ...args);
3276
3319
  let hora = current_timestamp();
3277
3320
  if (f_error) {
3278
3321
  if (f_error === _console.error) {
@@ -3284,8 +3327,8 @@ var gobjJs = (function(exports) {
3284
3327
  }
3285
3328
  emit_log_callback("error", msg, hora);
3286
3329
  }
3287
- function log_warning(format) {
3288
- let msg = format_log(format);
3330
+ function log_warning(format, ...args) {
3331
+ let msg = format_log(format, ...args);
3289
3332
  let hora = current_timestamp();
3290
3333
  if (f_warning) {
3291
3334
  if (f_warning === _console.warn) {
@@ -3297,24 +3340,24 @@ var gobjJs = (function(exports) {
3297
3340
  }
3298
3341
  emit_log_callback("warning", msg, hora);
3299
3342
  }
3300
- function log_info(format) {
3301
- let msg = format_log(format);
3343
+ function log_info(format, ...args) {
3344
+ let msg = format_log(format, ...args);
3302
3345
  let hora = current_timestamp();
3303
3346
  if (f_info) {
3304
3347
  if (console_wants("info", msg)) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
3305
3348
  }
3306
3349
  emit_log_callback("info", msg, hora);
3307
3350
  }
3308
- function log_debug(format) {
3309
- let msg = format_log(format);
3351
+ function log_debug(format, ...args) {
3352
+ let msg = format_log(format, ...args);
3310
3353
  let hora = current_timestamp();
3311
3354
  if (f_debug) {
3312
3355
  if (console_wants("debug", msg)) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
3313
3356
  }
3314
3357
  emit_log_callback("debug", msg, hora);
3315
3358
  }
3316
- function trace_msg(format) {
3317
- let msg = format_log(format);
3359
+ function trace_msg(format, ...args) {
3360
+ let msg = format_log(format, ...args);
3318
3361
  let hora = current_timestamp();
3319
3362
  if (f_debug) {
3320
3363
  if (console_wants("msg", msg)) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
@@ -3568,7 +3611,7 @@ var gobjJs = (function(exports) {
3568
3611
  if ((is_secret_name(key.slice(-128)) || value_is_secret && key === "value") && value !== void 0 && value !== null && value !== "") shown = "********";
3569
3612
  else shown = _json_mask_secrets(value, memo, depth + 1, budget);
3570
3613
  if (shown !== value) changed = true;
3571
- result[key] = shown;
3614
+ set_own_key(result, key, shown);
3572
3615
  }
3573
3616
  if (truncated) result["<more>"] = MASK_TOO_LARGE;
3574
3617
  }
@@ -3640,7 +3683,7 @@ var gobjJs = (function(exports) {
3640
3683
  ************************************************************/
3641
3684
  function json_object_update(destination, source) {
3642
3685
  if (!source) return destination;
3643
- for (let property of Object.keys(source)) destination[property] = source[property];
3686
+ for (let property of Object.keys(source)) set_own_key(destination, property, source[property]);
3644
3687
  return destination;
3645
3688
  }
3646
3689
  /************************************************************
@@ -3649,7 +3692,7 @@ var gobjJs = (function(exports) {
3649
3692
  ************************************************************/
3650
3693
  function json_object_update_existing(destination, source) {
3651
3694
  if (!source) return destination;
3652
- for (let property in source) if (source.hasOwnProperty(property) && destination.hasOwnProperty(property)) destination[property] = source[property];
3695
+ for (let property in source) if (Object.prototype.hasOwnProperty.call(source, property) && Object.prototype.hasOwnProperty.call(destination, property)) set_own_key(destination, property, source[property]);
3653
3696
  return destination;
3654
3697
  }
3655
3698
  /************************************************************
@@ -3658,32 +3701,32 @@ var gobjJs = (function(exports) {
3658
3701
  ************************************************************/
3659
3702
  function json_object_update_missing(destination, source) {
3660
3703
  if (!source) return destination;
3661
- for (let property in source) if (source.hasOwnProperty(property) && !destination.hasOwnProperty(property)) destination[property] = source[property];
3704
+ for (let property in source) if (Object.prototype.hasOwnProperty.call(source, property) && !Object.prototype.hasOwnProperty.call(destination, property)) set_own_key(destination, property, source[property]);
3662
3705
  return destination;
3663
3706
  }
3664
3707
  /************************************************************
3665
3708
  * Simulate jansson function
3666
3709
  ************************************************************/
3667
3710
  function json_object_get(o, key) {
3668
- if (o && o.hasOwnProperty(key)) return o[key];
3711
+ if (o && Object.prototype.hasOwnProperty.call(o, key)) return o[key];
3669
3712
  }
3670
3713
  /************************************************************
3671
3714
  * Simulate jansson function
3672
3715
  ************************************************************/
3673
3716
  function json_object_del(o, k) {
3674
- if (o && o.hasOwnProperty(k)) delete o[k];
3717
+ if (o && Object.prototype.hasOwnProperty.call(o, k)) delete o[k];
3675
3718
  }
3676
3719
  /************************************************************
3677
3720
  * Simulate jansson function
3678
3721
  ************************************************************/
3679
3722
  function json_object_set(o, k, v) {
3680
- o[k] = v;
3723
+ set_own_key(o, k, v);
3681
3724
  }
3682
3725
  /************************************************************
3683
3726
  * Simulate jansson function
3684
3727
  ************************************************************/
3685
3728
  function json_object_set_new(o, k, v) {
3686
- o[k] = v;
3729
+ set_own_key(o, k, v);
3687
3730
  }
3688
3731
  /************************************************************
3689
3732
  * Simulate jansson function
@@ -3863,6 +3906,8 @@ var gobjJs = (function(exports) {
3863
3906
  if (is_number(jn_var1) || is_number(jn_var2)) {
3864
3907
  let val1 = Number(jn_var1);
3865
3908
  let val2 = Number(jn_var2);
3909
+ if (Number.isNaN(val1)) val1 = 0;
3910
+ if (Number.isNaN(val2)) val2 = 0;
3866
3911
  if (val1 > val2) return 1;
3867
3912
  else if (val1 < val2) return -1;
3868
3913
  else return 0;
@@ -3925,11 +3970,31 @@ var gobjJs = (function(exports) {
3925
3970
  ************************************************************/
3926
3971
  function kw_has_key(kw, key) {
3927
3972
  if (key in kw) {
3928
- if (kw.hasOwnProperty(key)) return true;
3973
+ if (Object.prototype.hasOwnProperty.call(kw, key)) return true;
3929
3974
  }
3930
3975
  return false;
3931
3976
  }
3932
3977
  /************************************************************
3978
+ * A key that reaches the prototype chain instead of the data:
3979
+ * any key the object does not hold 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
+ return !Object.prototype.hasOwnProperty.call(obj, key);
3987
+ }
3988
+ function set_own_key(obj, key, value) {
3989
+ if (key === "__proto__") Object.defineProperty(obj, key, {
3990
+ value,
3991
+ writable: true,
3992
+ enumerable: true,
3993
+ configurable: true
3994
+ });
3995
+ else obj[key] = value;
3996
+ }
3997
+ /************************************************************
3933
3998
  * The value at `path` (keys joined by a backtick), as the C
3934
3999
  * kw_find_path() finds it: undefined when it is not there.
3935
4000
  * A kw that is not a dict or a list is LOGGED ("kw must be list
@@ -3956,7 +4021,12 @@ var gobjJs = (function(exports) {
3956
4021
  }
3957
4022
  let ss = path.split("`");
3958
4023
  let len = ss.length;
3959
- for (let i = 0; i < len - 1; i++) {
4024
+ for (let i = 0; i < len; i++) {
4025
+ if (is_prototype_segment(kw, ss[i])) {
4026
+ if (verbose) log_error(`${prefix}path not found: '${path}'`);
4027
+ return;
4028
+ }
4029
+ if (i === len - 1) break;
3960
4030
  kw = kw[ss[i]];
3961
4031
  if (kw === void 0 || kw === null) {
3962
4032
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
@@ -4339,17 +4409,13 @@ var gobjJs = (function(exports) {
4339
4409
  return -1;
4340
4410
  }
4341
4411
  let ss = path.split("`");
4342
- if (ss.length <= 1) {
4343
- kw[path] = value;
4344
- return 0;
4345
- }
4346
4412
  let len = ss.length;
4347
4413
  for (let i = 0; i < len; i++) {
4348
4414
  let key = ss[i];
4349
- if (i === len - 1) kw[key] = value;
4415
+ if (i === len - 1) set_own_key(kw, key, value);
4350
4416
  else {
4351
- let seg = kw[key];
4352
- if (seg === void 0) kw[key] = {};
4417
+ let seg = is_prototype_segment(kw, key) ? void 0 : kw[key];
4418
+ if (seg === void 0) set_own_key(kw, key, {});
4353
4419
  else if (!is_object(seg) && !is_array(seg)) {
4354
4420
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_set_dict_value(): segment '${key}' is not a dict or a list: '${path}'`);
4355
4421
  return -1;
@@ -4404,9 +4470,9 @@ var gobjJs = (function(exports) {
4404
4470
  if (!matched) break;
4405
4471
  continue;
4406
4472
  }
4407
- let jn_record_value = kw_get_dict_value(0, kw, path, 0, 0);
4408
- if (!jn_record_value) jn_record_value = json_object_get(kw, path);
4409
- if (!jn_record_value) {
4473
+ let jn_record_value = kw_get_dict_value(0, kw, path, void 0, 0);
4474
+ if (jn_record_value === void 0) jn_record_value = json_object_get(kw, path);
4475
+ if (jn_record_value === void 0) {
4410
4476
  matched = false;
4411
4477
  break;
4412
4478
  }
@@ -4500,14 +4566,14 @@ var gobjJs = (function(exports) {
4500
4566
  let kw_clone = {};
4501
4567
  if (is_string(keys) && !empty_string(keys)) {
4502
4568
  let key = keys;
4503
- if (kw.hasOwnProperty(key)) kw_clone[key] = kw[key];
4569
+ if (Object.prototype.hasOwnProperty.call(kw, key)) set_own_key(kw_clone, key, kw[key]);
4504
4570
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4505
4571
  } else if (is_object(keys) && json_object_size(keys) > 0) {
4506
- for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) kw_clone[key] = kw[key];
4572
+ for (let key of Object.keys(keys)) if (Object.prototype.hasOwnProperty.call(kw, key)) set_own_key(kw_clone, key, kw[key]);
4507
4573
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4508
4574
  } else if (is_array(keys) && json_array_size(keys) > 0) for (let j = 0; j < keys.length; j++) {
4509
4575
  let key = keys[j];
4510
- if (kw.hasOwnProperty(key)) kw_clone[key] = kw[key];
4576
+ if (Object.prototype.hasOwnProperty.call(kw, key)) set_own_key(kw_clone, key, kw[key]);
4511
4577
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4512
4578
  }
4513
4579
  else return kw;
@@ -4525,17 +4591,18 @@ var gobjJs = (function(exports) {
4525
4591
  ***************************************************************************/
4526
4592
  function kw_clone_by_not_keys(gobj, kw, keys, verbose) {
4527
4593
  let kw_clone = {};
4594
+ if (!is_object(kw)) return kw_clone;
4528
4595
  json_object_update(kw_clone, kw);
4529
4596
  if (is_string(keys) && !empty_string(keys)) {
4530
4597
  let key = keys;
4531
- if (kw_get_dict_value(gobj, kw, key, 0, 0)) json_object_del(kw_clone, key);
4598
+ if (Object.prototype.hasOwnProperty.call(kw, key)) json_object_del(kw_clone, key);
4532
4599
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4533
4600
  } else if (is_object(keys) && json_object_size(keys) > 0) {
4534
- for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
4601
+ for (let key of Object.keys(keys)) if (Object.prototype.hasOwnProperty.call(kw, key)) json_object_del(kw_clone, key);
4535
4602
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4536
4603
  } else if (is_array(keys) && json_array_size(keys) > 0) for (let j = 0; j < keys.length; j++) {
4537
4604
  let key = keys[j];
4538
- if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
4605
+ if (Object.prototype.hasOwnProperty.call(kw, key)) json_object_del(kw_clone, key);
4539
4606
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4540
4607
  }
4541
4608
  else return {};
@@ -4766,7 +4833,7 @@ var gobjJs = (function(exports) {
4766
4833
  let new_ids = [];
4767
4834
  if (is_string(ids)) new_ids.push(ids);
4768
4835
  else if (is_object(ids)) {
4769
- for (let id in ids) if (ids.hasOwnProperty(id)) new_ids.push(id);
4836
+ for (let id in ids) if (Object.prototype.hasOwnProperty.call(ids, id)) new_ids.push(id);
4770
4837
  } else if (is_array(ids)) ids.forEach(function(item) {
4771
4838
  if (is_string(item)) {
4772
4839
  if (!empty_string(item)) new_ids.push(item);
@@ -5019,7 +5086,7 @@ var gobjJs = (function(exports) {
5019
5086
  function _traverse_dict(obj, callback, full_path) {
5020
5087
  if (full_path === void 0 || !is_string(full_path)) full_path = "";
5021
5088
  for (let key of Object.keys(obj)) {
5022
- if (!obj.hasOwnProperty(key)) continue;
5089
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
5023
5090
  let sufix = (full_path.length ? "`" : "") + key;
5024
5091
  full_path += sufix;
5025
5092
  callback.apply(this, [
@@ -5488,9 +5555,15 @@ var gobjJs = (function(exports) {
5488
5555
  * will be 'data-i18n' attr
5489
5556
  *
5490
5557
  * content -> string | [createElement2() or parameters of createElement2]
5558
+ * | HTMLElement | SVGElement | Text
5491
5559
  * if string begins with '<' then
5492
5560
  * it will be converted to HTMLElement
5493
5561
  * content = createOneHtml(string)
5562
+ * ⚠️ So a string is MARKUP when it starts with '<': never
5563
+ * pass DATA (a value from a backend, a name a user typed)
5564
+ * as a bare string, or "<img src=x onerror=...>" runs.
5565
+ * Pass it as a Text node, which is always text:
5566
+ * ['span', {}, document.createTextNode(value)]
5494
5567
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5495
5568
  * it will be overridden with the translation
5496
5569
  * content = translate(attrs['i18n']));
@@ -5894,7 +5967,7 @@ var gobjJs = (function(exports) {
5894
5967
  return;
5895
5968
  }
5896
5969
  if (depth === 0) return;
5897
- flat[path] = value;
5970
+ set_own_key(flat, path, value);
5898
5971
  };
5899
5972
  if (jn === void 0 || jn === null) return flat;
5900
5973
  walk(jn, "", 0);
@@ -5929,7 +6002,7 @@ var gobjJs = (function(exports) {
5929
6002
  current[seg] = flat[key];
5930
6003
  } else {
5931
6004
  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`);
5932
- current[seg] = flat[key];
6005
+ set_own_key(current, seg, flat[key]);
5933
6006
  }
5934
6007
  break;
5935
6008
  }
@@ -5942,10 +6015,10 @@ var gobjJs = (function(exports) {
5942
6015
  current[seg] = child;
5943
6016
  }
5944
6017
  } else {
5945
- child = current[seg];
6018
+ child = is_prototype_segment(current, seg) ? void 0 : current[seg];
5946
6019
  if (child === void 0) {
5947
6020
  child = next_is_index ? [] : {};
5948
- current[seg] = child;
6021
+ set_own_key(current, seg, child);
5949
6022
  }
5950
6023
  }
5951
6024
  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`);
@@ -5996,11 +6069,11 @@ var gobjJs = (function(exports) {
5996
6069
  if (flat === null || typeof flat !== "object" || Array.isArray(flat)) throw new Error("flat_apply: a flat json is an object of id -> value");
5997
6070
  if (diff === null || typeof diff !== "object") throw new Error("flat_apply: a diff is the object flat_diff() answers");
5998
6071
  for (const key of Object.keys(diff.removed || {})) delete flat[key];
5999
- for (const key of Object.keys(diff.added || {})) flat[key] = diff.added[key];
6072
+ for (const key of Object.keys(diff.added || {})) set_own_key(flat, key, diff.added[key]);
6000
6073
  for (const key of Object.keys(diff.changed || {})) {
6001
6074
  const change = diff.changed[key];
6002
6075
  if (!change || !Object.prototype.hasOwnProperty.call(change, "to")) throw new Error(`flat_apply: changed '${key}' without a 'to'`);
6003
- flat[key] = change.to;
6076
+ set_own_key(flat, key, change.to);
6004
6077
  }
6005
6078
  return flat;
6006
6079
  }
@@ -6708,6 +6781,7 @@ var gobjJs = (function(exports) {
6708
6781
  ***************************************************************/
6709
6782
  function mt_play(gobj) {
6710
6783
  let default_service = gobj_default_service();
6784
+ if (!default_service) return 0;
6711
6785
  if (!gobj_is_running(default_service)) gobj_start(default_service);
6712
6786
  if (!gobj_is_playing(default_service)) gobj_play(default_service);
6713
6787
  return 0;
@@ -6716,7 +6790,8 @@ var gobjJs = (function(exports) {
6716
6790
  * Framework Method: Pause
6717
6791
  ***************************************************************/
6718
6792
  function mt_pause(gobj) {
6719
- gobj_pause(gobj_default_service());
6793
+ let default_service = gobj_default_service();
6794
+ if (default_service && gobj_is_playing(default_service)) gobj_pause(default_service);
6720
6795
  return 0;
6721
6796
  }
6722
6797
  /***************************************************************
@@ -6972,6 +7047,7 @@ var gobjJs = (function(exports) {
6972
7047
  function mt_create(gobj) {
6973
7048
  let priv = gobj.priv;
6974
7049
  priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), "C_TIMER", {}, gobj);
7050
+ priv.ws_seq = 0;
6975
7051
  priv.url = gobj_read_str_attr(gobj, "url");
6976
7052
  priv.remote_yuno_name = gobj_read_str_attr(gobj, "remote_yuno_name");
6977
7053
  priv.remote_yuno_role = gobj_read_str_attr(gobj, "remote_yuno_role");
@@ -7006,6 +7082,16 @@ var gobjJs = (function(exports) {
7006
7082
  function mt_start(gobj) {
7007
7083
  let priv = gobj.priv;
7008
7084
  priv.retry_ms = 0;
7085
+ if (gobj_current_state(gobj) !== "ST_DISCONNECTED") {
7086
+ gobj_send_event(gobj, "EV_ON_CLOSE", {
7087
+ url: priv.url,
7088
+ ws_seq: priv.ws_seq,
7089
+ code: 1e3,
7090
+ reason: "restarted",
7091
+ was_clean: true
7092
+ }, gobj);
7093
+ clear_timeout(priv.gobj_timer);
7094
+ }
7009
7095
  priv.websocket = setup_websocket(gobj);
7010
7096
  return 0;
7011
7097
  }
@@ -7129,6 +7215,7 @@ var gobjJs = (function(exports) {
7129
7215
  if (gobj.priv.websocket) log_error(`Websocket ALREADY setup`);
7130
7216
  const url = gobj_read_str_attr(gobj, "url");
7131
7217
  log_debug(`====> Starting WebSocket to '${url}' (${gobj_short_name(gobj)})`);
7218
+ const ws_seq = ++gobj.priv.ws_seq;
7132
7219
  let websocket;
7133
7220
  try {
7134
7221
  websocket = new WebSocket(url);
@@ -7141,9 +7228,14 @@ var gobjJs = (function(exports) {
7141
7228
  return null;
7142
7229
  }
7143
7230
  websocket.onopen = () => {
7144
- gobj_send_event(gobj, "EV_ON_OPEN", { url }, gobj);
7231
+ if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
7232
+ gobj_send_event(gobj, "EV_ON_OPEN", {
7233
+ url,
7234
+ ws_seq
7235
+ }, gobj);
7145
7236
  };
7146
7237
  websocket.onmessage = (e) => {
7238
+ if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
7147
7239
  gobj_send_event(gobj, "EV_ON_MESSAGE", {
7148
7240
  url,
7149
7241
  data: e.data
@@ -7151,9 +7243,13 @@ var gobjJs = (function(exports) {
7151
7243
  };
7152
7244
  websocket.onclose = (e) => {
7153
7245
  if (gobj_is_destroying(gobj)) return;
7246
+ if (ws_seq !== gobj.priv.ws_seq) return;
7154
7247
  if (!gobj_read_bool_attr(gobj_yuno(), "browser_beforeunload")) gobj_send_event(gobj, "EV_ON_CLOSE", {
7155
7248
  url,
7156
- e
7249
+ ws_seq,
7250
+ code: e.code,
7251
+ reason: e.reason,
7252
+ was_clean: e.wasClean
7157
7253
  }, gobj);
7158
7254
  else log_warning("Close websocket by unload page");
7159
7255
  };
@@ -7174,7 +7270,7 @@ var gobjJs = (function(exports) {
7174
7270
  try {
7175
7271
  websocket.close(code, reason);
7176
7272
  } catch (e) {
7177
- log_error("Error closing WebSocket:", e.message);
7273
+ log_error(`${gobj_short_name(gobj)}: Error closing WebSocket: ${e.message}`);
7178
7274
  }
7179
7275
  }
7180
7276
  /***************************************************************
@@ -7300,29 +7396,29 @@ var gobjJs = (function(exports) {
7300
7396
  try {
7301
7397
  x = JSON.parse(data);
7302
7398
  } catch (e) {
7303
- log_error("parsing inter_event json: " + e);
7399
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event json: ${e}`);
7304
7400
  return null;
7305
7401
  }
7306
7402
  if (!(x instanceof Object)) {
7307
- log_error("parsing inter_event: websocket data not a json object");
7403
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: websocket data not a json object`);
7308
7404
  return null;
7309
7405
  }
7310
7406
  let event = x["event"];
7311
7407
  if (!event) {
7312
- log_error("parsing inter_event: no event");
7408
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: no event`);
7313
7409
  return null;
7314
7410
  }
7315
7411
  if (typeof event !== "string") {
7316
- log_error("parsing inter_event: event not a string");
7412
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: event not a string`);
7317
7413
  return null;
7318
7414
  }
7319
7415
  let kw = x["kw"];
7320
7416
  if (!kw) {
7321
- log_error("parsing inter_kw: no kw");
7417
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_kw: no kw`);
7322
7418
  return null;
7323
7419
  }
7324
7420
  if (!(kw instanceof Object)) {
7325
- log_error("parsing inter_event: kw not a json object");
7421
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: kw not a json object`);
7326
7422
  return null;
7327
7423
  }
7328
7424
  return {
@@ -7382,10 +7478,9 @@ var gobjJs = (function(exports) {
7382
7478
  ***************************************************************/
7383
7479
  function ac_on_close(gobj, event, kw, src) {
7384
7480
  let priv = gobj.priv;
7385
- let e = kw.e;
7386
7481
  let url = kw.url;
7387
7482
  set_remote_log_functions();
7388
- log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${e.code}, Reason: "${e.reason}", Clean: ${e.wasClean})`);
7483
+ log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7389
7484
  if (priv.websocket) {
7390
7485
  priv.websocket.onopen = null;
7391
7486
  priv.websocket.onmessage = null;
@@ -7402,15 +7497,15 @@ var gobjJs = (function(exports) {
7402
7497
  remote_yuno_service: priv.remote_yuno_service
7403
7498
  });
7404
7499
  } else {
7405
- log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${e.code}, Reason: "${e.reason}", Clean: ${e.wasClean})`);
7500
+ log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7406
7501
  gobj_publish_event(gobj, "EV_ON_OPEN_ERROR", {
7407
7502
  url,
7408
7503
  remote_yuno_name: priv.remote_yuno_name,
7409
7504
  remote_yuno_role: priv.remote_yuno_role,
7410
7505
  remote_yuno_service: priv.remote_yuno_service,
7411
- code: e.code,
7412
- reason: e.reason,
7413
- was_clean: e.wasClean
7506
+ code: kw.code,
7507
+ reason: kw.reason,
7508
+ was_clean: kw.was_clean
7414
7509
  });
7415
7510
  }
7416
7511
  if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, next_retry(gobj));
@@ -7508,6 +7603,10 @@ var gobjJs = (function(exports) {
7508
7603
  function ac_on_message(gobj, event, kw, src) {
7509
7604
  let url = gobj.priv.url;
7510
7605
  let iev_msg = iev_create_from_json(gobj, kw.data);
7606
+ if (!iev_msg) {
7607
+ log_warning(`${gobj_short_name(gobj)}: frame dropped from ${url}: ${String(kw.data).substring(0, 256)}`);
7608
+ return -1;
7609
+ }
7511
7610
  if (is_traffic_tracing(gobj)) {
7512
7611
  let prefix = gobj_name(gobj_yuno()) + " <== " + url;
7513
7612
  let size = kw.data.length;
@@ -7533,8 +7632,14 @@ var gobjJs = (function(exports) {
7533
7632
  return 0;
7534
7633
  }
7535
7634
  let iev_dst_service = kw_get_str(gobj, event_id, "dst_service", "");
7536
- if (msg_type === "__subscribing__") return -1;
7537
- if (msg_type === "__unsubscribing__") return -1;
7635
+ if (msg_type === "__subscribing__") {
7636
+ log_warning(`${gobj_short_name(gobj)}: subscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
7637
+ return -1;
7638
+ }
7639
+ if (msg_type === "__unsubscribing__") {
7640
+ log_warning(`${gobj_short_name(gobj)}: unsubscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
7641
+ return -1;
7642
+ }
7538
7643
  if (gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
7539
7644
  gobj_send_event(gobj, iev_event, iev_kw, gobj);
7540
7645
  return 0;