@yuneta/gobj-js 7.26.0 → 7.26.2

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 CHANGED
@@ -610,9 +610,10 @@ kw_clone_by_not_keys(gobj, kw, keys, verbose)
610
610
  // A filter value is compared as a value: {online: false}, {channel: 0}
611
611
  // and {name: ""} match (up to 7.25.9 a false value never did):
612
612
  // kw_select(null, [{id: "a", online: false}], {online: false}) → [{id: "a", ...}]
613
- // A key that names the prototype ("__proto__", "constructor",
614
- // "prototype") is a key like any other, as in C: it is read only when the
615
- // kw holds it, and written as the kw's own key, never into Object.prototype.
613
+ // A key is read only when the kw OWNS it ("toString" or "constructor" on
614
+ // a plain {} are not there) and written as its own key, "__proto__"
615
+ // included, as in C: never into a prototype. The helpers that copy
616
+ // (json_object_update(), kw_clone_by_*(), flat_apply()...) do the same.
616
617
 
617
618
  // Flags: KW_REQUIRED, KW_CREATE, KW_EXTRACT, KW_RECURSIVE, KW_WILD_NUMBER
618
619
 
@@ -895,17 +895,20 @@ function json2item(gobj, sdata, it, jn_value_) {
895
895
  break;
896
896
  case data_type_t.DTP_JSON:
897
897
  jn_value2 = jn_value_;
898
- if (is_string(jn_value_)) try {
899
- jn_value2 = JSON.parse(jn_value_);
900
- } catch (error) {
901
- jn_value2 = jn_value_;
898
+ if (is_string(jn_value_)) {
899
+ const t = jn_value_.trim();
900
+ if (t.startsWith("{") || t.startsWith("[")) try {
901
+ jn_value2 = JSON.parse(t);
902
+ } catch (error) {
903
+ jn_value2 = jn_value_;
904
+ }
902
905
  }
903
906
  break;
904
907
  case data_type_t.DTP_POINTER: jn_value2 = jn_value_;
905
908
  }
906
909
  if (jn_value2 === void 0) log_error(`${gobj_short_name(gobj)}: attr undefined: ${it.name}`);
907
910
  sdata[it.name] = jn_value2;
908
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = jn_value2;
911
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, it.name)) gobj.priv[it.name] = jn_value2;
909
912
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
910
913
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
911
914
  }
