@yuneta/gobj-js 7.26.1 → 7.26.3

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.
@@ -911,7 +911,7 @@
911
911
  }
912
912
  if (jn_value2 === void 0) log_error(`${gobj_short_name(gobj)}: attr undefined: ${it.name}`);
913
913
  sdata[it.name] = jn_value2;
914
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = jn_value2;
914
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, it.name)) gobj.priv[it.name] = jn_value2;
915
915
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
916
916
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
917
917
  }
@@ -2114,7 +2114,7 @@
2114
2114
  function gobj_read_attr(gobj, name, src) {
2115
2115
  let jn_attrs = gobj.jn_attrs;
2116
2116
  if (name in jn_attrs) {
2117
- if (jn_attrs.hasOwnProperty(name)) {
2117
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, name)) {
2118
2118
  let value = jn_attrs[name];
2119
2119
  if (gobj.gclass.gmt.mt_reading) return gobj.gclass.gmt.mt_reading(gobj, name, value);
2120
2120
  return value;
@@ -2220,9 +2220,9 @@
2220
2220
  if (ss.length <= 1) {
2221
2221
  let key = path;
2222
2222
  if (key in jn_attrs) {
2223
- if (jn_attrs.hasOwnProperty(key)) {
2223
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) {
2224
2224
  jn_attrs[key] = value;
2225
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
2225
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, key)) gobj.priv[key] = value;
2226
2226
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2227
2227
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2228
2228
  }
@@ -2243,9 +2243,9 @@
2243
2243
  }
2244
2244
  let jn_attrs = gobj.jn_attrs;
2245
2245
  if (key in jn_attrs) {
2246
- if (jn_attrs.hasOwnProperty(key)) {
2246
+ if (Object.prototype.hasOwnProperty.call(jn_attrs, key)) {
2247
2247
  jn_attrs[key] = value;
2248
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) gobj.priv[key] = value;
2248
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, key)) gobj.priv[key] = value;
2249
2249
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2250
2250
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, key);
2251
2251
  }
@@ -2272,7 +2272,7 @@
2272
2272
  if (exclude_flag && it.flag & exclude_flag) continue;
2273
2273
  if (include_flag === -1 || it.flag & include_flag) {
2274
2274
  set_default(gobj, gobj.jn_attrs, it);
2275
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
2275
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, it.name)) gobj.priv[it.name] = gobj.jn_attrs[it.name];
2276
2276
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, it.name);
2277
2277
  }
2278
2278
  }
@@ -2306,7 +2306,7 @@
2306
2306
  let hs = gobj_hsdata2(gobj, name, false);
2307
2307
  if (hs) {
2308
2308
  hs[name] = parseBoolean(value);
2309
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2309
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2310
2310
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2311
2311
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2312
2312
  }
@@ -2322,7 +2322,7 @@
2322
2322
  let hs = gobj_hsdata2(gobj, name, false);
2323
2323
  if (hs) {
2324
2324
  hs[name] = parseInt(value);
2325
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2325
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2326
2326
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2327
2327
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2328
2328
  }
@@ -2338,7 +2338,7 @@
2338
2338
  let hs = gobj_hsdata2(gobj, name, false);
2339
2339
  if (hs) {
2340
2340
  hs[name] = String(value);
2341
- if (is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) gobj.priv[name] = hs[name];
2341
+ if (is_object(gobj.priv) && Object.prototype.hasOwnProperty.call(gobj.priv, name)) gobj.priv[name] = hs[name];
2342
2342
  if (gobj.obflag & obflag_t.obflag_created && !(gobj.obflag & obflag_t.obflag_destroyed)) {
2343
2343
  if (gobj.gclass.gmt.mt_writing) gobj.gclass.gmt.mt_writing(gobj, name);
2344
2344
  }
@@ -2726,8 +2726,8 @@
2726
2726
  kw,
2727
2727
  renamed_event: ""
2728
2728
  };
2729
- let kw_match = Object.assign({}, kw);
2730
- let config_match = Object.assign({}, __config__);
2729
+ let kw_match = json_object_update({}, kw);
2730
+ let config_match = json_object_update({}, __config__);
2731
2731
  kw_match.__config__ = config_match;
