@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.
@@ -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,11 @@ var gobjJs = (function(exports) {
888
895
  }
889
896
  break;
890
897
  case data_type_t.DTP_JSON:
898
+ jn_value2 = jn_value_;
891
899
  if (is_string(jn_value_)) try {
892
900
  jn_value2 = JSON.parse(jn_value_);
893
901
  } 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;
902
+ jn_value2 = jn_value_;
900
903
  }
901
904
  break;
902
905
  case data_type_t.DTP_POINTER: jn_value2 = jn_value_;
@@ -1201,6 +1204,10 @@ var gobjJs = (function(exports) {
1201
1204
  * find a service
1202
1205
  ************************************************************/
1203
1206
  function gobj_find_service(service_name, verbose) {
1207
+ if (!is_string(service_name)) {
1208
+ log_error(`gobj_find_service(): service name must be a string: ${service_name}`);
1209
+ return null;
1210
+ }
1204
1211
  service_name = service_name.toLowerCase();
1205
1212
  let service_gobj = __jn_services__[service_name];
1206
1213
  if (!service_gobj) {
@@ -1358,9 +1365,10 @@ var gobjJs = (function(exports) {
1358
1365
  return null;
1359
1366
  }
1360
1367
  if (is_string(parent)) {
1361
- parent = gobj_find_service(parent);
1368
+ const parent_name = parent;
1369
+ parent = gobj_find_service(parent_name);
1362
1370
  if (!parent) {
1363
- log_warning(`parent service not found: ${parent}`);
1371
+ log_warning(`parent service not found: ${parent_name}`);
1364
1372
  return null;
1365
1373
  }
1366
1374
  }
@@ -1473,6 +1481,7 @@ var gobjJs = (function(exports) {
1473
1481
  parent.gclass.gmt.mt_child_removed(parent, gobj);
1474
1482
  }
1475
1483
  if (gobj.gobj_flag & gobj_flag_t.gobj_flag_service) _deregister_service(gobj);
1484
+ if (gobj === __default_service__) __default_service__ = null;
1476
1485
  gobj_unsubscribe_list(gobj, gobj.dl_subscriptions, true);
1477
1486
  gobj_unsubscribe_list(gobj, gobj.dl_subscribings, true);
1478
1487
  if (parent) {
@@ -1818,7 +1827,7 @@ var gobjJs = (function(exports) {
1818
1827
  log_error(`gobj NULL of bad type`);
1819
1828
  return null;
1820
1829
  }
1821
- if (gobj.bottom_gobj) log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);
1830
+ if (gobj.bottom_gobj && bottom_gobj) log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);
1822
1831
  gobj.bottom_gobj = bottom_gobj;
1823
1832
  }
1824
1833
  /***************************************************************************
@@ -2233,7 +2242,7 @@ var gobjJs = (function(exports) {
2233
2242
  jn_attrs[key] = value;
2234
2243
  if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
2235
2244
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2236
- if (gobj.mt_writing) gobj.mt_writing(gobj, key);
2245
+ if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2237
2246
  }
2238
2247
  return 0;
2239
2248
  }
@@ -2257,8 +2266,8 @@ var gobjJs = (function(exports) {
2257
2266
  if (!it.name) continue;
2258
2267
  if (exclude_flag && it.flag & exclude_flag) continue;
2259
2268
  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;
2269
+ set_default(gobj, gobj.jn_attrs, it);
2270
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
2262
2271
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
2263
2272
  }
2264
2273
  }
@@ -2292,7 +2301,7 @@ var gobjJs = (function(exports) {
2292
2301
  let hs = gobj_hsdata2(gobj, name, false);
2293
2302
  if (hs) {
2294
2303
  hs[name] = parseBoolean(value);
2295
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = value;
2304
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2296
2305
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2297
2306
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2298
2307
  }
@@ -2308,7 +2317,7 @@ var gobjJs = (function(exports) {
2308
2317
  let hs = gobj_hsdata2(gobj, name, false);
2309
2318
  if (hs) {
2310
2319
  hs[name] = parseInt(value);
2311
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = value;
2320
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2312
2321
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2313
2322
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2314
2323
  }
@@ -2324,7 +2333,7 @@ var gobjJs = (function(exports) {
2324
2333
  let hs = gobj_hsdata2(gobj, name, false);
2325
2334
  if (hs) {
2326
2335
  hs[name] = String(value);
2327
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = value;
2336
+ if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2328
2337
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2329
2338
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2330
2339
  }
@@ -2378,15 +2387,15 @@ var gobjJs = (function(exports) {
2378
2387
  log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);
2379
2388
  return -1;
2380
2389
  }
2381
- if (gobj.parent && gobj.parent.mt_child_removed) gobj.parent.mt_child_removed(gobj.parent, gobj);
2390
+ if (gobj.parent && gobj.parent.gclass.gmt.mt_child_removed) gobj.parent.gclass.gmt.mt_child_removed(gobj.parent, gobj);
2382
2391
  if (gobj.parent) {
2383
2392
  _remove_child(gobj.parent, gobj);
2384
2393
  gobj.parent = null;
2385
2394
  }
2386
2395
  _add_child(parent, gobj);
2387
- if (parent.mt_child_added) {
2396
+ if (parent.gclass.gmt.mt_child_added) {
2388
2397
  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);
2398
+ parent.gclass.gmt.mt_child_added(parent, gobj);
2390
2399
  }
2391
2400
  return 0;
2392
2401
  }
@@ -2498,9 +2507,19 @@ var gobjJs = (function(exports) {
2498
2507
  let snapshot = __dl_posted_events__;
2499
2508
  __dl_posted_events__ = [];
2500
2509
  let delivered = 0;
2501
- for (let msg of snapshot) {
2510
+ for (let i = 0; i < snapshot.length; i++) {
2511
+ const msg = snapshot[i];
2502
2512
  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);
2513
+ try {
2514
+ gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);
2515
+ } catch (e) {
2516
+ __dl_posted_events__ = snapshot.slice(i + 1).concat(__dl_posted_events__);
2517
+ if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
2518
+ __posted_events_scheduled__ = true;
2519
+ setTimeout(gobj_deliver_posted_events, 0);
2520
+ }
2521
+ throw e;
2522
+ }
2504
2523
  delivered++;
2505
2524
  }
2506
2525
  if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
@@ -2578,7 +2597,16 @@ var gobjJs = (function(exports) {
2578
2597
  let ret = -1;
2579
2598
  try {
2580
2599
  if (event_action.action) ret = event_action.action(dst, event, kw, src);
2581
- } finally {}
2600
+ } catch (e) {
2601
+ __inside__--;
2602
+ if (!(e && e.__gobj_logged__)) {
2603
+ log_error(`${gobj_short_name(dst)}: action of ${event} in ${dst.current_state.state_name} THREW: ${e && e.stack ? e.stack : e}`);
2604
+ try {
2605
+ e.__gobj_logged__ = true;
2606
+ } catch (e2) {}
2607
+ }
2608
+ throw e;
2609
+ }
2582
2610
  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
2611
  __inside__--;
2584
2612
  return ret;
@@ -3249,10 +3277,22 @@ var gobjJs = (function(exports) {
3249
3277
  f_warning = _console.warn;
3250
3278
  }
3251
3279
  }
3280
+ /************************************************************
3281
+ * JSON.stringify for a log line: a circular object (a gobj,
3282
+ * a DOM node) must not make the log call itself throw.
3283
+ ************************************************************/
3284
+ function log_stringify(v) {
3285
+ try {
3286
+ return JSON.stringify(v);
3287
+ } catch (e) {
3288
+ return String(v);
3289
+ }
3290
+ }
3252
3291
  function format_log(format) {
3253
3292
  const args = Array.prototype.slice.call(arguments);
3254
3293
  let output = "";
3255
3294
  if (typeof format === "string") {
3295
+ if (args.length === 1) return format;
3256
3296
  let i = 1;
3257
3297
  output = format.replace(/%[sdifoO]/g, (match) => {
3258
3298
  const val = args[i++];
@@ -3262,17 +3302,17 @@ var gobjJs = (function(exports) {
3262
3302
  case "%i": return parseInt(val);
3263
3303
  case "%f": return parseFloat(val);
3264
3304
  case "%o":
3265
- case "%O": return typeof val === "object" ? JSON.stringify(val) : String(val);
3305
+ case "%O": return typeof val === "object" ? log_stringify(val) : String(val);
3266
3306
  default: return match;
3267
3307
  }
3268
3308
  });
3269
- const rest = args.slice(i).map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg));
3309
+ const rest = args.slice(i).map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg));
3270
3310
  if (rest.length > 0) output += " " + rest.join(" ");
3271
- } else output = args.map((arg) => typeof arg === "object" ? JSON.stringify(arg) : String(arg)).join(" ");
3311
+ } else output = args.map((arg) => typeof arg === "object" ? log_stringify(arg) : String(arg)).join(" ");
3272
3312
  return output;
3273
3313
  }
3274
- function log_error(format) {
3275
- let msg = format_log(format);
3314
+ function log_error(format, ...args) {
3315
+ let msg = format_log(format, ...args);
3276
3316
  let hora = current_timestamp();
3277
3317
  if (f_error) {
3278
3318
  if (f_error === _console.error) {
@@ -3284,8 +3324,8 @@ var gobjJs = (function(exports) {
3284
3324
  }
3285
3325
  emit_log_callback("error", msg, hora);
3286
3326
  }
3287
- function log_warning(format) {
3288
- let msg = format_log(format);
3327
+ function log_warning(format, ...args) {
3328
+ let msg = format_log(format, ...args);
3289
3329
  let hora = current_timestamp();
3290
3330
  if (f_warning) {
3291
3331
  if (f_warning === _console.warn) {
@@ -3297,24 +3337,24 @@ var gobjJs = (function(exports) {
3297
3337
  }
3298
3338
  emit_log_callback("warning", msg, hora);
3299
3339
  }
3300
- function log_info(format) {
3301
- let msg = format_log(format);
3340
+ function log_info(format, ...args) {
3341
+ let msg = format_log(format, ...args);
3302
3342
  let hora = current_timestamp();
3303
3343
  if (f_info) {
3304
3344
  if (console_wants("info", msg)) f_info("%c" + hora + " INFO: " + String(msg), "color:cyan");
3305
3345
  }
3306
3346
  emit_log_callback("info", msg, hora);
3307
3347
  }
3308
- function log_debug(format) {
3309
- let msg = format_log(format);
3348
+ function log_debug(format, ...args) {
3349
+ let msg = format_log(format, ...args);
3310
3350
  let hora = current_timestamp();
3311
3351
  if (f_debug) {
3312
3352
  if (console_wants("debug", msg)) f_debug("%c" + hora + " DEBUG: " + String(msg), "color:silver");
3313
3353
  }
3314
3354
  emit_log_callback("debug", msg, hora);
3315
3355
  }
3316
- function trace_msg(format) {
3317
- let msg = format_log(format);
3356
+ function trace_msg(format, ...args) {
3357
+ let msg = format_log(format, ...args);
3318
3358
  let hora = current_timestamp();
3319
3359
  if (f_debug) {
3320
3360
  if (console_wants("msg", msg)) f_debug("%c" + hora + " MSG: " + String(msg), "color:cyan");
@@ -3863,6 +3903,8 @@ var gobjJs = (function(exports) {
3863
3903
  if (is_number(jn_var1) || is_number(jn_var2)) {
3864
3904
  let val1 = Number(jn_var1);
3865
3905
  let val2 = Number(jn_var2);
3906
+ if (Number.isNaN(val1)) val1 = 0;
3907
+ if (Number.isNaN(val2)) val2 = 0;
3866
3908
  if (val1 > val2) return 1;
3867
3909
  else if (val1 < val2) return -1;
3868
3910
  else return 0;
@@ -3930,6 +3972,28 @@ var gobjJs = (function(exports) {
3930
3972
  return false;
3931
3973
  }
3932
3974
  /************************************************************
3975
+ * A key that reaches the prototype chain instead of the data:
3976
+ * "__proto__", "constructor" or "prototype" when the object
3977
+ * does not hold it as its OWN key. A walk through one of them
3978
+ * read, or WROTE, Object.prototype: the flat id
3979
+ * "__proto__`polluted" set a key on every object of the page.
3980
+ * In C they are keys like any other, so here too: read them
3981
+ * only as own keys, and write "__proto__" as an own key.
3982
+ ************************************************************/
3983
+ function is_prototype_segment(obj, key) {
3984
+ if (key === "__proto__" || key === "constructor" || key === "prototype") return !Object.prototype.hasOwnProperty.call(obj, key);
3985
+ return false;
3986
+ }
3987
+ function set_own_key(obj, key, value) {
3988
+ if (key === "__proto__") Object.defineProperty(obj, key, {
3989
+ value,
3990
+ writable: true,
3991
+ enumerable: true,
3992
+ configurable: true
3993
+ });
3994
+ else obj[key] = value;
3995
+ }
3996
+ /************************************************************
3933
3997
  * The value at `path` (keys joined by a backtick), as the C
3934
3998
  * kw_find_path() finds it: undefined when it is not there.
3935
3999
  * A kw that is not a dict or a list is LOGGED ("kw must be list
@@ -3956,7 +4020,12 @@ var gobjJs = (function(exports) {
3956
4020
  }
3957
4021
  let ss = path.split("`");
3958
4022
  let len = ss.length;
3959
- for (let i = 0; i < len - 1; i++) {
4023
+ for (let i = 0; i < len; i++) {
4024
+ if (is_prototype_segment(kw, ss[i])) {
4025
+ if (verbose) log_error(`${prefix}path not found: '${path}'`);
4026
+ return;
4027
+ }
4028
+ if (i === len - 1) break;
3960
4029
  kw = kw[ss[i]];
3961
4030
  if (kw === void 0 || kw === null) {
3962
4031
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
@@ -4339,17 +4408,13 @@ var gobjJs = (function(exports) {
4339
4408
  return -1;
4340
4409
  }
4341
4410
  let ss = path.split("`");
4342
- if (ss.length <= 1) {
4343
- kw[path] = value;
4344
- return 0;
4345
- }
4346
4411
  let len = ss.length;
4347
4412
  for (let i = 0; i < len; i++) {
4348
4413
  let key = ss[i];
4349
- if (i === len - 1) kw[key] = value;
4414
+ if (i === len - 1) set_own_key(kw, key, value);
4350
4415
  else {
4351
- let seg = kw[key];
4352
- if (seg === void 0) kw[key] = {};
4416
+ let seg = is_prototype_segment(kw, key) ? void 0 : kw[key];
4417
+ if (seg === void 0) set_own_key(kw, key, {});
4353
4418
  else if (!is_object(seg) && !is_array(seg)) {
4354
4419
  log_error(`${gobj ? gobj_short_name(gobj) + ": " : ""}kw_set_dict_value(): segment '${key}' is not a dict or a list: '${path}'`);
4355
4420
  return -1;
@@ -4404,9 +4469,9 @@ var gobjJs = (function(exports) {
4404
4469
  if (!matched) break;
4405
4470
  continue;
4406
4471
  }
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) {
4472
+ let jn_record_value = kw_get_dict_value(0, kw, path, void 0, 0);
4473
+ if (jn_record_value === void 0) jn_record_value = json_object_get(kw, path);
4474
+ if (jn_record_value === void 0) {
4410
4475
  matched = false;
4411
4476
  break;
4412
4477
  }
@@ -4525,10 +4590,11 @@ var gobjJs = (function(exports) {
4525
4590
  ***************************************************************************/
4526
4591
  function kw_clone_by_not_keys(gobj, kw, keys, verbose) {
4527
4592
  let kw_clone = {};
4593
+ if (!is_object(kw)) return kw_clone;
4528
4594
  json_object_update(kw_clone, kw);
4529
4595
  if (is_string(keys) && !empty_string(keys)) {
4530
4596
  let key = keys;
4531
- if (kw_get_dict_value(gobj, kw, key, 0, 0)) json_object_del(kw_clone, key);
4597
+ if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
4532
4598
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4533
4599
  } else if (is_object(keys) && json_object_size(keys) > 0) {
4534
4600
  for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
@@ -5488,9 +5554,15 @@ var gobjJs = (function(exports) {
5488
5554
  * will be 'data-i18n' attr
5489
5555
  *
5490
5556
  * content -> string | [createElement2() or parameters of createElement2]
5557
+ * | HTMLElement | SVGElement | Text
5491
5558
  * if string begins with '<' then
5492
5559
  * it will be converted to HTMLElement
5493
5560
  * content = createOneHtml(string)
5561
+ * ⚠️ So a string is MARKUP when it starts with '<': never
5562
+ * pass DATA (a value from a backend, a name a user typed)
5563
+ * as a bare string, or "<img src=x onerror=...>" runs.
5564
+ * Pass it as a Text node, which is always text:
5565
+ * ['span', {}, document.createTextNode(value)]
5494
5566
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5495
5567
  * it will be overridden with the translation
5496
5568
  * content = translate(attrs['i18n']));
@@ -5929,7 +6001,7 @@ var gobjJs = (function(exports) {
5929
6001
  current[seg] = flat[key];
5930
6002
  } else {
5931
6003
  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];
6004
+ set_own_key(current, seg, flat[key]);
5933
6005
  }
5934
6006
  break;
5935
6007
  }
@@ -5942,10 +6014,10 @@ var gobjJs = (function(exports) {
5942
6014
  current[seg] = child;
5943
6015
  }
5944
6016
  } else {
5945
- child = current[seg];
6017
+ child = is_prototype_segment(current, seg) ? void 0 : current[seg];
5946
6018
  if (child === void 0) {
5947
6019
  child = next_is_index ? [] : {};
5948
- current[seg] = child;
6020
+ set_own_key(current, seg, child);
5949
6021
  }
5950
6022
  }
5951
6023
  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`);
@@ -6708,6 +6780,7 @@ var gobjJs = (function(exports) {
6708
6780
  ***************************************************************/
6709
6781
  function mt_play(gobj) {
6710
6782
  let default_service = gobj_default_service();
6783
+ if (!default_service) return 0;
6711
6784
  if (!gobj_is_running(default_service)) gobj_start(default_service);
6712
6785
  if (!gobj_is_playing(default_service)) gobj_play(default_service);
6713
6786
  return 0;
@@ -6716,7 +6789,8 @@ var gobjJs = (function(exports) {
6716
6789
  * Framework Method: Pause
6717
6790
  ***************************************************************/
6718
6791
  function mt_pause(gobj) {
6719
- gobj_pause(gobj_default_service());
6792
+ let default_service = gobj_default_service();
6793
+ if (default_service && gobj_is_playing(default_service)) gobj_pause(default_service);
6720
6794
  return 0;
6721
6795
  }
6722
6796
  /***************************************************************
@@ -6972,6 +7046,7 @@ var gobjJs = (function(exports) {
6972
7046
  function mt_create(gobj) {
6973
7047
  let priv = gobj.priv;
6974
7048
  priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), "C_TIMER", {}, gobj);
7049
+ priv.ws_seq = 0;
6975
7050
  priv.url = gobj_read_str_attr(gobj, "url");
6976
7051
  priv.remote_yuno_name = gobj_read_str_attr(gobj, "remote_yuno_name");
6977
7052
  priv.remote_yuno_role = gobj_read_str_attr(gobj, "remote_yuno_role");
@@ -7006,6 +7081,16 @@ var gobjJs = (function(exports) {
7006
7081
  function mt_start(gobj) {
7007
7082
  let priv = gobj.priv;
7008
7083
  priv.retry_ms = 0;
7084
+ if (gobj_current_state(gobj) !== "ST_DISCONNECTED") {
7085
+ gobj_send_event(gobj, "EV_ON_CLOSE", {
7086
+ url: priv.url,
7087
+ ws_seq: priv.ws_seq,
7088
+ code: 1e3,
7089
+ reason: "restarted",
7090
+ was_clean: true
7091
+ }, gobj);
7092
+ clear_timeout(priv.gobj_timer);
7093
+ }
7009
7094
  priv.websocket = setup_websocket(gobj);
7010
7095
  return 0;
7011
7096
  }
@@ -7140,10 +7225,16 @@ var gobjJs = (function(exports) {
7140
7225
  log_error(`${gobj_short_name(gobj)}: Failed to initialize WebSocket.`);
7141
7226
  return null;
7142
7227
  }
7228
+ const ws_seq = ++gobj.priv.ws_seq;
7143
7229
  websocket.onopen = () => {
7144
- gobj_send_event(gobj, "EV_ON_OPEN", { url }, gobj);
7230
+ if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
7231
+ gobj_send_event(gobj, "EV_ON_OPEN", {
7232
+ url,
7233
+ ws_seq
7234
+ }, gobj);
7145
7235
  };
7146
7236
  websocket.onmessage = (e) => {
7237
+ if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
7147
7238
  gobj_send_event(gobj, "EV_ON_MESSAGE", {
7148
7239
  url,
7149
7240
  data: e.data
@@ -7151,9 +7242,13 @@ var gobjJs = (function(exports) {
7151
7242
  };
7152
7243
  websocket.onclose = (e) => {
7153
7244
  if (gobj_is_destroying(gobj)) return;
7245
+ if (ws_seq !== gobj.priv.ws_seq) return;
7154
7246
  if (!gobj_read_bool_attr(gobj_yuno(), "browser_beforeunload")) gobj_send_event(gobj, "EV_ON_CLOSE", {
7155
7247
  url,
7156
- e
7248
+ ws_seq,
7249
+ code: e.code,
7250
+ reason: e.reason,
7251
+ was_clean: e.wasClean
7157
7252
  }, gobj);
7158
7253
  else log_warning("Close websocket by unload page");
7159
7254
  };
@@ -7174,7 +7269,7 @@ var gobjJs = (function(exports) {
7174
7269
  try {
7175
7270
  websocket.close(code, reason);
7176
7271
  } catch (e) {
7177
- log_error("Error closing WebSocket:", e.message);
7272
+ log_error(`${gobj_short_name(gobj)}: Error closing WebSocket: ${e.message}`);
7178
7273
  }
7179
7274
  }
7180
7275
  /***************************************************************
@@ -7300,29 +7395,29 @@ var gobjJs = (function(exports) {
7300
7395
  try {
7301
7396
  x = JSON.parse(data);
7302
7397
  } catch (e) {
7303
- log_error("parsing inter_event json: " + e);
7398
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event json: ${e}`);
7304
7399
  return null;
7305
7400
  }
7306
7401
  if (!(x instanceof Object)) {
7307
- log_error("parsing inter_event: websocket data not a json object");
7402
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: websocket data not a json object`);
7308
7403
  return null;
7309
7404
  }
7310
7405
  let event = x["event"];
7311
7406
  if (!event) {
7312
- log_error("parsing inter_event: no event");
7407
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: no event`);
7313
7408
  return null;
7314
7409
  }
7315
7410
  if (typeof event !== "string") {
7316
- log_error("parsing inter_event: event not a string");
7411
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: event not a string`);
7317
7412
  return null;
7318
7413
  }
7319
7414
  let kw = x["kw"];
7320
7415
  if (!kw) {
7321
- log_error("parsing inter_kw: no kw");
7416
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_kw: no kw`);
7322
7417
  return null;
7323
7418
  }
7324
7419
  if (!(kw instanceof Object)) {
7325
- log_error("parsing inter_event: kw not a json object");
7420
+ log_warning(`${gobj_short_name(gobj)}: parsing inter_event: kw not a json object`);
7326
7421
  return null;
7327
7422
  }
7328
7423
  return {
@@ -7382,10 +7477,9 @@ var gobjJs = (function(exports) {
7382
7477
  ***************************************************************/
7383
7478
  function ac_on_close(gobj, event, kw, src) {
7384
7479
  let priv = gobj.priv;
7385
- let e = kw.e;
7386
7480
  let url = kw.url;
7387
7481
  set_remote_log_functions();
7388
- log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${e.code}, Reason: "${e.reason}", Clean: ${e.wasClean})`);
7482
+ log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7389
7483
  if (priv.websocket) {
7390
7484
  priv.websocket.onopen = null;
7391
7485
  priv.websocket.onmessage = null;
@@ -7402,15 +7496,15 @@ var gobjJs = (function(exports) {
7402
7496
  remote_yuno_service: priv.remote_yuno_service
7403
7497
  });
7404
7498
  } else {
7405
- log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${e.code}, Reason: "${e.reason}", Clean: ${e.wasClean})`);
7499
+ log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7406
7500
  gobj_publish_event(gobj, "EV_ON_OPEN_ERROR", {
7407
7501
  url,
7408
7502
  remote_yuno_name: priv.remote_yuno_name,
7409
7503
  remote_yuno_role: priv.remote_yuno_role,
7410
7504
  remote_yuno_service: priv.remote_yuno_service,
7411
- code: e.code,
7412
- reason: e.reason,
7413
- was_clean: e.wasClean
7505
+ code: kw.code,
7506
+ reason: kw.reason,
7507
+ was_clean: kw.was_clean
7414
7508
  });
7415
7509
  }
7416
7510
  if (gobj_is_running(gobj)) set_timeout(priv.gobj_timer, next_retry(gobj));
@@ -7508,6 +7602,10 @@ var gobjJs = (function(exports) {
7508
7602
  function ac_on_message(gobj, event, kw, src) {
7509
7603
  let url = gobj.priv.url;
7510
7604
  let iev_msg = iev_create_from_json(gobj, kw.data);
7605
+ if (!iev_msg) {
7606
+ log_warning(`${gobj_short_name(gobj)}: frame dropped from ${url}: ${String(kw.data).substring(0, 256)}`);
7607
+ return -1;
7608
+ }
7511
7609
  if (is_traffic_tracing(gobj)) {
7512
7610
  let prefix = gobj_name(gobj_yuno()) + " <== " + url;
7513
7611
  let size = kw.data.length;
@@ -7533,8 +7631,14 @@ var gobjJs = (function(exports) {
7533
7631
  return 0;
7534
7632
  }
7535
7633
  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;
7634
+ if (msg_type === "__subscribing__") {
7635
+ log_warning(`${gobj_short_name(gobj)}: subscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
7636
+ return -1;
7637
+ }
7638
+ if (msg_type === "__unsubscribing__") {
7639
+ log_warning(`${gobj_short_name(gobj)}: unsubscription event ignored, I'm client (service: ${iev_dst_service}, event: ${iev_event})`);
7640
+ return -1;
7641
+ }
7538
7642
  if (gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {
7539
7643
  gobj_send_event(gobj, iev_event, iev_kw, gobj);
7540
7644
  return 0;