@@ -2108,7 +2111,7 @@ function gobj_has_attr(gobj, name) {
2108
2111
  function gobj_read_attr(gobj, name, src) {
2109
2112
  let jn_attrs = gobj.jn_attrs;
2110
2113
  if (name in jn_attrs) {
2111
- if (jn_attrs.hasOwnProperty(name)) {
2114
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, name)) {
2112
2115
  let value = jn_attrs[name];
2113
2116
  if (gobj.gclass.gmt.mt_reading) return gobj.gclass.gmt.mt_reading(gobj, name, value);
2114
2117
  return value;
@@ -2214,9 +2217,9 @@ function gobj_write_attr(gobj, path, value, src) {
2214
2217
  if (ss.length <= 1) {
2215
2218
  let key = path;
2216
2219
  if (key in jn_attrs) {
2217
- if (jn_attrs.hasOwnProperty(key)) {
2220
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) {
2218
2221
  jn_attrs[key] = value;
2219
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
2222
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, key)) gobj.priv[key] = value;
2220
2223
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2221
2224
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2222
2225
  }
@@ -2237,9 +2240,9 @@ function gobj_write_attr(gobj, path, value, src) {
2237
2240
  }
2238
2241
  let jn_attrs = gobj.jn_attrs;
2239
2242
  if (key in jn_attrs) {
2240
- if (jn_attrs.hasOwnProperty(key)) {
2243
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) {
2241
2244
  jn_attrs[key] = value;
2242
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
2245
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, key)) gobj.priv[key] = value;
2243
2246
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2244
2247
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2245
2248
  }
@@ -2266,7 +2269,7 @@ function sdata_write_default_values(gobj, include_flag, exclude_flag) {
2266
2269
  if (exclude_flag && it.flag & exclude_flag) continue;
2267
2270
  if (include_flag === -1 || it.flag & include_flag) {
2268
2271
  set_default(gobj, gobj.jn_attrs, it);
2269
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
2272
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
2270
2273
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
2271
2274
  }
2272
2275
  }
@@ -2300,7 +2303,7 @@ function gobj_write_bool_attr(gobj, name, value) {
2300
2303
  let hs = gobj_hsdata2(gobj, name, false);
2301
2304
  if (hs) {
2302
2305
  hs[name] = parseBoolean(value);
2303
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2306
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2304
2307
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2305
2308
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2306
2309
  }
@@ -2316,7 +2319,7 @@ function gobj_write_integer_attr(gobj, name, value) {
2316
2319
  let hs = gobj_hsdata2(gobj, name, false);
2317
2320
  if (hs) {
2318
2321
  hs[name] = parseInt(value);
2319
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2322
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2320
2323
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2321
2324
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2322
2325
  }
@@ -2332,7 +2335,7 @@ function gobj_write_str_attr(gobj, name, value) {
2332
2335
  let hs = gobj_hsdata2(gobj, name, false);
2333
2336
  if (hs) {
2334
2337
  hs[name] = String(value);
2335
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2338
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2336
2339
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2337
2340
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2338
2341
  }
@@ -2599,7 +2602,7 @@ function gobj_send_event(dst, event, kw, src) {
2599
2602
  } catch (e) {
2600
2603
  __inside__--;
2601
2604
  if (!(e && e.__gobj_logged__)) {
2602
- log_error(`${gobj_short_name(dst)}: action of ${event} in ${dst.current_state.state_name} THREW: ${e && e.stack ? e.stack : e}`);
2605
+ log_error(`${gobj_short_name(dst)}: action of ${event} in ${state.state_name} THREW: ${e && e.stack ? e.stack : e}`);
2603
2606
  try {
2604
2607
  e.__gobj_logged__ = true;
2605
2608
  } catch (e2) {}
@@ -2720,8 +2723,8 @@ function _subscription_match_kw(kw, event) {
2720
2723
  kw,
2721
2724
  renamed_event: ""
2722
2725
  };
2723
- let kw_match = Object.assign({}, kw);
2724
- let config_match = Object.assign({}, __config__);
2726
+ let kw_match = json_object_update({}, kw);
2727
+ let config_match = json_object_update({}, __config__);
2725
2728
  kw_match.__config__ = config_match;
2726
2729
  let renamed_event = "";
2727
2730
  let rename = config_match.__rename_event_name__;
@@ -2729,7 +2732,7 @@ function _subscription_match_kw(kw, event) {
2729
2732
  if (event_type) {
2730
2733
  renamed_event = event_type.event_name;
2731
2734
  delete config_match.__rename_event_name__;
2732
- if (event && json_size(kw_match.__global__) > 0) kw_match.__global__ = Object.assign({}, kw_match.__global__, { __original_event_name__: event });
2735
+ if (event && json_size(kw_match.__global__) > 0) kw_match.__global__ = json_object_update(json_object_update({}, kw_match.__global__), { __original_event_name__: event });
2733
2736
  }
2734
2737
  delete config_match.__hard_subscription__;
2735
2738
  delete config_match.__own_event__;
@@ -3105,7 +3108,7 @@ function gobj_publish_event(publisher, event, kw) {
3105
3108
  }
3106
3109
  }
3107
3110
  let kw2publish = kw;
3108
- if (json_size(__local__) > 0 || json_size(__global__) > 0) kw2publish = Object.assign({}, kw);
3111
+ if (json_size(__local__) > 0 || json_size(__global__) > 0) kw2publish = json_object_update({}, kw);
3109
3112
  if (json_size(__local__) > 0) kw_pop(kw2publish, __local__);
3110
3113
  if (__config__) {}
3111
3114
  if (json_size(__global__) > 0) json_object_update(kw2publish, json_deep_copy(__global__));
@@ -3607,7 +3610,7 @@ function _json_mask_secrets(jn, memo, depth, budget) {
3607
3610
  if ((is_secret_name(key.slice(-128)) || value_is_secret && key === "value") && value !== void 0 && value !== null && value !== "") shown = "********";
3608
3611
  else shown = _json_mask_secrets(value, memo, depth + 1, budget);
3609
3612
  if (shown !== value) changed = true;
3610
- result[key] = shown;
3613
+ set_own_key(result, key, shown);
3611
3614
  }
3612
3615
  if (truncated) result["<more>"] = MASK_TOO_LARGE;
3613
3616
  }
@@ -3642,10 +3645,7 @@ function json_deep_copy(obj) {
3642
3645
  ************************************************************/
3643
3646
  function duplicate_objects(...sourceObjects) {
3644
3647
  const result = {};
3645
- for (const obj of sourceObjects) {
3646
- const clonedObj = structuredClone(obj);
3647
- Object.assign(result, clonedObj);
3648
- }
3648
+ for (const obj of sourceObjects) json_object_update(result, structuredClone(obj));
3649
3649
  return result;
3650
3650
  }
3651
3651
  /************************************************************
@@ -3679,7 +3679,7 @@ function json_is_identical(kw1, kw2) {
3679
3679
  ************************************************************/
3680
3680
  function json_object_update(destination, source) {
3681
3681
  if (!source) return destination;
3682
- for (let property of Object.keys(source)) destination[property] = source[property];
3682
+ for (let property of Object.keys(source)) set_own_key(destination, property, source[property]);
3683
3683
  return destination;
3684
3684
  }
3685
3685
  /************************************************************
@@ -3688,7 +3688,7 @@ function json_object_update(destination, source) {
3688
3688
  ************************************************************/
3689
3689
  function json_object_update_existing(destination, source) {
3690
3690
  if (!source) return destination;
3691
- for (let property in source) if (source.hasOwnProperty(property) && destination.hasOwnProperty(property)) destination[property] = source[property];
3691
+ 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]);
3692
3692
  return destination;
3693
3693
  }
3694
3694
  /************************************************************
@@ -3697,32 +3697,32 @@ function json_object_update_existing(destination, source) {
3697
3697
  ************************************************************/
3698
3698
  function json_object_update_missing(destination, source) {
3699
3699
  if (!source) return destination;
3700
- for (let property in source) if (source.hasOwnProperty(property) && !destination.hasOwnProperty(property)) destination[property] = source[property];
3700
+ 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]);
3701
3701
  return destination;
3702
3702
  }
3703
3703
  /************************************************************
3704
3704
  * Simulate jansson function
3705
3705
  ************************************************************/
3706
3706
  function json_object_get(o, key) {
3707
- if (o && o.hasOwnProperty(key)) return o[key];
3707
+ if (o && Object.prototype.hasOwnProperty.call(o, key)) return o[key];
3708
3708
  }
3709
3709
  /************************************************************
3710
3710
  * Simulate jansson function
3711
3711
  ************************************************************/
3712
3712
  function json_object_del(o, k) {
3713
- if (o && o.hasOwnProperty(k)) delete o[k];
3713
+ if (o && Object.prototype.hasOwnProperty.call(o, k)) delete o[k];
3714
3714
  }
3715
3715
  /************************************************************
3716
3716
  * Simulate jansson function
3717
3717
  ************************************************************/
3718
3718
  function json_object_set(o, k, v) {
3719
- o[k] = v;
3719
+ set_own_key(o, k, v);
3720
3720
  }
3721
3721
  /************************************************************
3722
3722
  * Simulate jansson function
3723
3723
  ************************************************************/
3724
3724
  function json_object_set_new(o, k, v) {
3725
- o[k] = v;
3725
+ set_own_key(o, k, v);
3726
3726
  }
3727
3727
  /************************************************************
3728
3728
  * Simulate jansson function
@@ -3966,22 +3966,20 @@ function kw_pop(kw1, kw2) {
3966
3966
  ************************************************************/
3967
3967
  function kw_has_key(kw, key) {
3968
3968
  if (key in kw) {
3969
- if (kw.hasOwnProperty(key)) return true;
3969
+ if (Object.prototype.hasOwnProperty.call(kw, key)) return true;
3970
3970
  }
3971
3971
  return false;
3972
3972
  }
3973
3973
  /************************************************************
3974
3974
  * A key that reaches the prototype chain instead of the data:
3975
- * "__proto__", "constructor" or "prototype" when the object
3976
- * does not hold it as its OWN key. A walk through one of them
3975
+ * any key the object does not hold as its OWN key. A walk through one of them
3977
3976
  * read, or WROTE, Object.prototype: the flat id
3978
3977
  * "__proto__`polluted" set a key on every object of the page.
3979
3978
  * In C they are keys like any other, so here too: read them
3980
3979
  * only as own keys, and write "__proto__" as an own key.
3981
3980
  ************************************************************/
3982
3981
  function is_prototype_segment(obj, key) {
3983
- if (key === "__proto__" || key === "constructor" || key === "prototype") return !Object.prototype.hasOwnProperty.call(obj, key);
3984
- return false;
3982
+ return !Object.prototype.hasOwnProperty.call(obj, key);
3985
3983
  }
3986
3984
  function set_own_key(obj, key, value) {
3987
3985
  if (key === "__proto__") Object.defineProperty(obj, key, {
@@ -4020,6 +4018,13 @@ function kw_find_path(gobj, kw, path, verbose) {
4020
4018
  let ss = path.split("`");
4021
4019
  let len = ss.length;
4022
4020
  for (let i = 0; i < len; i++) {
4021
+ if (is_array(kw)) {
4022
+ if (!/^[0-9]+$/.test(ss[i])) {
4023
+ if (verbose) log_error(`${prefix}path not found: '${path}'`);
4024
+ return;
4025
+ }
4026
+ ss[i] = String(Number(ss[i]));
4027
+ }
4023
4028
  if (is_prototype_segment(kw, ss[i])) {
4024
4029
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
4025
4030
  return;
@@ -4437,7 +4442,7 @@ function kw_set_subdict_value(gobj, kw, path, key, value) {
4437
4442
  log_error("subdict is not an object");
4438
4443
  return -1;
4439
4444
  }
4440
- subdict[key] = value;
4445
+ set_own_key(subdict, key, value);
4441
4446
  return 0;
4442
4447
  }
4443
4448
  /***************************************************************************
@@ -4564,14 +4569,14 @@ function kw_clone_by_keys(gobj, kw, keys, verbose) {
4564
4569
  let kw_clone = {};
4565
4570
  if (is_string(keys) && !empty_string(keys)) {
4566
4571
  let key = keys;
4567
- if (kw.hasOwnProperty(key)) kw_clone[key] = kw[key];
4572
+ if (Object.prototype.hasOwnProperty.call(kw, key)) set_own_key(kw_clone, key, kw[key]);
4568
4573
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4569
4574
  } else if (is_object(keys) && json_object_size(keys) > 0) {
4570
- for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) kw_clone[key] = kw[key];
4575
+ for (let key of Object.keys(keys)) if (Object.prototype.hasOwnProperty.call(kw, key)) set_own_key(kw_clone, key, kw[key]);
4571
4576
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4572
4577
  } else if (is_array(keys) && json_array_size(keys) > 0) for (let j = 0; j < keys.length; j++) {
4573
4578
  let key = keys[j];
4574
- if (kw.hasOwnProperty(key)) kw_clone[key] = kw[key];
4579
+ if (Object.prototype.hasOwnProperty.call(kw, key)) set_own_key(kw_clone, key, kw[key]);
4575
4580
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4576
4581
  }
4577
4582
  else return kw;
@@ -4593,14 +4598,14 @@ function kw_clone_by_not_keys(gobj, kw, keys, verbose) {
4593
4598
  json_object_update(kw_clone, kw);
4594
4599
  if (is_string(keys) && !empty_string(keys)) {
4595
4600
  let key = keys;
4596
- if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
4601
+ if (Object.prototype.hasOwnProperty.call(kw, key)) json_object_del(kw_clone, key);
4597
4602
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4598
4603
  } else if (is_object(keys) && json_object_size(keys) > 0) {
4599
- for (let key of Object.keys(keys)) if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
4604
+ for (let key of Object.keys(keys)) if (Object.prototype.hasOwnProperty.call(kw, key)) json_object_del(kw_clone, key);
4600
4605
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4601
4606
  } else if (is_array(keys) && json_array_size(keys) > 0) for (let j = 0; j < keys.length; j++) {
4602
4607
  let key = keys[j];
4603
- if (kw.hasOwnProperty(key)) json_object_del(kw_clone, key);
4608
+ if (Object.prototype.hasOwnProperty.call(kw, key)) json_object_del(kw_clone, key);
4604
4609
  else if (verbose) log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);
4605
4610
  }
4606
4611
  else return {};
@@ -4745,7 +4750,7 @@ function kwid_new_dict(gobj, kw, path) {
4745
4750
  else if (is_array(kw)) for (let i = 0; i < kw.length; i++) {
4746
4751
  let kv = kw[i];
4747
4752
  let id = kw_get_str(gobj, kv, "id", "", kw_flag_t.KW_REQUIRED);
4748
- if (!empty_string(id)) new_dict[id] = kv;
4753
+ if (!empty_string(id)) set_own_key(new_dict, id, kv);
4749
4754
  }
4750
4755
  else log_error(`${gobj_short_name(gobj)} kwid_new_dict: data type unknown`);
4751
4756
  return new_dict;
@@ -4831,7 +4836,7 @@ function kwid_get_ids(gobj, ids) {
4831
4836
  let new_ids = [];
4832
4837
  if (is_string(ids)) new_ids.push(ids);
4833
4838
  else if (is_object(ids)) {
4834
- for (let id in ids) if (ids.hasOwnProperty(id)) new_ids.push(id);
4839
+ for (let id in ids) if (Object.prototype.hasOwnProperty.call(ids, id)) new_ids.push(id);
4835
4840
  } else if (is_array(ids)) ids.forEach(function(item) {
4836
4841
  if (is_string(item)) {
4837
4842
  if (!empty_string(item)) new_ids.push(item);
@@ -5084,7 +5089,7 @@ function send_http_json_post(url, data, on_response) {
5084
5089
  function _traverse_dict(obj, callback, full_path) {
5085
5090
  if (full_path === void 0 || !is_string(full_path)) full_path = "";
5086
5091
  for (let key of Object.keys(obj)) {
5087
- if (!obj.hasOwnProperty(key)) continue;
5092
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
5088
5093
  let sufix = (full_path.length ? "`" : "") + key;
5089
5094
  full_path += sufix;
5090
5095
  callback.apply(this, [
@@ -5191,11 +5196,11 @@ function jdb_update(jdb, topic_name, path, kw) {
5191
5196
  }
5192
5197
  if (ids.length === 0 && v) {
5193
5198
  if (is_array(v)) v.push(kw);
5194
- else if (v["id"] === kw["id"]) Object.assign(v, kw);
5199
+ else if (v["id"] === kw["id"]) json_object_update(v, kw);
5195
5200
  else {
5196
5201
  let v_ = kw_get_dict_value(null, v, jdb.hook, [], 1);
5197
5202
  let v__ = _jdb_get(v_, jdb.hook, kw["id"], false);
5198
- if (v__) Object.assign(v__, kw);
5203
+ if (v__) json_object_update(v__, kw);
5199
5204
  else v_.push(kw);
5200
5205
  }
5201
5206
  }
@@ -5562,6 +5567,10 @@ parent: document.body
5562
5567
  * as a bare string, or "<img src=x onerror=...>" runs.
5563
5568
  * Pass it as a Text node, which is always text:
5564
5569
  * ['span', {}, document.createTextNode(value)]
5570
+ * In a LIST of children a node (element, svg, Text) is
5571
+ * appended as it is and a string is always text -- but a
5572
+ * list whose first item is a string is read as ONE
5573
+ * description (the string is its tag).
5565
5574
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5566
5575
  * it will be overridden with the translation
5567
5576
  * content = translate(attrs['i18n']));
@@ -5614,8 +5623,11 @@ function createElement2(description, translate_fn) {
5614
5623
  } else if (is_array(content)) {
5615
5624
  if (content.length > 0) {
5616
5625
  if (is_string(content[0])) el.appendChild(createElement2(content, translate_fn));
5617
- else for (let child of content) if (Array.isArray(child) && child.length > 0) el.appendChild(createElement2(child, translate_fn));
5618
- else if (child instanceof HTMLElement) el.appendChild(child);
5626
+ else for (let child of content) if (Array.isArray(child)) {
5627
+ if (child.length > 0) el.appendChild(createElement2(child, translate_fn));
5628
+ } else if (child instanceof Node) el.appendChild(child);
5629
+ else if (is_string(child)) el.appendChild(document.createTextNode(child));
5630
+ else if (child !== null && child !== void 0 && child !== false) log_error(`createElement2: child ignored, type ${typeof child}`);
5619
5631
  }
5620
5632
  } else if (content instanceof HTMLElement || content instanceof Text || content instanceof SVGElement) el.appendChild(content);
5621
5633
  else if (content != null) {
@@ -5965,7 +5977,7 @@ function json2flat(jn) {
5965
5977
  return;
5966
5978
  }
5967
5979
  if (depth === 0) return;
5968
- flat[path] = value;
5980
+ set_own_key(flat, path, value);
5969
5981
  };
5970
5982
  if (jn === void 0 || jn === null) return flat;
5971
5983
  walk(jn, "", 0);
@@ -6048,12 +6060,12 @@ function flat_diff(flat1, flat2) {
6048
6060
  removed: {},
6049
6061
  changed: {}
6050
6062
  };
6051
- for (const key of Object.keys(a)) if (!Object.prototype.hasOwnProperty.call(b, key)) diff.removed[key] = a[key];
6052
- else if (!flat_value_equal(a[key], b[key])) diff.changed[key] = {
6063
+ for (const key of Object.keys(a)) if (!Object.prototype.hasOwnProperty.call(b, key)) set_own_key(diff.removed, key, a[key]);
6064
+ else if (!flat_value_equal(a[key], b[key])) set_own_key(diff.changed, key, {
6053
6065
  from: a[key],
6054
6066
  to: b[key]
6055
- };
6056
- for (const key of Object.keys(b)) if (!Object.prototype.hasOwnProperty.call(a, key)) diff.added[key] = b[key];
6067
+ });
6068
+ for (const key of Object.keys(b)) if (!Object.prototype.hasOwnProperty.call(a, key)) set_own_key(diff.added, key, b[key]);
6057
6069
  return diff;
6058
6070
  }
6059
6071
  /************************************************************
@@ -6067,11 +6079,11 @@ function flat_apply(flat, diff) {
6067
6079
  if (flat === null || typeof flat !== "object" || Array.isArray(flat)) throw new Error("flat_apply: a flat json is an object of id -> value");
6068
6080
  if (diff === null || typeof diff !== "object") throw new Error("flat_apply: a diff is the object flat_diff() answers");
6069
6081
  for (const key of Object.keys(diff.removed || {})) delete flat[key];
6070
- for (const key of Object.keys(diff.added || {})) flat[key] = diff.added[key];
6082
+ for (const key of Object.keys(diff.added || {})) set_own_key(flat, key, diff.added[key]);
6071
6083
  for (const key of Object.keys(diff.changed || {})) {
6072
6084
  const change = diff.changed[key];
6073
6085
  if (!change || !Object.prototype.hasOwnProperty.call(change, "to")) throw new Error(`flat_apply: changed '${key}' without a 'to'`);
6074
- flat[key] = change.to;
6086
+ set_own_key(flat, key, change.to);
6075
6087
  }
6076
6088
  return flat;
6077
6089
  }
@@ -7161,7 +7173,7 @@ function mt_inject_event(gobj, event, kw, src) {
7161
7173
  window.console.error(`Not in session`);
7162
7174
  return -1;
7163
7175
  }
7164
- kw = Object.assign({}, is_object(kw) ? kw : {});
7176
+ kw = json_object_update({}, is_object(kw) ? kw : {});
7165
7177
  if (is_object(kw["__md_iev__"])) kw["__md_iev__"] = json_deep_copy(kw["__md_iev__"]);
7166
7178
  if (msg_iev_get_stack(gobj, kw, IEVENT_STACK_ID)) {} else {
7167
7179
  let jn_ievent_id = build_cli_ievent_request(gobj, gobj_name(src), kw_get_str(gobj, kw, "__service__", 0, 0));
@@ -7213,18 +7225,25 @@ function setup_websocket(gobj) {
7213
7225
  if (gobj.priv.websocket) log_error(`Websocket ALREADY setup`);
7214
7226
  const url = gobj_read_str_attr(gobj, "url");
7215
7227
  log_debug(`====> Starting WebSocket to '${url}' (${gobj_short_name(gobj)})`);
7228
+ const ws_seq = ++gobj.priv.ws_seq;
7216
7229
  let websocket;
7217
7230
  try {
7218
7231
  websocket = new WebSocket(url);
7219
7232
  } catch (e) {
7220
7233
  log_error(`${gobj_short_name(gobj)}: Cannot open WebSocket to '${url}', Error: ${e.message}`);
7234
+ gobj_post_event(gobj, "EV_ON_CLOSE", {
7235
+ url,
7236
+ ws_seq,
7237
+ code: 1006,
7238
+ reason: e.message,
7239
+ was_clean: false
7240
+ }, gobj);
7221
7241
  return null;
7222
7242
  }
7223
7243
  if (!websocket) {
7224
7244
  log_error(`${gobj_short_name(gobj)}: Failed to initialize WebSocket.`);
7225
7245
  return null;
7226
7246
  }
7227
- const ws_seq = ++gobj.priv.ws_seq;
7228
7247
  websocket.onopen = () => {
7229
7248
  if (ws_seq !== gobj.priv.ws_seq || gobj_is_destroying(gobj)) return;
7230
7249
  gobj_send_event(gobj, "EV_ON_OPEN", {
@@ -7477,6 +7496,7 @@ function ac_on_open(gobj, event, kw, src) {
7477
7496
  function ac_on_close(gobj, event, kw, src) {
7478
7497
  let priv = gobj.priv;
7479
7498
  let url = kw.url;
7499
+ if (kw.ws_seq !== void 0 && kw.ws_seq !== priv.ws_seq) return 0;
7480
7500
  set_remote_log_functions();
7481
7501
  log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7482
7502
  if (priv.websocket) {
@@ -7494,7 +7514,7 @@ function ac_on_close(gobj, event, kw, src) {
7494
7514
  remote_yuno_role: priv.remote_yuno_role,
7495
7515
  remote_yuno_service: priv.remote_yuno_service
7496
7516
  });
7497
- } else {
7517
+ } else if (!gobj_is_running(gobj)) {} else {
7498
7518
  log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7499
7519
  gobj_publish_event(gobj, "EV_ON_OPEN_ERROR", {
7500
7520
  url,