2732
2732
  let renamed_event = "";
2733
2733
  let rename = config_match.__rename_event_name__;
@@ -2735,7 +2735,7 @@
2735
2735
  if (event_type) {
2736
2736
  renamed_event = event_type.event_name;
2737
2737
  delete config_match.__rename_event_name__;
2738
- if (event && json_size(kw_match.__global__) > 0) kw_match.__global__ = Object.assign({}, kw_match.__global__, { __original_event_name__: event });
2738
+ if (event && json_size(kw_match.__global__) > 0) kw_match.__global__ = json_object_update(json_object_update({}, kw_match.__global__), { __original_event_name__: event });
2739
2739
  }
2740
2740
  delete config_match.__hard_subscription__;
2741
2741
  delete config_match.__own_event__;
@@ -3111,7 +3111,7 @@
3111
3111
  }
3112
3112
  }
3113
3113
  let kw2publish = kw;
3114
- if (json_size(__local__) > 0 || json_size(__global__) > 0) kw2publish = Object.assign({}, kw);
3114
+ if (json_size(__local__) > 0 || json_size(__global__) > 0) kw2publish = json_object_update({}, kw);
3115
3115
  if (json_size(__local__) > 0) kw_pop(kw2publish, __local__);
3116
3116
  if (__config__) {}
3117
3117
  if (json_size(__global__) > 0) json_object_update(kw2publish, json_deep_copy(__global__));
@@ -3648,10 +3648,7 @@
3648
3648
  ************************************************************/
3649
3649
  function duplicate_objects(...sourceObjects) {
3650
3650
  const result = {};
3651
- for (const obj of sourceObjects) {
3652
- const clonedObj = structuredClone(obj);
3653
- Object.assign(result, clonedObj);
3654
- }
3651
+ for (const obj of sourceObjects) json_object_update(result, structuredClone(obj));
3655
3652
  return result;
3656
3653
  }
3657
3654
  /************************************************************
@@ -4024,6 +4021,13 @@
4024
4021
  let ss = path.split("`");
4025
4022
  let len = ss.length;
4026
4023
  for (let i = 0; i < len; i++) {
4024
+ if (is_array(kw)) {
4025
+ if (!/^[0-9]+$/.test(ss[i])) {
4026
+ if (verbose) log_error(`${prefix}path not found: '${path}'`);
4027
+ return;
4028
+ }
4029
+ ss[i] = String(Number(ss[i]));
4030
+ }
4027
4031
  if (is_prototype_segment(kw, ss[i])) {
4028
4032
  if (verbose) log_error(`${prefix}path not found: '${path}'`);
4029
4033
  return;
@@ -4441,7 +4445,7 @@
4441
4445
  log_error("subdict is not an object");
4442
4446
  return -1;
4443
4447
  }
4444
- subdict[key] = value;
4448
+ set_own_key(subdict, key, value);
4445
4449
  return 0;
4446
4450
  }
4447
4451
  /***************************************************************************
@@ -4749,7 +4753,7 @@
4749
4753
  else if (is_array(kw)) for (let i = 0; i < kw.length; i++) {
4750
4754
  let kv = kw[i];
4751
4755
  let id = kw_get_str(gobj, kv, "id", "", kw_flag_t.KW_REQUIRED);
4752
- if (!empty_string(id)) new_dict[id] = kv;
4756
+ if (!empty_string(id)) set_own_key(new_dict, id, kv);
4753
4757
  }
4754
4758
  else log_error(`${gobj_short_name(gobj)} kwid_new_dict: data type unknown`);
4755
4759
  return new_dict;
@@ -5195,11 +5199,11 @@
5195
5199
  }
5196
5200
  if (ids.length === 0 && v) {
5197
5201
  if (is_array(v)) v.push(kw);
5198
- else if (v["id"] === kw["id"]) Object.assign(v, kw);
5202
+ else if (v["id"] === kw["id"]) json_object_update(v, kw);
5199
5203
  else {
5200
5204
  let v_ = kw_get_dict_value(null, v, jdb.hook, [], 1);
5201
5205
  let v__ = _jdb_get(v_, jdb.hook, kw["id"], false);
5202
- if (v__) Object.assign(v__, kw);
5206
+ if (v__) json_object_update(v__, kw);
5203
5207
  else v_.push(kw);
5204
5208
  }
5205
5209
  }
@@ -5400,6 +5404,68 @@
5400
5404
  /***************************************************************************
5401
5405
  *
5402
5406
  ***************************************************************************/
