@yuneta/gobj-js 7.9.11 → 7.12.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.
@@ -90,9 +90,7 @@
90
90
  case "x":
91
91
  arg = (parseInt(arg, 10) >>> 0).toString(16);
92
92
  break;
93
- case "X":
94
- arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase();
95
- break;
93
+ case "X": arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase();
96
94
  }
97
95
  if (re.json.test(ph.type)) output += arg;
98
96
  else {
@@ -780,9 +778,7 @@
780
778
  }
781
779
  else jn_value = svalue;
782
780
  break;
783
- case data_type_t.DTP_POINTER:
784
- jn_value = svalue;
785
- break;
781
+ case data_type_t.DTP_POINTER: jn_value = svalue;
786
782
  }
787
783
  if (jn_value === void 0) {
788
784
  log_error(`default_value WRONG, it: ${it.name}, value: ${it.default_value}`);
@@ -852,9 +848,7 @@
852
848
  return -1;
853
849
  }
854
850
  break;
855
- case data_type_t.DTP_POINTER:
856
- jn_value2 = jn_value_;
857
- break;
851
+ case data_type_t.DTP_POINTER: jn_value2 = jn_value_;
858
852
  }
859
853
  if (jn_value2 === void 0) log_error(`${gobj_short_name(gobj)}: attr undefined: ${it.name}`);
860
854
  sdata[it.name] = jn_value2;
@@ -1133,6 +1127,7 @@
1133
1127
  } catch (e) {}
1134
1128
  if (!gclass) {
1135
1129
  if (verbose) log_error(`gclass not found: ${gclass_name}`);
1130
+ return null;
1136
1131
  }
1137
1132
  return gclass;
1138
1133
  }
@@ -1157,8 +1152,8 @@
1157
1152
  function gobj_find_service(service_name, verbose) {
1158
1153
  service_name = service_name.toLowerCase();
1159
1154
  let service_gobj = __jn_services__[service_name];
1160
- if (!service_gobj && verbose) {
1161
- log_error(`gobj service not found: ${service_name}`);
1155
+ if (!service_gobj) {
1156
+ if (verbose) log_error(`gobj service not found: ${service_name}`);
1162
1157
  return null;
1163
1158
  }
1164
1159
  return service_gobj;
@@ -1418,6 +1413,7 @@
1418
1413
  gobj_stop(gobj);
1419
1414
  }
1420
1415
  gobj.obflag |= obflag_t.obflag_destroying;
1416
+ purge_posted_events(gobj);
1421
1417
  let trace_creation = __trace_gobj_create_delete__(gobj);
1422
1418
  if (trace_creation) trace_machine(sprintf("💔💔⏩ destroying: %s", gobj_full_name(gobj)));
1423
1419
  let parent = gobj_parent(gobj);
@@ -1573,12 +1569,14 @@
1573
1569
  log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);
1574
1570
  return -1;
1575
1571
  }
1576
- if (!gobj_is_running(gobj)) if (!(gobj.gclass.gclass_flag & gclass_flag_t.gcflag_required_start_to_play)) {
1577
- log_warning(`${gobj_short_name(gobj)}: GObj playing without previous start`);
1578
- gobj_start(gobj);
1579
- } else {
1580
- log_error(`${gobj_short_name(gobj)}: Cannot play, start not done`);
1581
- return -1;
1572
+ if (!gobj_is_running(gobj)) {
1573
+ if (!(gobj.gclass.gclass_flag & gclass_flag_t.gcflag_required_start_to_play)) {
1574
+ log_warning(`${gobj_short_name(gobj)}: GObj playing without previous start`);
1575
+ gobj_start(gobj);
1576
+ } else {
1577
+ log_error(`${gobj_short_name(gobj)}: Cannot play, start not done`);
1578
+ return -1;
1579
+ }
1582
1580
  }
1583
1581
  if (__trace_gobj_start_stop__(gobj)) trace_machine(sprintf("⏯ ⏯ play: %s", gobj_full_name(gobj)));
1584
1582
  gobj.playing = true;
@@ -2357,13 +2355,97 @@
2357
2355
  return true;
2358
2356
  }
2359
2357
  /************************************************************
2360
- * post_event, by now only in js
2358
+ * Posted events: gobj_send_event(), but on the next turn
2359
+ *
2360
+ * Same contract as the C side (see gobj.h). It exists to get out of the
2361
+ * stack you are standing on: gobj_publish_event() dispatches synchronously,
2362
+ * so a subscriber action runs inside the publisher's own stack, and
2363
+ * destroying that publisher there dismantles what is still iterating.
2364
+ *
2365
+ * The queue is drained with setTimeout(0) and NOT with queueMicrotask():
2366
+ * a microtask runs before the browser can paint or handle an input, so a
2367
+ * chain of posted events would hold the page exactly the way it used to
2368
+ * hold the event loop in C. A macrotask gives the browser its turn between
2369
+ * one event and the next.
2370
+ *
2371
+ * Delivery is a SNAPSHOT: the events queued when the drain begins are the
2372
+ * ones delivered in it, and whatever an action posts while it runs waits
2373
+ * for the following turn.
2361
2374
  ************************************************************/
2362
- function gobj_post_event(gobj, event, kw, src) {
2363
- setTimeout(() => {
2364
- if (gobj_is_destroying(gobj)) return;
2365
- gobj_send_event(gobj, event, kw, src);
2366
- }, 10);
2375
+ var MAX_POSTED_EVENTS = 1e4;
2376
+ var __dl_posted_events__ = [];
2377
+ var __posted_events_scheduled__ = false;
2378
+ function gobj_post_event(dst, event, kw, src) {
2379
+ if (!dst || !(dst instanceof GObj)) {
2380
+ log_error(`gobj_post_event(): gobj dst NULL, event ${event}`);
2381
+ return -1;
2382
+ }
2383
+ if (dst.obflag & (obflag_t.obflag_destroyed | obflag_t.obflag_destroying)) {
2384
+ log_error(`gobj_post_event(): gobj dst DESTROYING, event ${event}`);
2385
+ return -1;
2386
+ }
2387
+ if (empty_string(event)) {
2388
+ log_error(`gobj_post_event(): event EMPTY`);
2389
+ return -1;
2390
+ }
2391
+ if (!gobj_has_event(dst, event, 0)) {
2392
+ log_error(`gobj_post_event(): event NOT DEFINED in gclass ${gobj_gclass_name(dst)}, event ${event}`);
2393
+ return -1;
2394
+ }
2395
+ if (__dl_posted_events__.length >= MAX_POSTED_EVENTS) {
2396
+ log_error(`gobj_post_event(): too many posted events, this is NOT a work queue, event ${event}, pending ${__dl_posted_events__.length}`);
2397
+ return -1;
2398
+ }
2399
+ __dl_posted_events__.push({
2400
+ dst,
2401
+ event,
2402
+ kw,
2403
+ src
2404
+ });
2405
+ if (is_machine_tracing(dst, event) && !is_machine_not_tracing(src, event)) trace_machine(sprintf("📬 posted(%s%s), ev: %s, pending: %d", !dst.running ? "!!" : "", gobj_short_name(dst), event, __dl_posted_events__.length));
2406
+ if (!__posted_events_scheduled__) {
2407
+ __posted_events_scheduled__ = true;
2408
+ setTimeout(gobj_deliver_posted_events, 0);
2409
+ }
2410
+ return 0;
2411
+ }
2412
+ /************************************************************
2413
+ * How many posted events wait for delivery
2414
+ ************************************************************/
2415
+ function gobj_posted_events_size() {
2416
+ return __dl_posted_events__.length;
2417
+ }
2418
+ /************************************************************
2419
+ * Deliver the posted events. One turn, one snapshot.
2420
+ ************************************************************/
2421
+ function gobj_deliver_posted_events() {
2422
+ __posted_events_scheduled__ = false;
2423
+ let snapshot = __dl_posted_events__;
2424
+ __dl_posted_events__ = [];
2425
+ let delivered = 0;
2426
+ for (let msg of snapshot) {
2427
+ if (msg.dst.obflag & (obflag_t.obflag_destroyed | obflag_t.obflag_destroying)) continue;
2428
+ gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);
2429
+ delivered++;
2430
+ }
2431
+ if (__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {
2432
+ __posted_events_scheduled__ = true;
2433
+ setTimeout(gobj_deliver_posted_events, 0);
2434
+ }
2435
+ return delivered;
2436
+ }
2437
+ /************************************************************
2438
+ * Take a gobj out of the queue of posted events.
2439
+ *
2440
+ * Called from gobj_destroy(), and the two halves are not the same thing:
2441
+ * as DESTINATION the entry is dropped, as SOURCE only the pointer is
2442
+ * cleared -- the destination still wants its event, and it arrives with
2443
+ * src null, which every action already has to accept.
2444
+ ************************************************************/
2445
+ function purge_posted_events(gobj) {
2446
+ if (__dl_posted_events__.length === 0) return;
2447
+ for (let msg of __dl_posted_events__) if (msg.src === gobj) msg.src = null;
2448
+ __dl_posted_events__ = __dl_posted_events__.filter((msg) => msg.dst !== gobj);
2367
2449
  }
2368
2450
  /************************************************************
2369
2451
  * send_event
@@ -2599,7 +2681,7 @@
2599
2681
  log_error(`subscriber NULL: ev ${event}`);
2600
2682
  return 0;
2601
2683
  }
2602
- const IGNORED_KEYS = new Set([
2684
+ const IGNORED_KEYS = /* @__PURE__ */ new Set([
2603
2685
  "__config__",
2604
2686
  "__global__",
2605
2687
  "__local__",
@@ -2655,7 +2737,7 @@
2655
2737
  log_error(`subscriber NULL: ev ${event}`);
2656
2738
  return 0;
2657
2739
  }
2658
- const IGNORED_KEYS = new Set([
2740
+ const IGNORED_KEYS = /* @__PURE__ */ new Set([
2659
2741
  "__config__",
2660
2742
  "__global__",
2661
2743
  "__local__",
@@ -2849,9 +2931,10 @@
2849
2931
  if (tracea > 1) trace_json(kw);
2850
2932
  }
2851
2933
  if (gobj.gclass.gmt.mt_command_parser) return gobj.gclass.gmt.mt_command_parser(gobj, command, kw, src);
2852
- if (gobj.gclass.command_table) if (__global_command_parser_fn__) return __global_command_parser_fn__(gobj, command, kw, src);
2853
- else return build_command_response(gobj, -1, sprintf("%s: global command parser not available", gobj_short_name(gobj)), 0, 0);
2854
- else return build_command_response(gobj, -1, sprintf("%s: command table not available", gobj_short_name(gobj)), 0, 0);
2934
+ if (gobj.gclass.command_table) {
2935
+ if (__global_command_parser_fn__) return __global_command_parser_fn__(gobj, command, kw, src);
2936
+ else return build_command_response(gobj, -1, sprintf("%s: global command parser not available", gobj_short_name(gobj)), 0, 0);
2937
+ } else return build_command_response(gobj, -1, sprintf("%s: command table not available", gobj_short_name(gobj)), 0, 0);
2855
2938
  }
2856
2939
  /************************************************************
2857
2940
  * Exec gobj stats. Return a webix
@@ -2958,22 +3041,26 @@
2958
3041
  function log_error(format) {
2959
3042
  let msg = format_log(format);
2960
3043
  let hora = current_timestamp();
2961
- if (f_error) if (f_error === _console.error) {
2962
- if (__console_output_enabled__) f_error("%c" + hora + " ERROR: " + String(msg), "color:red");
2963
- } else {
2964
- if (__console_output_enabled__) _console.error("%c" + hora + " ERROR: " + String(msg), "color:red");
2965
- f_error(`${hora} ERROR: ${String(msg)}`);
3044
+ if (f_error) {
3045
+ if (f_error === _console.error) {
3046
+ if (__console_output_enabled__) f_error("%c" + hora + " ERROR: " + String(msg), "color:red");
3047
+ } else {
3048
+ if (__console_output_enabled__) _console.error("%c" + hora + " ERROR: " + String(msg), "color:red");
3049
+ f_error(`${hora} ERROR: ${String(msg)}`);
3050
+ }
2966
3051
  }
2967
3052
  emit_log_callback("error", msg, hora);
2968
3053
  }
2969
3054
  function log_warning(format) {
2970
3055
  let msg = format_log(format);
2971
3056
  let hora = current_timestamp();
2972
- if (f_warning) if (f_warning === _console.warn) {
2973
- if (__console_output_enabled__) f_warning("%c" + hora + " WARNING: " + String(msg), "color:yellow");
2974
- } else {
2975
- if (__console_output_enabled__) _console.warn("%c" + hora + " WARNING: " + String(msg), "color:yellow");
2976
- f_warning(`${hora} WARNING: ${String(msg)}`);
3057
+ if (f_warning) {
3058
+ if (f_warning === _console.warn) {
3059
+ if (__console_output_enabled__) f_warning("%c" + hora + " WARNING: " + String(msg), "color:yellow");
3060
+ } else {
3061
+ if (__console_output_enabled__) _console.warn("%c" + hora + " WARNING: " + String(msg), "color:yellow");
3062
+ f_warning(`${hora} WARNING: ${String(msg)}`);
3063
+ }
2977
3064
  }
2978
3065
  emit_log_callback("warning", msg, hora);
2979
3066
  }
@@ -4009,10 +4096,12 @@
4009
4096
  vv["id"] = field_id;
4010
4097
  vv["value"] = v[field_id];
4011
4098
  } else {
4012
- if (!kw_has_key(v, field_value)) if (json_size(v) > 0) field_value = Object.keys(v)[0];
4013
- else {
4014
- log_error("list2options(): object without field value: " + field_value);
4015
- continue;
4099
+ if (!kw_has_key(v, field_value)) {
4100
+ if (json_size(v) > 0) field_value = Object.keys(v)[0];
4101
+ else {
4102
+ log_error("list2options(): object without field value: " + field_value);
4103
+ continue;
4104
+ }
4016
4105
  }
4017
4106
  vv["id"] = v[field_id];
4018
4107
  vv["value"] = v[field_value];
@@ -4328,13 +4417,15 @@
4328
4417
  if (is_object(v)) v = kw_get_dict_value(null, v, jdb.hook, [], 1);
4329
4418
  v = _jdb_get(v, null, id, false);
4330
4419
  }
4331
- if (ids.length === 0 && v) if (is_array(v)) v.push(kw);
4332
- else if (v["id"] === kw["id"]) Object.assign(v, kw);
4333
- else {
4334
- let v_ = kw_get_dict_value(null, v, jdb.hook, [], 1);
4335
- let v__ = _jdb_get(v_, jdb.hook, kw["id"], false);
4336
- if (v__) Object.assign(v__, kw);
4337
- else v_.push(kw);
4420
+ if (ids.length === 0 && v) {
4421
+ if (is_array(v)) v.push(kw);
4422
+ else if (v["id"] === kw["id"]) Object.assign(v, kw);
4423
+ else {
4424
+ let v_ = kw_get_dict_value(null, v, jdb.hook, [], 1);
4425
+ let v__ = _jdb_get(v_, jdb.hook, kw["id"], false);
4426
+ if (v__) Object.assign(v__, kw);
4427
+ else v_.push(kw);
4428
+ }
4338
4429
  }
4339
4430
  return topic;
4340
4431
  }
@@ -4360,13 +4451,15 @@
4360
4451
  if (is_object(v)) v = kw_get_dict_value(null, v, jdb.hook, null, 0);
4361
4452
  v = _jdb_get(v, null, id, false);
4362
4453
  }
4363
- if (ids.length === 0 && v) if (is_array(v)) {
4364
- let idx = id_index_in_obj_list(v, kw["id"]);
4365
- if (idx >= 0) v.splice(idx, 1);
4366
- } else {
4367
- let v_ = kw_get_dict_value(null, v, jdb.hook, null, 0);
4368
- let idx = id_index_in_obj_list(v_, kw["id"]);
4369
- if (idx >= 0) v_.splice(idx, 1);
4454
+ if (ids.length === 0 && v) {
4455
+ if (is_array(v)) {
4456
+ let idx = id_index_in_obj_list(v, kw["id"]);
4457
+ if (idx >= 0) v.splice(idx, 1);
4458
+ } else {
4459
+ let v_ = kw_get_dict_value(null, v, jdb.hook, null, 0);
4460
+ let idx = id_index_in_obj_list(v_, kw["id"]);
4461
+ if (idx >= 0) v_.splice(idx, 1);
4462
+ }
4370
4463
  }
4371
4464
  return topic;
4372
4465
  }
@@ -5093,41 +5186,42 @@
5093
5186
  * }
5094
5187
  ************************************************************/
5095
5188
  function treedb_decoder_fkey(col, fkey) {
5096
- if (is_string(fkey)) if (fkey.indexOf("^") === -1) {
5097
- let fkey_desc = col.fkey;
5098
- if (json_object_size(fkey_desc) !== 1) {
5099
- log_error("bad fkey 1");
5100
- log_error(col);
5101
- log_error(fkey);
5102
- return null;
5103
- }
5104
- let topic_name;
5105
- let hook_name;
5106
- for (const k of Object.keys(fkey_desc)) {
5107
- topic_name = k;
5108
- hook_name = fkey_desc[k];
5109
- break;
5110
- }
5111
- return {
5112
- topic_name,
5113
- id: fkey,
5114
- hook_name
5115
- };
5116
- } else {
5117
- let tt = fkey.split("^");
5118
- if (tt.length !== 3) {
5119
- log_error("bad fkey 2");
5120
- log_error(col);
5121
- log_error(fkey);
5122
- return null;
5189
+ if (is_string(fkey)) {
5190
+ if (fkey.indexOf("^") === -1) {
5191
+ let fkey_desc = col.fkey;
5192
+ if (json_object_size(fkey_desc) !== 1) {
5193
+ log_error("bad fkey 1");
5194
+ log_error(col);
5195
+ log_error(fkey);
5196
+ return null;
5197
+ }
5198
+ let topic_name;
5199
+ let hook_name;
5200
+ for (const k of Object.keys(fkey_desc)) {
5201
+ topic_name = k;
5202
+ hook_name = fkey_desc[k];
5203
+ break;
5204
+ }
5205
+ return {
5206
+ topic_name,
5207
+ id: fkey,
5208
+ hook_name
5209
+ };
5210
+ } else {
5211
+ let tt = fkey.split("^");
5212
+ if (tt.length !== 3) {
5213
+ log_error("bad fkey 2");
5214
+ log_error(col);
5215
+ log_error(fkey);
5216
+ return null;
5217
+ }
5218
+ return {
5219
+ topic_name: tt[0],
5220
+ id: tt[1],
5221
+ hook_name: tt[2]
5222
+ };
5123
5223
  }
5124
- return {
5125
- topic_name: tt[0],
5126
- id: tt[1],
5127
- hook_name: tt[2]
5128
- };
5129
- }
5130
- else if (is_object(fkey)) return {
5224
+ } else if (is_object(fkey)) return {
5131
5225
  topic_name: fkey.topic_name,
5132
5226
  id: fkey.id,
5133
5227
  hook_name: fkey.hook_name
@@ -5169,38 +5263,39 @@
5169
5263
  * }
5170
5264
  ********************************************/
5171
5265
  function treedb_decoder_hook(col, hook) {
5172
- if (is_string(hook)) if (hook.indexOf("^") === -1) {
5173
- let hook_desc = col.hook;
5174
- if (json_object_size(hook_desc) !== 1) {
5175
- log_error("bad hook 1");
5176
- log_error(col);
5177
- log_error(hook);
5178
- return null;
5179
- }
5180
- let topic_name;
5181
- for (let k of Object.keys(hook_desc)) {
5182
- topic_name = k;
5183
- hook_desc[k];
5184
- break;
5185
- }
5186
- return {
5187
- topic_name,
5188
- id: hook
5189
- };
5190
- } else {
5191
- let tt = hook.split("^");
5192
- if (tt.length !== 2) {
5193
- log_error("bad hook 2");
5194
- log_error(col);
5195
- log_error(hook);
5196
- return null;
5266
+ if (is_string(hook)) {
5267
+ if (hook.indexOf("^") === -1) {
5268
+ let hook_desc = col.hook;
5269
+ if (json_object_size(hook_desc) !== 1) {
5270
+ log_error("bad hook 1");
5271
+ log_error(col);
5272
+ log_error(hook);
5273
+ return null;
5274
+ }
5275
+ let topic_name;
5276
+ for (let k of Object.keys(hook_desc)) {
5277
+ topic_name = k;
5278
+ hook_desc[k];
5279
+ break;
5280
+ }
5281
+ return {
5282
+ topic_name,
5283
+ id: hook
5284
+ };
5285
+ } else {
5286
+ let tt = hook.split("^");
5287
+ if (tt.length !== 2) {
5288
+ log_error("bad hook 2");
5289
+ log_error(col);
5290
+ log_error(hook);
5291
+ return null;
5292
+ }
5293
+ return {
5294
+ topic_name: tt[0],
5295
+ id: tt[1]
5296
+ };
5197
5297
  }
5198
- return {
5199
- topic_name: tt[0],
5200
- id: tt[1]
5201
- };
5202
- }
5203
- else if (is_object(hook)) return {
5298
+ } else if (is_object(hook)) return {
5204
5299
  topic_name: hook.topic_name,
5205
5300
  id: hook.id
5206
5301
  };
@@ -5306,9 +5401,7 @@
5306
5401
  case "template":
5307
5402
  field_desc.enum_list = col.template;
5308
5403
  break;
5309
- case "table":
5310
- field_desc.enum_list = col.table;
5311
- break;
5404
+ case "table": field_desc.enum_list = col.table;
5312
5405
  }
5313
5406
  field_desc.type = f;
5314
5407
  } else if (str_in_list(treedb_field_attributes, f)) switch (f) {
@@ -5321,9 +5414,7 @@
5321
5414
  case "required":
5322
5415
  field_desc.is_required = true;
5323
5416
  break;
5324
- case "hidden":
5325
- field_desc.is_hidden = true;
5326
- break;
5417
+ case "hidden": field_desc.is_hidden = true;
5327
5418
  }
5328
5419
  }
5329
5420
  return field_desc;
@@ -5360,9 +5451,7 @@
5360
5451
  case "required":
5361
5452
  field_desc.is_required = true;
5362
5453
  break;
5363
- case "hidden":
5364
- field_desc.is_hidden = true;
5365
- break;
5454
+ case "hidden": field_desc.is_hidden = true;
5366
5455
  }
5367
5456
  }
5368
5457
  if (!field_desc.real_type) field_desc.real_type = "string";
@@ -5386,7 +5475,8 @@
5386
5475
  Object.entries(template).forEach(([field, col]) => {
5387
5476
  let default_value;
5388
5477
  if (is_object(col)) default_value = col.default;
5389
- new_record[field] = kw_get_dict_value(null, kw, field, default_value);
5478
+ let value = kw_get_dict_value(null, kw, field, default_value);
5479
+ new_record[field] = value;
5390
5480
  });
5391
5481
  return new_record;
5392
5482
  }
@@ -5467,7 +5557,6 @@
5467
5557
  if (priv.msec > 0) {
5468
5558
  if (!gobj_is_running(gobj)) gobj_start(gobj);
5469
5559
  } else if (gobj_is_running(gobj)) gobj_stop(gobj);
5470
- break;
5471
5560
  }
5472
5561
  }
5473
5562
  /***************************************************************
@@ -5826,9 +5915,7 @@
5826
5915
  case "remote_yuno_role":
5827
5916
  priv.remote_yuno_role = gobj_read_str_attr(gobj, "remote_yuno_role");
5828
5917
  break;
5829
- case "remote_yuno_service":
5830
- priv.remote_yuno_service = gobj_read_str_attr(gobj, "remote_yuno_service");
5831
- break;
5918
+ case "remote_yuno_service": priv.remote_yuno_service = gobj_read_str_attr(gobj, "remote_yuno_service");
5832
5919
  }
5833
5920
  }
5834
5921
  /***************************************************************
@@ -6370,12 +6457,13 @@
6370
6457
  return 0;
6371
6458
  }
6372
6459
  let gobj_service = gobj_find_service(iev_dst_service, true);
6373
- if (gobj_service) if (gobj_has_event(gobj_service, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) gobj_send_event(gobj_service, iev_event, iev_kw, gobj);
6374
- else {
6375
- log_error(`${gobj_short_name(gobj)}: Service found but no event or not public, service '${gobj_short_name(gobj_service)}', ev '${iev_event}'`);
6376
- return -1;
6377
- }
6378
- else if (gobj_is_pure_child(gobj)) gobj_send_event(gobj_parent(gobj), iev_event, iev_kw, gobj);
6460
+ if (gobj_service) {
6461
+ if (gobj_has_event(gobj_service, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) gobj_send_event(gobj_service, iev_event, iev_kw, gobj);
6462
+ else {
6463
+ log_error(`${gobj_short_name(gobj)}: Service found but no event or not public, service '${gobj_short_name(gobj_service)}', ev '${iev_event}'`);
6464
+ return -1;
6465
+ }
6466
+ } else if (gobj_is_pure_child(gobj)) gobj_send_event(gobj_parent(gobj), iev_event, iev_kw, gobj);
6379
6467
  else gobj_publish_event(gobj, iev_event, iev_kw);
6380
6468
  return 0;
6381
6469
  }
@@ -6580,6 +6668,7 @@
6580
6668
  exports.gobj_create_yuno = gobj_create_yuno;
6581
6669
  exports.gobj_current_state = gobj_current_state;
6582
6670
  exports.gobj_default_service = gobj_default_service;
6671
+ exports.gobj_deliver_posted_events = gobj_deliver_posted_events;
6583
6672
  exports.gobj_destroy = gobj_destroy;
6584
6673
  exports.gobj_find_child = gobj_find_child;
6585
6674
  exports.gobj_find_gobj = gobj_find_gobj;
@@ -6611,6 +6700,7 @@
6611
6700
  exports.gobj_pause = gobj_pause;
6612
6701
  exports.gobj_play = gobj_play;
6613
6702
  exports.gobj_post_event = gobj_post_event;
6703
+ exports.gobj_posted_events_size = gobj_posted_events_size;
6614
6704
  exports.gobj_publish_event = gobj_publish_event;
6615
6705
  exports.gobj_read_attr = gobj_read_attr;
6616
6706
  exports.gobj_read_attrs = gobj_read_attrs;