5407
+ /***************************************************************************
5408
+ * Markup that createElement2() inserts AS HTML, said out loud.
5409
+ *
5410
+ * createElement2() reads a string that starts with '<' as markup. That
5411
+ * decision depends on the CONTENT of the string, not on who wrote it, so
5412
+ * a value from a backend or typed by a user that starts with '<' runs as
5413
+ * html. html_markup() is the explicit way to ask for markup: the string
5414
+ * is the caller's own (an icon, an svg), never data.
5415
+ *
5416
+ * ['span', {class: 'icon'}, html_markup('<i class="yi-copy"></i>')]
5417
+ *
5418
+ * With set_strings_are_text(true) a plain string is ALWAYS text and
5419
+ * html_markup() is the only way to insert markup.
5420
+ ***************************************************************************/
5421
+ var HtmlMarkup = class {
5422
+ constructor(html) {
5423
+ this.html = html;
5424
+ Object.freeze(this);
5425
+ }
5426
+ toString() {
5427
+ return this.html;
5428
+ }
5429
+ };
5430
+ function html_markup(html) {
5431
+ if (typeof html !== "string") {
5432
+ log_error(`html_markup: not a string, type ${typeof html}`);
5433
+ return new HtmlMarkup("");
5434
+ }
5435
+ return new HtmlMarkup(html);
5436
+ }
5437
+ function is_html_markup(v) {
5438
+ return v instanceof HtmlMarkup;
5439
+ }
5440
+ function markup_fragment(markup) {
5441
+ const template = document.createElement("template");
5442
+ template.innerHTML = markup.html.trim();
5443
+ return template.content;
5444
+ }
5445
+ var __strings_are_text__ = false;
5446
+ var __markup_strings_warned__ = /* @__PURE__ */ new Set();
5447
+ /***************************************************************************
5448
+ * The mode of createElement2() for a plain string that starts with '<':
5449
+ * false (default): it is markup, as it always was.
5450
+ * true: it is TEXT; markup is asked for with html_markup().
5451
+ * An app turns it on once its own code and the libraries it mounts pass
5452
+ * every deliberate markup through html_markup(). A string that starts
5453
+ * with '<' is then logged once (a deliberate one not migrated yet, or a
5454
+ * datum that used to run as html).
5455
+ ***************************************************************************/
5456
+ function set_strings_are_text(on) {
5457
+ __strings_are_text__ = !!on;
5458
+ }
5459
+ function strings_are_text() {
5460
+ return __strings_are_text__;
5461
+ }
5462
+ function warn_markup_string(content) {
5463
+ if (__markup_strings_warned__.size >= 100) return;
5464
+ const key = content.slice(0, 80);
5465
+ if (__markup_strings_warned__.has(key)) return;
5466
+ __markup_strings_warned__.add(key);
5467
+ log_warning(`createElement2: a string that starts with '<' is TEXT (set_strings_are_text): use html_markup() if it is markup: ${JSON.stringify(key)}`);
5468
+ }
5403
5469
  function createOneHtml(htmlString) {
5404
5470
  const template = document.createElement("template");
5405
5471
  template.innerHTML = htmlString.trim();
@@ -5561,11 +5627,18 @@
5561
5627
  * if string begins with '<' then
5562
5628
  * it will be converted to HTMLElement
5563
5629
  * content = createOneHtml(string)
5630
+ * | html_markup(string): markup, said out loud (any mode)
5564
5631
  * ⚠️ So a string is MARKUP when it starts with '<': never
5565
5632
  * pass DATA (a value from a backend, a name a user typed)
5566
5633
  * as a bare string, or "<img src=x onerror=...>" runs.
5567
5634
  * Pass it as a Text node, which is always text:
5568
5635
  * ['span', {}, document.createTextNode(value)]
5636
+ * In a LIST of children a node (element, svg, Text) is
5637
+ * appended as it is and a string is always text -- but a
5638
+ * list whose first item is a string is read as ONE
5639
+ * description (the string is its tag).
5640
+ * With set_strings_are_text(true) a plain string is
5641
+ * always text, and markup only comes in html_markup().
5569
5642
  * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')
5570
5643
  * it will be overridden with the translation
5571
5644
  * content = translate(attrs['i18n']));
@@ -5608,18 +5681,26 @@
5608
5681
  el.setAttribute("data-i18n", data_i18next);
5609
5682
  }
5610
5683
  } else el.setAttribute(attr, attrs[attr]);
5611
- if (is_string(content)) {
5684
+ if (is_html_markup(content)) el.appendChild(markup_fragment(content));
5685
+ else if (is_string(content)) {
5612
5686
  content = content.trim();
5613
- if (content.length > 0 && content[0] === "<") el.appendChild(createOneHtml(content));
5614
- else if (translate_fn && data_i18next) {
5615
- let translated = translate_fn(data_i18next);
5616
- el.textContent = translated ? translated : content;
5617
- } else el.textContent = content;
5687
+ if (content.length > 0 && content[0] === "<" && !__strings_are_text__) el.appendChild(createOneHtml(content));
5688
+ else {
5689
+ if (content.length > 0 && content[0] === "<") warn_markup_string(content);
5690
+ if (translate_fn && data_i18next) {
5691
+ let translated = translate_fn(data_i18next);
5692
+ el.textContent = translated ? translated : content;
5693
+ } else el.textContent = content;
5694
+ }
5618
5695
  } else if (is_array(content)) {
5619
5696
  if (content.length > 0) {
5620
5697
  if (is_string(content[0])) el.appendChild(createElement2(content, translate_fn));
5621
- else for (let child of content) if (Array.isArray(child) && child.length > 0) el.appendChild(createElement2(child, translate_fn));
5622
- else if (child instanceof HTMLElement) el.appendChild(child);
5698
+ else for (let child of content) if (Array.isArray(child)) {
5699
+ if (child.length > 0) el.appendChild(createElement2(child, translate_fn));
5700
+ } else if (child instanceof Node) el.appendChild(child);
5701
+ else if (is_html_markup(child)) el.appendChild(markup_fragment(child));
5702
+ else if (is_string(child)) el.appendChild(document.createTextNode(child));
5703
+ else if (child !== null && child !== void 0 && child !== false) log_error(`createElement2: child ignored, type ${typeof child}`);
5623
5704
  }
5624
5705
  } else if (content instanceof HTMLElement || content instanceof Text || content instanceof SVGElement) el.appendChild(content);
5625
5706
  else if (content != null) {
@@ -6052,12 +6133,12 @@
6052
6133
  removed: {},
6053
6134
  changed: {}
6054
6135
  };
6055
- for (const key of Object.keys(a)) if (!Object.prototype.hasOwnProperty.call(b, key)) diff.removed[key] = a[key];
6056
- else if (!flat_value_equal(a[key], b[key])) diff.changed[key] = {
6136
+ for (const key of Object.keys(a)) if (!Object.prototype.hasOwnProperty.call(b, key)) set_own_key(diff.removed, key, a[key]);
6137
+ else if (!flat_value_equal(a[key], b[key])) set_own_key(diff.changed, key, {
6057
6138
  from: a[key],
6058
6139
  to: b[key]
6059
- };
6060
- for (const key of Object.keys(b)) if (!Object.prototype.hasOwnProperty.call(a, key)) diff.added[key] = b[key];
6140
+ });
6141
+ for (const key of Object.keys(b)) if (!Object.prototype.hasOwnProperty.call(a, key)) set_own_key(diff.added, key, b[key]);
6061
6142
  return diff;
6062
6143
  }
6063
6144
  /************************************************************
@@ -7165,7 +7246,7 @@
7165
7246
  window.console.error(`Not in session`);
7166
7247
  return -1;
7167
7248
  }
7168
- kw = Object.assign({}, is_object(kw) ? kw : {});
7249
+ kw = json_object_update({}, is_object(kw) ? kw : {});
7169
7250
  if (is_object(kw["__md_iev__"])) kw["__md_iev__"] = json_deep_copy(kw["__md_iev__"]);
7170
7251
  if (msg_iev_get_stack(gobj, kw, IEVENT_STACK_ID)) {} else {
7171
7252
  let jn_ievent_id = build_cli_ievent_request(gobj, gobj_name(src), kw_get_str(gobj, kw, "__service__", 0, 0));
@@ -7223,6 +7304,13 @@
7223
7304
  websocket = new WebSocket(url);
7224
7305
  } catch (e) {
7225
7306
  log_error(`${gobj_short_name(gobj)}: Cannot open WebSocket to '${url}', Error: ${e.message}`);
7307
+ gobj_post_event(gobj, "EV_ON_CLOSE", {
7308
+ url,
7309
+ ws_seq,
7310
+ code: 1006,
7311
+ reason: e.message,
7312
+ was_clean: false
7313
+ }, gobj);
7226
7314
  return null;
7227
7315
  }
7228
7316
  if (!websocket) {
@@ -7481,6 +7569,7 @@
7481
7569
  function ac_on_close(gobj, event, kw, src) {
7482
7570
  let priv = gobj.priv;
7483
7571
  let url = kw.url;
7572
+ if (kw.ws_seq !== void 0 && kw.ws_seq !== priv.ws_seq) return 0;
7484
7573
  set_remote_log_functions();
7485
7574
  log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7486
7575
  if (priv.websocket) {
@@ -7498,7 +7587,7 @@
7498
7587
  remote_yuno_role: priv.remote_yuno_role,
7499
7588
  remote_yuno_service: priv.remote_yuno_service
7500
7589
  });
7501
- } else {
7590
+ } else if (!gobj_is_running(gobj)) {} else {
7502
7591
  log_warning(`${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ${url} (Code: ${kw.code}, Reason: "${kw.reason}", Clean: ${kw.was_clean})`);
7503
7592
  gobj_publish_event(gobj, "EV_ON_OPEN_ERROR", {
7504
7593
  url,
@@ -7960,6 +8049,7 @@
7960
8049
  exports.gobj_yuno_id = gobj_yuno_id;
7961
8050
  exports.gobj_yuno_name = gobj_yuno_name;
7962
8051
  exports.gobj_yuno_role = gobj_yuno_role;
8052
+ exports.html_markup = html_markup;
7963
8053
  exports.id_index_in_obj_list = id_index_in_obj_list;
7964
8054
  exports.index_in_list = index_in_list;
7965
8055
  exports.is_array = is_array;
@@ -7967,6 +8057,7 @@
7967
8057
  exports.is_date = is_date;
7968
8058
  exports.is_function = is_function;
7969
8059
  exports.is_gobj = is_gobj;
8060
+ exports.is_html_markup = is_html_markup;
7970
8061
  exports.is_metadata_key = is_metadata_key;
7971
8062
  exports.is_null = is_null;
7972
8063
  exports.is_number = is_number;
@@ -8058,6 +8149,7 @@
8058
8149
  exports.set_console_log_filter = set_console_log_filter;
8059
8150
  exports.set_log_callback = set_log_callback;
8060
8151
  exports.set_remote_log_functions = set_remote_log_functions;
8152
+ exports.set_strings_are_text = set_strings_are_text;
8061
8153
  exports.set_timeout = set_timeout;
8062
8154
  exports.set_timeout_periodic = set_timeout_periodic;
8063
8155
  exports.sprintf = sprintf;
@@ -8065,6 +8157,7 @@
8065
8157
  exports.str_in_list = str_in_list;
8066
8158
  exports.strcasecmp = strcasecmp;
8067
8159
  exports.strcmp = strcmp;
8160
+ exports.strings_are_text = strings_are_text;
8068
8161
  exports.strncmp = strncmp;
8069
8162
  exports.strs_in_list = strs_in_list;
8070
8163
  exports.strstr = strstr;