@yuneta/gobj-js 7.25.2 → 7.25.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.
@@ -1 +1 @@
1
- {"version":3,"file":"gobj-js.umd.min.js","names":["GCLASS_NAME","attrs_table","PRIVATE_DATA","__gclass__","mt_create","mt_writing","mt_start","mt_stop","mt_destroy","ac_timeout","gmt","create_gclass","GCLASS_NAME","attrs_table","PRIVATE_DATA","__gclass__","mt_create","mt_writing","mt_start","mt_stop","mt_destroy","gmt","create_gclass"],"sources":["../src/sprintf.js","../src/command_parser.js","../src/stats_parser.js","../src/gobj.js","../src/helpers.js","../src/dbsimple.js","../src/lib_treedb.js","../src/c_timer.js","../src/c_yuno.js","../src/c_ievent_cli.js"],"sourcesContent":["/*\n https://github.com/alexei/sprintf.js/blob/master/src/sprintf.js\n Copyright (c) 2007-present, Alexandru Mărășteanu <hello@alexei.ro>\n */\n\nlet re = {\n not_string: /[^s]/,\n not_bool: /[^t]/,\n not_type: /[^T]/,\n not_primitive: /[^v]/,\n number: /[diefg]/,\n numeric_arg: /[bcdiefguxX]/,\n json: /[j]/,\n not_json: /[^j]/,\n text: /^[^\\x25]+/,\n modulo: /^\\x25{2}/,\n placeholder: /^\\x25(?:([1-9]\\d*)\\$|\\(([^)]+)\\))?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-gijostTuvxX])/,\n key: /^([a-z_][a-z_\\d]*)/i,\n key_access: /^\\.([a-z_][a-z_\\d]*)/i,\n index_access: /^\\[(\\d+)\\]/,\n sign: /^[+-]/\n};\n\nfunction sprintf(key) {\n // `arguments` is not an array, but should be fine for this call\n return sprintf_format(sprintf_parse(key), arguments);\n}\n\nfunction vsprintf(fmt, argv) {\n return sprintf.apply(null, [fmt].concat(argv || []));\n}\n\nfunction sprintf_format(parse_tree, argv) {\n var cursor = 1, tree_length = parse_tree.length, arg, output = '', i, k, ph, pad, pad_character, pad_length, is_positive, sign;\n for (i = 0; i < tree_length; i++) {\n if (typeof parse_tree[i] === 'string') {\n output += parse_tree[i];\n }\n else if (typeof parse_tree[i] === 'object') {\n ph = parse_tree[i]; // convenience purposes only\n if (ph.keys) { // keyword argument\n arg = argv[cursor];\n for (k = 0; k < ph.keys.length; k++) {\n if (arg == undefined) {\n throw new Error(sprintf('[sprintf] Cannot access property \"%s\" of undefined value \"%s\"', ph.keys[k], ph.keys[k-1]));\n }\n arg = arg[ph.keys[k]];\n }\n }\n else if (ph.param_no) { // positional argument (explicit)\n arg = argv[ph.param_no];\n }\n else { // positional argument (implicit)\n arg = argv[cursor++];\n }\n\n if (re.not_type.test(ph.type) && re.not_primitive.test(ph.type) && arg instanceof Function) {\n arg = arg();\n }\n\n if (re.numeric_arg.test(ph.type) && (typeof arg !== 'number' && isNaN(arg))) {\n throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg));\n }\n\n if (re.number.test(ph.type)) {\n is_positive = arg >= 0;\n }\n\n switch (ph.type) {\n case 'b':\n arg = parseInt(arg, 10).toString(2);\n break;\n case 'c':\n arg = String.fromCharCode(parseInt(arg, 10));\n break;\n case 'd':\n case 'i':\n arg = parseInt(arg, 10);\n break;\n case 'j':\n arg = JSON.stringify(arg, null, ph.width ? parseInt(ph.width) : 0);\n break;\n case 'e':\n arg = ph.precision ? parseFloat(arg).toExponential(ph.precision) : parseFloat(arg).toExponential();\n break;\n case 'f':\n arg = ph.precision ? parseFloat(arg).toFixed(ph.precision) : parseFloat(arg);\n break;\n case 'g':\n arg = ph.precision ? String(Number(arg.toPrecision(ph.precision))) : parseFloat(arg);\n break;\n case 'o':\n arg = (parseInt(arg, 10) >>> 0).toString(8);\n break;\n case 's':\n arg = String(arg);\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 't':\n arg = String(!!arg);\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 'T':\n arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase();\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 'u':\n arg = parseInt(arg, 10) >>> 0;\n break;\n case 'v':\n arg = arg.valueOf();\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 'x':\n arg = (parseInt(arg, 10) >>> 0).toString(16);\n break;\n case 'X':\n arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase();\n break;\n }\n if (re.json.test(ph.type)) {\n output += arg;\n }\n else {\n if (re.number.test(ph.type) && (!is_positive || ph.sign)) {\n sign = is_positive ? '+' : '-';\n arg = arg.toString().replace(re.sign, '');\n }\n else {\n sign = '';\n }\n pad_character = ph.pad_char ? ph.pad_char === '0' ? '0' : ph.pad_char.charAt(1) : ' ';\n pad_length = ph.width - (sign + arg).length;\n pad = ph.width ? (pad_length > 0 ? pad_character.repeat(pad_length) : '') : '';\n output += ph.align ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg);\n }\n }\n }\n return output;\n}\n\nlet sprintf_cache = Object.create(null);\n\nfunction sprintf_parse(fmt) {\n if (sprintf_cache[fmt]) {\n return sprintf_cache[fmt];\n }\n\n let _fmt = fmt, match, parse_tree = [], arg_names = 0;\n while (_fmt) {\n if ((match = re.text.exec(_fmt)) !== null) {\n parse_tree.push(match[0]);\n }\n else if ((match = re.modulo.exec(_fmt)) !== null) {\n parse_tree.push('%');\n }\n else if ((match = re.placeholder.exec(_fmt)) !== null) {\n if (match[2]) {\n arg_names |= 1;\n var field_list = [], replacement_field = match[2], field_match = [];\n if ((field_match = re.key.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {\n if ((field_match = re.key_access.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n }\n else if ((field_match = re.index_access.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n }\n else {\n throw new SyntaxError('[sprintf] failed to parse named argument key');\n }\n }\n }\n else {\n throw new SyntaxError('[sprintf] failed to parse named argument key');\n }\n match[2] = field_list;\n }\n else {\n arg_names |= 2;\n }\n if (arg_names === 3) {\n throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported');\n }\n\n parse_tree.push(\n {\n placeholder: match[0],\n param_no: match[1],\n keys: match[2],\n sign: match[3],\n pad_char: match[4],\n align: match[5],\n width: match[6],\n precision: match[7],\n type: match[8]\n }\n );\n }\n else {\n throw new SyntaxError('[sprintf] unexpected placeholder');\n }\n _fmt = _fmt.substring(match[0].length);\n }\n return sprintf_cache[fmt] = parse_tree;\n}\n\nexport { sprintf, vsprintf };\n","/****************************************************************************\n * command_parser.js\n *\n * Command parser\n *\n * Copyright (c) 2025, ArtGins.\n * All Rights Reserved. ****************************************************************************/\n\n/***************************************************************\n *\n ***************************************************************/\nfunction command_parser(\n gobj,\n command,\n kw,\n src\n) {\n\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction build_command_response(\n gobj,\n result,\n comment,\n schema,\n data\n) {\n return {\n result: result,\n comment: comment || {},\n schema: schema || {},\n data: data || []\n };\n}\n\nexport {\n command_parser,\n build_command_response,\n};\n","/****************************************************************************\n * stats_parser.js\n *\n * Stats parser\n *\n * Copyright (c) 2025, ArtGins.\n * All Rights Reserved. ****************************************************************************/\n\n/***************************************************************\n *\n ***************************************************************/\nfunction stats_parser(\n gobj,\n stats,\n kw,\n src\n) {\n\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction build_stats_response(\n gobj,\n result,\n comment,\n schema,\n data\n) {\n return {\n result: result,\n comment: comment || {},\n schema: schema || {},\n data: data || []\n };\n}\n\nexport {\n stats_parser,\n build_stats_response,\n};\n","/*********************************************************************************\n * Objects with a simple Finite State Machine.\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025-2026, ArtGins.\n *********************************************************************************/\n/* jshint bitwise: false */\n\nimport {\n kw_flag_t,\n is_string,\n is_object,\n is_array,\n is_number,\n log_error,\n log_warning,\n empty_string,\n json_deep_copy,\n json_object_update,\n json_object_get,\n json_object_del,\n json_object_set,\n json_object_set_new,\n index_in_list,\n json_array_size,\n strcasecmp,\n kw_get_dict,\n kw_get_bool,\n kw_match_simple,\n kw_get_int,\n json_array_append,\n kw_get_dict_value,\n trace_json,\n json_array_remove,\n kw_get_str,\n kw_has_key,\n kw_pop,\n kw_get_pointer,\n json_object_size,\n log_debug,\n json_array_append_new,\n parseBoolean,\n is_gobj,\n json_size,\n json_is_identical,\n get_function_name,\n} from \"./helpers.js\";\n\nimport {sprintf} from \"./sprintf.js\";\nimport {build_command_response} from \"./command_parser.js\";\nimport {build_stats_response} from \"./stats_parser.js\";\n\n/**************************************************************************\n * Constants\n **************************************************************************/\nlet YUNETA_VERSION = \"7.0.0a\";\n\n/**************************************************************************\n * Private data\n **************************************************************************/\nlet __jn_global_settings__ = null;\nlet __global_load_persistent_attrs_fn__ = null;\nlet __global_save_persistent_attrs_fn__ = null;\nlet __global_remove_persistent_attrs_fn__ = null;\nlet __global_list_persistent_attrs_fn__ = null;\nlet __global_command_parser_fn__ = null;\nlet __global_stats_parser_fn__ = null;\n\n/*\n * System (gobj) output events\n */\nlet dl_global_event_types = [];\n\nlet _gclass_register = Object.create(null);\nlet __jn_services__ = {};\n\nlet __yuno__ = null;\nlet __default_service__ = null;\nlet __inside__ = 0;\n\n/**************************************************************************\n * SData - Structured Data\n **************************************************************************/\nconst data_type_t = Object.freeze({\n DTP_STRING: 1,\n DTP_BOOLEAN: 2,\n DTP_INTEGER: 3,\n DTP_REAL: 4,\n DTP_LIST: 5,\n DTP_DICT: 6,\n DTP_JSON: 7,\n DTP_POINTER: 8\n});\n\n// Macros as functions\nconst DTP_IS_STRING = (type) => type === data_type_t.DTP_STRING;\nconst DTP_IS_BOOLEAN = (type) => type === data_type_t.DTP_BOOLEAN;\nconst DTP_IS_INTEGER = (type) => type === data_type_t.DTP_INTEGER;\nconst DTP_IS_REAL = (type) => type === data_type_t.DTP_REAL;\nconst DTP_IS_LIST = (type) => type === data_type_t.DTP_LIST;\nconst DTP_IS_DICT = (type) => type === data_type_t.DTP_DICT;\nconst DTP_IS_JSON = (type) => type === data_type_t.DTP_JSON;\nconst DTP_IS_POINTER = (type) => type === data_type_t.DTP_POINTER;\nconst DTP_IS_SCHEMA = (type) => type === DTP_SCHEMA;\nconst DTP_SCHEMA = data_type_t.DTP_POINTER;\nconst DTP_IS_NUMBER = (type) => DTP_IS_INTEGER(type) || DTP_IS_REAL(type) || DTP_IS_BOOLEAN(type);\n\nconst sdata_flag_t = Object.freeze({\n SDF_NOTACCESS: 0x00000001,\n SDF_RD: 0x00000002,\n SDF_WR: 0x00000004,\n SDF_REQUIRED: 0x00000008,\n SDF_PERSIST: 0x00000010,\n SDF_VOLATIL: 0x00000020,\n SDF_RESOURCE: 0x00000040,\n SDF_PKEY: 0x00000080,\n SDF_DEPRECATED: 0x00000100,\n SDF_FUTURE2: 0x00000200,\n SDF_WILD_CMD: 0x00000400,\n SDF_STATS: 0x00000800,\n SDF_FKEY: 0x00001000,\n SDF_RSTATS: 0x00002000,\n SDF_PSTATS: 0x00004000,\n SDF_AUTHZ_R: 0x00008000,\n SDF_AUTHZ_W: 0x00010000,\n SDF_AUTHZ_X: 0x00020000,\n SDF_AUTHZ_P: 0x00040000,\n SDF_AUTHZ_S: 0x00080000,\n SDF_AUTHZ_RS: 0x00100000\n});\n\nconst SDF_PUBLIC_ATTR = sdata_flag_t.SDF_RD | sdata_flag_t.SDF_WR | sdata_flag_t.SDF_STATS |\n sdata_flag_t.SDF_PERSIST | sdata_flag_t.SDF_VOLATIL |\n sdata_flag_t.SDF_RSTATS | sdata_flag_t.SDF_PSTATS;\nconst ATTR_WRITABLE = sdata_flag_t.SDF_WR | sdata_flag_t.SDF_PERSIST;\nconst ATTR_READABLE = SDF_PUBLIC_ATTR;\n\nclass SDataDesc {\n constructor(type, name, flag = 0, default_value = null, description = \"\",\n alias = null, header = null, fillspace = 0, json_fn = null, schema = null, authpth = null) {\n this.type = type;\n this.name = name;\n this.alias = alias;\n this.flag = flag;\n this.default_value= default_value;\n this.header = header;\n this.fillspace = fillspace;\n this.description = description;\n this.json_fn = json_fn;\n this.schema = schema;\n this.authpth = authpth;\n }\n}\n\nconst SDATA_END = () => new SDataDesc(0, null);\nconst SDATA = (type, name, flag, default_value, description) => new SDataDesc(type, name, flag, default_value, description);\nconst SDATACM = (type, name, alias, items, json_fn, description) => new SDataDesc(type, name, 0, null, description, alias, null, 0, json_fn, items, null);\nconst SDATACM2 = (type, name, flag, alias, items, json_fn, description) => new SDataDesc(type, name, flag, null, description, alias, null, 0, json_fn, items, null);\nconst SDATAPM = (type, name, flag, default_value, description) => new SDataDesc(type, name, flag, default_value, description);\nconst SDATAAUTHZ = (type, name, flag, alias, items, description) => new SDataDesc(type, name, flag, null, description, alias, null, 0, null, items, null);\nconst SDATAPM0 = (type, name, flag, authpth, description) => new SDataDesc(type, name, flag, null, description, null, null, 0, null, null, authpth);\nconst SDATADF = (type, name, flag, header, fillspace, description) => new SDataDesc(type, name, flag, null, description, null, header, fillspace);\n\n/***************************************************************\n * Structures\n ***************************************************************/\nclass GClass {\n constructor(\n gclass_name,\n gmt,\n lmt,\n attrs_table,\n priv,\n authz_table,\n command_table,\n s_user_trace_level,\n gclass_flag\n ) {\n this.gclass_name = gclass_name;\n this.dl_states = []; // FSM list states and their ev/action/next\n this.dl_events = []; // FSM list of events (gobj_event_t, event_flag_t)\n this.gmt = gmt; // Global methods\n this.lmt = lmt;\n\n this.attrs_table = attrs_table;\n this.priv = priv;\n this.authz_table = authz_table; // acl\n this.command_table = command_table; // if it exits then mt_command is not used.\n\n this.s_user_trace_level = s_user_trace_level;\n this.gclass_flag = Number(gclass_flag) || 0;\n\n this.instances = 0; // instances of this gclass\n this.trace_level = 0;\n this.no_trace_level = 0;\n this.jn_trace_filter = null;\n this.fsm_checked = false;\n }\n}\n\nclass GObj {\n constructor(gobj_name, gclass, kw, parent, gobj_flag) {\n this.__refs__ = 0;\n this.gclass = gclass;\n this.parent = null; // assign in _add_child()\n this.dl_children = [];\n this.dl_subscriptions = []; // subscriptions of this gobj to events of others gobj.\n this.dl_subscribings = []; // subscribed events\n this.current_state = gclass.dl_states[0];\n this.last_state = null;\n this.obflag = 0;\n this.gobj_flag = Number(gobj_flag) || 0;\n\n // Data allocated\n this.gobj_name = gobj_name;\n this.jn_attrs = null;\n this.jn_stats = {};\n this.jn_user_data = {};\n this.full_name = null;\n this.short_name = null;\n this.priv = json_deep_copy(gclass.priv);\n\n this.running = false; // set by gobj_start/gobj_stop\n this.playing = false; // set by gobj_play/gobj_pause\n this.disabled = false; // set by gobj_enable/gobj_disable\n this.bottom_gobj = null;\n\n this.trace_level = 0;\n this.no_trace_level = 0;\n }\n}\n\n/*\n * gclass_flag_t\n * Features of the gclass\n *\n // Example usage:\n\n let flags = gclass_flag_t.gcflag_manual_start | gclass_flag_t.gcflag_singleton;\n\n if (flags & gclass_flag_t.gcflag_manual_start) {\n console.log(\"Manual start flag is set\");\n }\n\n */\n\nconst gclass_flag_t = Object.freeze({\n gcflag_manual_start: 0x0001, // gobj_start_tree() doesn't start automatically\n gcflag_no_check_output_events: 0x0002, // When publishing, don't check events in output_event_list\n gcflag_ignore_unknown_attrs: 0x0004, // When creating a gobj, ignore non-existing attrs\n gcflag_required_start_to_play: 0x0008, // Don't play if start wasn't done\n gcflag_singleton: 0x0010, // Can only have one instance\n});\n\n/*\n * gobj_flag_t\n * Features of the gobj\n *\n // Example usage:\n\n let gobj_flag = gobj_flag_t.gobj_flag_yuno | gobj_flag_t.gobj_flag_service;\n\n // Check if a flag is set\n\n if (gobj_flag & gobj_flag_t.gobj_flag_service) {\n console.log(\"Service flag is set\");\n }\n\n // Convert to array of names for debugging\n\n function print_gobj_flags(flagValue) {\n return Object.keys(gobj_flag_t).filter(key => flagValue & gobj_flag_t[key]);\n }\n\n */\nconst gobj_flag_t = Object.freeze({\n gobj_flag_yuno: 0x0001,\n gobj_flag_default_service: 0x0002,\n gobj_flag_service: 0x0004, // Interface (events, attrs, commands, stats)\n gobj_flag_volatil: 0x0008,\n gobj_flag_pure_child: 0x0010, // Pure child sends events directly to parent\n gobj_flag_autostart: 0x0020, // Set by gobj_create_tree0 too\n gobj_flag_autoplay: 0x0040, // Set by gobj_create_tree0 too\n});\n\n/*\n * obflag_t\n * Features realtime of the gobj\n */\nconst obflag_t = Object.freeze({\n obflag_destroying: 0x0001,\n obflag_destroyed: 0x0002,\n obflag_created: 0x0004,\n});\n\nconst event_flag_t = Object.freeze({\n EVF_NO_WARN_SUBS : 0x0001, // Don't warn of \"Publish event WITHOUT subscribers\"\n EVF_OUTPUT_EVENT : 0x0002, // Output Event\n EVF_SYSTEM_EVENT : 0x0004, // System Event\n EVF_PUBLIC_EVENT : 0x0008, // You should document a public event, it's the API\n});\n\nconst walk_type_t = Object.freeze({\n /*\n * One must be selected\n */\n WALK_TOP2BOTTOM : 0x0001,\n WALK_BOTTOM2TOP : 0x0002,\n WALK_BYLEVEL : 0x0004,\n\n /*\n * One must be selected when WALK_BYLEVEL is selected.\n */\n WALK_FIRST2LAST : 0x0010,\n WALK_LAST2FIRST : 0x0020,\n});\n\n\n/*---------------------------*\n * FSM\n *---------------------------*/\nclass Event_Action { // C event_action_t\n constructor(event_name, action, next_state) {\n this.event_name = event_name;\n this.action = action;\n this.next_state = next_state;\n }\n}\n\nclass State { // C state_t\n constructor(state_name) {\n this.state_name = state_name;\n this.dl_actions = [];\n }\n}\n\nclass Event_Type { // C event_type_t\n constructor(event_name, event_flag) {\n this.event_name = event_name;\n this.event_flag = Number(event_flag) || 0;\n }\n}\n\n/*\n * Indent a trace line by its nesting depth, the same as the C kernel's\n * tab() (gobj.c): TWO spaces per level of `__inside__`, and never zero\n * — it writes bf[0] before the loop, so even at depth 0 a line starts\n * one space in. This was `2n - 1` here, one short at every level, so a\n * trace read side by side with a node's did not line up.\n */\nfunction tab()\n{\n return ' '.repeat(Math.max(1, __inside__ * 2));\n}\n\n/* Machine (automata) trace format, mirroring the C kernel:\n * 0 = legacy (\"🔄 mach(gclass^name), st: STATE, ev: EVENT, ac: …, from(…)\"\n * + a \"🔀🔀 new st(…)\" line + a \"<- mach(…) ret: N\" line —\n * THREE lines for one transition)\n * 1 = simpler (\"🔄 EVENT dst STATE from src\") — one line per transition,\n * no return line and no state-change line.\n *\n * DEFAULT 1, which is the C kernel's default (`trace_machine_format` in\n * gobj.c: \"0 legacy, 1 simpler, 2 full\"). The JS port shipped 0 and so read\n * three lines a transition where a node read one — the same trace, three\n * times the wall, and the two sides did not look alike. */\nlet __trace_machine_format__ = 1;\n\nfunction gobj_set_trace_machine_format(format)\n{\n __trace_machine_format__ = (Number(format) === 1) ? 1 : 0;\n}\n\nfunction gobj_trace_machine_format()\n{\n return __trace_machine_format__;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction trace_machine(msg)\n{\n if(is_object(msg)) {\n msg = JSON.stringify(msg);\n }\n log_debug(tab() + String(msg));\n}\n\n\n/***************************************************************\n * Trace levels\n *\n * The SAME names and the SAME bits as the C kernel (gobj.h's\n * enum + gobj.c's s_global_trace_level), so a level means one\n * thing across the two implementations and a habit learned on\n * one side transfers to the other. The levels that only exist\n * on a node (fs, liburing, gbuffers) keep their bit anyway:\n * dropping them would shift every bit above and break exactly\n * that alignment.\n *\n * 16 higher bits are global, 16 lower bits are per-gclass user\n * levels (`s_user_trace_level` in gclass_create).\n ***************************************************************/\nconst trace_level_t = Object.freeze({\n TRACE_MACHINE: 0x00010000,\n TRACE_CREATE_DELETE: 0x00020000,\n TRACE_CREATE_DELETE2: 0x00040000,\n TRACE_SUBSCRIPTIONS: 0x00080000,\n TRACE_START_STOP: 0x00100000,\n TRACE_EV_KW: 0x00200000,\n TRACE_AUTHZS: 0x00400000,\n TRACE_STATES: 0x00800000,\n TRACE_GBUFFERS: 0x01000000,\n TRACE_TIMER: 0x02000000,\n TRACE_FS: 0x04000000,\n TRACE_URING: 0x08000000,\n TRACE_TIMER_PERIODIC: 0x10000000,\n TRACE_URING_TIME: 0x20000000,\n TRACE_COMMANDS: 0x40000000\n});\n\nconst TRACE_USER_LEVEL = 0x0000FFFF;\nconst TRACE_GLOBAL_LEVEL1 = 0x0FFF0000;\n\n/* Name → bit, in the C table's order. */\nconst s_global_trace_level = [\n [\"machine\", trace_level_t.TRACE_MACHINE, \"Trace machine\"],\n [\"create_delete\", trace_level_t.TRACE_CREATE_DELETE, \"Trace create/delete of gobjs\"],\n [\"create_delete2\", trace_level_t.TRACE_CREATE_DELETE2, \"Trace create/delete of gobjs level 2: with kw\"],\n [\"subscriptions\", trace_level_t.TRACE_SUBSCRIPTIONS, \"Trace subscriptions of gobjs\"],\n [\"start_stop\", trace_level_t.TRACE_START_STOP, \"Trace start/stop of gobjs\"],\n [\"ev_kw\", trace_level_t.TRACE_EV_KW, \"Trace event keywords\"],\n [\"authzs\", trace_level_t.TRACE_AUTHZS, \"Trace authorizations\"],\n [\"states\", trace_level_t.TRACE_STATES, \"Trace change of states\"],\n [\"gbuffers\", trace_level_t.TRACE_GBUFFERS, \"Trace gbuffers\"],\n [\"timer\", trace_level_t.TRACE_TIMER, \"Trace timers\"],\n [\"fs\", trace_level_t.TRACE_FS, \"Trace file system\"],\n [\"liburing\", trace_level_t.TRACE_URING, \"Trace liburing mixins\"],\n [\"timer_periodic\", trace_level_t.TRACE_TIMER_PERIODIC, \"Trace periodic timers\"],\n [\"liburing_timer\", trace_level_t.TRACE_URING_TIME, \"Trace liburing timer\"],\n [\"commands\", trace_level_t.TRACE_COMMANDS, \"Trace commands\"]\n];\n\nlet __global_trace_level__ = 0;\nlet __global_trace_no_level__ = 0;\nlet __deep_trace__ = 0;\n\n/*\n * A gclass's own levels, `s_user_trace_level` in gclass_create: a list of\n * [name, description], in bit order -- the first is 0x0001, like the C\n * table of {name, description}.\n */\nfunction level2bit(level, s_user_trace_level)\n{\n for(const [name, bit] of s_global_trace_level) {\n if(name === level) {\n return bit;\n }\n }\n if(Array.isArray(s_user_trace_level)) {\n for(let i = 0; i < s_user_trace_level.length && i < 16; i++) {\n if(s_user_trace_level[i] && s_user_trace_level[i][0] === level) {\n return 1 << i;\n }\n }\n }\n return 0;\n}\n\n/* The names of the bits set in `bitmask`, global and the gclass's own. */\nfunction bit2level(bitmask, s_user_trace_level)\n{\n let levels = [];\n for(const [name, bit] of s_global_trace_level) {\n if(bitmask & bit) {\n levels.push(name);\n }\n }\n if(Array.isArray(s_user_trace_level)) {\n for(let i = 0; i < s_user_trace_level.length && i < 16; i++) {\n if(s_user_trace_level[i] && (bitmask & (1 << i))) {\n levels.push(s_user_trace_level[i][0]);\n }\n }\n }\n return levels;\n}\n\n/*\n * A level name, a decimal bitmask as a string, or empty for \"all\": all the\n * global levels, or, with a gclass, all of its own (the C kernel's \"\").\n */\nfunction trace_bitmask(level, who, s_user_trace_level)\n{\n if(empty_string(level)) {\n return s_user_trace_level === undefined ? TRACE_GLOBAL_LEVEL1 : TRACE_USER_LEVEL;\n }\n if(/^[0-9]+$/.test(String(level))) {\n const n = Number(level);\n if(n) {\n return n;\n }\n }\n const bit = level2bit(String(level), s_user_trace_level);\n if(!bit) {\n log_error(`${who}: trace level NOT FOUND: ${level}`);\n return 0;\n }\n return bit;\n}\n\n/************************************************************\n * The levels in force for a gobj: global, plus its gclass's,\n * plus its own — the union, exactly as the C kernel computes\n * it in gobj_trace_level().\n ************************************************************/\nfunction gobj_trace_level(gobj)\n{\n if(__deep_trace__) {\n return 0xFFFFFFFF;\n }\n let bitmask = __global_trace_level__;\n if(gobj) {\n bitmask |= gobj.trace_level || 0;\n if(gobj.gclass) {\n bitmask |= gobj.gclass.trace_level || 0;\n }\n }\n return bitmask;\n}\n\nfunction gobj_trace_no_level(gobj)\n{\n let bitmask = __global_trace_no_level__;\n if(gobj) {\n bitmask |= gobj.no_trace_level || 0;\n if(gobj.gclass) {\n bitmask |= gobj.gclass.no_trace_level || 0;\n }\n }\n return bitmask;\n}\n\nfunction __trace_gobj_create_delete__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_CREATE_DELETE;\n}\n\nfunction __trace_gobj_subscriptions__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_SUBSCRIPTIONS;\n}\n\nfunction __trace_gobj_start_stop__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_START_STOP;\n}\n\nfunction __trace_gobj_ev_kw__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_EV_KW;\n}\n\nfunction __trace_gobj_states__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_STATES;\n}\n\n/************************************************************\n * Must trace a command? — the C kernel's is_commands_tracing()\n ************************************************************/\nfunction is_commands_tracing(gobj)\n{\n if(__deep_trace__ > 1) {\n return true;\n }\n if(!gobj) {\n return false;\n }\n return (gobj_trace_level(gobj) & trace_level_t.TRACE_COMMANDS) ? true : false;\n}\n\n/************************************************************\n * Must trace? — the C kernel's is_machine_tracing(), including\n * the two event-specific levels: `timer` and `timer_periodic`\n * light up only for their own event.\n ************************************************************/\nfunction is_machine_tracing(gobj, event)\n{\n if(__deep_trace__ > 1) {\n return true;\n }\n if(!gobj) {\n return false;\n }\n const level = gobj_trace_level(gobj);\n const trace =\n (level & trace_level_t.TRACE_MACHINE) ||\n ((level & trace_level_t.TRACE_TIMER_PERIODIC) && event === \"EV_TIMEOUT_PERIODIC\") ||\n ((level & trace_level_t.TRACE_TIMER) && event === \"EV_TIMEOUT\");\n\n return trace ? true : false;\n}\n\n/************************************************************\n * Must NOT trace? Asked of the SOURCE, so a noisy sender can\n * be silenced without turning the destination off.\n ************************************************************/\nfunction is_machine_not_tracing(gobj, event)\n{\n if(__deep_trace__ > 1) {\n return false;\n }\n if(!gobj) {\n return true;\n }\n const level = gobj_trace_no_level(gobj);\n const no_trace =\n (level & trace_level_t.TRACE_MACHINE) ||\n ((level & trace_level_t.TRACE_TIMER_PERIODIC) && event === \"EV_TIMEOUT_PERIODIC\") ||\n ((level & trace_level_t.TRACE_TIMER) && event === \"EV_TIMEOUT\");\n\n return no_trace ? true : false;\n}\n\n/************************************************************\n * The setters — same signatures as the C kernel\n ************************************************************/\nfunction gobj_set_global_trace(level, set)\n{\n const bitmask = trace_bitmask(level, \"gobj_set_global_trace\");\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n __global_trace_level__ |= bitmask;\n } else {\n __global_trace_level__ &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_set_global_no_trace(level, set)\n{\n const bitmask = trace_bitmask(level, \"gobj_set_global_no_trace\");\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n __global_trace_no_level__ |= bitmask;\n } else {\n __global_trace_no_level__ &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_global_trace_level()\n{\n return __global_trace_level__;\n}\n\nfunction gobj_global_trace_no_level()\n{\n return __global_trace_no_level__;\n}\n\n/* By bitmask, the C kernel's gobj_set_global_trace2(): 0xFFFFFFFF clears all. */\nfunction gobj_set_global_trace2(bitmask, set)\n{\n if(set) {\n __global_trace_level__ = (__global_trace_level__ | bitmask) >>> 0;\n } else {\n __global_trace_level__ = (__global_trace_level__ & ~bitmask) >>> 0;\n }\n return 0;\n}\n\nfunction gobj_set_global_no_trace2(bitmask, set)\n{\n if(set) {\n __global_trace_no_level__ = (__global_trace_no_level__ | bitmask) >>> 0;\n } else {\n __global_trace_no_level__ = (__global_trace_no_level__ & ~bitmask) >>> 0;\n }\n return 0;\n}\n\n/*\n * The levels in force, by NAME -- the C kernel's getters, same names.\n * gobj_get_gclass_trace_level() includes the global levels, as in C;\n * gobj_get_gclass_trace_level2() is the gclass's own only.\n */\nfunction gobj_get_global_trace_level()\n{\n return bit2level(__global_trace_level__, null);\n}\n\nfunction gobj_get_global_trace_no_level()\n{\n return bit2level(__global_trace_no_level__, null);\n}\n\nfunction gobj_get_gclass_trace_level(gclass)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_get_gclass_trace_level: gclass NOT FOUND: ${gclass}`);\n return [];\n }\n return bit2level(gclass_.trace_level | __global_trace_level__, gclass_.s_user_trace_level);\n}\n\nfunction gobj_get_gclass_trace_level2(gclass)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_get_gclass_trace_level2: gclass NOT FOUND: ${gclass}`);\n return [];\n }\n return bit2level(gclass_.trace_level, gclass_.s_user_trace_level);\n}\n\nfunction gobj_get_gclass_trace_no_level(gclass)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_get_gclass_trace_no_level: gclass NOT FOUND: ${gclass}`);\n return [];\n }\n return bit2level(gclass_.no_trace_level, gclass_.s_user_trace_level);\n}\n\n/* Everything at once, for a session that is chasing something. */\nfunction gobj_set_deep_trace(value)\n{\n __deep_trace__ = Number(value) || 0;\n return 0;\n}\n\n/*\n * Per gclass: `gclass` is the gclass object or its name, so the\n * caller does not need a handle it may not have.\n */\nfunction gobj_set_gclass_trace(gclass, level, set)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_set_gclass_trace: gclass NOT FOUND: ${gclass}`);\n return -1;\n }\n const bitmask = (level === null) ? 0xFFFFFFFF :\n trace_bitmask(level, \"gobj_set_gclass_trace\", gclass_.s_user_trace_level || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gclass_.trace_level |= bitmask;\n } else {\n gclass_.trace_level &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_set_gobj_trace(gobj, level, set)\n{\n if(!gobj) {\n log_error(`gobj_set_gobj_trace: gobj NULL`);\n return -1;\n }\n const bitmask = trace_bitmask(level, \"gobj_set_gobj_trace\", (gobj.gclass && gobj.gclass.s_user_trace_level) || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gobj.trace_level |= bitmask;\n } else {\n gobj.trace_level &= ~bitmask;\n }\n return 0;\n}\n\n/*\n * Per gclass, the SILENCING side. What every C main() uses to keep\n * the timers out of a `machine` trace:\n *\n * gobj_set_gclass_no_trace(\"C_TIMER\", \"machine\", true);\n * gobj_set_global_no_trace(\"timer_periodic\", true);\n *\n * `machine` traces every event by design, timers included, so without\n * this a one-second tick buries whatever you were following.\n */\nfunction gobj_set_gclass_no_trace(gclass, level, set)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_set_gclass_no_trace: gclass NOT FOUND: ${gclass}`);\n return -1;\n }\n const bitmask = (level === null) ? 0xFFFFFFFF :\n trace_bitmask(level, \"gobj_set_gclass_no_trace\", gclass_.s_user_trace_level || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gclass_.no_trace_level |= bitmask;\n } else {\n gclass_.no_trace_level &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_set_gobj_no_trace(gobj, level, set)\n{\n if(!gobj) {\n log_error(`gobj_set_gobj_no_trace: gobj NULL`);\n return -1;\n }\n const bitmask = trace_bitmask(level, \"gobj_set_gobj_no_trace\", (gobj.gclass && gobj.gclass.s_user_trace_level) || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gobj.no_trace_level |= bitmask;\n } else {\n gobj.no_trace_level &= ~bitmask;\n }\n return 0;\n}\n\n/* The catalogue, for a dev panel or a \"what can I turn on?\" list. */\nfunction gobj_repr_global_trace_levels()\n{\n return s_global_trace_level.map(([name, bit, description]) => ({\n name: name, bit: bit, description: description,\n set: (__global_trace_level__ & bit) ? true : false\n }));\n}\n\n/************************************************************\n * Start up\n ************************************************************/\nfunction gobj_start_up(\n jn_global_settings,\n load_persistent_attrs_fn,\n save_persistent_attrs_fn,\n remove_persistent_attrs_fn,\n list_persistent_attrs_fn,\n global_command_parser_fn,\n global_stats_parser_fn\n)\n{\n __jn_global_settings__ = jn_global_settings;\n __global_load_persistent_attrs_fn__ = load_persistent_attrs_fn;\n __global_save_persistent_attrs_fn__ = save_persistent_attrs_fn;\n __global_remove_persistent_attrs_fn__ = remove_persistent_attrs_fn;\n __global_list_persistent_attrs_fn__ = list_persistent_attrs_fn;\n __global_command_parser_fn__ = global_command_parser_fn;\n __global_stats_parser_fn__ = global_stats_parser_fn;\n\n /*----------------------------------------*\n * Build Global Events\n *----------------------------------------*/\n const global_events = [\n [\"EV_STATE_CHANGED\", event_flag_t.EVF_SYSTEM_EVENT|\n event_flag_t.EVF_OUTPUT_EVENT|\n event_flag_t.EVF_NO_WARN_SUBS],\n [0, 0]\n ];\n\n for (let i = 0; i < global_events.length; i++) {\n let event_name = global_events[i][0];\n let event_flag = global_events[i][1];\n\n _add_event_type(dl_global_event_types, event_name, event_flag);\n }\n\n\n return 0;\n}\n\n/************************************************************\n * Register gclass\n ************************************************************/\nfunction _register_gclass(\n gclass,\n gclass_name\n)\n{\n if(!gclass || !(gclass instanceof GClass)) {\n log_error(`gclass undefined`);\n return -1;\n }\n if(!gclass_name) {\n log_error(`gclass_name undefined`);\n return -1;\n }\n\n let gclass_ = _gclass_register[gclass_name];\n if (gclass_) {\n log_error(`gclass ALREADY REGISTERED: ${gclass_name}`);\n return -1;\n }\n _gclass_register[gclass_name] = gclass;\n return 0;\n}\n\n/***************************************************************************\n * Build default values\n ***************************************************************************/\nfunction sdata_create(gobj, sdata_desc)\n{\n let sdata = {};\n\n if(!is_array(sdata_desc)) {\n log_error(`sdata_desc MUST be an array`);\n trace_json(sdata_desc);\n return sdata;\n }\n for(let i=0; i < sdata_desc.length; i++) {\n const it = sdata_desc[i];\n if(!it.name) {\n continue;\n }\n set_default(gobj, sdata, it);\n }\n\n return sdata;\n}\n\n/***************************************************************************\n * Set array values to sdata, from json or binary\n ***************************************************************************/\nfunction set_default(gobj, sdata, it)\n{\n let jn_value;\n let svalue = it.default_value;\n\n switch(it.type) {\n case data_type_t.DTP_STRING:\n jn_value = String(svalue);\n break;\n case data_type_t.DTP_BOOLEAN:\n jn_value = parseBoolean(svalue);\n break;\n case data_type_t.DTP_INTEGER:\n jn_value = parseInt(svalue);\n if(isNaN(jn_value)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_REAL:\n jn_value = Number(svalue);\n if(isNaN(jn_value)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_LIST:\n if(is_string(svalue)) {\n try {\n jn_value = JSON.parse(svalue);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value = svalue;\n }\n if(!is_array(jn_value)) {\n jn_value = [];\n }\n break;\n case data_type_t.DTP_DICT:\n if(is_string(svalue)) {\n try {\n jn_value = JSON.parse(svalue);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value = svalue;\n }\n if(!is_object(jn_value)) {\n jn_value = {};\n }\n break;\n case data_type_t.DTP_JSON:\n if(is_string(svalue)) {\n try {\n jn_value = JSON.parse(svalue);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value = svalue;\n }\n break;\n case data_type_t.DTP_POINTER:\n jn_value = svalue;\n break;\n }\n\n if(jn_value === undefined) {\n log_error(`default_value WRONG, it: ${it.name}, value: ${it.default_value}`);\n jn_value = null;\n }\n\n sdata[it.name] = jn_value;\n return 0;\n}\n\n/***************************************************************************\n * Set array values to sdata, from json or binary\n ***************************************************************************/\nfunction json2item(gobj, sdata, it, jn_value_)\n{\n let jn_value2;\n\n switch(it.type) {\n case data_type_t.DTP_STRING:\n if(jn_value_ === null || jn_value_ === undefined) {\n /*\n * C parity: a DTP_STRING attr cannot hold a null\n * pointer, the convention is empty string. Without\n * this branch JSON.stringify(null) below produced the\n * literal 4-char string \"null\", which then leaks into\n * IEvent payloads (e.g. IDENTITY_CARD's jwt) and\n * silently breaks empty-string checks on the wire.\n */\n jn_value2 = \"\";\n } else if(is_string(jn_value_)) {\n jn_value2 = String(jn_value_);\n } else {\n let s = JSON.stringify(jn_value_);\n if(s) {\n jn_value2 = String(s);\n }\n }\n break;\n case data_type_t.DTP_BOOLEAN:\n jn_value2 = parseBoolean(jn_value_);\n break;\n case data_type_t.DTP_INTEGER:\n jn_value2 = parseInt(jn_value_);\n if(isNaN(jn_value2)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_REAL:\n jn_value2 = Number(jn_value_);\n if(isNaN(jn_value2)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_LIST:\n if(is_string(jn_value_)) {\n try {\n jn_value2 = JSON.parse(jn_value_);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value2 = jn_value_;\n }\n if(!is_array(jn_value2)) {\n log_error(`attr must be an array: ${it.name}`);\n return -1;\n }\n break;\n\n case data_type_t.DTP_DICT:\n if(is_string(jn_value_)) {\n try {\n jn_value2 = JSON.parse(jn_value_);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value2 = jn_value_;\n }\n if(!is_object(jn_value2)) {\n log_error(`attr must be an object: ${it.name}`);\n return -1;\n }\n break;\n\n case data_type_t.DTP_JSON:\n if(is_string(jn_value_)) {\n try {\n jn_value2 = JSON.parse(jn_value_);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value2 = jn_value_;\n }\n if(!is_array(jn_value2) && !is_object(jn_value2)) {\n log_error(`attr must be a json dict/list: ${it.name}`);\n return -1;\n }\n break;\n\n case data_type_t.DTP_POINTER:\n jn_value2 = jn_value_;\n break;\n }\n\n if(jn_value2 === undefined) {\n log_error(`${gobj_short_name(gobj)}: attr undefined: ${it.name}`);\n }\n\n sdata[it.name] = jn_value2;\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) {\n gobj.priv[it.name] = jn_value2;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, it.name);\n }\n }\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_hsdata(gobj)\n{\n return gobj.jn_attrs;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_hsdata2(gobj, name, verbose)\n{\n if(gobj_has_attr(gobj, name)) {\n return gobj_hsdata(gobj);\n } else if(gobj && gobj.bottom_gobj) {\n return gobj_hsdata2(gobj.bottom_gobj, name, verbose);\n }\n if(verbose) {\n log_error(`GClass Attribute NOT FOUND: ${gobj_short_name(gobj)}, attr ${name}`);\n }\n return null;\n}\n\n/***************************************************************************\n * Return the data description of the attribute `attr`\n * If `attr` is null returns full attr's table\n ***************************************************************************/\nfunction gclass_attr_desc(gclass, attr, verbose)\n{\n if(!gclass || !(gclass instanceof GClass)) {\n if(verbose) {\n log_error(`gclass NULL`);\n }\n return null;\n }\n\n if(!attr) {\n return gclass.attrs_table;\n }\n\n for(let i=0; i < gclass.attrs_table.length; i++) {\n const it = gclass.attrs_table[i];\n if (it.name && it.name === attr) {\n return it;\n }\n }\n\n if(verbose) {\n log_error(`${gclass.gclass_name}: GClass Attribute NOT FOUND: ${attr}`);\n }\n return null;\n}\n\n/************************************************************\n * create and register gclass\n ************************************************************/\nfunction gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n lmt,\n attrs_table,\n priv,\n authz_table,\n command_table,\n s_user_trace_level,\n gclass_flag\n) {\n if(empty_string(gclass_name)) {\n log_error(`gclass_name EMPTY`);\n return null;\n }\n if (gclass_name.includes('`') ||\n gclass_name.includes('^') ||\n gclass_name.includes('.'))\n {\n log_error(`GClass name CANNOT have '.' or '^' or '\\`' char: ${gclass_name}`);\n return null;\n }\n if(gclass_find_by_name(gclass_name)) {\n log_error(`GClass ALREADY exists: ${gclass_name}`);\n return null;\n }\n let gclass = new GClass(\n gclass_name,\n gmt,\n lmt,\n attrs_table,\n priv,\n authz_table,\n command_table,\n s_user_trace_level,\n gclass_flag\n );\n\n _register_gclass(gclass, gclass_name);\n\n /*----------------------------------------*\n * Build States\n *----------------------------------------*/\n const states_size = states.length;\n for (let i = 0; i < states_size; i++) {\n let state_name = states[i][0]; // First element is state name\n let ev_action_list = states[i][1]; // Second element is the array of actions\n\n if(empty_string(state_name)) {\n continue;\n }\n if(gclass_add_state(gclass, state_name)<0) {\n // Error already logged\n gclass_unregister(gclass);\n return null;\n }\n\n const ev_action_size = ev_action_list.length;\n for (let j = 0; j < ev_action_size; j++) {\n let event_name = ev_action_list[j][0];\n let action = ev_action_list[j][1];\n let next_state = ev_action_list[j][2];\n\n if(empty_string(event_name)) {\n continue;\n }\n gclass_add_ev_action(\n gclass,\n state_name,\n event_name,\n action,\n next_state\n );\n }\n }\n\n /*----------------------------------------*\n * Build Events\n *----------------------------------------*/\n for (let i = 0; i < event_types.length; i++) {\n let event_name = event_types[i][0];\n let event_type = event_types[i][1];\n\n if(empty_string(event_name)) {\n continue;\n }\n if(gclass_event_type(gclass, event_name)) {\n log_error(`SMachine: event repeated in input_events: ${event_name}`);\n gclass_unregister(gclass);\n return null;\n }\n\n gclass_add_event_type(gclass, event_name, event_type);\n }\n\n /*----------------------------------------*\n * Check FSM\n *----------------------------------------*/\n if(!gclass.fsm_checked) {\n if(gclass_check_fsm(gclass)<0) {\n gclass_unregister(gclass);\n return null;\n }\n gclass.fsm_checked = true;\n }\n\n return gclass;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_unregister(gclass)\n{\n let gclass_name;\n if(is_string(gclass)) {\n gclass_name = gclass;\n } else if(gclass instanceof GClass) {\n gclass_name = gclass.gclass_name;\n } else {\n log_error(`Cannot unregister gclass, type unknown`);\n return -1;\n }\n\n let gclass_ = _gclass_register[gclass_name];\n if(!gclass_) {\n log_error(`Cannot unregister gclass, not found: ${gclass_name}`);\n return -1;\n }\n if(gclass_.instances > 0) {\n log_error(`Cannot unregister gclass, instances in use: ${gclass_name}`);\n return -1;\n }\n\n delete _gclass_register[gclass_name];\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction _find_state(gclass, state_name)\n{\n const size = gclass.dl_states.length;\n const dl = gclass.dl_states;\n\n for(let i=0; i<size; i++) {\n let state = dl[i];\n if(state.state_name && state.state_name === state_name) {\n return state;\n }\n }\n return null;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction _find_event_action(state, event_name)\n{\n const size = state.dl_actions.length;\n const dl = state.dl_actions;\n\n for(let i=0; i<size; i++) {\n let event_action = dl[i];\n if(event_action.event_name && event_action.event_name === event_name) {\n return event_action;\n }\n }\n return null;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_add_state(gclass, state_name)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n if(_find_state(gclass, state_name)) {\n log_error(`state already exists: ${state_name}`);\n return -1;\n }\n\n gclass.dl_states.push(new State(state_name));\n\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_add_ev_action(\n gclass,\n state_name,\n event_name,\n action,\n next_state\n)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n if(empty_string(state_name)) {\n log_error(`state_name EMPTY`);\n return -1;\n }\n\n let state = _find_state(gclass, state_name);\n if(!state) {\n log_error(`state not found: ${state_name}`);\n return -1;\n }\n\n if(_find_event_action(state, event_name)) {\n log_error(`event already exists: gclass ${gclass.gclass_name}, state ${state_name}, event ${event_name}`);\n return -1;\n }\n\n state.dl_actions.push(new Event_Action(event_name, action, next_state));\n\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction _add_event_type(dl, event_name, event_flag)\n{\n if(!empty_string(event_name)) {\n dl.push(new Event_Type(event_name, event_flag));\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_add_event_type(gclass, event_name, event_flag)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n return _add_event_type(gclass.dl_events, event_name, event_flag);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_event_type(gclass, event_name)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return 0;\n }\n\n const size = gclass.dl_events.length;\n const dl = gclass.dl_events;\n\n for(let i=0; i<size; i++) {\n let event_type = dl[i];\n if(event_type.event_name && event_type.event_name === event_name) {\n return event_type;\n }\n }\n\n return null;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_check_fsm(gclass)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n let ret = 0;\n\n /*\n * check states\n */\n if(!json_array_size(gclass.dl_states)) {\n log_error(`GClass without states: ${gclass.gclass_name}`);\n ret += -1;\n }\n\n /*\n * check state's event in input_list\n */\n for(let i=0; i<gclass.dl_states.length; i++) {\n let state = gclass.dl_states[i];\n if(empty_string(state.state_name)) {\n continue;\n }\n // gobj_state_t state_name;\n // dl_list_t dl_actions;\n\n for(let j=0; j<state.dl_actions.length; j++) {\n let event_action = state.dl_actions[j];\n if(empty_string(event_action.event_name)) {\n continue;\n }\n // gobj_event_t event_name;\n // gobj_action_fn action;\n // gobj_state_t next_state;\n let event_type = gclass_event_type(gclass, event_action.event_name);\n if(!event_type) {\n log_error(`SMachine: state's event NOT in input_events: gclass ${gclass.gclass_name}, state ${state.state_name}, event ${event_action.event_name}`);\n ret += -1;\n }\n\n if(event_action.next_state) {\n let next_state = _find_state(gclass, event_action.next_state);\n if(!next_state) {\n log_error(`SMachine: next state NOT in state names: gclass ${gclass.gclass_name}, state ${state.state_name}, next_state ${event_action.next_state}`);\n ret += -1;\n }\n }\n }\n }\n\n /*\n * check input_list's event in state\n */\n for(let i=0; i<gclass.dl_events.length; i++) {\n let event_type = gclass.dl_events[i];\n if(empty_string(event_type.event_name)) {\n continue;\n }\n // gobj_event_t event_type.event_name;\n // event_flag_t event_type.event_flag;\n if(!is_number(event_type.event_flag)) {\n log_error(`SMachine: event flag is NOT number: gclass ${gclass.gclass_name}, event ${event_type.event_name}`);\n ret += -1;\n }\n if(!(event_type.event_flag & event_flag_t.EVF_OUTPUT_EVENT)) {\n let found = false;\n\n for(let j=0; j<gclass.dl_states.length; j++) {\n let state = gclass.dl_states[j];\n if(empty_string(state.state_name)) {\n continue;\n }\n let event_action = _find_event_action(state, event_type.event_name);\n if(event_action) {\n found = true;\n }\n }\n\n if(!found) {\n log_error(`SMachine: input_list's event NOT in state: gclass ${gclass.gclass_name}, event ${event_type.event_name}`);\n ret += -1;\n }\n }\n }\n\n return ret;\n}\n\n/************************************************************\n * Find gclass\n ************************************************************/\nfunction gclass_find_by_name(gclass_name, verbose)\n{\n let gclass = null;\n try {\n gclass = _gclass_register[gclass_name];\n } catch (e) {\n }\n if(!gclass) {\n if(verbose) {\n log_error(`gclass not found: ${gclass_name}`);\n }\n /*\n * NULL, not undefined: a missing key answers `undefined`, and a\n * caller writing the obvious `gclass_find_by_name(\"X\") === null`\n * then gets FALSE for a gclass that is not there. gobj-ui had four\n * guards written exactly like that -- one of them the \"not\n * registered by the app\" message that could therefore never print,\n * leaving a missing gclass to surface as \"can't access property\n * jn_attrs, e is null\" from whoever used what gobj_create refused\n * to build.\n */\n return null;\n }\n return gclass;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_services()\n{\n let jn_register = [];\n\n for(const key of Object.keys(__jn_services__)) {\n json_array_append_new(jn_register, key);\n }\n\n return jn_register;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_default_service()\n{\n if(!__default_service__ || (__default_service__.obflag & obflag_t.obflag_destroyed)) {\n return null;\n }\n return __default_service__;\n}\n\n/************************************************************\n * find a service\n ************************************************************/\nfunction gobj_find_service(\n service_name,\n verbose\n)\n{\n service_name = service_name.toLowerCase();\n let service_gobj = __jn_services__[service_name];\n if(!service_gobj) {\n if(verbose) {\n log_error(`gobj service not found: ${service_name}`);\n }\n /*\n * Same contract as gclass_find_by_name: ALWAYS null when there is\n * no service. It used to answer `null` with verbose and `undefined`\n * without it -- the same absent service giving a different falsy\n * value depending on a logging flag -- and handing that undefined\n * to a DTP_POINTER attr logs \"attr undefined\" on every use.\n */\n return null;\n }\n return service_gobj;\n}\n\n/************************************************************\n * register a service\n ************************************************************/\nfunction _register_service(gobj)\n{\n let service_name = gobj_name(gobj);\n service_name = service_name.toLowerCase();\n if(__jn_services__[service_name]) {\n log_error(`service ALREADY REGISTERED: ${service_name}. Will be UPDATED`);\n }\n __jn_services__[service_name] = gobj;\n return 0;\n}\n\n/************************************************************\n * deregister a service\n ************************************************************/\nfunction _deregister_service(gobj)\n{\n let service_name = gobj_name(gobj);\n service_name = service_name.toLowerCase();\n if(!__jn_services__[service_name]) {\n log_error(`\"service NOT found in register\": ${service_name}`);\n return -1;\n }\n delete __jn_services__[service_name];\n return 0;\n}\n\n/************************************************************\n * add child.\n ************************************************************/\nfunction _add_child(parent, child)\n{\n if(child.parent) {\n log_error(`_add_child() ALREADY HAS PARENT: ${child.gobj_name}`);\n }\n parent.dl_children.push(child);\n child.parent = parent;\n}\n\n/************************************************************\n * remove child\n ************************************************************/\nfunction _remove_child(parent, child)\n{\n let index = index_in_list(parent.dl_children, child);\n if (index >= 0) {\n json_array_remove(parent.dl_children, index);\n child.parent = null;\n }\n}\n\n/************************************************************\n * Example how change CONFIG of a gclass (temporarily)\n *\n let CONFIG = gobj_get_gclass_config(\"Ka_scrollview\", true);\n let old_dragging = CONFIG.draggable;\n CONFIG.draggable = true;\n\n let gobj_ka_scrollview = self.yuno.gobj_create(\n \"xxx\",\n Ka_scrollview,\n {\n ...\n },\n self // this will provoke EV_SHOWED,EV_KEYDOWN\n );\n\n CONFIG.draggable = old_dragging;\n\n ************************************************************/\nfunction gobj_get_gclass_config(gclass_name, verbose)\n{\n let gclass = gclass_find_by_name(gclass_name, verbose);\n if(gclass && gclass.gmt.mt_get_gclass_config) {\n return gclass.gmt.mt_get_gclass_config.call();\n } else {\n if(verbose) {\n log_error(sprintf(\n \"gobj_get_gclass_config: '%s' gclass without mt_get_gclass_config\", gclass_name\n ));\n }\n return null;\n }\n}\n\n/************************************************************\n * Only gobj services can load/save persistent attrs.\n * WARNING: persistent attrs are loaded automatically in the creation of gobjs\n ************************************************************/\nfunction gobj_load_persistent_attrs(\n gobj,\n keys // str, list or dict.\n) {\n if(!gobj_is_service(gobj)) {\n log_error(`${gobj_short_name(gobj)}: Only gobj services can load/save writable-persistent`);\n return -1;\n }\n if(__global_load_persistent_attrs_fn__) {\n return __global_load_persistent_attrs_fn__(gobj, keys);\n }\n return -1;\n}\n\n/************************************************************\n * Only gobj services can load/save persistent attrs.\n ************************************************************/\nfunction gobj_save_persistent_attrs(\n gobj,\n keys // str, list or dict.\n) {\n if(!gobj_is_service(gobj)) {\n log_error(`${gobj_short_name(gobj)}: Only gobj services can load/save writable-persistent`);\n return -1;\n }\n if(__global_save_persistent_attrs_fn__) {\n return __global_save_persistent_attrs_fn__(gobj, keys);\n }\n return -1;\n}\n\n/************************************************************\n * Only gobj services can load/save persistent attrs.\n ************************************************************/\nfunction gobj_remove_persistent_attrs(\n gobj,\n keys // str, list or dict.\n) {\n\n if(!gobj_is_service(gobj)) {\n log_error(`${gobj_short_name(gobj)}: Only gobj services can load/save writable-persistent`);\n return -1;\n }\n if(!__global_remove_persistent_attrs_fn__) {\n return -1;\n }\n return __global_remove_persistent_attrs_fn__(gobj, keys);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_list_persistent_attrs(gobj, keys)\n{\n if(!__global_list_persistent_attrs_fn__) {\n return null;\n }\n return __global_list_persistent_attrs_fn__(gobj, keys);\n}\n\n/************************************************************\n * Update existing in first level, and all in next levels\n ************************************************************/\nfunction _json_object_update_config(destination, source) {\n if(!source) {\n return destination;\n }\n for (let property in source) {\n if (source.hasOwnProperty(property) && destination.hasOwnProperty(property)) {\n if(is_object(destination[property]) && is_object(source[property])) {\n json_object_update(\n destination[property],\n source[property]\n );\n } else {\n destination[property] = source[property];\n }\n }\n }\n return destination;\n}\n\n/***************************************************************************\n * ATTR:\n ***************************************************************************/\nfunction print_attr_not_found(gobj, name)\n{\n if(name !== \"__json_config_variables__\") {\n log_error(`GClass Attribute NOT FOUND: ${gobj_short_name(gobj)}, attr ${name}`);\n }\n}\n\n/***************************************************************************\n * Update sdata fields from a json dict.\n * Constraint: if flag is -1\n * => all fields!\n * else\n * => matched flag\n ***************************************************************************/\nfunction json2sdata(\n hsdata,\n kw, // not owned\n flag,\n not_found_cb, // Called when the key not exist in hsdata\n gobj)\n{\n if(!hsdata || !kw) {\n log_error(`hsdata or kw NULL`);\n return -1;\n }\n let ret = 0;\n\n for (const [key, jn_value] of Object.entries(kw)) {\n const it = gclass_attr_desc(gobj.gclass, key, false);\n if(!it) {\n if(not_found_cb) {\n not_found_cb(gobj, key);\n ret--;\n }\n continue;\n }\n if(!(flag === -1 || (it.flag & flag))) {\n continue;\n }\n if(it.flag & sdata_flag_t.SDF_DEPRECATED) {\n log_warning(`${gobj_short_name(gobj)}: Deprecated attribute used in gobj creation: ${key}`);\n }\n ret += json2item(gobj, hsdata, it, jn_value);\n }\n\n return ret;\n}\n\n/************************************************************\n * ATTR:\n * Get data from json kw parameter,\n * and put the data in config sdata.\n ************************************************************/\nfunction write_json_parameters(gobj, kw, jn_global)\n{\n let hs = gobj_hsdata(gobj);\n let new_kw = kw; // kw_apply_json_config_variables(kw, jn_global_mine);\n\n let ret = json2sdata(\n hs,\n new_kw,\n -1,\n (gobj.gclass.gclass_flag & gclass_flag_t.gcflag_ignore_unknown_attrs)?0:print_attr_not_found,\n gobj\n );\n if(ret < 0) {\n log_error(`${gobj_short_name(gobj)} json2data() FAILED`);\n trace_json(new_kw);\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag\n) {\n /*--------------------------------*\n * Check parameters\n *--------------------------------*/\n if(gobj_flag & (gobj_flag_t.gobj_flag_yuno)) {\n if(__yuno__) {\n log_error(`__yuno__ already created`);\n return null;\n }\n gobj_flag |= gobj_flag_t.gobj_flag_service;\n\n } else {\n if(!parent) {\n log_error(`gobj NEEDS a parent!`);\n return null;\n }\n\n if(!(typeof parent === 'string' || parent instanceof GObj)) {\n log_error(`BAD TYPE of parent: ${parent}`);\n return null;\n }\n\n if(is_string(parent)) {\n // find the named gobj\n parent = gobj_find_service(parent);\n if (!parent) {\n log_warning(`parent service not found: ${parent}`);\n return null;\n }\n }\n }\n\n if(gobj_flag & (gobj_flag_t.gobj_flag_service)) {\n if(gobj_find_service(gobj_name, false)) {\n log_error(`service ALREADY registered: ${gclass_name}^${gobj_name}`);\n return null;\n }\n }\n\n if(gobj_flag & (gobj_flag_t.gobj_flag_default_service)) {\n if(__default_service__) {\n log_error(`default service ALREADY registered: ${gclass_name}^${gobj_name}`);\n return null;\n }\n gobj_flag |= gobj_flag_t.gobj_flag_service;\n }\n\n if(empty_string(gclass_name)) {\n log_error(`gclass_name must be a string`);\n return null;\n }\n let gclass = gclass_find_by_name(gclass_name, false);\n if(!gclass) {\n log_error(`GClass not registered: ${gclass_name}^${gobj_name}`);\n return null;\n }\n if(!is_string(gobj_name)) {\n log_error(`gobj_name must be a string: ${gclass_name}`);\n return null;\n }\n\n if(!empty_string(gobj_name)) {\n /*\n * Check that the gobj_name: cannot contain `\n */\n if(gobj_name.includes('`')) {\n log_error(`gobj_name cannot contain char \\': ${gclass_name}^${gobj_name}`);\n return null;\n }\n /*\n * Check that the gobj_name: cannot contain ^\n */\n if(gobj_name.includes('^')) {\n log_error(`gobj_name cannot contain char ^: ${gclass_name}^${gobj_name}`);\n return null;\n }\n }\n\n /*--------------------------------*\n * Alloc memory\n * Initialize variables\n *--------------------------------*/\n let gobj = new GObj(gobj_name, gclass, kw, parent, gobj_flag);\n gobj.jn_attrs = sdata_create(gobj, gclass.attrs_table);\n\n // Now mt_writing is only informative, not needed to update priv\n for(const [key, value] of Object.entries(gobj.jn_attrs)) {\n if(key in gobj.priv) {\n gobj.priv[key] = value;\n }\n }\n\n let trace_creation = __trace_gobj_create_delete__(gobj);\n if(trace_creation) {\n trace_machine(sprintf(\"💙💙⏩ creating: %s^%s\",\n gclass.gclass_name, gobj_name\n ));\n }\n\n /*--------------------------*\n * Register service\n *--------------------------*/\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_service)) {\n _register_service(gobj);\n }\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_yuno)) {\n __yuno__ = gobj;\n }\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_default_service)) {\n __default_service__ = gobj;\n }\n\n /*--------------------------------------*\n * Add to parent\n *--------------------------------------*/\n if(!(gobj.gobj_flag & (gobj_flag_t.gobj_flag_yuno))) {\n _add_child(parent, gobj);\n }\n\n /*--------------------------------*\n * Mark as created\n *--------------------------------*/\n gobj.obflag |= obflag_t.obflag_created;\n gobj.gclass.instances++;\n\n /*--------------------------------*\n * Write configuration\n * WARNING collateral damage:\n * write_json_parameters was before Mark as created!\n *--------------------------------*/\n write_json_parameters(gobj, kw, __jn_global_settings__);\n\n /*--------------------------------------*\n * Load writable and persistent attrs\n * of services and __root__\n *--------------------------------------*/\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_service)) {\n if(__global_load_persistent_attrs_fn__) {\n __global_load_persistent_attrs_fn__(gobj, null);\n }\n }\n\n /*--------------------------------*\n * Exec mt_create\n *--------------------------------*/\n if(gobj.gclass.gmt.mt_create2) {\n gobj.gclass.gmt.mt_create2(gobj, kw);\n } else if(gobj.gclass.gmt.mt_create) {\n gobj.gclass.gmt.mt_create(gobj);\n }\n\n /*--------------------------------------*\n * Inform to parent\n * when the child is full operative\n *-------------------------------------*/\n if(parent && parent.gclass.gmt.mt_child_added) {\n if(trace_creation) {\n trace_machine(sprintf(\n \"👦👦🔵 child_added(%s): %s\",\n gobj_full_name(parent),\n gobj_short_name(gobj)\n ));\n }\n parent.gclass.gmt.mt_child_added(parent, gobj);\n }\n\n if(trace_creation) {\n trace_machine(sprintf(\"💙💙⏪ created: %s\", gobj_full_name(gobj)));\n }\n\n return gobj;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_create_yuno(\n gobj_name,\n gclass_name,\n kw\n) {\n return gobj_create2(gobj_name, gclass_name, kw, null, gobj_flag_t.gobj_flag_yuno);\n}\n\nfunction gobj_create_service(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(gobj_name, gclass_name, kw, parent, gobj_flag_t.gobj_flag_service);\n}\n\nfunction gobj_create_default_service(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag_t.gobj_flag_default_service|gobj_flag_t.gobj_flag_autostart\n );\n}\n\nfunction gobj_create_volatil(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag_t.gobj_flag_volatil\n );\n}\n\nfunction gobj_create_pure_child(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag_t.gobj_flag_pure_child\n );\n}\n\nfunction gobj_create(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n 0\n );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_destroy(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return;\n }\n\n /*--------------------------------*\n * Check parameters\n *--------------------------------*/\n if(gobj.__refs__ > 0) {\n log_error(`${gobj_short_name(gobj)}: gobj DESTROYING with references: ${gobj.__refs__}`);\n }\n /*--------------------------------------------------------*\n * Pause and Stop\n *\n * BEFORE raising obflag_destroying, and that order is the\n * whole point: gobj_pause() and gobj_stop() refuse a gobj\n * that is already destroying -- rightly so, nobody OUTSIDE\n * may stop something already being dismantled -- so doing\n * this after the flag logged \"gobj NULL or DESTROYED\" and\n * quietly skipped mt_pause / mt_stop: the gobj was taken\n * apart without ever releasing its timers, subscriptions\n * and DOM listeners. The two errors below are still loud:\n * destroying a live gobj remains the CALLER's bug, and the\n * fix there is gobj_stop_tree() before gobj_destroy().\n * What changed is that the rescue now runs instead of\n * pretending to.\n *\n * Quiescing first also means mt_stop() sees exactly what an\n * orderly stop sees -- it matters for a gclass that stops\n * its children there, since that path carries the same\n * destroying guard.\n *--------------------------------------------------------*/\n if(gobj.playing) {\n log_error(`Destroying a PLAYING gobj: ${gobj_full_name(gobj)}`);\n gobj_pause(gobj);\n }\n if(gobj.running) {\n log_error(`Destroying a RUNNING gobj: ${gobj_full_name(gobj)}`);\n gobj_stop(gobj);\n }\n\n gobj.obflag |= obflag_t.obflag_destroying;\n\n /*\n * AFTER the flag, so it also takes what mt_stop() may have posted\n * above: from here on gobj_post_event() refuses this gobj.\n */\n purge_posted_events(gobj);\n\n let trace_creation = __trace_gobj_create_delete__(gobj);\n if(trace_creation) {\n trace_machine(sprintf(\"💔💔⏩ destroying: %s\", gobj_full_name(gobj)));\n }\n\n /*----------------------------------------------*\n * Inform to parent now,\n * when the child is NOT still full operative\n *----------------------------------------------*/\n let parent = gobj_parent(gobj);\n if(parent && parent.gclass.gmt.mt_child_removed) {\n if(trace_creation) {\n trace_machine(sprintf(\"👦👦🔴 child_removed(%s): %s\",\n gobj_full_name(parent),\n gobj_short_name(gobj)\n ));\n }\n parent.gclass.gmt.mt_child_removed(parent, gobj);\n }\n\n /*--------------------------------*\n * Deregister if service\n *--------------------------------*/\n if(gobj.gobj_flag & gobj_flag_t.gobj_flag_service) {\n _deregister_service(gobj);\n }\n\n /*--------------------------------*\n * Delete subscriptions\n *--------------------------------*/\n gobj_unsubscribe_list(gobj, gobj.dl_subscriptions, true);\n gobj_unsubscribe_list(gobj, gobj.dl_subscribings, true);\n\n /*--------------------------------*\n * Delete from parent\n *--------------------------------*/\n if(parent) {\n _remove_child(parent, gobj);\n if(gobj_is_volatil(gobj)) {\n if(gobj_bottom_gobj(parent) === gobj &&\n !gobj_is_destroying(parent))\n {\n gobj_set_bottom_gobj(parent, null);\n }\n }\n }\n\n /*--------------------------------*\n * Delete children\n *--------------------------------*/\n gobj_destroy_children(gobj);\n\n /*-------------------------------------------------*\n * Exec mt_destroy\n * Call this after all children are destroyed.\n * Then you can delete resources used by children\n * (example: event_loop in main/threads)\n *-------------------------------------------------*/\n if(gobj.obflag & obflag_t.obflag_created) {\n if(gobj.gclass.gmt.mt_destroy) {\n gobj.gclass.gmt.mt_destroy(gobj);\n }\n }\n\n /*--------------------------------*\n * Mark as destroyed\n *--------------------------------*/\n if(trace_creation) {\n trace_machine(sprintf(\"💔💔⏪ destroyed: %s\", gobj_full_name(gobj)));\n }\n gobj.obflag |= obflag_t.obflag_destroyed;\n\n /*--------------------------------*\n * Dealloc data\n *--------------------------------*/\n if(gobj.obflag & obflag_t.obflag_created) {\n gobj.gclass.instances--;\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_destroy_children(gobj)\n{\n let dl_children = gobj.dl_children.slice();\n\n for(let i=0; i < dl_children.length; i++) {\n let child = dl_children[i];\n if (!gobj_is_destroying(child)) {\n gobj_destroy(child);\n }\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_start(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(gobj.running) {\n log_error(`${gobj_short_name(gobj)}: GObj ALREADY RUNNING`);\n return -1;\n }\n if(gobj.disabled) {\n log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);\n return -1;\n }\n\n /*\n * TODO Check required attributes.\n */\n // json_t *jn_required_attrs = gobj_check_required_attrs(gobj);\n // if(jn_required_attrs) {\n // gobj_log_error(gobj, LOG_OPT_TRACE_STACK,\n // \"function\", \"%s\", __FUNCTION__,\n // \"msgset\", \"%s\", MSGSET_OPERATIONAL_ERROR,\n // \"msg\", \"%s\", \"Cannot start without all required attributes\",\n // \"attrs\", \"%j\", jn_required_attrs,\n // NULL\n // );\n // JSON_DECREF(jn_required_attrs)\n // return -1;\n // }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏺ ⏺ start: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.running = true;\n\n let ret = 0;\n if(gobj.gclass.gmt.mt_start) {\n ret = gobj.gclass.gmt.mt_start(gobj);\n }\n return ret;\n}\n\n/***************************************************************************\n * Start all children of the gobj.\n ***************************************************************************/\nfunction cb_start_child(child, user_data, user_data2)\n{\n if(child.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start) {\n return 0;\n }\n if(!gobj_is_destroying(child) && !gobj_is_running(child) && !gobj_is_disabled(child)) {\n gobj_start(child);\n }\n return 0;\n}\nfunction gobj_start_children(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n return gobj_walk_gobj_children(gobj, walk_type_t.WALK_FIRST2LAST, cb_start_child, 0, 0);\n}\n\n/***************************************************************************\n * Start this gobj and all children tree of the gobj.\n ***************************************************************************/\nfunction cb_start_child_tree(child, user_data, user_data2)\n{\n if(child.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start) {\n return 1;\n }\n if(gobj_is_disabled(child)) {\n return 1;\n }\n if(!gobj_is_running(child)) {\n gobj_start(child);\n }\n return 0;\n}\nfunction gobj_start_tree(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏺ ⏺ ⏺ ⏺ start_tree: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n if((gobj.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start)) {\n return 0;\n } else if(gobj.disabled) {\n return 0;\n } else {\n if(!gobj.running) {\n gobj_start(gobj);\n }\n }\n return gobj_walk_gobj_children_tree(gobj, walk_type_t.WALK_TOP2BOTTOM, cb_start_child_tree, 0, 0);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_stop(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(!gobj.running) {\n log_error(`${gobj_short_name(gobj)}: GObj NOT RUNNING`);\n return -1;\n }\n if(gobj.playing) {\n // It's auto-stopping but display error (magic but warn!).\n log_warning(`${gobj_short_name(gobj)}: GObj stopping without previous pause`);\n gobj_pause(gobj);\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏹ ⏹ stop: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.running = false;\n\n let ret = 0;\n if(gobj.gclass.gmt.mt_stop) {\n ret = gobj.gclass.gmt.mt_stop(gobj);\n }\n\n return ret;\n}\n\n/***************************************************************************\n * Stop all children of the gobj.\n ***************************************************************************/\nfunction cb_stop_child(child, user_data, user_data2)\n{\n if(gobj_is_running(child)) {\n gobj_stop(child);\n }\n return 0;\n}\nfunction gobj_stop_children(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n return gobj_walk_gobj_children(gobj, walk_type_t.WALK_FIRST2LAST, cb_stop_child, 0, 0);\n}\n\n/***************************************************************************\n * Stop this gobj and all children tree of the gobj.\n ***************************************************************************/\nfunction gobj_stop_tree(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏹ ⏹ ⏹ ⏹ stop_tree: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n if(gobj_is_running(gobj)) {\n gobj_stop(gobj);\n }\n return gobj_walk_gobj_children_tree(gobj, walk_type_t.WALK_TOP2BOTTOM, cb_stop_child, 0, 0);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_play(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(`gobj NULL or DESTROYED: ${gobj_short_name(gobj)}`);\n return -1;\n }\n if(gobj.playing) {\n log_error(`${gobj_short_name(gobj)}: GObj ALREADY PLAYING`);\n return -1;\n }\n if(gobj.disabled) {\n log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);\n return -1;\n }\n if(!gobj_is_running(gobj)) {\n if(!(gobj.gclass.gclass_flag & gclass_flag_t.gcflag_required_start_to_play)) {\n // Default: It's auto-starting but display error (magic but warn!).\n log_warning(`${gobj_short_name(gobj)}: GObj playing without previous start`);\n gobj_start(gobj);\n } else {\n log_error(`${gobj_short_name(gobj)}: Cannot play, start not done`);\n return -1;\n }\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏯ ⏯ play: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.playing = true;\n\n let ret = 0;\n if(gobj.gclass.gmt.mt_play) {\n ret = gobj.gclass.gmt.mt_play(gobj);\n /* `ret === false` too: the C contract is an int and -1 is the\n * failure, but a javascript mt_play says it with `false` — and\n * `false < 0` is FALSE, so the gobj was left PLAYING after a play\n * that failed. */\n if(ret < 0 || ret === false) {\n gobj.playing = false;\n }\n }\n return ret;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_pause(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(!gobj.playing) {\n log_error(`${gobj_short_name(gobj)}: GObj NOT PLAYING`);\n return -1;\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏸ ⏸ pause: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.playing = false;\n\n if(gobj.gclass.gmt.mt_pause) {\n return gobj.gclass.gmt.mt_pause(gobj);\n } else {\n return 0;\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_running(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n return false;\n }\n return gobj.running;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_disabled(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n return true;\n }\n return gobj.disabled;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_service(gobj)\n{\n if(gobj && (gobj.gobj_flag & (gobj_flag_t.gobj_flag_service))) {\n return true;\n } else {\n return false;\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_playing(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n return false;\n }\n return gobj.playing;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno()\n{\n if(!__yuno__ || (__yuno__.obflag & obflag_t.obflag_destroyed)) {\n return null;\n }\n return __yuno__;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno_name()\n{\n let yuno = gobj_yuno();\n if(!yuno) {\n return \"\";\n }\n return gobj_name(yuno);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno_role()\n{\n let yuno = gobj_yuno();\n if(!yuno) {\n return \"\";\n }\n return gobj_read_str_attr(yuno, \"yuno_role\");\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno_id()\n{\n let yuno = gobj_yuno();\n if(!yuno) {\n return \"\";\n }\n return gobj_read_str_attr(yuno, \"yuno_id\");\n}\n\n/***************************************************************************\n * Return name\n ***************************************************************************/\nfunction gobj_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj bad type`);\n return null;\n }\n\n return gobj.gobj_name;\n}\n\n/***************************************************************************\n * Return mach name. Same as gclass name.\n ***************************************************************************/\nfunction gobj_gclass_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n return gobj.gclass.gclass_name;\n}\n\n/************************************************************\n * get short name (gclass^name)\n ************************************************************/\nfunction gobj_short_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj bad type`);\n return null;\n }\n\n return gobj.gclass.gclass_name + '^' + gobj_name(gobj);\n}\n\n/************************************************************\n * Get full name\n ************************************************************/\nfunction gobj_full_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n let full_name = gobj_short_name(gobj);\n let parent = gobj_parent(gobj);\n while(parent) {\n let prefix = gobj_short_name(parent);\n full_name = prefix + '`' + full_name;\n parent = gobj_parent(parent);\n }\n return full_name;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_parent(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n return gobj.parent;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_volatil(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(gobj.gobj_flag & gobj_flag_t.gobj_flag_volatil) {\n return true;\n }\n return false;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_is_pure_child(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(gobj.gobj_flag & gobj_flag_t.gobj_flag_pure_child) {\n return true;\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_destroying(gobj)\n{\n if(!is_gobj(gobj)) {\n return true;\n }\n\n if(gobj.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n return true;\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_bottom_gobj(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n return gobj.bottom_gobj;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_set_bottom_gobj(gobj, bottom_gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(gobj.bottom_gobj) {\n log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);\n }\n gobj.bottom_gobj = bottom_gobj;\n}\n\n/***************************************************************************\n * Return the data description of the attribute `attr`\n * If `attr` is null returns full attr's table\n ***************************************************************************/\nfunction gobj_attr_desc(gobj, attr, verbose)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(!attr) {\n return gobj.gclass.attrs_table;\n }\n\n return gclass_attr_desc(gobj.gclass, attr, verbose);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_walk_gobj_children(\n gobj,\n walk_type, // walk_type_t\n cb_walking,\n user_data,\n user_data2\n) {\n if(gobj_is_destroying(gobj)) {\n log_error(`gobj NULL, destroying, or bad type`);\n return 0;\n }\n\n return rc_walk_by_list(gobj.dl_children, walk_type, cb_walking, user_data, user_data2);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_walk_gobj_children_tree(\n gobj,\n walk_type, // walk_type_t\n cb_walking,\n user_data,\n user_data2\n) {\n if(gobj_is_destroying(gobj)) {\n log_error(`gobj NULL, destroying, or bad type`);\n return 0;\n }\n\n return rc_walk_by_tree(gobj.dl_children, walk_type, cb_walking, user_data, user_data2);\n}\n\n/***************************************************************\n * Walking\n ***************************************************************/\n/***************************************************************\n * What a WALK CALLBACK answered, as the number the contract is\n * written in: -1 stop the walk, 0 descend into the children,\n * >0 do not descend.\n *\n * A javascript callback that simply RETURNS NOTHING is the common\n * case, and `undefined` is neither `< 0` nor `=== 0`, so the walk\n * used to read it as \"do not descend\" and skipped the subtree in\n * silence. Nothing is 0 here — the neutral answer, the one C gives\n * when an action has nothing to say.\n *\n * A boolean is NOT guessed: `true`/`false` could mean either half of\n * this contract, so it is reported and taken as 0. A walk that\n * silently loses a subtree is the thing this whole function exists\n * to stop.\n ***************************************************************/\nfunction walk_ret(ret)\n{\n if(typeof ret === \"number\" && isFinite(ret)) {\n return ret;\n }\n if(ret === undefined || ret === null) {\n return 0;\n }\n log_error(\n `walk callback must return a NUMBER (-1 stop, 0 descend, >0 skip children), ` +\n `got ${typeof ret}: taken as 0`\n );\n return 0;\n}\n\nfunction rc_walk_by_list(\n iter_, // dl_list_t\n walk_type, // walk_type_t\n cb_walking, // cb_walking_t\n user_data,\n user_data2\n) {\n /*\n * This let destroy the current item\n */\n let iter = [...iter_];\n\n let child;\n if(walk_type & walk_type_t.WALK_LAST2FIRST) {\n for(let i=iter.length; i>0; i--) {\n child = iter[i-1];\n let ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n }\n }\n } else {\n for(let i=0; i<iter.length; i++) {\n child = iter[i];\n let ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n }\n }\n }\n\n return 0;\n}\n\n/***************************************************************\n * Walking\n * If cb_walking return negative, the iter will stop.\n * Valid options:\n * WALK_BYLEVEL:\n * WALK_FIRST2LAST\n * or\n * WALK_LAST2FIRST\n ***************************************************************/\nfunction rc_walk_by_level(\n iter, // dl_list_t\n walk_type, // walk_type_t\n cb_walking, // cb_walking_t\n user_data,\n user_data2\n) {\n /*\n * First my children\n */\n let ret = rc_walk_by_list(iter, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n\n /*\n * Now child's children\n */\n let child;\n if(walk_type & walk_type_t.WALK_LAST2FIRST) {\n for(let i=iter.length; i>0; i--) {\n child = iter[i-1];\n\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_level(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n }\n } else {\n for(let i=0; i<iter.length; i++) {\n child = iter[i];\n\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_level(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n }\n }\n\n return ret;\n}\n\n/***************************************************************\n * Walking\n * If cb_walking return negative, the iter will stop.\n * return 0, continue\n * return positive, step current branch (only in WALK_TOP2BOTTOM)\n * Valid options:\n * WALK_TOP2BOTTOM\n * or\n * WALK_BOTTOM2TOP\n * or\n * WALK_BYLEVEL:\n * WALK_FIRST2LAST\n * or\n * WALK_LAST2FIRST\n ***************************************************************/\nfunction rc_walk_by_tree(\n iter, // dl_list_t\n walk_type, // walk_type_t\n cb_walking, // cb_walking_t\n user_data,\n user_data2\n) {\n if(walk_type & walk_type_t.WALK_BYLEVEL) {\n return rc_walk_by_level(iter, walk_type, cb_walking, user_data, user_data2);\n }\n\n let ret;\n let child;\n if(walk_type & walk_type_t.WALK_BOTTOM2TOP) {\n for(let i=iter.length; i>0; i--) {\n child = iter[i-1];\n\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_tree(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n\n ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n }\n\n }\n } else {\n for(let i=0; i<iter.length; i++) {\n child = iter[i];\n\n ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n } else if(ret === 0) {\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_tree(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n } else {\n // positive, continue next\n }\n }\n }\n\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction its_me(gobj, shortname)\n{\n let n = shortname.split(\"^\");\n let gobj_name_ =null;\n let gclass_name_ = null;\n if(n.length === 2) {\n gclass_name_ = n[0];\n gobj_name_ = n[1];\n if(gclass_name_ !== gobj_gclass_name(gobj)) {\n return false;\n }\n } else if(n.length === 1) {\n gobj_name_ = n[0];\n } else {\n return false;\n }\n return gobj_name_ === gobj_name(gobj);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_find_gobj(gobj, path)\n{\n if(empty_string(path)) {\n return null;\n }\n /*\n * WARNING code repeated\n */\n const path_ = path.toLowerCase();\n if(path_ === \"__default_service__\") {\n return __default_service__;\n }\n if(path_ === \"__yuno__\" || path_ === \"__root__\") {\n return __yuno__;\n }\n\n return gobj_search_path(__yuno__, path);\n}\n\n/***************************************************************************\n * Match child.\n ***************************************************************************/\nfunction gobj_match_gobj(gobj, jn_filter)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return false;\n }\n\n let __gclass_name__ = jn_filter.__gclass_name__;\n let __gobj_name__ = jn_filter.__gobj_name__;\n let __prefix_gobj_name__ = jn_filter.__prefix_gobj_name__;\n let __disabled__ = jn_filter.__disabled__;\n let __state__ = jn_filter.__state__;\n\n /*\n * Check the system keys of the jn_filter used in find loop\n */\n if(__gclass_name__) {\n if(__gclass_name__ !== gobj_gclass_name(gobj)) {\n return false;\n }\n }\n if(__gobj_name__) {\n if(__gobj_name__ !== gobj_name(gobj)) {\n return false;\n }\n }\n if(__prefix_gobj_name__) {\n let l = __prefix_gobj_name__.length;\n let name = gobj_name(gobj).substring(0, l);\n if(__prefix_gobj_name__ !== name) {\n return false;\n }\n }\n if(__state__) {\n let state = gobj_current_state(gobj);\n if(__state__ !== state) {\n return false;\n }\n }\n\n let jn_attrs = gobj.jn_attrs;\n\n for(const key of Object.keys(jn_filter)) {\n if(key === \"__gclass_name__\" ||\n key === \"__gobj_name__\" ||\n key === \"__prefix_gobj_name__\" ||\n key === \"__disabled__\" ||\n key === \"__state__\") {\n continue;\n }\n if(gobj_has_attr(gobj, key)) {\n if(jn_attrs[key] !== jn_filter[key]) {\n return false;\n }\n }\n }\n return true;\n}\n\n/***************************************************************************\n * Returns the first matched child.\n ***************************************************************************/\nfunction gobj_find_child(gobj, jn_filter)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n\n const dl_children = gobj.dl_children;\n for(let i=0; i < dl_children.length; i++) {\n const child = dl_children[i];\n if(gobj_match_gobj(child, jn_filter)) {\n return child;\n }\n }\n\n return null;\n}\n\n/************************************************************\n * Return child's list matched with kw attributes\n ************************************************************/\nfunction gobj_match_children(gobj, jn_filter)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n\n jn_filter = jn_filter || {};\n let children = [];\n\n const dl_children = gobj.dl_children;\n for(let i=0; i < dl_children.length; i++) {\n const child = dl_children[i];\n if(gobj_match_gobj(child, jn_filter)) {\n children.push(child);\n }\n }\n\n return children;\n}\n\n/************************************************************\n * Returns the matched children searching in the tree.\n ************************************************************/\nfunction gobj_match_children_tree(gobj, jn_filter)\n{\n jn_filter = jn_filter || {};\n\n function _walk_child_tree(d, o)\n {\n let dl_children = o.dl_children;\n for (let i=0; i < dl_children.length; i++) {\n let child = dl_children[i];\n if(gobj_match_gobj(child, jn_filter)) {\n d.push(child);\n }\n _walk_child_tree(d, child);\n }\n }\n\n let list = [];\n _walk_child_tree(list, gobj);\n return list;\n}\n\n/***************************************************************************\n * Return the object searched by path.\n * The separator of tree's gobj must be '`'\n ***************************************************************************/\nfunction gobj_search_path(gobj, path)\n{\n if(!path) {\n return null;\n }\n /*\n * Get node and compare with this\n */\n let p = path.split(\"`\");\n let shortname = p[0];\n if(!its_me(gobj, shortname)) {\n return null;\n }\n if(p.length===1) {\n // No more nodes\n return gobj;\n }\n\n /*\n * Get next node and compare with children\n */\n let n = p[1];\n let nn = n.split(\"^\");\n let filter = {};\n if(nn.length === 1) {\n filter.__gobj_name__ = nn;\n } else {\n filter.__gclass_name__ = nn[0];\n filter.__gobj_name__ = nn[1];\n }\n\n /*\n * Search in children\n */\n let child = gobj_find_child(gobj, filter);\n if(!child) {\n return null;\n }\n p.splice(0, 1);\n p = p.join(\"`\");\n return gobj_search_path(child, p);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_has_attr(gobj, name)\n{\n if(empty_string(name)) {\n return false; // WARNING must be a silence function!\n }\n return !!gclass_attr_desc(gobj.gclass, name, false);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_read_attr(gobj, name, src)\n{\n let jn_attrs = gobj.jn_attrs;\n\n // TODO implement inherited attributes\n // TODO if attribute not found then find in bottom gobj\n if(name in jn_attrs) {\n if(jn_attrs.hasOwnProperty(name)) {\n // TODO must be a item2json, to call mt_reading\n let value = jn_attrs[name];\n if(gobj.gclass.gmt.mt_reading) {\n return gobj.gclass.gmt.mt_reading(gobj, name, value);\n }\n return value;\n }\n }\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return null;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_attrs(\n gobj,\n include_flag, // sdata_flag_t\n src\n) {\n let jn_attrs = {};\n\n let sdata_desc = gobj.gclass.attrs_table;\n\n for(let i=0; i < sdata_desc.length; i++) {\n const it = sdata_desc[i];\n if(!it.name) {\n continue;\n }\n\n if(include_flag === -1 || (it.flag & include_flag)) {\n let value;\n if(gobj.gclass.gmt.mt_reading &&\n !(gobj.obflag & obflag_t.obflag_destroyed)) {\n value = gobj.gclass.gmt.mt_reading(gobj, it.name);\n if(value === undefined) {\n value = json_object_get(gobj.jn_attrs, it.name);\n }\n } else {\n value = json_object_get(gobj.jn_attrs, it.name);\n }\n json_object_set(jn_attrs, it.name, value);\n }\n }\n\n return jn_attrs;\n}\n\n/***************************************************************************\n * ATTR: read bool\n ***************************************************************************/\nfunction gobj_read_bool_attr(gobj, name)\n{\n if(name) {\n if(strcasecmp(name, \"__disabled__\")===0) {\n return gobj_is_disabled(gobj);\n } else if(strcasecmp(name, \"__running__\")===0) {\n return gobj_is_running(gobj);\n } else if(strcasecmp(name, \"__playing__\")===0) {\n return gobj_is_playing(gobj);\n } else if(strcasecmp(name, \"__service__\")===0) {\n return gobj_is_service(gobj);\n }\n }\n\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_integer_attr(gobj, name)\n{\n if(name && strcasecmp(name, \"__trace_level__\")===0) {\n // TODO return gobj_trace_level(gobj);\n }\n\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_str_attr(gobj, name)\n{\n if(name && strcasecmp(name, \"__state__\")===0) {\n return gobj_current_state(gobj);\n }\n\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_pointer_attr(gobj, name)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_write_attr(\n gobj,\n path, // If it has ` then segments are gobj and leaf is the attribute (+bottom)\n value,\n src\n) {\n // TODO implement inherited attributes\n // TODO if attribute not found then find in bottom gobj\n\n if(!is_string(path)) {\n log_error(sprintf(\n \"gobj_write_attr(%s): path must be a string\",\n gobj_short_name(gobj))\n );\n return -1;\n }\n let jn_attrs = gobj.jn_attrs;\n\n let ss = path.split(\"`\");\n if(ss.length<=1) {\n let key = path;\n if(key in jn_attrs) {\n if(jn_attrs.hasOwnProperty(key)) {\n jn_attrs[key] = value;\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) {\n gobj.priv[key] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, key);\n }\n }\n return 0;\n }\n }\n log_error(sprintf(\"gobj_write_attr(%s): attr not found '%s'\", gobj_short_name(gobj), key));\n return -1;\n }\n\n let key;\n let len = ss.length;\n for(let i=0; i<len; i++) {\n key = ss[i];\n let child = gobj_find_child(gobj, {\"__gobj_name__\": key});\n if(child && i<len-1) {\n gobj = child;\n continue;\n }\n\n // TODO this write in childs, is not well checked!\n let jn_attrs = gobj.jn_attrs;\n\n if(key in jn_attrs) {\n if(jn_attrs.hasOwnProperty(key)) {\n jn_attrs[key] = value;\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) {\n gobj.priv[key] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.mt_writing) {\n gobj.mt_writing(gobj, key);\n }\n }\n return 0;\n }\n }\n break;\n }\n\n log_error(sprintf(\"gobj_write_attr(%s): attr not found '%s'\", gobj_short_name(gobj), key));\n return -1;\n}\n\n/***************************************************************************\n * WRITE - high level\n ***************************************************************************/\nfunction sdata_write_default_values(\n gobj,\n include_flag, // sdata_flag_t\n exclude_flag // sdata_flag_t\n)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n let sdata_desc = gobj.gclass.attrs_table;\n\n for(let i=0; i < sdata_desc.length; i++) {\n const it = sdata_desc[i];\n if(!it.name) {\n continue;\n }\n\n if(exclude_flag && (it.flag & exclude_flag)) {\n continue;\n }\n if(include_flag === -1 || (it.flag & include_flag)) {\n const value = set_default(gobj, gobj.jn_attrs, it);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) {\n gobj.priv[it.name] = value;\n }\n\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, it.name);\n }\n }\n }\n return 0;\n}\n\n/***************************************************************************\n * ATTR: write\n * Reset volatile attributes\n ***************************************************************************/\nfunction gobj_reset_volatil_attrs(gobj)\n{\n return sdata_write_default_values(\n gobj,\n sdata_flag_t.SDF_VOLATIL, // include_flag\n 0 // exclude_flag\n );\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_attrs(\n gobj,\n kw,\n include_flag, // sdata_flag_t\n src\n) {\n let hs = gobj_hsdata(gobj);\n let ret = 0;\n for (const [attr, jn_value] of Object.entries(kw)) {\n let it = gobj_attr_desc(gobj, attr, true);\n if(!it) {\n continue;\n }\n if(!(include_flag === -1 || (it.flag & include_flag))) {\n continue;\n }\n ret += json2item(gobj, hs, it, jn_value);\n }\n\n return ret;\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_bool_attr(gobj, name, value)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n hs[name] = parseBoolean(value);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) {\n gobj.priv[name] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, name);\n }\n }\n return 0;\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return -1;\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_integer_attr(gobj, name, value)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n hs[name] = parseInt(value);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) {\n gobj.priv[name] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, name);\n }\n }\n return 0;\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return -1;\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_str_attr(gobj, name, value)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n hs[name] = String(value);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) {\n gobj.priv[name] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, name);\n }\n }\n return 0;\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return -1;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_change_state(gobj, state_name)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n\n if(gobj.current_state.state_name === state_name) {\n return false;\n }\n let new_state = _find_state(gobj.gclass, state_name);\n if(!new_state) {\n log_error(`${gobj_short_name(gobj)}: state unknown, state ${state_name}`);\n return false;\n }\n gobj.last_state = gobj.current_state;\n gobj.current_state = new_state;\n\n let tracea = is_machine_tracing(gobj, \"EV_STATE_CHANGED\");\n let tracea_states = __trace_gobj_states__(gobj) ? true : false;\n if(tracea || tracea_states) {\n if(__trace_machine_format__ === 1) {\n /* No state line, like the C kernel: in the simpler shape the\n * transition line already carries the state it ran in, and a\n * second line per change doubles the trace to say it again. */\n } else {\n trace_machine(sprintf(\"🔀🔀 mach(%s%s^%s), new st(%s), prev st(%s)\",\n (!gobj.running)?\"!!\":\"\",\n gobj_gclass_name(gobj), gobj_name(gobj),\n gobj_current_state(gobj),\n gobj.last_state.state_name\n ));\n }\n }\n\n // TODO let kw_st = {};\n // kw_st[\"previous_state\"] = gobj.last_state.state_name;\n // kw_st[\"current_state\"] = gobj.current_state.state_name;\n //\n // if(gobj.gclass.gmt.mt_state_changed) {\n // gobj.gclass.gmt.mt_state_changed(gobj, \"EV_STATE_CHANGED\", kw_st);\n // } else {\n // gobj_publish_event(gobj, \"EV_STATE_CHANGED\", kw_st);\n // }\n\n return true;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_current_state(gobj)\n{\n /*\n * Aligned with the C kernel's gobj_current_state(): only NULL-guard\n * and return the state name. A gobj being destroyed still has a\n * valid current_state, and reporting it is harmless — callers test\n * it against a state string. (Do NOT log on obflag_destroying here:\n * destroy tears down subscriptions, which calls mt_subscription_*\n * whose first line reads this; a log there is a false positive.)\n */\n if(!is_gobj(gobj)) {\n log_error(\"hgobj NULL\");\n return \"\";\n }\n\n return gobj.current_state.state_name;\n}\n\n/************************************************************\n * Change parent\n ************************************************************/\nfunction gobj_change_parent(gobj, parent)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n if(!(parent instanceof GObj)) {\n log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);\n return -1;\n }\n\n /*--------------------------------------*\n * Remove from current parent\n *--------------------------------------*/\n if (gobj.parent && gobj.parent.mt_child_removed) {\n gobj.parent.mt_child_removed(gobj.parent, gobj);\n }\n if (gobj.parent) {\n _remove_child(gobj.parent, gobj);\n gobj.parent = null;\n }\n\n /*--------------------------------------*\n * Add to new parent\n *--------------------------------------*/\n _add_child(parent, gobj);\n\n /*--------------------------------------*\n * Inform to parent\n *-------------------------------------*/\n if(parent.mt_child_added) {\n let trace_creation = __trace_gobj_create_delete__(gobj);\n if(trace_creation) {\n log_debug(sprintf(\"👦👦🔵 child_added(%s): %s\", gobj_full_name(parent), gobj_short_name(gobj)));\n }\n parent.mt_child_added(parent, gobj);\n }\n\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_event_type( // silent function\n gobj,\n event,\n include_system_events\n)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n let event_type = gclass_event_type(gobj.gclass, event);\n if(event_type) {\n return event_type;\n }\n\n if(include_system_events) {\n /*\n * Check global (gobj) output events\n */\n const size = dl_global_event_types.length;\n const dl = dl_global_event_types;\n\n for(let i=0; i<size; i++) {\n let event_type = dl[i];\n if(event_type.event_name && event_type.event_name === event) {\n return event_type;\n }\n }\n }\n\n return null;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_has_event(gobj, event, event_flag)\n{\n let event_type = gobj_event_type(gobj, event, false);\n if(!event_type) {\n return false;\n }\n\n if(event_flag && !(event_type.event_flag & event_flag)) {\n return false;\n }\n\n return true;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_has_output_event(gobj, event, event_flag)\n{\n let event_type = gobj_event_type(gobj, event, false);\n if(!event_type) {\n return false;\n }\n\n if(event_flag && !(event_type.event_flag & event_flag)) {\n return false;\n }\n\n if(!(event_type.event_flag & event_flag_t.EVF_OUTPUT_EVENT)) {\n return false;\n }\n\n return true;\n}\n\n/************************************************************\n * Posted events: gobj_send_event(), but on the next turn\n *\n * Same contract as the C side (see gobj.h). It exists to get out of the\n * stack you are standing on: gobj_publish_event() dispatches synchronously,\n * so a subscriber action runs inside the publisher's own stack, and\n * destroying that publisher there dismantles what is still iterating.\n *\n * The queue is drained with setTimeout(0) and NOT with queueMicrotask():\n * a microtask runs before the browser can paint or handle an input, so a\n * chain of posted events would hold the page exactly the way it used to\n * hold the event loop in C. A macrotask gives the browser its turn between\n * one event and the next.\n *\n * Delivery is a SNAPSHOT: the events queued when the drain begins are the\n * ones delivered in it, and whatever an action posts while it runs waits\n * for the following turn.\n ************************************************************/\nconst MAX_POSTED_EVENTS = 10000;\nlet __dl_posted_events__ = [];\nlet __posted_events_scheduled__ = false;\n\nfunction gobj_post_event(dst, event, kw, src)\n{\n if(!dst || !(dst instanceof GObj)) {\n log_error(`gobj_post_event(): gobj dst NULL, event ${event}`);\n return -1;\n }\n if(dst.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n log_error(`gobj_post_event(): gobj dst DESTROYING, event ${event}`);\n return -1;\n }\n if(empty_string(event)) {\n log_error(`gobj_post_event(): event EMPTY`);\n return -1;\n }\n\n /*\n * Checked now, not when it is delivered: otherwise the\n * \"Event NOT DEFINED in state\" arrives a turn later, with a stack that\n * points at the drain instead of at whoever posted it.\n */\n if(!gobj_has_event(dst, event, 0)) {\n log_error(\n `gobj_post_event(): event NOT DEFINED in gclass ` +\n `${gobj_gclass_name(dst)}, event ${event}`\n );\n return -1;\n }\n\n if(__dl_posted_events__.length >= MAX_POSTED_EVENTS) {\n log_error(\n `gobj_post_event(): too many posted events, this is NOT a work ` +\n `queue, event ${event}, pending ${__dl_posted_events__.length}`\n );\n return -1;\n }\n\n __dl_posted_events__.push({dst: dst, event: event, kw: kw, src: src});\n\n if(is_machine_tracing(dst, event) && !is_machine_not_tracing(src, event)) {\n trace_machine(sprintf(\"📬 posted(%s%s), ev: %s, pending: %d\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n event,\n __dl_posted_events__.length\n ));\n }\n\n if(!__posted_events_scheduled__) {\n __posted_events_scheduled__ = true;\n setTimeout(gobj_deliver_posted_events, 0);\n }\n\n return 0;\n}\n\n/************************************************************\n * How many posted events wait for delivery\n ************************************************************/\nfunction gobj_posted_events_size()\n{\n return __dl_posted_events__.length;\n}\n\n/************************************************************\n * Deliver the posted events. One turn, one snapshot.\n ************************************************************/\nfunction gobj_deliver_posted_events()\n{\n __posted_events_scheduled__ = false;\n\n let snapshot = __dl_posted_events__;\n __dl_posted_events__ = [];\n\n let delivered = 0;\n for(let msg of snapshot) {\n if(msg.dst.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n continue; // destroyed after it was queued, in this same snapshot\n }\n gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);\n delivered++;\n }\n\n /*\n * What the actions posted while this ran is already in the new list.\n */\n if(__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {\n __posted_events_scheduled__ = true;\n setTimeout(gobj_deliver_posted_events, 0);\n }\n\n return delivered;\n}\n\n/************************************************************\n * Take a gobj out of the queue of posted events.\n *\n * Called from gobj_destroy(), and the two halves are not the same thing:\n * as DESTINATION the entry is dropped, as SOURCE only the pointer is\n * cleared -- the destination still wants its event, and it arrives with\n * src null, which every action already has to accept.\n ************************************************************/\nfunction purge_posted_events(gobj)\n{\n if(__dl_posted_events__.length === 0) {\n return;\n }\n for(let msg of __dl_posted_events__) {\n if(msg.src === gobj) {\n msg.src = null;\n }\n }\n __dl_posted_events__ = __dl_posted_events__.filter(msg => msg.dst !== gobj);\n}\n\n/************************************************************\n * send_event\n ************************************************************/\nfunction gobj_send_event(dst, event, kw, src)\n{\n if(!dst || !(dst instanceof GObj)) {\n log_error(`gobj dst NULL`);\n return -1;\n }\n\n if(dst.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n log_error(`gobj dst DESTROYED`);\n return -1;\n }\n\n let state = dst.current_state;\n if(!state) {\n log_error(`${gobj_short_name(dst)}: current_state NULL`);\n return -1;\n }\n\n /*----------------------------------*\n * Find the event/action in state\n *----------------------------------*/\n let tracea = is_machine_tracing(dst, event) && !is_machine_not_tracing(src, event);\n\n __inside__ ++;\n\n let event_action = _find_event_action(state, event);\n if(!event_action) {\n if(dst.gclass.gmt.mt_inject_event) {\n __inside__ --;\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n trace_machine(sprintf(\"🔜 %s %s%s %s\",\n event?event:\"\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n state.state_name\n ));\n } else {\n trace_machine(sprintf(\"🔃 mach(%s%s), st: %s, ev: %s, from(%s%s)\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n state.state_name,\n event?event:\"\",\n (src && !src.running)?\"!!\":\"\",\n gobj_short_name(src)\n ));\n }\n if(kw) {\n if(__trace_gobj_ev_kw__(dst)) {\n if(json_object_size(kw)) {\n trace_json(kw);\n }\n }\n }\n }\n return dst.gclass.gmt.mt_inject_event(dst, event, kw, src);\n }\n\n if(tracea) {\n trace_machine(sprintf(\n \"📛 mach(%s%s^%s), st: %s, ev: %s, 📛📛ERROR Event NOT DEFINED in state📛📛, from(%s%s^%s)\",\n (!dst.running)?\"!!\":\"\",\n gobj_gclass_name(dst), gobj_name(dst),\n state.state_name,\n event?event:\"\",\n (src && !src.running)?\"!!\":\"\",\n gobj_gclass_name(src), gobj_name(src)\n ));\n }\n log_error(`📛📛 Event NOT DEFINED in state 📛📛: ${gobj_short_name(dst)}, ${state.state_name}, ${event}`);\n\n __inside__ --;\n\n return -1;\n }\n\n /*----------------------------------*\n * Check AUTHZ\n *----------------------------------*/\n// if(ev_desc.authz & EV_AUTHZ_INJECT) {\n// }\n\n /*----------------------------------*\n * Exec the event\n *----------------------------------*/\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n /* Compact one-liner, like the C kernel's trace_machine_format==1. */\n trace_machine(sprintf(\"🔄 %s %s%s %s from %s%s\",\n event?event:\"\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n state.state_name,\n (src && !src.running)?\"!!\":\"\",\n gobj_short_name(src)\n ));\n } else {\n let action_name = \"\";\n if(event_action.action) {\n action_name = get_function_name(event_action.action);\n }\n trace_machine(sprintf(\"🔄 mach(%s%s^%s), st: %s, ev: %s%s%s, ac: %s, from(%s%s^%s)\",\n (!dst.running)?\"!!\":\"\",\n gobj_gclass_name(dst), gobj_name(dst),\n state.state_name,\n \"\", //On_Black RBlue,\n event?event:\"\",\n \"\", //Color_Off,\n action_name,\n (src && !src.running)?\"!!\":\"\",\n gobj_gclass_name(src), gobj_name(src)\n ));\n }\n if(kw) {\n if(__trace_gobj_ev_kw__(dst)) {\n if(json_object_size(kw)) {\n trace_json(kw);\n }\n }\n }\n }\n\n /*\n * IMPORTANT HACK\n * Set new state BEFORE run 'action'\n *\n * The next state is changed before executing the action.\n * If you don’t like this behavior, set the next-state to NULL\n * and use change_state() to change the state inside the actions.\n */\n if(event_action.next_state) {\n gobj_change_state(dst, event_action.next_state);\n }\n\n let ret = -1;\n try {\n if(event_action.action) {\n // Execute the action\n ret = (event_action.action)(dst, event, kw, src);\n } else {\n // No action, there is nothing amiss!.\n }\n } finally {\n }\n\n if(tracea && __trace_machine_format__ !== 1 && !(dst.obflag & obflag_t.obflag_destroyed)) {\n trace_machine(sprintf(\"<- mach(%s%s^%s), st: %s, ev: %s, ret: %d\",\n (!dst.running)?\"!!\":\"\",\n gobj_gclass_name(dst), gobj_name(dst),\n dst.current_state.state_name,\n event?event:\"\",\n is_number(ret)?ret:0\n ));\n }\n\n __inside__ --;\n\n return ret;\n}\n\nconst subs_flag_t = Object.freeze({\n__hard_subscription__ : 0x00000001,\n__own_event__ : 0x00000002, // If gobj_send_event return -1 don't continue publishing\n});\n\n/*\n *\n */\nconst subscription_desc = [\n/*-ATTR-type--------------------name-----------flag-default-description---------- */\nSDATA(data_type_t.DTP_POINTER, \"publisher\", 0, null, \"publisher gobj\"),\nSDATA(data_type_t.DTP_POINTER, \"subscriber\", 0, null, \"subscriber gobj\"),\nSDATA(data_type_t.DTP_STRING, \"event\", 0, \"\", \"event name subscribed\"),\nSDATA(data_type_t.DTP_STRING, \"renamed_event\",0, \"\", \"rename event name\"),\nSDATA(data_type_t.DTP_INTEGER, \"subs_flag\", 0, 0, \"subscription flag\"),\nSDATA(data_type_t.DTP_JSON, \"__config__\", 0, null, \"subscription config\"),\nSDATA(data_type_t.DTP_JSON, \"__global__\", 0, null, \"global kw, merge in publishing\"),\nSDATA(data_type_t.DTP_JSON, \"__local__\", 0, null, \"local kw, remove in publishing\"),\nSDATA(data_type_t.DTP_JSON, \"__filter__\", 0, null, \"filter kw, filter in publishing\"),\nSDATA(data_type_t.DTP_STRING, \"__service__\", 0, \"\", \"subscription service\"),\nSDATA_END()\n];\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction _create_subscription(\n publisher,\n event,\n kw,\n subscriber)\n{\n let subs = sdata_create(publisher, subscription_desc);\n json_object_set_new(subs, \"event\", event);\n json_object_set_new(subs, \"subscriber\", subscriber);\n json_object_set_new(subs, \"publisher\", publisher);\n\n let subs_flag = 0;\n\n if(kw) {\n let __config__ = kw_get_dict(publisher, kw, \"__config__\", null);\n let __global__ = kw_get_dict(publisher, kw, \"__global__\", null);\n let __local__ = kw_get_dict(publisher, kw, \"__local__\", null);\n let __filter__ = kw_get_dict_value(publisher, kw, \"__filter__\", null);\n let __service__ = kw_get_str(publisher, kw, \"__service__\", \"\");\n\n if(json_size(__global__)>0) {\n let kw_clone = json_deep_copy(__global__);\n json_object_set_new(subs, \"__global__\", kw_clone);\n }\n if(json_size(__config__)>0) {\n let kw_clone = json_deep_copy(__config__);\n json_object_set_new(subs, \"__config__\", kw_clone);\n\n// TODO\n// if(kw_has_key(kw_clone, \"__rename_event_name__\")) {\n// const char *renamed_event = kw_get_str(gobj?, kw_clone, \"__rename_event_name__\", 0, 0);\n// sdata_write_str(subs, \"renamed_event\", renamed_event);\n// json_object_del(kw_clone, \"__rename_event_name__\");\n// subs_flag |= __rename_event_name__;\n//\n// // Get/Create __global__\n// json_t *kw_global = sdata_read_json(subs, \"__global__\");\n// if(!kw_global) {\n// kw_global = json_object();\n// sdata_write_json(subs, \"__global__\", kw_global);\n// kw_decref(kw_global); // Incref above\n// }\n// kw_set_dict_value(\n// kw_global,\n// \"__original_event_name__\",\n// json_string(event)\n// );\n// }\n\n if(kw_has_key(kw_clone, \"__hard_subscription__\")) {\n let hard_subscription = kw_get_bool(publisher,\n kw_clone, \"__hard_subscription__\", false\n );\n json_object_del(kw_clone, \"__hard_subscription__\");\n if(hard_subscription) {\n subs_flag |= subs_flag_t.__hard_subscription__;\n }\n }\n if(kw_has_key(kw_clone, \"__own_event__\")) {\n let own_event= kw_get_bool(publisher,\n kw_clone, \"__own_event__\", false\n );\n json_object_del(kw_clone, \"__own_event__\");\n if(own_event) {\n subs_flag |= subs_flag_t.__own_event__;\n }\n }\n }\n if(json_size(__local__)>0) {\n let kw_clone = json_deep_copy(__local__);\n json_object_set_new(subs, \"__local__\", kw_clone);\n }\n if(json_size(__filter__)>0) {\n let kw_clone = json_deep_copy(__filter__);\n json_object_set_new(subs, \"__filter__\", kw_clone);\n }\n if(!empty_string(__service__)) {\n json_object_set_new(subs, \"__service__\", __service__);\n }\n }\n json_object_set_new(subs, \"subs_flag\", subs_flag);\n\n return subs;\n}\n\n/***************************************************************************\n * Match subscription\n ***************************************************************************/\nfunction _match_subscription(\n subs,\n publisher,\n event,\n kw,\n subscriber\n) {\n let __config__ = kw_get_dict(publisher, kw, \"__config__\", null);\n let __global__ = kw_get_dict(publisher, kw, \"__global__\", null);\n let __local__ = kw_get_dict(publisher, kw, \"__local__\", null);\n let __filter__ = kw_get_dict_value(publisher, kw, \"__filter__\", null);\n\n let match = true;\n\n if(publisher) {\n let publisher_ = kw_get_pointer(null, subs, \"publisher\", null);\n if(publisher !== publisher_) {\n match = false;\n }\n }\n\n if(subscriber) {\n let subscriber_ = kw_get_pointer(null, subs, \"subscriber\", null);\n if(subscriber !== subscriber_) {\n match = false;\n }\n }\n\n if(event) {\n let event_ = kw_get_str(null, subs, \"event\", \"\");\n if(event !== event_) {\n match = false;\n }\n }\n\n if(json_size(__config__)>0) {\n let kw_config = kw_get_dict(null, subs, \"__config__\", null);\n if(json_size(kw_config)>0) {\n if(!json_is_identical(kw_config, __config__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n if(json_size(__global__)>0) {\n let kw_global = kw_get_dict(null, subs, \"__global__\", null);\n if(json_size(kw_global)>0) {\n if(!json_is_identical(kw_global, __global__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n if(json_size(__local__)>0) {\n let kw_local = kw_get_dict(null, subs, \"__local__\", null);\n if(json_size(kw_local)>0) {\n if(!json_is_identical(kw_local, __local__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n if(json_size(__filter__)>0) {\n let kw_filter = kw_get_dict_value(null, subs, \"__filter__\", null);\n if(json_size(kw_filter)>0) {\n if(!json_is_identical(kw_filter, __filter__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n\n return match;\n}\n\n/***************************************************************************\n * Return a list of subscriptions in the list dl_subs\n * filtering by matching:\n * publisher\n * event,\n * kw (__config__, __global__, __local__, __filter__),\n * subscriber\n ***************************************************************************/\nfunction _find_subscriptions(\n dl_subs,\n publisher,\n event,\n kw,\n subscriber\n) {\n let iter = [];\n\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n if(_match_subscription(\n subs,\n publisher,\n event,\n kw, // NOT owned\n subscriber\n )) {\n json_array_append(iter, subs);\n }\n }\n\n return iter;\n}\n\n/***************************************************************************\n * Find idx of subscription in dl_subs, -1 not found\n ***************************************************************************/\nfunction _get_subs_idx(\n dl_subs,\n publisher,\n event,\n kw,\n subscriber\n) {\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n if(_match_subscription(\n subs,\n publisher,\n event,\n kw, // NOT owned\n subscriber\n )) {\n return i;\n }\n }\n\n return -1;\n}\n\n/***************************************************************************\n * Delete subscription in publisher and subscriber\n ***************************************************************************/\nfunction _delete_subscription(\n gobj,\n subs,\n force,\n not_inform\n) {\n let publisher = kw_get_pointer(gobj, subs, \"publisher\", null, kw_flag_t.KW_REQUIRED);\n let subscriber = kw_get_pointer(gobj, subs, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n let event = kw_get_str(gobj, subs, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n let subs_flag = kw_get_int(gobj, subs, \"subs_flag\", null, kw_flag_t.KW_REQUIRED);\n let hard_subscription = (subs_flag & subs_flag_t.__hard_subscription__)?1:0;\n\n /*-------------------------------*\n * Check if hard subscription\n *-------------------------------*/\n if(hard_subscription) {\n if(!force) {\n return -1;\n }\n }\n\n /*-----------------------------*\n * Trace\n *-----------------------------*/\n let tracea = __trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher);\n if(tracea) {\n trace_machine(sprintf(\n \"💜💜👎 unsubscribing event '%s': publisher %s, subscriber'%s'\",\n event?event:\"\",\n gobj_short_name(publisher),\n gobj_short_name(subscriber)\n ));\n trace_json(subs);\n }\n\n /*------------------------------------------------*\n * Inform (BEFORE) of subscription removed\n *------------------------------------------------*/\n if(!(publisher.obflag & obflag_t.obflag_destroyed)) {\n if(!not_inform) {\n if(publisher.gclass.gmt.mt_subscription_deleted) {\n publisher.gclass.gmt.mt_subscription_deleted(\n publisher,\n subs\n );\n }\n }\n }\n\n /*--------------------------------*\n * Delete subscription\n *--------------------------------*/\n let idx = _get_subs_idx(\n publisher.dl_subscriptions,\n publisher,\n event,\n subs,\n subscriber\n );\n\n if(idx >= 0) {\n json_array_remove(publisher.dl_subscriptions, idx);\n } else {\n log_error(`${gobj_short_name(gobj)}: subscription in publisher not found`);\n trace_json(subs);\n }\n\n idx = _get_subs_idx(\n subscriber.dl_subscribings,\n publisher,\n event,\n subs,\n subscriber\n );\n if(idx >= 0) {\n json_array_remove(subscriber.dl_subscribings, idx);\n } else {\n log_error(`${gobj_short_name(gobj)}: subscription in subscriber not found`);\n trace_json(subs);\n }\n\n return 0;\n}\n\n/***************************************************************************\n * Subscribe to an event\n *\n * event is only one event (not a string list like ginsfsm).\n *\n * See .h\n ***************************************************************************/\nfunction gobj_subscribe_event(\n publisher,\n event,\n kw,\n subscriber)\n{\n if(kw == null) {\n kw = {};\n }\n\n /*---------------------*\n * Check something\n *---------------------*/\n if(!publisher) {\n log_error(`publisher NULL: ev ${event}`);\n return 0;\n }\n if(!subscriber) {\n log_error(`subscriber NULL: ev ${event}`);\n return 0;\n }\n\n const IGNORED_KEYS = new Set(\n [\"__config__\", \"__global__\", \"__local__\", \"__filter__\", \"__service__\"]\n );\n Object.keys(kw).forEach(key => {\n if (!IGNORED_KEYS.has(key)) {\n log_error(`${gobj_short_name(publisher)}: key ignored in subscription (key: ${key}, event: ${event})`);\n }\n });\n\n /*--------------------------------------------------------------*\n * Event must be in output event list\n * You can avoid this with gcflag_no_check_output_events flag\n *--------------------------------------------------------------*/\n if(!empty_string(event)) {\n if(!gobj_has_output_event(publisher, event, event_flag_t.EVF_OUTPUT_EVENT)) {\n if(!(publisher.gclass.gclass_flag & gclass_flag_t.gcflag_no_check_output_events)) {\n log_error(`event NOT in output event list: ${gobj_short_name(publisher)}, ${event}`);\n return 0;\n }\n }\n } else {\n event = \"\"; // In C use NULL, in JS or others use \"\"\n }\n\n /*-------------------------------------------------*\n * Check AUTHZ\n *-------------------------------------------------*/\n\n /*------------------------------*\n * Find repeated subscription\n *------------------------------*/\n let dl_subs = _find_subscriptions(\n publisher.dl_subscriptions,\n publisher,\n event,\n kw,\n subscriber\n );\n if(json_array_size(dl_subs) > 0) {\n log_error(`${gobj_short_name(publisher)}: ${json_array_size(dl_subs)} subscription(s) REPEATED, will be deleted and override`);\n trace_json(dl_subs, \"subscription REPEATED\");\n gobj_unsubscribe_list(publisher, dl_subs, false);\n }\n\n /*-----------------------------*\n * Create subscription\n *-----------------------------*/\n let subs = _create_subscription(\n publisher,\n event,\n kw,\n subscriber\n );\n if(!subs) {\n log_error(`${gobj_short_name(publisher)}: _create_subscription() FAILED`);\n return 0;\n }\n\n json_array_append(publisher.dl_subscriptions, subs);\n json_array_append(subscriber.dl_subscribings, subs);\n\n /*-----------------------------*\n * Trace\n *-----------------------------*/\n let tracea = __trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher);\n if(tracea) {\n trace_machine(sprintf(\n \"💜💜👍 subscribing event '%s', publisher '%s', subscriber %s\",\n event?event:\"\",\n gobj_short_name(publisher),\n gobj_short_name(subscriber)\n ));\n if(kw && (__trace_gobj_ev_kw__(subscriber) || __trace_gobj_ev_kw__(publisher))) {\n trace_json(kw);\n }\n }\n\n /*--------------------------------*\n * Inform new subscription\n *--------------------------------*/\n if(publisher.gclass.gmt.mt_subscription_added) {\n let result = publisher.gclass.gmt.mt_subscription_added(\n publisher,\n subs\n );\n /* `false` as well as a negative: the hook refuses the subscription,\n * and in javascript that is how it says so. */\n if(result < 0 || result === false) {\n _delete_subscription(publisher, subs, true, true);\n subs = 0;\n }\n }\n\n return subs;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_unsubscribe_event(\n publisher,\n event,\n kw,\n subscriber)\n{\n if(kw == null) {\n kw = {};\n }\n\n /*---------------------*\n * Check something\n *---------------------*/\n if(!publisher) {\n log_error(`publisher NULL: ev ${event}`);\n return 0;\n }\n if(!subscriber) {\n log_error(`subscriber NULL: ev ${event}`);\n return 0;\n }\n\n const IGNORED_KEYS = new Set(\n [\"__config__\", \"__global__\", \"__local__\", \"__filter__\", \"__service__\"]\n );\n Object.keys(kw).forEach(key => {\n if (!IGNORED_KEYS.has(key)) {\n log_error(`${gobj_short_name(publisher)}: key ignored in subscription (key: ${key}, event: ${event})`);\n }\n });\n\n /*--------------------------------------------------------------*\n * Event must be in output event list\n * You can avoid this with gcflag_no_check_output_events flag\n *--------------------------------------------------------------*/\n if(!empty_string(event)) {\n if(!gobj_has_output_event(publisher, event, event_flag_t.EVF_OUTPUT_EVENT)) {\n if(!(publisher.gclass.gclass_flag & gclass_flag_t.gcflag_no_check_output_events)) {\n log_error(`event NOT in output event list: ${gobj_short_name(publisher)}, ev ${event}`);\n return 0;\n }\n }\n } else {\n event = \"\"; // In C use NULL, in JS or others use \"\"\n }\n\n /*-----------------------------*\n * Find subscription\n *-----------------------------*/\n let dl_subs = _find_subscriptions(\n publisher.dl_subscriptions,\n publisher,\n event,\n kw,\n subscriber\n );\n\n let deleted = 0;\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n _delete_subscription(publisher, subs, false, false);\n deleted++;\n }\n\n if(!deleted) {\n log_warning(`${gobj_short_name(publisher)}: No subscription found`);\n trace_json(kw, \"No subscription found\");\n }\n\n return 0;\n}\n\n/***************************************************************************\n * Unsubscribe a list of subscription hsdata\n ***************************************************************************/\nfunction gobj_unsubscribe_list(\n gobj,\n dl_subs,\n force // delete hard_subscription subs too\n)\n{\n let dl = [...dl_subs];\n for(let i=0; i<dl.length; i++) {\n let subs = dl[i];\n _delete_subscription(gobj, subs, force, false);\n }\n return 0;\n}\n\n/***************************************************************************\n * Return a list of subscriptions in the publisher gobj,\n * filtering by matching:\n * event,\n * kw (__config__, __global__, __local__, __filter__),\n * subscriber\n ***************************************************************************/\nfunction gobj_find_subscriptions(\n publisher,\n event,\n kw,\n subscriber)\n{\n if(kw == null) {\n kw = {};\n }\n return _find_subscriptions(\n publisher.dl_subscriptions,\n publisher,\n event,\n kw,\n subscriber\n );\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_list_subscriptions(gobj2view)\n{\n let subscriptions = gobj_find_subscriptions(\n gobj2view,\n null, // event,\n null, // kw (__config__, __global__, __local__)\n null // subscriber\n );\n for(let i=0; i<subscriptions.length; i++) {\n let sub = subscriptions[i];\n let publisher = kw_get_pointer(gobj2view, sub, \"publisher\", null, kw_flag_t.KW_REQUIRED);\n let subscriber = kw_get_pointer(gobj2view, sub, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n let event_ = kw_get_str(gobj2view, sub, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n\n json_object_set_new(sub, \"s_event\", event_);\n json_object_set_new(sub, \"s_publisher\", gobj_short_name(publisher));\n json_object_set_new(sub, \"s_subscriber\", gobj_short_name(subscriber));\n }\n\n let subscribings = gobj_find_subscribings( // Return is YOURS\n gobj2view,\n 0, // event,\n null, // kw (__config__, __global__, __local__)\n 0 // subscriber\n );\n for(let i=0; i<subscribings.length; i++) {\n let sub = subscribings[i];\n let publisher = kw_get_pointer(gobj2view, sub, \"publisher\", null, kw_flag_t.KW_REQUIRED);\n let subscriber = kw_get_pointer(gobj2view, sub, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n let event_ = kw_get_str(gobj2view, sub, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n\n json_object_set_new(sub, \"s_event\", event_);\n json_object_set_new(sub, \"s_publisher\", gobj_short_name(publisher));\n json_object_set_new(sub, \"s_subscriber\", gobj_short_name(subscriber));\n }\n\n return {\n \"subscriptions\": subscriptions,\n \"subscribings\": subscribings,\n \"total subscriptions\": json_array_size(subscriptions),\n \"total_subscribings\": json_array_size(subscribings)\n };\n}\n\n/***************************************************************************\n * Return a list of subscribings\n * filtering by matching:\n * event,\n * kw (__config__, __global__, __local__, __filter__),\n * subscriber\n ***************************************************************************/\nfunction gobj_find_subscribings(\n subscriber,\n event,\n kw, // kw (__config__, __global__, __local__, __filter__)\n publisher\n)\n{\n return _find_subscriptions(\n subscriber.dl_subscribings,\n publisher,\n event,\n kw,\n subscriber\n );\n}\n\n/***************************************************************************\n * Return the sum of returns of gobj_send_event\n ***************************************************************************/\nfunction gobj_publish_event(\n publisher,\n event,\n kw)\n{\n if(!is_object(kw)) {\n kw = {};\n }\n\n /*---------------------*\n * Check something\n *---------------------*/\n if(!publisher || publisher.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(empty_string(event)) {\n log_error(`${gobj_short_name(publisher)}: event EMPTY`);\n return -1;\n }\n\n /*--------------------------------------------------------------*\n * Event must be in output event list\n * You can avoid this with gcflag_no_check_output_events flag\n *--------------------------------------------------------------*/\n let ev = gobj_event_type(publisher, event, true);\n if(!(ev && (ev.event_flag & (event_flag_t.EVF_SYSTEM_EVENT|event_flag_t.EVF_OUTPUT_EVENT)))) {\n /*\n * HACK ev can be null,\n * there are gclasses like c_iogate that are intermediate of other events.\n */\n if(!(publisher.gclass.gclass_flag & gclass_flag_t.gcflag_no_check_output_events)) {\n log_error(`event NOT in output event list: ${gobj_short_name(publisher)}, ev ${event}`);\n return -1;\n }\n }\n\n let tracea = (__trace_gobj_subscriptions__(publisher) || is_machine_tracing(publisher, event)) &&\n !is_machine_not_tracing(publisher, event);\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n trace_machine(sprintf(\"🔝🔝 %s %s%s %s\",\n event?event:\"\",\n (!publisher.running)?\"!!\":\"\",\n gobj_short_name(publisher),\n publisher.current_state.state_name\n ));\n } else {\n trace_machine(sprintf(\"🔝🔝 mach(%s%s^%s), st: %s, ev: %s%s%s\",\n (!publisher.running)?\"!!\":\"\",\n gobj_gclass_name(publisher), gobj_name(publisher),\n publisher.current_state.state_name,\n \"\", //On_Black BBlue,\n event?event:\"\",\n \"\" //Color_Off\n ));\n }\n /* The kw only with `ev_kw`, and only with something IN it, like the\n * C kernel: the `machine` trace alone printed the payload of every\n * publication, in the console and in any monitor. */\n if(__trace_gobj_ev_kw__(publisher) && json_object_size(kw)) {\n trace_json(kw);\n }\n }\n\n /*----------------------------------------------------------*\n * Own publication method\n * Return:\n * -1 broke . return\n * 0 continue without publish . return\n * 1 publish and continue . continue below\n *----------------------------------------------------------*/\n if(publisher.gclass.gmt.mt_publish_event) {\n let topublish = publisher.gclass.gmt.mt_publish_event(\n publisher,\n event,\n kw // not owned\n );\n if(topublish<=0) {\n return topublish;\n }\n }\n\n /*--------------------------------------------------------------*\n * Default publication method\n *--------------------------------------------------------------*/\n let dl_subs = [...publisher.dl_subscriptions]; // Create a shallow copy\n let sent_count = 0;\n let ret = 0;\n\n for(let idx=0; idx<dl_subs.length; idx++) {\n let subs = dl_subs[idx];\n /*-------------------------------------*\n * Pre-filter\n * kw NOT owned! you can modify the publishing kw\n * Return:\n * -1 broke\n * 0 continue without publish\n * 1 continue to publish\n *-------------------------------------*/\n if(publisher.gclass.gmt.mt_publication_pre_filter) {\n let topublish = publisher.gclass.gmt.mt_publication_pre_filter(\n publisher,\n subs,\n event,\n kw // not owned\n );\n if(topublish<0) {\n break;\n } else if(!topublish) {\n /* `!topublish` and not `=== 0`: this hook is written in\n * javascript, where the natural way to say \"do not publish\"\n * is `false` — and `false === 0` is FALSE, so it published.\n * Same trap as the `__filter__` guard below. */\n continue;\n }\n }\n let subscriber = kw_get_pointer(publisher, subs, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n if(!(subscriber && !gobj_is_destroying(subscriber))) {\n continue;\n }\n\n /*\n * Check if event null or event in event_list\n */\n let subs_flag = kw_get_int(publisher, subs, \"subs_flag\", 0, kw_flag_t.KW_REQUIRED);\n let event_ = kw_get_str(publisher, subs, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n if(empty_string(event_) || strcasecmp(event_, event)===0) {\n let __config__ = kw_get_dict(publisher, subs, \"__config__\", null, 0);\n let __global__ = kw_get_dict(publisher, subs, \"__global__\", null, 0);\n let __local__ = kw_get_dict(publisher, subs, \"__local__\", null, 0);\n let __filter__ = kw_get_dict_value(publisher, subs, \"__filter__\", null, 0);\n\n /*\n * Check renamed_event\n */\n// TODO review const char *event_name = sdata_read_str(subs, \"renamed_event\");\n// if(empty_string(event_name)) {\n// event_name = event;\n// }\n\n /*\n * Duplicate the kw to publish if not shared\n * NOW always shared\n */\n let kw2publish = kw;\n\n /*-------------------------------------*\n * User filter method or filter parameter\n * Return:\n * -1 (broke),\n * 0 continue without publish,\n * 1 continue and publish\n *-------------------------------------*/\n let topublish = 1;\n if(publisher.gclass.gmt.mt_publication_filter) {\n topublish = publisher.gclass.gmt.mt_publication_filter(\n publisher,\n event,\n kw2publish, // not owned\n subscriber\n );\n } else if(json_size(__filter__)>0) {\n /* `kw_match_simple()` answers a BOOLEAN, and what is\n * compared below is `topublish === 0`. `false === 0` is\n * FALSE in javascript, so a filter that did not match fell\n * straight through the guard and published anyway: the\n * trace said 👎 and the subscriber got the event all the\n * same. Normalize to the 1/0 the contract is written in\n * (-1 break, 0 skip, 1 publish), which is what the C side\n * passes around. */\n topublish = kw_match_simple(kw2publish , __filter__) ? 1 : 0;\n if(tracea) {\n trace_machine(sprintf(\n \"💜💜🔄%s publishing with filter, event '%s', subscriber'%s', publisher %s\",\n topublish?\"👍\":\"👎\",\n event?event:\"\",\n gobj_short_name(subscriber),\n gobj_short_name(publisher)\n ));\n trace_json(__filter__);\n }\n }\n\n if(topublish<0) {\n break;\n } else if(!topublish) {\n /*\n * Must not be published\n * Next subs\n *\n * `!topublish` and not `=== 0`: a filter or an\n * mt_publication_filter that answers `false` means the same\n * as 0, and a strict comparison with the number let it\n * through.\n */\n continue;\n }\n\n /*\n * Check if System event: don't send it if subscriber has not it\n */\n let ev_ = gobj_event_type(subscriber, event, true);\n if(ev_) {\n if(ev_.event_flag & event_flag_t.EVF_SYSTEM_EVENT) {\n if(!gobj_has_event(subscriber, ev_.event_name, 0)) {\n continue;\n }\n }\n }\n\n /*\n * Remove local keys\n */\n if(__local__) {\n kw_pop(kw2publish,\n __local__ // not owned\n );\n }\n\n /*\n * Apply transformation filters\n * TODO review, I think it was used only from c_agent\n */\n if(__config__) {\n// json_t *jn_trans_filters = kw_get_dict_value(\n// publisher, __config__, \"__trans_filter__\", 0, 0\n// );\n// if(jn_trans_filters) {\n// kw2publish = apply_trans_filters(publisher, kw2publish, jn_trans_filters);\n// }\n }\n\n /*\n * Add global keys\n */\n if(__global__) {\n json_object_update(kw2publish, __global__);\n }\n\n /*\n * Send event\n */\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n /* The event as PUBLISHED and the one the subscriber is\n * sent, which a `__rename_event_name__` can make\n * different -- the C kernel prints both, and the pair is\n * the only place the rename is visible. */\n trace_machine(sprintf(\"🔝🔄 %s (%s) %s%s\",\n event?event:\"\",\n event?event:\"\",\n (!subscriber.running)?\"!!\":\"\",\n gobj_short_name(subscriber)\n ));\n } else {\n trace_machine(sprintf(\"🔝🔄 mach(%s%s), st: %s, ev: %s, from(%s%s)\",\n (!subscriber.running)?\"!!\":\"\",\n gobj_short_name(subscriber),\n gobj_current_state(subscriber),\n event?event:\"\",\n (publisher && !publisher.running)?\"!!\":\"\",\n gobj_short_name(publisher)\n ));\n }\n if(__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish)) {\n trace_json(kw2publish);\n }\n }\n\n let ret_ = gobj_send_event(\n subscriber,\n event,\n kw2publish,\n publisher\n );\n if(ret_ < 0 && (subs_flag & subs_flag_t.__own_event__)) {\n sent_count = -1; // Return of -1 indicates that someone owned the event\n break;\n }\n ret += ret_;\n sent_count++;\n\n if(gobj_is_destroying(publisher)) {\n /*\n * break all, self publisher deleted\n */\n break;\n }\n }\n }\n\n if(!sent_count) {\n if(!ev || !(ev.event_flag & event_flag_t.EVF_NO_WARN_SUBS)) {\n log_warning(`${gobj_short_name(publisher)}: Publish event WITHOUT subscribers, ev ${event}`);\n // if(__trace_gobj_ev_kw__(publisher)) {\n // if(json_object_size(kw)) {\n // gobj_trace_json(publisher, kw, \"Publish event WITHOUT subscribers\");\n // }\n // }\n }\n }\n\n return ret;\n}\n\n/************************************************************\n * Exec gobj command. Return a webix\n ************************************************************/\nfunction gobj_command(gobj, command, kw, src)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n /*-----------------------------------------------*\n * Trace\n *-----------------------------------------------*/\n let tracea = is_commands_tracing(gobj) ||\n (is_machine_tracing(gobj, null) && !is_machine_not_tracing(src, null));\n if(tracea) {\n trace_machine(sprintf(\"🌀🌀 mach(%s%s), cmd: %s, src: %s\",\n (!gobj_is_running(gobj))?\"!!\":\"\",\n gobj_short_name(gobj),\n command,\n gobj_short_name(src)\n ));\n if(__trace_gobj_ev_kw__(gobj)) {\n trace_json(kw);\n }\n }\n\n /*-----------------------------------------------*\n * The local mt_command_parser has preference\n *-----------------------------------------------*/\n if(gobj.gclass.gmt.mt_command_parser) {\n return gobj.gclass.gmt.mt_command_parser(gobj, command, kw, src);\n }\n\n /*-----------------------------------------------*\n * If it has command_table\n * then use the global command parser\n *-----------------------------------------------*/\n if(gobj.gclass.command_table) {\n if(__global_command_parser_fn__) {\n return __global_command_parser_fn__(gobj, command, kw, src);\n } else {\n return build_command_response(\n gobj,\n -1, // result\n sprintf(\"%s: global command parser not available\", gobj_short_name(gobj)), // jn_comment\n 0, // jn_schema\n 0 // jn_data\n );\n }\n } else {\n return build_command_response(\n gobj,\n -1, // result\n sprintf(\"%s: command table not available\",gobj_short_name(gobj)), // jn_comment\n 0, // jn_schema\n 0 // jn_data\n );\n }\n}\n\n/************************************************************\n * Exec gobj stats. Return a webix\n ************************************************************/\nfunction gobj_stats(gobj, stats, kw, src)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n /*--------------------------------------*\n * The local mt_stats has preference\n *--------------------------------------*/\n if(gobj.gclass.gmt.mt_stats) {\n return gobj.gclass.gmt.mt_stats(gobj, stats, kw, src);\n }\n\n /*-----------------------------------------------*\n * Then use the global stats parser\n *-----------------------------------------------*/\n if(__global_stats_parser_fn__) {\n return __global_stats_parser_fn__(gobj, stats, kw, src);\n } else {\n return build_stats_response(\n gobj,\n -1, // result\n sprintf(\"%s, stats parser not available\", gobj_short_name(gobj)),// jn_comment\n 0, // jn_schema\n 0 // jn_data\n );\n }\n}\n\n\n//=======================================================================\n// Expose the class via the global object\n//=======================================================================\nexport {\n __yuno__,\n YUNETA_VERSION,\n data_type_t,\n sdata_flag_t,\n SDataDesc,\n SDATA,\n SDATACM,\n SDATACM2,\n SDATAPM,\n SDATAAUTHZ,\n SDATAPM0,\n SDATADF,\n SDATA_END,\n gobj_flag_t,\n gclass_flag_t,\n event_flag_t,\n walk_type_t,\n GObj,\n gobj_start_up,\n gobj_hsdata,\n gclass_create,\n gclass_unregister,\n gclass_add_state,\n gclass_add_ev_action,\n gclass_event_type,\n gclass_add_event_type,\n gclass_check_fsm,\n gclass_find_by_name,\n gobj_services,\n gobj_default_service,\n gobj_find_service,\n gobj_load_persistent_attrs,\n gobj_save_persistent_attrs,\n gobj_remove_persistent_attrs,\n gobj_list_persistent_attrs,\n gobj_create2,\n gobj_create_yuno,\n gobj_create_service,\n gobj_create_default_service,\n gobj_create_volatil,\n gobj_create_pure_child,\n gobj_create,\n gobj_destroy,\n gobj_start,\n gobj_start_children,\n gobj_start_tree,\n gobj_stop,\n gobj_stop_children,\n gobj_stop_tree,\n gobj_play,\n gobj_pause,\n gobj_is_running,\n gobj_is_playing,\n gobj_is_service,\n gobj_yuno,\n gobj_yuno_name,\n gobj_yuno_role,\n gobj_yuno_id,\n gobj_name,\n gobj_gclass_name,\n gobj_short_name,\n trace_level_t,\n gobj_set_global_trace,\n gobj_set_global_no_trace,\n gobj_global_trace_level,\n gobj_global_trace_no_level,\n gobj_set_global_trace2,\n gobj_set_global_no_trace2,\n gobj_get_global_trace_level,\n gobj_get_global_trace_no_level,\n gobj_get_gclass_trace_level,\n gobj_get_gclass_trace_level2,\n gobj_get_gclass_trace_no_level,\n gobj_set_gclass_trace,\n gobj_set_gobj_trace,\n gobj_set_gclass_no_trace,\n gobj_set_gobj_no_trace,\n gobj_set_deep_trace,\n gobj_trace_level,\n gobj_trace_no_level,\n gobj_repr_global_trace_levels,\n gobj_set_trace_machine_format,\n gobj_trace_machine_format,\n gobj_full_name,\n gobj_parent,\n gobj_is_volatil,\n gobj_is_pure_child,\n gobj_is_destroying,\n gobj_bottom_gobj,\n gobj_set_bottom_gobj,\n gobj_walk_gobj_children,\n gobj_walk_gobj_children_tree,\n gobj_find_gobj,\n gobj_match_gobj,\n gobj_find_child,\n gobj_match_children,\n gobj_match_children_tree,\n gobj_search_path,\n gobj_has_attr,\n gobj_read_attr,\n gobj_read_attrs,\n gobj_write_attr,\n gobj_write_attrs,\n gobj_read_bool_attr,\n gobj_read_integer_attr,\n gobj_read_str_attr,\n gobj_read_pointer_attr,\n gobj_write_bool_attr,\n gobj_write_integer_attr,\n gobj_write_str_attr,\n gobj_reset_volatil_attrs,\n gobj_change_state,\n gobj_current_state,\n gobj_change_parent,\n\n gobj_has_event,\n gobj_has_output_event,\n gobj_post_event,\n gobj_posted_events_size,\n gobj_deliver_posted_events,\n gobj_send_event,\n\n gobj_subscribe_event,\n gobj_unsubscribe_event,\n gobj_unsubscribe_list,\n gobj_find_subscriptions,\n gobj_list_subscriptions,\n gobj_find_subscribings,\n gobj_publish_event,\n gobj_command,\n gobj_stats,\n};\n","/*********************************************************************************\n * Helper functions\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025, ArtGins.\n *********************************************************************************/\nimport {\n GObj,\n gobj_short_name,\n} from \"./gobj.js\";\n\nimport {sprintf} from \"./sprintf.js\";\n\nconst kw_flag_t = Object.freeze({\n KW_REQUIRED : 0x0001, // Log error message if not exist.\n KW_CREATE : 0x0002, // Create if not exist\n KW_WILD_NUMBER : 0x0004, // For numbers work with real/int/bool/string without error logging\n KW_EXTRACT : 0x0008, // Extract (delete) the key on read from dictionary.\n KW_BACKWARD : 0x0010, // Search backward in lists or arrays\n KW_VERBOSE : 0x0020, //\n KW_LOWER : 0x0040, //\n KW_RECURSIVE : 0x0080, //\n});\n\nconst json_type = Object.freeze({\n JSON_OBJECT: 1,\n JSON_ARRAY: 2,\n JSON_STRING: 3,\n JSON_INTEGER: 4,\n JSON_REAL: 5,\n JSON_TRUE: 6,\n JSON_FALSE: 7,\n JSON_NULL: 8\n});\n\n/************************************************************\n * log function\n ************************************************************/\n\n/********************************************\n * Log functions\n ********************************************/\n/* jshint node: true */\nconst _console = typeof window !== \"undefined\" ? window.console : console;\nlet f_error = _console.error;\nlet f_warning = _console.warn;\nlet f_info = _console.info;\nlet f_debug = _console.debug;\n\n/* Optional sink that mirrors every framework log line (error / warning /\n * info / debug / msg) somewhere else — e.g. a GUI dev monitor that shows the\n * browser console inside the app. It runs IN ADDITION to the console; null\n * (default) leaves behaviour unchanged. Called as (level, msg, hora).\n * CONTRACT: `msg` is a string for every text level, EXCEPT level \"json\"\n * (trace_json payloads), where it is the raw object so the sink can\n * pretty-print it — a sink must handle both. */\nlet __log_callback__ = null;\n\n/* The lines the log helpers wrote since the page loaded, bounded. A sink is\n * installed by application code, well after the first lines are written\n * (gobj_start_up, the yuno, the first services): without this, a monitor\n * would start mid-way through what the browser console shows whole. A new\n * sink is handed this backlog first, so both show the same session. A json\n * line is kept as text, because the object it came from goes on changing. */\nconst LOG_BACKLOG_MAX = 600;\nconst __log_backlog__ = [];\n\nfunction keep_in_backlog(level, msg, hora)\n{\n let m = msg;\n if(level === \"json\") {\n try {\n m = JSON.stringify(msg);\n } catch(e) {\n m = String(msg);\n }\n }\n __log_backlog__.push([level, m, hora]);\n if(__log_backlog__.length > LOG_BACKLOG_MAX) {\n __log_backlog__.shift();\n }\n}\n\nfunction set_log_callback(fn)\n{\n fn = (typeof fn === \"function\") ? fn : null;\n if(fn && fn !== __log_callback__) {\n /* The same sink installed again (an app that re-applies its dev\n * setup) is not replayed to, or it would see every line twice. */\n __log_callback__ = fn;\n for(const [level, m, hora] of __log_backlog__.slice()) {\n let msg = m;\n if(level === \"json\") {\n try {\n msg = JSON.parse(m);\n } catch(e) {\n msg = m;\n }\n }\n __deliver_log__(level, msg, hora);\n }\n return;\n }\n __log_callback__ = fn;\n}\n\n/* Master switch for the DIRECT browser-console writes of the log helpers\n * (log_error/log_warning/log_info/log_debug, trace_msg, trace_json).\n * Default on: the framework logs to the console as it always has. A GUI dev\n * monitor can turn it off to route output to its own window only (see\n * gobj-ui's yui_dev.js \"Output\" selector). Orthogonal to everything else:\n * the log-sink callback (set_log_callback) still fires — so the monitor keeps\n * receiving lines while the console stays clean — and remote log functions\n * (set_remote_log_functions) still fire too. */\nlet __console_output_enabled__ = true;\n\nfunction set_console_log_enabled(enabled)\n{\n __console_output_enabled__ = enabled ? true : false;\n}\n\n/* A per-LINE say over the console writes, on top of the master switch above.\n * `fn(level, msg)` returns true to let the line through; null (default)\n * lets everything through, which is the behaviour there has always been.\n *\n * It exists because the console write happens BEFORE the log sink is\n * called, so nothing downstream can un-print a line: a consumer that wants\n * to silence a class of lines on the console -- gobj-ui's dev monitor\n * silencing the timer traffic of the `machine` trace, which is two lines a\n * second for ever -- has no way to do it except here. The alternative was\n * for the monitor to turn this console off entirely and reprint everything\n * itself, which duplicates the format of every helper below.\n *\n * It filters the CONSOLE only. The log sink still receives every line, so a\n * monitor keeps its own complete record and decides separately what to show. */\nlet __console_log_filter__ = null;\n\nfunction set_console_log_filter(fn)\n{\n __console_log_filter__ = (typeof fn === \"function\") ? fn : null;\n}\n\n/* Does the console want this line? A filter that throws is ignored: a\n * broken one must never be able to silence the log. */\nfunction console_wants(level, msg)\n{\n if(!__console_output_enabled__) {\n return false;\n }\n if(!__console_log_filter__) {\n return true;\n }\n try {\n return __console_log_filter__(level, msg) ? true : false;\n } catch(e) {\n return true;\n }\n}\n\nlet __in_log_callback__ = false;\n\nfunction emit_log_callback(level, msg, hora)\n{\n if(__in_log_callback__) {\n return; /* a line logged BY the sink is not part of the session */\n }\n keep_in_backlog(level, msg, hora);\n __deliver_log__(level, msg, hora);\n}\n\nfunction __deliver_log__(level, msg, hora)\n{\n if(__log_callback__ && !__in_log_callback__) {\n /* Re-entrancy guard: a sink that itself logs (directly or through any\n * framework helper) must not loop back into itself. */\n __in_log_callback__ = true;\n try {\n /* Pass msg as-is: text levels already send a string; \"json\" sends\n * the raw object so the sink can pretty-print it. */\n __log_callback__(level, msg, hora);\n } catch(e) {\n /* A broken sink must never break the framework's own logging. */\n } finally {\n __in_log_callback__ = false;\n }\n }\n}\n\nfunction set_remote_log_functions(remote_log_fn)\n{\n if(remote_log_fn) {\n f_error = remote_log_fn;\n f_warning = remote_log_fn;\n } else {\n f_error = _console.error;\n f_warning = _console.warn;\n }\n}\n\nfunction format_log(format)\n{\n const args = Array.prototype.slice.call(arguments);\n let output = \"\";\n\n if (typeof format === 'string') {\n let i = 1;\n output = format.replace(/%[sdifoO]/g, match => {\n const val = args[i++];\n switch (match) {\n case '%s': return String(val);\n case '%d':\n case '%i': return parseInt(val);\n case '%f': return parseFloat(val);\n case '%o':\n case '%O':\n return typeof val === 'object' ? JSON.stringify(val) : String(val);\n default: return match;\n }\n });\n\n // Append any remaining arguments (e.g. raw objects or extra messages)\n const rest = args.slice(i).map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg) : String(arg)\n );\n\n if (rest.length > 0) {\n output += \" \" + rest.join(\" \");\n }\n } else {\n // If no format string, join all args\n output = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg) : String(arg)\n ).join(\" \");\n }\n\n return output;\n}\n\nfunction log_error(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_error) {\n if(f_error === _console.error) {\n if(console_wants(\"error\", msg)) {\n f_error(\"%c\" + hora + \" ERROR: \" + String(msg), \"color:red\");\n }\n } else {\n if(console_wants(\"error\", msg)) {\n _console.error(\"%c\" + hora + \" ERROR: \" + String(msg), \"color:red\");\n }\n f_error(`${hora} ERROR: ${String(msg)}`);\n }\n }\n emit_log_callback(\"error\", msg, hora);\n}\n\nfunction log_warning(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_warning) {\n if(f_warning === _console.warn) {\n if(console_wants(\"warning\", msg)) {\n f_warning(\"%c\" + hora + \" WARNING: \" + String(msg), \"color:yellow\");\n }\n } else {\n if(console_wants(\"warning\", msg)) {\n _console.warn(\"%c\" + hora + \" WARNING: \" + String(msg), \"color:yellow\");\n }\n f_warning(`${hora} WARNING: ${String(msg)}`);\n }\n }\n emit_log_callback(\"warning\", msg, hora);\n}\n\nfunction log_info(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_info) {\n if(console_wants(\"info\", msg)) {\n f_info(\"%c\" + hora + \" INFO: \" + String(msg), \"color:cyan\");\n }\n }\n emit_log_callback(\"info\", msg, hora);\n}\n\nfunction log_debug(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_debug) {\n if(console_wants(\"debug\", msg)) {\n f_debug(\"%c\" + hora + \" DEBUG: \" + String(msg), \"color:silver\");\n }\n }\n emit_log_callback(\"debug\", msg, hora);\n}\n\nfunction trace_msg(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_debug) {\n if(console_wants(\"msg\", msg)) {\n f_debug(\"%c\" + hora + \" MSG: \" + String(msg), \"color:cyan\");\n }\n }\n emit_log_callback(\"msg\", msg, hora);\n}\n\nfunction trace_json(jn, msg)\n{\n if(console_wants(\"json\", msg)) {\n if(msg) {\n _console.warn(\"=====> \" + msg);\n }\n _console.dir(jn);\n }\n /* Also mirror it to the log sink (e.g. the dev monitor) so the payload\n * shows next to the trace that dumped it — console.dir stays in the\n * browser console only. */\n emit_log_callback(\"json\", jn, current_timestamp());\n}\n\n/************************************************************\n * Duplicate an object (new references)\n * using the modern structuredClone (Deep copy of a single object)\n ************************************************************/\nfunction json_deep_copy(obj) // old __duplicate__,\n{\n return structuredClone(obj); // jshint ignore:line\n}\n\n/************************************************************\n * Duplicate objects (new references) in a new object\n * using the modern structuredClone\n ************************************************************/\nfunction duplicate_objects(...sourceObjects)\n{\n const result = {};\n for (const obj of sourceObjects) {\n const clonedObj = structuredClone(obj); // jshint ignore:line\n Object.assign(result, clonedObj); // Merge into the result object\n }\n return result;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction json_is_identical(kw1, kw2)\n{\n if(kw1 === kw2) {\n return true;\n }\n if(kw1 === null || kw2 === null) {\n return kw1 === kw2;\n }\n if(typeof kw1 !== typeof kw2) {\n return false;\n }\n if(Array.isArray(kw1) !== Array.isArray(kw2)) {\n return false;\n }\n if(Array.isArray(kw1)) {\n if(kw1.length !== kw2.length) {\n return false;\n }\n for(let i = 0; i < kw1.length; i++) {\n if(!json_is_identical(kw1[i], kw2[i])) {\n return false;\n }\n }\n return true;\n }\n if(typeof kw1 === \"object\") {\n let keys1 = Object.keys(kw1).sort();\n let keys2 = Object.keys(kw2).sort();\n if(keys1.length !== keys2.length) {\n return false;\n }\n for(let i = 0; i < keys1.length; i++) {\n if(keys1[i] !== keys2[i]) {\n return false;\n }\n if(!json_is_identical(kw1[keys1[i]], kw2[keys2[i]])) {\n return false;\n }\n }\n return true;\n }\n return kw1 === kw2;\n}\n\n/************************************************************\n * Extend a dict with another dict (NOT recursive),\n * adding new keys and overwriting existing keys.\n ************************************************************/\nfunction json_object_update(destination, source) // old __extend_dict__\n{\n if(!source) {\n return destination;\n }\n for (let property of Object.keys(source)) {\n destination[property] = source[property];\n }\n return destination;\n}\n\n/************************************************************\n * Update a dict with another dict:\n * ONLY existing items!! (NOT recursive)\n ************************************************************/\nfunction json_object_update_existing(destination, source) // old __update_dict__\n{\n if(!source) {\n return destination;\n }\n for (let property in source) {\n if(source.hasOwnProperty(property) && destination.hasOwnProperty(property)) {\n destination[property] = source[property];\n }\n }\n return destination;\n}\n\n/************************************************************\n * Update a dict with another dict:\n * ONLY missing items!! (NOT recursive)\n ************************************************************/\nfunction json_object_update_missing(destination, source)\n{\n if(!source) {\n return destination;\n }\n for (let property in source) {\n if(source.hasOwnProperty(property) && !destination.hasOwnProperty(property)) {\n destination[property] = source[property];\n }\n }\n return destination;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_get(o, key)\n{\n if(o && o.hasOwnProperty(key)) {\n return o[key];\n }\n return undefined;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_del(o, k)\n{\n if(o && o.hasOwnProperty(k)) {\n delete o[k];\n }\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_set(o, k, v)\n{\n o[k] = v;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_set_new(o, k, v)\n{\n o[k] = v;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_get(a, i)\n{\n if(!is_array(a)) {\n return undefined;\n }\n return a[i];\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_append(a, v)\n{\n a.push(v);\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_append_new(a, v)\n{\n a.push(v);\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_remove(a, idx)\n{\n a.splice(idx, 1);\n}\n\n/************************************************************\n * Extend array\n ************************************************************/\nfunction json_array_extend(destination, source) // old __extend_list__\n{\n if(!source) {\n return destination;\n }\n Array.prototype.push.apply(destination, source);\n return destination;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction json_object_size(a)\n{\n if(is_object(a)) {\n return Object.keys(a).length;\n }\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction json_array_size(a)\n{\n if(is_array(a)) {\n return a.length;\n }\n return 0;\n}\n\n/************************************************************\n * How much content a json carries: elements of a container,\n * 1 for a non-empty string, 0 for everything else\n * (null/undefined, scalars). C twin: json_size() in helpers.h.\n ************************************************************/\nfunction json_size(a)\n{\n if(is_object(a)) {\n return Object.keys(a).length;\n } else if(is_array(a)) {\n return a.length;\n } else if(is_string(a) && a.length > 0) {\n return 1;\n } else {\n return 0;\n }\n}\n\n/************************************************************\n * \"There is nothing usable here\": null/undefined, {}, [],\n * \"\" and any scalar. C twin: empty_json() in helpers.h,\n * where it is the guard to write instead of `if(!jn)` --\n * there an absent DTP_JSON is json_null(), a valid pointer.\n * Here `if(!x)` happens to work, and that difference is what\n * a port across the two runtimes gets wrong: write the same\n * question in both.\n *\n * The other question -- \"absent or explicitly null\", C's\n * json_absent() -- is is_null() here, since javascript has\n * no second null to tell apart.\n ************************************************************/\nfunction empty_json(a)\n{\n return json_size(a) === 0;\n}\n\n/************************************************************\n * json_equal (like jansson library)\n * Returns 1 if value1 and value2 are equal.\n * Returns 0 if they are unequal\n ************************************************************/\nfunction json_equal(json1, json2)\n{\n if (!json1 || !json2) {\n return 0;\n }\n\n if (json_typeof(json1) !== json_typeof(json2)) {\n return 0;\n }\n\n /* this covers true, false and null as they are singletons */\n if (json1 === json2) {\n return 1;\n }\n\n switch (json_typeof(json1)) {\n case json_type.JSON_OBJECT:\n return json_object_equal(json1, json2);\n case json_type.JSON_ARRAY:\n return json_array_equal(json1, json2);\n case json_type.JSON_STRING:\n return json_string_equal(json1, json2);\n case json_type.JSON_INTEGER:\n return json_integer_equal(json1, json2);\n case json_type.JSON_REAL:\n return json_real_equal(json1, json2);\n default:\n return 0;\n }\n}\n\nfunction json_object_equal(object1, object2) {\n let value2;\n\n if (json_object_size(object1) !== json_object_size(object2)) {\n return 0;\n }\n\n //json_object_foreach((json_t *)object1, key, value1) {\n for (const [key, value1] of Object.entries(object1)) {\n value2 = json_object_get(object2, key);\n\n if (!json_equal(value1, value2)) {\n return 0;\n }\n }\n\n return 1;\n}\n\nfunction json_array_equal(array1, array2) {\n let i, size;\n\n size = json_array_size(array1);\n if (size !== json_array_size(array2)) {\n return 0;\n }\n\n for (i = 0; i < size; i++) {\n let value1, value2;\n\n value1 = json_array_get(array1, i);\n value2 = json_array_get(array2, i);\n\n if (!json_equal(value1, value2)) {\n return 0;\n }\n }\n\n return 1;\n}\n\nfunction json_string_equal(string1, string2) {\n return string1 === string2?1:0;\n}\n\nfunction json_integer_equal(integer1, integer2) {\n return integer1 === integer2?1:0;\n}\n\nfunction json_real_equal(real1, real2) {\n return real1 === real2?1:0;\n}\n\nfunction json_typeof(jn)\n{\n if(is_object(jn)) {\n return json_type.JSON_OBJECT;\n }\n if(is_array(jn)) {\n return json_type.JSON_ARRAY;\n }\n if(is_string(jn)) {\n return json_type.JSON_STRING;\n }\n if(is_pure_number(jn)) {\n return json_type.JSON_INTEGER;\n }\n if(is_number(jn)) {\n return json_type.JSON_REAL;\n }\n if(is_boolean(jn)) {\n if(Boolean(jn)===true) {\n return json_type.JSON_TRUE;\n } else {\n return json_type.JSON_FALSE;\n }\n }\n if(is_null(jn)) {\n return json_type.JSON_NULL;\n }\n\n log_error(`Not a json type`);\n return 0;\n}\n\n/************************************************************\n * Return if a value is an object (excluding arrays & null)\n ************************************************************/\nfunction is_object(value) {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/************************************************************\n * Return if a value is an array\n ************************************************************/\nfunction is_array(value) {\n return Array.isArray(value);\n}\n\n/************************************************************\n * Return if a value is a string\n ************************************************************/\nfunction is_string(value) {\n return typeof value === \"string\";\n}\n\n/************************************************************\n * Return if a value is a number (excluding NaN & Infinity)\n ************************************************************/\nfunction is_number(value) {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n/************************************************************\n * Return if a value is a boolean\n ************************************************************/\nfunction is_boolean(value) {\n return typeof value === \"boolean\";\n}\n\n/************************************************************\n * Return if a value is null or undefined\n ************************************************************/\nfunction is_null(value) {\n return value == null; // Covers both `null` and `undefined`\n}\n\n/************************************************************\n * Check if a string is a number\n * The function correctly identifies both integer and floating-point numbers.\n * It handles special cases like scientific notation (e.g., \"1.2e3\"),\n * positive/negative numbers, and fractional numbers without leading digits.\n * It returns false for non-numeric strings, empty strings,\n * and strings with only whitespace.\n ************************************************************/\nfunction is_pure_number(str)\n{\n if(is_number(str)) {\n return true;\n }\n if(!is_string(str)) {\n return false;\n }\n\n // Convert the string to a number\n const num = Number(str);\n\n // Check if the result is NaN (Not-a-Number)\n if (isNaN(num)) {\n return false; // The string is not a number\n }\n\n // Optionally, you can check if the input is exactly equal to the parsed number\n // This ensures that the input is a valid number string\n return str.trim() !== '' && !isNaN(num);\n}\n\n/************************************************************\n * Return if a value is a Date object\n ************************************************************/\nfunction is_date(value) {\n return value instanceof Date && !isNaN(value);\n}\n\n/************************************************************\n * Return if a value is a function\n ************************************************************/\nfunction is_function(value) {\n return typeof value === \"function\";\n}\n\n/************************************************************\n * Return if a value is an instance of GObj\n ************************************************************/\nfunction is_gobj(value) {\n return value instanceof GObj;\n}\n\n/************************************************************\n * Return if a value is an empty string or not a string\n ************************************************************/\nfunction empty_string(value) {\n return !is_string(value) || value.length === 0;\n}\n\n/*\n * Converts a string to a bool.\n *\n * This conversion will:\n *\n * - match 'true', 'on', or '1' as true.\n * - ignore all white-space padding\n * - ignore capitalization (case).\n *\n * ' tRue ','ON', and '1 ' will all evaluate as true.\n *\n */\nfunction parseBoolean(s)\n{\n if(is_number(s)) {\n return Boolean(s);\n }\n\n // will match one and only one of the string 'true','1', or 'on' rerardless\n // of capitalization and regardless off surrounding white-space.\n //\n let regex=/^\\s*(true|1|on)\\s*$/i;\n\n return regex.test(s);\n}\n\n/************************************************************\n * Like C functions\n ************************************************************/\nfunction strncmp(str1, str2, lgth)\n{\n // Binary safe string comparison\n //\n // version: 909.322\n // discuss at: http://phpjs.org/functions/strncmp\n // + original by: Waldo Malqui Silva\n // + input by: Steve Hilder\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + revised by: gorthaur\n // + reimplemented by: Brett Zamir (http://brett-zamir.me)\n // * example 1: strncmp(\"aaa\", \"aab\", 2);\n // * returns 1: 0\n // * example 2: strncmp(\"aaa\", \"aab\", 3 );\n // * returns 2: -1\n var s1 = (str1+\"\").substring(0, lgth);\n var s2 = (str2+\"\").substring(0, lgth);\n\n return ( ( s1 === s2 ) ? 0 : ( ( s1 > s2 ) ? 1 : -1 ) );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strcmp(str1, str2)\n{\n // http://kevin.vanzonneveld.net\n // + original by: Waldo Malqui Silva\n // + input by: Steve Hilder\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + revised by: gorthaur\n // * example 1: strcmp( \"waldo\", \"owald\" );\n // * returns 1: 1\n // * example 2: strcmp( \"owald\", \"waldo\" );\n // * returns 2: -1\n\n return ( ( str1 === str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strcasecmp(str1, str2)\n{\n // http://kevin.vanzonneveld.net\n // + original by: Waldo Malqui Silva\n // + input by: Steve Hilder\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + revised by: gorthaur\n // * example 1: strcmp( \"waldo\", \"owald\" );\n // * returns 1: 1\n // * example 2: strcmp( \"owald\", \"waldo\" );\n // * returns 2: -1\n let s1 = str1.toLowerCase();\n let s2 = str2.toLowerCase();\n\n return ( ( s1 === s2 ) ? 0 : ( ( s1 > s2 ) ? 1 : -1 ) );\n}\n\n/***************************************************************************\n Only compare str/int/real/bool items\n Complex types are done as matched\n Return lower, iqual, higher (-1, 0, 1), like strcmp\n***************************************************************************/\nfunction cmp_two_simple_json(jn_var1, jn_var2)\n{\n /*\n * Discard complex types, done as matched\n */\n if(is_object(jn_var1) ||\n is_object(jn_var2) ||\n is_array(jn_var1) ||\n is_array(jn_var2)) {\n return 0;\n }\n\n /*\n * First try number\n */\n if(is_number(jn_var1) || is_number(jn_var2)) {\n let val1 = Number(jn_var1);\n let val2 = Number(jn_var2);\n if(val1 > val2) {\n return 1;\n } else if(val1 < val2) {\n return -1;\n } else {\n return 0;\n }\n }\n\n /*\n * Try boolean\n */\n if(is_boolean(jn_var1) || is_boolean(jn_var2)) {\n let val1 = Number(jn_var1);\n let val2 = Number(jn_var2);\n if(val1 > val2) {\n return 1;\n } else if(val1 < val2) {\n return -1;\n } else {\n return 0;\n }\n }\n\n /*\n * Try string\n */\n let val1 = String(jn_var1);\n let val2 = String(jn_var2);\n return strcmp(val1, val2);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strstr(haystack, needle, bool)\n{\n // Finds first occurrence of a string within another\n //\n // version: 1103.1210\n // discuss at: http://phpjs.org/functions/strstr\n // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + bugfixed by: Onno Marsman\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // * example 1: strstr(‘Kevin van Zonneveld’, ‘van’);\n // * returns 1: ‘van Zonneveld’\n // * example 2: strstr(‘Kevin van Zonneveld’, ‘van’, true);\n // * returns 2: ‘Kevin ‘\n // * example 3: strstr(‘name@example.com’, ‘@’);\n // * returns 3: ‘@example.com’\n // * example 4: strstr(‘name@example.com’, ‘@’, true);\n // * returns 4: ‘name’\n var pos = 0;\n\n haystack += \"\";\n pos = haystack.indexOf(needle);\n if (pos === -1) {\n return false;\n } else {\n if (bool) {\n return haystack.substring(0, pos);\n } else {\n return haystack.slice(pos);\n }\n }\n}\n\n/***************************************************************************\n * Metadata key (variable) has a prefix of 2 underscore\n ***************************************************************************/\nfunction is_metadata_key(key)\n{\n if(!is_string(key)) {\n return false;\n }\n let i;\n for(i = 0; i < key.length; i++) {\n if (key[i] !== '_') {\n break;\n }\n if(i > 2) {\n break;\n }\n }\n return (i === 2);\n}\n\n/***************************************************************************\n * Private key (variable) has a prefix of 1 underscore\n ***************************************************************************/\nfunction is_private_key(key)\n{\n if(!is_string(key)) {\n return false;\n }\n let i;\n for(i = 0; i < key.length; i++) {\n if (key[i] !== '_') {\n break;\n }\n if(i > 2) {\n break;\n }\n }\n return (i === 1);\n}\n\n/************************************************************\n * Remove from `kw1` all keys in `kw2`.\n * `kw2` can be a string, object, or array.\n ************************************************************/\nfunction kw_pop(kw1, kw2)\n{\n if (typeof kw2 === \"object\" && !Array.isArray(kw2)) {\n // If kw2 is an object, remove its keys from kw1\n for (const key of Object.keys(kw2)) {\n delete kw1[key];\n }\n } else if (Array.isArray(kw2)) {\n // If kw2 is an array, recursively remove each element from kw1\n for (const item of kw2) {\n kw_pop(kw1, item);\n }\n } else if (typeof kw2 === \"string\") {\n // If kw2 is a string, remove it as a key from kw1\n delete kw1[kw2];\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_has_key(kw, key)\n{\n if(key in kw) {\n if (kw.hasOwnProperty(key)) {\n return true;\n }\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_find_path(gobj, kw, path, verbose)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n if(!(is_object(kw) || is_array(kw))) {\n log_error(`${gobj_short_name(gobj)}: kw must be list or dict`);\n return 0;\n }\n if(!is_string(path)) {\n log_error(`${gobj_short_name(gobj)}: path must be a string: ${String(path)}`);\n return 0;\n }\n let ss = path.split('`');\n if(ss.length<=1) {\n return kw[path];\n }\n let len = ss.length;\n for(let i=0; i<len; i++) {\n let key = ss[i];\n kw = kw[key];\n if(kw === undefined) {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: path not found: ${String(path)}`);\n }\n return undefined;\n }\n }\n return kw;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strrchr_split(str, char)\n{\n let index = str.lastIndexOf(char);\n if(index === -1) {\n return [str, \"\"]; // If char is not found, return whole string as first part and empty second part\n }\n return [str.substring(0, index), str.substring(index + 1)];\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_delete(gobj, kw, path)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let [path_, k] = strrchr_split(path, '`');\n if(!empty_string(k)) {\n let v = kw_find_path(gobj, kw, path_, true);\n json_object_del(v, k);\n } else {\n json_object_del(kw, path);\n }\n return 0;\n}\n\n/************************************************************\n * As the C kw_get_bool(): a boolean found is the answer, and\n * anything else gives the default back -- unless KW_WILD_NUMBER\n * asks to read a number (0 is false), a string (\"true\"/\"false\"\n * in any case, else its integer) or null (false). Before gobj-js\n * 7.25.2 the value went through Boolean(), so \"false\" was TRUE.\n ************************************************************/\nfunction kw_get_bool(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let b = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n const wild = flag && (flag & kw_flag_t.KW_WILD_NUMBER);\n\n if(b === undefined) {\n if(create) {\n let v = Boolean(default_value);\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return Boolean(default_value);\n }\n\n let value;\n if(is_boolean(b)) {\n value = b;\n } else if(wild && is_number(b)) {\n value = (b !== 0);\n } else if(wild && is_string(b)) {\n if(b.toLowerCase() === \"true\") {\n value = true;\n } else if(b.toLowerCase() === \"false\") {\n value = false;\n } else {\n value = (parseInt(b) || 0) !== 0;\n }\n } else if(wild && b === null) {\n value = false;\n } else {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE a boolean: ${path}`);\n trace_msg(kw);\n }\n return Boolean(default_value);\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n return value;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_int(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = parseInt(default_value);\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return parseInt(default_value);\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n if(!is_number(v)) {\n if(required) {\n log_error(`path value MUST BE a number: ${path}`);\n trace_msg(kw);\n }\n return parseInt(default_value);\n }\n\n return parseInt(v);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_real(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = Number(default_value);\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return Number(default_value);\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n if(!is_number(v)) {\n if(required) {\n log_error(`path value MUST BE a number: ${path}`);\n trace_msg(kw);\n }\n return Number(default_value);\n }\n\n return Number(v);\n}\n\n/************************************************************\n * The default comes back AS GIVEN, as in the C kw_get_str()\n * (`const char *default_value`, where 0 is NULL). Turned into\n * a string, a default of 0 or null was \"0\" or \"null\", which is\n * TRUE: an `if(value)` on the answer took an absent key for a\n * present one. KW_CREATE stores a string default, and null for\n * any other, as C stores json_null() for a NULL default.\n ************************************************************/\nfunction kw_get_str(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n kw_set_dict_value(gobj, kw, path,\n is_string(default_value)? default_value : null);\n return default_value;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n if(!is_string(v)) {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE a string: ${path}`);\n trace_msg(kw);\n }\n return default_value;\n }\n\n return v;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_pointer(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = default_value;\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n * As the C kw_get_dict(): a dict found is the answer, and\n * anything else gives the default back AS GIVEN (null stays\n * null). KW_CREATE stores a dict default, never a null one.\n * Before gobj-js 7.25.2 the answer went through Object(), so a\n * null default came back as {} and a 0 as a Number object.\n ************************************************************/\nfunction kw_get_dict(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create && is_object(default_value) && kw) {\n kw_set_dict_value(gobj, kw, path, default_value);\n return default_value;\n }\n if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(!is_object(v)) {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE a dict: ${path}`);\n trace_msg(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_dict_value(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = default_value;\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n * As the C kw_get_list(): a list found is the answer, and\n * anything else gives the default back AS GIVEN. KW_CREATE\n * stores a list default, never a null one. Before gobj-js\n * 7.25.2 the answer went through Array(), which WRAPS its\n * argument: a list found came back as [list], a default of []\n * as [[]] and a null one as [null].\n ************************************************************/\nfunction kw_get_list(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create && is_array(default_value) && kw) {\n kw_set_dict_value(gobj, kw, path, default_value);\n return default_value;\n }\n if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(!is_array(v)) {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE an array: ${path}`);\n trace_msg(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_set_dict_value(gobj, kw, path, value)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n if(!is_object(kw)) {\n log_error(\"kw is not an object\");\n return -1;\n }\n\n let ss = path.split('`');\n if(ss.length<=1) {\n kw[path] = value;\n return 0;\n }\n\n let len = ss.length;\n for(let i=0; i<len; i++) {\n let key = ss[i];\n if(i === len-1) {\n /* last segment */\n kw[key] = value;\n\n } else {\n let seg = kw[key];\n if(seg === undefined) {\n kw[key] = {};\n }\n kw = kw[key];\n }\n }\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_set_subdict_value(gobj, kw, path, key, value)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n if(!is_object(kw)) {\n log_error(\"kw is not an object\");\n return -1;\n }\n\n let subdict = kw_get_dict(gobj, kw, path, {}, kw_flag_t.KW_CREATE);\n if(!is_object(subdict)) {\n log_error(\"subdict is not an object\");\n return -1;\n }\n subdict[key] = value;\n\n return 0;\n}\n\n/***************************************************************************\n Match a json dict with a json filter (only compare str/number)\n ***************************************************************************/\nfunction _kw_match_simple(\n kw, // not owned\n jn_filter, // owned\n prefix_path\n)\n{\n let path = \"\";\n let matched = false;\n\n if(is_array(jn_filter)) {\n // Empty array evaluate as false, until a match condition occurs.\n matched = false;\n for(let idx = 0; idx < jn_filter.length; idx++) {\n let jn_filter_value = jn_filter[idx];\n /*\n * Complex variable, recursive\n */\n if(empty_string(prefix_path)) {\n path = sprintf(\"%s\", prefix_path);\n } else {\n path = sprintf(\"%s`%d\", prefix_path, idx);\n }\n\n matched = _kw_match_simple(\n kw, // not owned\n jn_filter_value, // owned\n path\n );\n if(matched) {\n break;\n }\n }\n\n } else if(is_object(jn_filter)) {\n // Object evaluate as true, until a NOT match condition occurs.\n matched = true;\n let keys = Object.keys(jn_filter);\n for(let i=0; i<keys.length; i++) {\n let key = keys[i];\n let jn_filter_value = jn_filter[key];\n if(empty_string(prefix_path)) {\n path = sprintf(\"%s\", key);\n } else {\n path = sprintf(\"%s`%s\", prefix_path, key);\n }\n\n if(is_array(jn_filter_value) || is_object(jn_filter_value)) {\n /*\n * Complex variable, recursive\n */\n matched = _kw_match_simple(\n kw, // not owned\n jn_filter_value, // owned\n path\n );\n if(!matched) {\n break;\n }\n continue;\n }\n\n /*\n * Get the record value, firstly by path else by name\n */\n // Firstly try the key as pointers\n let jn_record_value = kw_get_dict_value(0, kw, path, 0, 0);\n if(!jn_record_value) {\n // Secondly try the key with points (.) as full key\n jn_record_value = json_object_get(kw, path);\n }\n if(!jn_record_value) {\n matched = false;\n break;\n }\n\n /*\n * Do simple operation\n */\n let cmp = cmp_two_simple_json(jn_record_value, jn_filter_value);\n if(cmp!==0) {\n matched = false;\n break;\n }\n }\n }\n\n return matched;\n}\n\n/***************************************************************************\n Match a json dict with a json filter (only compare str/number)\n ***************************************************************************/\nfunction kw_match_simple(\n kw, // not owned\n jn_filter // owned\n)\n{\n if(json_size(jn_filter)===0) {\n // No filter, or an empty object or empty array evaluates as true.\n return true;\n }\n\n return _kw_match_simple(kw, jn_filter, \"\");\n}\n\n/***************************************************************************\n Get a the idx of simple json item in a json list.\n Return -1 if not found\n ***************************************************************************/\nfunction kw_find_json_in_list(\n gobj,\n kw_list,\n item,\n flag\n)\n{\n if(!item || !is_array(kw_list)) {\n if(flag) {\n log_error(`item NULL or kw_list is not a list`);\n }\n return -1;\n }\n\n for(let i=0; i<kw_list.length; i++) {\n let jn_item = kw_list[i];\n if(json_is_identical(item, jn_item)) {\n return i;\n }\n }\n\n if(flag) {\n log_error(`item not found in this list`);\n }\n return -1;\n}\n\n/*************************************************************\n Being `kw` a row's list or list of dicts [{},...],\n return a new list of **duplicated** kw filtering the rows by `jn_filter` (where),\n If match_fn is 0 then kw_match_simple is used.\n *************************************************************/\nfunction kw_select(gobj, kw, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!kw) {\n return null;\n }\n if(!match_fn) {\n match_fn = kw_match_simple;\n }\n let kw_new = [];\n\n if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let jn_value = kw[i];\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(json_deep_copy(jn_value));\n }\n }\n } else if(is_object(kw)) {\n if(match_fn(kw, jn_filter)) {\n kw_new.push(json_deep_copy(kw));\n }\n } else {\n log_error(\"kw_select() BAD kw parameter\");\n return null;\n }\n\n return kw_new;\n}\n\n/*************************************************************\n Being `kw` a row's list or list of dicts [{},...],\n return a new list of incref (clone) kw filtering the rows by `jn_filter` (where)\n If match_fn is 0 then kw_match_simple is used.\n *************************************************************/\nfunction kw_collect(gobj, kw, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!kw) {\n return null;\n }\n if(!match_fn) {\n match_fn = kw_match_simple;\n }\n let kw_new = [];\n\n if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let jn_value = kw[i];\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(jn_value);\n }\n }\n } else if(is_object(kw)) {\n if(match_fn(kw, jn_filter)) {\n kw_new.push(kw);\n }\n } else {\n log_error(\"kw_select() BAD kw parameter\");\n return null;\n }\n\n return kw_new;\n}\n\n/*************************************************************\n Return a new kw only with the keys got by dict's keys or list's keys (strings).\n Keys:\n \"$key\"\n [\"$key1\", \"$key2\", ...]\n {\"$key1\":*, \"$key2\":*, ...}\n\n It's not a deep copy, new keys are the paths.\n If paths are empty return kw\n *************************************************************/\nfunction kw_clone_by_keys(gobj, kw, keys, verbose) // old filter_dict\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let kw_clone = {};\n if(is_string(keys) && !empty_string(keys)) {\n let key = keys;\n if(kw.hasOwnProperty(key)) {\n kw_clone[key] = kw[key];\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n } else if(is_object(keys) && json_object_size(keys)>0) {\n for(let key of Object.keys(keys)) {\n if(kw.hasOwnProperty(key)) {\n kw_clone[key] = kw[key];\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else if(is_array(keys) && json_array_size(keys)>0) {\n for(let j=0; j<keys.length; j++) {\n let key = keys[j];\n if(kw.hasOwnProperty(key)) {\n kw_clone[key] = kw[key];\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else {\n return kw;\n }\n return kw_clone;\n}\n\n/***************************************************************************\n Return a new kw except the keys got by dict's keys or list's keys (strings).\n Keys:\n \"$key\"\n [\"$key1\", \"$key2\", ...]\n {\"$key1\":*, \"$key2\":*, ...}\n\n It's not a deep copy, new keys are the paths.\n If paths are empty return empty\n ***************************************************************************/\nfunction kw_clone_by_not_keys(\n gobj,\n kw,\n keys,\n verbose\n)\n{\n let kw_clone = {};\n json_object_update(kw_clone, kw);\n\n if(is_string(keys) && !empty_string(keys)) {\n let key = keys;\n let jn_value = kw_get_dict_value(gobj, kw, key, 0, 0);\n if(jn_value) {\n json_object_del(kw_clone, key);\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n } else if(is_object(keys) && json_object_size(keys)>0) {\n for(let key of Object.keys(keys)) {\n if(kw.hasOwnProperty(key)) {\n json_object_del(kw_clone, key);\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else if(is_array(keys) && json_array_size(keys)>0) {\n for(let j=0; j<keys.length; j++) {\n let key = keys[j];\n if(kw.hasOwnProperty(key)) {\n json_object_del(kw_clone, key);\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else {\n return {};\n }\n\n return kw_clone;\n}\n\n/********************************************\n * Get a local attribute\n ********************************************/\nfunction kw_get_local_storage_value(key, default_value, create = false)\n{\n if (typeof window === \"undefined\" || !window.localStorage) {\n return undefined; // Avoid errors in Node.js\n }\n\n try {\n let value = window.localStorage.getItem(key);\n\n if (value === null) { // `null` means key doesn't exist\n if (create) {\n kw_set_local_storage_value(key, default_value);\n }\n return default_value;\n }\n\n return JSON.parse(value); // Try parsing JSON\n } catch (e) {\n window.console.warn(`Error reading localStorage key \"${key}\":`, e);\n return default_value;\n }\n}\n\n/********************************************\n * Save a local attribute\n *\n * Returns 0 on success, -1 when the value did NOT reach the store.\n * It used to return nothing and only console.warn, so every caller up the\n * chain (db_save_persistent_attrs -> gobj_save_persistent_attrs -> the app)\n * reported success on a store that had rejected the write: a full or blocked\n * localStorage (quota, private mode) silently discarded the change while the\n * UI showed it as saved.\n ********************************************/\nfunction kw_set_local_storage_value(key, value)\n{\n if (typeof window === \"undefined\" || !window.localStorage) {\n return 0; // No store outside the browser: not a failure\n }\n if (!key || value === undefined) {\n log_error(`kw_set_local_storage_value(): invalid key or value: key=${key}`);\n return -1;\n }\n\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n return 0;\n } catch (e) {\n log_error(`kw_set_local_storage_value(): cannot save \"${key}\" ` +\n `(storage full or blocked?): ${e && e.message ? e.message : e}`);\n return -1;\n }\n}\n\n/********************************************\n * Remove local attribute\n ********************************************/\nfunction kw_remove_local_storage_value(key)\n{\n if (typeof window === \"undefined\" || !window.localStorage) {\n return; // Prevents errors in Node.js\n }\n if (!key) {\n window.console.warn(`Invalid key for localStorage removal: ${key}`);\n return;\n }\n\n try {\n window.localStorage.removeItem(key);\n } catch (e) {\n window.console.warn(`Error removing localStorage key \"${key}\":`, e);\n }\n}\n\n/*************************************************************\n Utility for databases.\n Return true if `id` is in the list/dict/str `ids`\n *************************************************************/\nfunction kwid_match_id(ids, id)\n{\n if(is_null(ids) || is_null(id)) {\n // No filter: everything passes.\n return true;\n }\n\n if(is_array(ids)) {\n if(ids.length===0) {\n // An empty list at the first level evaluates as true.\n return true;\n }\n for(let i=0; i<ids.length; i++) {\n let value = ids[i];\n if(value === id) {\n return true;\n }\n }\n\n } else if(is_object(ids)) {\n if(Object.keys(ids).length===0) {\n // An empty object at the first level evaluates as true.\n return true;\n }\n for(let key in ids) {\n if(key === id) {\n return true;\n }\n }\n\n } else if(is_string(ids)) {\n if(ids === id) {\n return true;\n }\n }\n\n return false;\n}\n\n/*************************************************************\n Utility for databases.\n Being `kw` a:\n - list of strings [s,...]\n - list of dicts [{},...]\n - dict of dicts {id:{},...}\n return a NEW list holding the rows that match `ids` and the\n `jn_filter` (where). If match_fn is 0 then kw_match_simple is used.\n\n WARNING the LIST is new; its elements are THE SAME objects, not\n copies. The C twin increfs each one and says \"clone\", which this\n comment repeated for years: javascript has no refcount, so a write\n through a collected row writes into `kw`. Copy what you mean to\n modify.\n\n Returns null -- not an empty list -- for a `kw` that is neither a\n list nor a dict, so a caller that reads `.length` off the answer\n must check it first (kwid_find_one_record does).\n *************************************************************/\nfunction kwid_collect(gobj, kw, ids, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!kw) {\n return null;\n }\n if(!match_fn) {\n match_fn = kw_match_simple;\n }\n let kw_new = [];\n\n if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let jn_value = kw[i];\n\n let id;\n if(is_object(jn_value)) {\n id = kw_get_str(gobj, jn_value, \"id\", \"\", 0);\n } else if(is_string(jn_value)) {\n id = jn_value;\n } else {\n continue;\n }\n\n if(!kwid_match_id(ids, id)) {\n continue;\n }\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(jn_value);\n }\n }\n } else if(is_object(kw)) {\n for(let id of Object.keys(kw)) {\n let jn_value = kw[id];\n\n if(!kwid_match_id(ids, id)) {\n continue;\n }\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(jn_value);\n }\n }\n\n } else {\n log_error(\"kw_collect() BAD kw parameter\");\n return null;\n }\n\n return kw_new;\n}\n\n/*************************************************************\n Utility for databases.\n Return a dict from a \"dict of records\" or \"list of records\".\n WARNING the \"id\" of a dict's record is hardcoded to its key.\n Convention:\n - all arrays are lists of records (dicts) with \"id\" as primary key\n - delimiter is '`' and '.'\n If path is empty then use kw\n\n WARNING \"new\" is the C twin's word, where it means a new REFERENCE:\n handed a dict, both return THAT dict and not a copy of it. Only the\n list case builds something new, and even then the records inside it\n are the same objects.\n *************************************************************/\nfunction kwid_new_dict(gobj, kw, path)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let new_dict = {};\n if(!empty_string(path)) {\n kw = kw_find_path(gobj, kw, path);\n }\n if(is_object(kw)) {\n new_dict = kw;\n\n } else if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let kv = kw[i];\n /* KW_REQUIRED, as the C twin passes: under the rule this\n * file serves -- the key of a data record is its `id` -- a\n * record without one is broken, and it used to be dropped\n * in silence. The dict then came back short, and nothing\n * said which row had gone or why. */\n let id = kw_get_str(gobj, kv, \"id\", \"\", kw_flag_t.KW_REQUIRED);\n if(!empty_string(id)) {\n new_dict[id] = kv;\n }\n }\n\n } else {\n log_error(`${gobj_short_name(gobj)} kwid_new_dict: data type unknown`);\n }\n\n return new_dict;\n}\n\n/*************************************************************\n Utility for databases.\n Return a list from a \"dict of records\" or \"list of records\".\n The NORMALIZING function of this family: whatever shape the data\n arrives in, what comes back is the shape a table indexed and\n sorted by `id` wants.\n Convention:\n - all arrays are lists of records (dicts) with \"id\" as primary key\n - delimiter is '`' and '.'\n If path is empty then use kw\n\n WARNING handed a DICT it writes each record's key into the record\n as its `id`, OVERWRITING one that differs -- in the source records,\n which it does not copy. That is the C twin's behaviour\n (`json_object_set_new(v, \"id\", ...)` in kwid.c) and it is the point:\n a dict keyed by id whose records disagree with their own key is\n exactly what this is for. Handed a LIST it returns that same list,\n untouched, as C returns a new reference to it.\n *************************************************************/\nfunction kwid_new_list(gobj, kw, path)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!empty_string(path)) {\n kw = kw_find_path(gobj, kw, path);\n }\n\n if(is_array(kw)) {\n return kw;\n }\n\n if(is_object(kw)) {\n let new_list = [];\n for(let id of Object.keys(kw)) {\n let record = kw[id];\n if(!is_object(record)) {\n log_error(\n `${gobj_short_name(gobj)} kwid_new_list: ` +\n `not a record: '${id}'`\n );\n continue;\n }\n record[\"id\"] = id; // WARNING id hardcoded, as in C\n new_list.push(record);\n }\n return new_list;\n }\n\n log_error(`${gobj_short_name(gobj)} kwid_new_list: wrong type for list`);\n return [];\n}\n\n/*************************************************************\n * Utility for databases. See kwid_collect parameters\n *************************************************************/\nfunction kwid_find_one_record(gobj, kw, ids, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let list = kwid_collect(gobj, kw, ids, jn_filter, match_fn);\n /* kwid_collect() answers null -- not an empty list -- for a kw that\n * is neither a list nor a dict, and for a kw that is missing\n * altogether. Reading `.length` off that is a TypeError thrown at\n * the caller, which is how a command answer with no data crashed a\n * view instead of finding nothing. */\n if(!list || list.length === 0) {\n return null;\n }\n return list[0];\n}\n\n/*************************************************************\n Utility for databases.\n Being `ids` a:\n\n \"$id\"\n\n {\n \"$id\": {\n \"id\": \"$id\",\n ...\n }\n ...\n }\n\n [\"$id\", ...]\n\n [\n \"$id\",\n {\n \"id\":$id,\n ...\n },\n ...\n ]\n\n return a list of all ids\n*************************************************************/\nfunction kwid_get_ids(gobj, ids)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!ids) {\n return [];\n }\n\n let new_ids = [];\n\n if(is_string(ids)) {\n /*\n \"$id\"\n */\n new_ids.push(ids);\n } else if(is_object(ids)) {\n /*\n {\n \"$id\": {\n \"id\": \"$id\",\n ...\n }\n ...\n }\n */\n for(let id in ids) {\n if (ids.hasOwnProperty(id)) {\n new_ids.push(id);\n }\n }\n } else if(is_array(ids)) {\n ids.forEach(function(item) {\n if(is_string(item)) {\n /*\n [\"$id\", ...]\n */\n if(!empty_string(item)) {\n new_ids.push(item);\n }\n } else if(is_object(item)) {\n /*\n [\n {\n \"id\":$id,\n ...\n },\n ...\n ]\n */\n let id = kw_get_str(gobj, item, \"id\", 0, 0);\n if(id) {\n new_ids.push(id);\n }\n }\n });\n }\n\n return new_ids;\n}\n\n/********************************************************\n * Convert [s] or [{}] or {}\n * in a webix list options:\n * [{id:\"\", value:\"\"}, ...]\n ********************************************************/\nfunction list2options(list, field_id, field_value)\n{\n field_id = field_id?field_id:\"id\";\n field_value = field_value?field_value:\"value\";\n\n let options = [];\n\n if(is_array(list)) {\n for(let i=0; i<list.length; i++) {\n let v = list[i];\n if(is_string(v)) {\n options.push({\n id: list[i],\n value: list[i]\n });\n } else if(is_object(v)) {\n let vv = {};\n if(!kw_has_key(v, field_id)) {\n /* If not exist, then get the first entry */\n if(json_size(v)>0) {\n field_id = Object.keys(v)[0];\n } else {\n log_error(\"list2options(): object without field id: \" + field_id);\n continue;\n }\n vv[\"id\"] = field_id;\n vv[\"value\"] = v[field_id];\n } else {\n if(!kw_has_key(v, field_value)) {\n /* If not exist, then get the first entry */\n if(json_size(v)>0) {\n field_value = Object.keys(v)[0];\n } else {\n log_error(\"list2options(): object without field value: \" + field_value);\n continue;\n }\n\n }\n vv[\"id\"] = v[field_id];\n vv[\"value\"] = v[field_value];\n }\n options.push(vv);\n\n } else {\n log_error(\"list2options(): case1 not implemented\");\n }\n }\n } else if(is_object(list)) {\n for(let k of Object.keys(list)) {\n options.push({\n id: k,\n value: k\n });\n }\n } else {\n log_error(\"list2options(): case2 not implemented\");\n }\n\n return options;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction id_index_in_obj_list(list, id) {\n if(!list) {\n return -1;\n }\n for(let i=0; i<list.length; i++) {\n if(list[i] && list[i].id === id) {\n return i;\n }\n }\n return -1;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction str_in_list(list, str, ignore_case)\n{\n if(!list || !str) {\n log_error(\"ERROR: str_in_list() list or str empty\");\n return false;\n }\n\n let len = list.length;\n\n if(ignore_case) {\n str = str.toLowerCase();\n\n for(let i = 0; i < len; i++) {\n let item = list[i];\n if(item && item.toLowerCase() === str) {\n return true;\n }\n }\n\n } else {\n for(let i = 0; i < len; i++) {\n if(list[i] === str) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strs_in_list(list, strs, ignore_case)\n{\n if(!list) {\n log_error(\"ERROR: strs_in_list() list empty\");\n return false;\n }\n if(!strs) {\n log_error(\"ERROR: strs_in_list() str empty\");\n return false;\n }\n\n for(let i=0; i<strs.length; i++) {\n let str = strs[i];\n if(str_in_list(list, str, ignore_case)) {\n return true;\n }\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction delete_from_list(list, elm)\n{\n for(let i=0; i<list.length; i++) {\n if(elm === list[i]) {\n list.splice(i, 1);\n return true;\n }\n }\n return false; // elm does not exist!\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_read_key(kw, key)\n{\n try {\n let __md_iev__ = kw[\"__md_iev__\"];\n if(__md_iev__) {\n return __md_iev__[key];\n }\n } catch (e) {\n return undefined;\n }\n return undefined;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_write_key(kw, key, value)\n{\n let __md_iev__ = kw[\"__md_iev__\"];\n if(!__md_iev__) {\n __md_iev__ = {};\n kw[\"__md_iev__\"] = __md_iev__;\n }\n __md_iev__[key] = value;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_push_stack(gobj, kw, stack, jn_data)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj is not a GObj`);\n return null;\n }\n if(!kw) {\n return;\n }\n\n let jn_stack = msg_iev_read_key(kw, stack);\n if(!jn_stack) {\n jn_stack = [];\n msg_iev_write_key(kw, stack, jn_stack);\n }\n try {\n // Code throwing an exception\n if(is_array(jn_stack)) {\n jn_stack.unshift(jn_data);\n }\n } catch(e) {\n log_error(e);\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_get_stack(gobj, kw, stack, verbose)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj is not a GObj`);\n return null;\n }\n if(!is_object(kw)) {\n log_error(`kw is not a dict`);\n return null;\n }\n\n let jn_stack = msg_iev_read_key(kw, stack);\n if(!jn_stack) {\n if(verbose) {\n log_error(`stack NOT FOUND: ${stack}`);\n }\n return null;\n }\n\n if(jn_stack.length === 0) {\n if(verbose) {\n log_error(`stack empty: ${stack}`);\n }\n return null;\n }\n return jn_stack[0];\n}\n\n/************************************************************\n *\n msg_type_list = [\n \"__identity__\", // Used in identity card\n \"__command__\", // Used in commands\n \"__stats__\", // Used in stats\n \"__subscribing__\", // Used in subscribing events\n \"__unsubscribing__\", // Used in unsubscribing events\n \"__message__\", // Used in messages\n\n \"__publishing__\",\n \"__query__\",\n \"__answer__\",\n \"__request__\",\n \"__response__\",\n \"__order__\",\n \"__poll__\",\n \"__first_shot__\"\n ];\n\n ************************************************************/\nfunction msg_iev_set_msg_type(\n gobj,\n kw,\n msg_type // empty string to delete the key\n)\n{\n if(!empty_string(msg_type)) {\n kw_set_subdict_value(gobj, kw, \"__md_iev__\", \"__msg_type__\", msg_type);\n } else {\n kw_delete(gobj, kw, \"__md_iev__`__msg_type__\");\n }\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_get_msg_type(gobj, kw)\n{\n return kw_get_str(gobj, kw, \"__md_iev__`__msg_type__\", \"\", 0);\n}\n\n/************************************************************\n * Load json file from server\n ************************************************************/\nfunction _fileLoaded(xhr) {\n return xhr.status === 0 && xhr.responseText && xhr.responseURL.startsWith(\"file:\");\n}\nfunction load_json_file(url, on_success, on_error)\n{\n let req = new XMLHttpRequest();\n req.open(\"GET\", url, true);\n req.setRequestHeader(\"Accept\", \"application/json\");\n\n req.onreadystatechange = function () {\n if (req.readyState === 4) {\n if (req.status === 200 || _fileLoaded(req)) {\n try {\n let json = JSON.parse(req.responseText);\n on_success(json);\n } catch (error) {\n if (on_error) {\n log_error(`JSON parse status ${req.status}, error: ${error.message}`);\n on_error(req.status);\n }\n }\n } else {\n if (on_error) {\n on_error(req.status);\n }\n }\n }\n };\n\n req.send();\n}\n\n/************************************************************\n * Post http\n * function on_response(status, response_data)\n ************************************************************/\nfunction send_http_json_post(url, data, on_response) {\n\n let xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url);\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n on_response(xhr.status, xhr.responseText);\n }\n };\n xhr.send(data);\n}\n\n/************************************************************\n * callback (obj, key, value, full_path)\n ************************************************************/\nfunction _traverse_dict(obj, callback, full_path)\n{\n if(full_path === undefined || !is_string(full_path)) {\n full_path = \"\";\n }\n for (let key of Object.keys(obj)) {\n if(!obj.hasOwnProperty(key)) {\n continue;\n }\n let sufix = (full_path.length? '`':'') + key;\n full_path += sufix;\n\n callback.apply(this, [obj, key, obj[key], full_path]);\n\n if(is_object(obj[key])) {\n //going one step down in the object tree!!\n _traverse_dict(obj[key], callback, full_path);\n }\n\n full_path = full_path.slice(0, -sufix.length);\n }\n}\n\n/************************************************************\n * Init json database\n * Hierarchical tree. To use in webix style.\n * If a record has children,\n * the own record has the key 'data' with the array of child records\n *\n * Initialization\n * --------------\n var jdb = {\n \"type\": [], // Can be [] or {}\n \"hook\": \"data\",\n \"schema\": { // topics\n \"app_menu\": [],\n \"account_menu\": []\n }\n };\n\n jdb_init(jdb);\n\n *\n * Inside example\n * --------------\n * jdb: {\n * hook: \"data\",\n * type: []\n * schema:{\n * app_menu: [],\n * account_menu: [],\n * ...\n * }\n * topics: {\n * app_menu: [\n * {\n * id: // Mandatory field\n * icon: // Remains: optional fields\n * value:\n * action:\n * },\n * {\n * id:\n * icon:\n * value:\n * action:\n * data: [\n * {\n * id:\n * icon:\n * value:\n * action:\n * },\n *\n * ]\n * },\n * ...\n * ]\n * }\n * }\n ************************************************************/\nfunction jdb_init(jdb, prefix, duplicate)\n{\n if(duplicate) {\n jdb = json_deep_copy(jdb);\n }\n let type = kw_get_dict_value(null, jdb, \"type\", [], 1);\n let hook = kw_get_str(null, jdb, \"hook\", \"data\", 1);\n let schema = kw_get_dict_value(null, jdb, \"schema\", {}, 1);\n let topics = kw_get_dict_value(null, jdb, \"topics\", {}, 1);\n\n // Create topics defined in schema\n let walk = function(obj, key, value, full_path) {\n if(key.substring(0, 2) !== \"__\") {\n kw_get_dict_value(null, topics, full_path, json_deep_copy(type), 1);\n //trace_msg(sprintf(\"full_path: '%s', key: %s, value: %j\", full_path, key, value));\n }\n };\n _traverse_dict(schema, walk, prefix);\n\n return jdb;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_update(jdb, topic_name, path, kw)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_update: topic not found: \" + topic_name);\n return null;\n }\n if(empty_string(kw[\"id\"])) {\n log_error(\"jdb_update: record without id: \" + kw);\n trace_msg(kw);\n return null;\n }\n\n let ids = path.split('`');\n\n let id;\n let v = topic;\n while((id = ids.shift())) {\n if(empty_string(id) || !v) {\n break;\n }\n if(is_object(v)) {\n v = kw_get_dict_value(null, v, jdb.hook, [], 1);\n }\n v = _jdb_get(v, null, id, false);\n }\n\n if(ids.length===0 && v) {\n if(is_array(v)) {\n v.push(kw);\n } else {\n if(v[\"id\"]===kw[\"id\"]) {\n Object.assign(v, kw);\n } else {\n let v_ = kw_get_dict_value(null, v, jdb.hook, [], 1);\n let v__ = _jdb_get(v_, jdb.hook, kw[\"id\"], false);\n if(v__) {\n Object.assign(v__, kw);\n } else {\n v_.push(kw);\n }\n }\n }\n }\n\n //trace_msg(JSON.stringify(topic, null, 4));\n\n return topic;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_delete(jdb, topic_name, path, kw)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_delete: topic not found: \" + topic_name);\n return null;\n }\n if(empty_string(kw[\"id\"])) {\n log_error(\"jdb_delete: record without id: \" + kw);\n trace_msg(kw);\n return null;\n }\n\n let ids = path.split('`');\n\n let id;\n let v = topic;\n while((id = ids.shift())) {\n if(empty_string(id) || !v) {\n break;\n }\n if(is_object(v)) {\n v = kw_get_dict_value(null, v, jdb.hook, null, 0);\n }\n v = _jdb_get(v, null, id, false);\n }\n\n if(ids.length===0 && v) {\n if(is_array(v)) {\n let idx = id_index_in_obj_list(v, kw[\"id\"]);\n if(idx >= 0) {\n v.splice(idx, 1);\n }\n } else {\n let v_ = kw_get_dict_value(null, v, jdb.hook, null, 0);\n let idx = id_index_in_obj_list(v_, kw[\"id\"]);\n if(idx >= 0) {\n v_.splice(idx, 1);\n }\n }\n }\n\n //trace_msg(JSON.stringify(topic, null, 4));\n\n return topic;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_get_topic(jdb, topic_name)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0, false);\n if(!topics) {\n log_error(\"jdb topics section not found\");\n trace_msg(jdb);\n return null;\n }\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0, false);\n if(!topic) {\n log_error(\"jdb topic not found: \" + topic_name);\n trace_msg(topics);\n return null;\n }\n return topic;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_get(jdb, topic_name, id, recursive)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_get: topic not found: \" + topic_name);\n return null;\n }\n if(recursive === undefined) {\n recursive = true;\n }\n return _jdb_get(topic, jdb.hook, id, recursive);\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_get_by_idx(jdb, topic_name, idx)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_get_by_idx: topic not found: \" + topic_name);\n return null;\n }\n if(idx < topic.length) {\n return topic[idx];\n } else {\n return {};\n }\n}\n\n/**************************************************\n * Busca el id en el arbol.\n * Los id deben ser únicos, como requiere webix\n **************************************************/\nfunction _jdb_get(v, hook, id, recursive)\n{\n if(!v) {\n return null;\n }\n let j;\n let ln = v.length;\n for(j=0; j<ln; j++) {\n let v_ = v[j];\n if(v_) {\n let id_ = v_[\"id\"];\n if(id_ && (id_ === id)) {\n return v_;\n }\n if(recursive) {\n if(kw_has_key(v_, hook)) {\n let v__ = _jdb_get(v_[hook], hook, id, recursive);\n if(v__) {\n return v__;\n }\n }\n }\n }\n }\n return null;\n}\n\n/***************************************************************************\n *\n * type can be: str, int, real, bool, null, dict, list\n * Example:\n\n static json_desc_t jn_xxx_desc[] = {\n // Name Type Default\n {\"string\", \"str\", \"\"},\n {\"string2\", \"str\", \"Pepe\"},\n {\"integer\", \"int\", \"0660\"}, // beginning with \"0\":octal,\"x\":hexa, others: integer\n {\"boolean\", \"bool\", \"false\"},\n {0} // HACK important, final null\n };\n\n ***************************************************************************/\nfunction create_json_record(json_desc, value) // here in js `json_desc` it's a dictionary with the defaults.\n{\n let record = json_deep_copy(json_desc); // Get fields and default values from json_desc\n json_object_update_existing(record, value); // Update (only with service fields) with user data\n\n return record;\n}\n\n/************************************************************\n * https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library\n ************************************************************/\nfunction jwtDecode(jwt)\n{\n function b64DecodeUnicode(str) {\n return decodeURIComponent(atob(str).replace(/(.)/g, function (m, p) {\n let code = p.charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = '0' + code;\n }\n return '%' + code;\n }));\n }\n\n function decode(str) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw \"Illegal base64url string!\";\n }\n\n try {\n return b64DecodeUnicode(output);\n } catch (err) {\n return atob(output);\n }\n }\n\n let jwtArray = jwt.split('.');\n\n return {\n header: decode(jwtArray[0]),\n payload: decode(jwtArray[1]),\n signature: decode(jwtArray[2])\n };\n}\n\n/************************************************************\n * Decoded jwt and return in json\n * 'what' can be \"header\", \"payload\" or \"signature\"\n * default is \"payload\"\n ************************************************************/\nfunction jwt2json(jwt, what)\n{\n try {\n let jwt_decoded = jwtDecode(jwt);\n switch(what) {\n case \"header\":\n return JSON.parse(jwt_decoded.header);\n case \"signature\":\n return JSON.parse(jwt_decoded.signature);\n case \"payload\":\n default:\n return JSON.parse(jwt_decoded.payload);\n }\n } catch (e) {\n return null;\n }\n}\n\n/***************************************************************************\n * Escape a value for safe insertion into an HTML context.\n * Use this whenever user- or server-supplied strings are interpolated\n * into an innerHTML / style.innerHTML template literal.\n ***************************************************************************/\nfunction escapeHtml(str)\n{\n if(str == null) {\n return '';\n }\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/***************************************************************************\n * Validate and escape a URL for use as an image/media src attribute.\n * Blocks javascript: and data: URIs that could be used for XSS.\n * Returns an empty string for any disallowed scheme.\n ***************************************************************************/\nfunction safeSrc(url)\n{\n if(!url) {\n return '';\n }\n const s = String(url).trim();\n if(/^javascript:/i.test(s) || /^data:/i.test(s)) {\n return '';\n }\n return escapeHtml(s);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction createOneHtml(htmlString)\n{\n // Convert the HTML string to DOM nodes\n const template = document.createElement('template');\n template.innerHTML = htmlString.trim(); // Trim to avoid extra text nodes\n\n return template.content.firstChild;\n}\n\n/***************************************************************************\n * Code written by ChatGPT\n Example usage:\n\n function makeDraggable(handle, target) {\n let offsetX = 0;\n let offsetY = 0;\n\n // Called when the drag starts\n const onMouseDown = (e) => {\n // Calculate the initial offset\n offsetX = e.clientX - target.getBoundingClientRect().left;\n offsetY = e.clientY - target.getBoundingClientRect().top;\n\n // Attach the listeners to the document to allow for free movement\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n };\n\n // Called when the mouse is moved\n const onMouseMove = (e) => {\n // Calculate the new position\n const x = e.clientX - offsetX;\n const y = e.clientY - offsetY;\n\n // Update the position of the target\n target.style.left = `${x}px`;\n target.style.top = `${y}px`;\n };\n\n // Called when the mouse button is released\n const onMouseUp = () => {\n // Remove the listeners from the document\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n };\n\n // Attach the mousedown listener to the handle\n handle.addEventListener('mousedown', onMouseDown);\n }\n\n function addResizeFunctionality(resizeHandle, windowElement) {\n let startX, startY, startWidth, startHeight;\n\n const onMouseDown = (e) => {\n // Prevent default action (like text selection) during resize\n e.preventDefault();\n\n startX = e.clientX;\n startY = e.clientY;\n startWidth = parseInt(document.defaultView.getComputedStyle(windowElement).width, 10);\n startHeight = parseInt(document.defaultView.getComputedStyle(windowElement).height, 10);\n\n document.documentElement.addEventListener('mousemove', onMouseMove, false);\n document.documentElement.addEventListener('mouseup', onMouseUp, false);\n };\n\n const onMouseMove = (e) => {\n // Calculate new size\n const newWidth = startWidth + e.clientX - startX;\n const newHeight = startHeight + e.clientY - startY;\n\n // Update window size\n windowElement.style.width = `${newWidth}px`;\n windowElement.style.height = `${newHeight}px`;\n };\n\n const onMouseUp = () => {\n // Remove the listeners when resizing is done\n document.documentElement.removeEventListener('mousemove', onMouseMove, false);\n document.documentElement.removeEventListener('mouseup', onMouseUp, false);\n };\n\n // Attach the mousedown listener to the resize handle\n resizeHandle.addEventListener('mousedown', onMouseDown, false);\n }\n\n\n function createWindow({ title, x, y, width, height, parent }) {\n const windowEl = createElement2([\n 'div',\n {\n class: 'window',\n // style: `position: absolute; left: ${x}px; top: ${y}px; width: ${width}px; height: ${height}px; display: flex; flex-direction: column; border: 1px solid black;`\n style: {\n position: \"absolute\",\n left: `${x}px`,\n top: `${y}px`,\n width: `${width}px`,\n height: `${height}px`,\n display: \"flex\",\n \"flex-direction\": \"column\",\n border: \"1px solid black\",\n }\n },\n [\n ['div', { class: 'window-top', style: 'display: flex; justify-content: space-between; padding: 5px; border-bottom: 1px solid black;cursor:move;' },\n [\n ['span', {}, title],\n ['button', {}, 'Close', {\n click: (e) => {\n e.target.closest('.window').remove();\n }\n }]\n ]\n ],\n ['div', { class: 'window-content', style: 'flex-grow: 1; padding: 5px;' }, 'This is the content area.'],\n ['div', { class: 'window-bottom', style: 'padding: 5px; border-top: 1px solid black; display: flex; justify-content: flex-end;' },\n [\n ['div', { class: 'resize-handle', style: 'width: 20px; height: 20px; cursor: nwse-resize;' }, '', {\n mousedown: (e) => {\n // Resize logic here\n }\n }]\n ]\n ]\n ]\n ]);\n\n const resizeHandle = windowEl.querySelector('.resize-handle');\n\n makeDraggable(windowEl.querySelector('.window-top'), windowEl);\n addResizeFunctionality(resizeHandle, windowEl);\n\n parent.appendChild(windowEl);\n }\n\n\n // Example usage\n createWindow({\n title: 'My Draggable Window',\n x: 100,\n y: 100,\n width: 400,\n height: 300,\n parent: document.body\n });\n ***************************************************************************/\n\n\n/***************************************************************************\n * Create a HTMLElement:\n * [tag, attrs, content, events]\n *\n * tag -> string\n *\n * attrs -> {key:string}\n * Special case for key=='style'\n * could be `style:'string'`\n * or `style:{k:s}`\n * Special case for key=='i18n' (or 'data-i18n' or 'data_i18next')\n * will be 'data-i18n' attr\n *\n * content -> string | [createElement2() or parameters of createElement2]\n * if string begins with '<' then\n * it will be converted to HTMLElement\n * content = createOneHtml(string)\n * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')\n* it will be overridden with the translation\n * content = translate(attrs['i18n']));\n *\n * events -> {event: ()}\n *\n * Return the created element\n *\n * Examples:\n * ['div', { class: 'window-top', style: 'border-bottom: 1px solid black;' },\n * [\n * ['span', {}, 'title'],\n * ['button', {}, 'Close', {\n * click: (e) => {\n * e.target.closest('.window').remove();\n * }\n * }]\n * ]\n * ]\n *\n * ['span', {style: {position: 'absolute'} }, 'title'],\n *\n ***************************************************************************/\nfunction createElement2(description, translate_fn) {\n let [tag, attrs, content, events] = description;\n\n /*\n * Create the html element\n */\n if (!tag) {\n log_error(\"Tag must be a valid HTML element.\");\n return;\n }\n let el = document.createElement(tag);\n\n /*\n * Append attributes\n */\n let data_i18next = '';\n\n if(attrs && typeof attrs === 'object') {\n for (let attr of Object.keys(attrs)) {\n if (attr === 'style' && typeof attrs[attr] === 'object') {\n // Convert the style object to a CSS string\n let styleString = '';\n\n for(const prop of Object.keys(attrs[attr])) {\n styleString += `${prop}: ${attrs[attr][prop]};`;\n }\n el.style.cssText = styleString;\n } else if (attr === 'style') {\n el.style.cssText = attrs[attr];\n } else {\n if(attr === 'i18n' || attr === 'data-i18n' ||\n attr === 'data_i18next' || attr === 'data-i18next') {\n /*\n * A nullish i18n key would render the literal\n * data-i18n=\"undefined\" and block translation\n * (e.g. a field whose `header` is undefined).\n * Skip the attribute instead of poisoning it.\n * An explicit empty string is still honoured.\n */\n if(attrs[attr] !== null && attrs[attr] !== undefined) {\n data_i18next = attrs[attr];\n el.setAttribute('data-i18n', data_i18next);\n }\n } else {\n el.setAttribute(attr, attrs[attr]);\n }\n }\n }\n }\n\n /*\n * Append content, it can be a string or another kids\n */\n if(is_string(content)) {\n content = content.trim();\n if(content.length > 0 && content[0] === '<') {\n el.appendChild(createOneHtml(content));\n } else {\n if(translate_fn && data_i18next) {\n let translated = translate_fn(data_i18next);\n el.textContent = translated?translated:content;\n } else {\n el.textContent = content;\n }\n }\n } else if(is_array(content)) {\n if(content.length > 0) {\n if(is_string(content[0])) {\n el.appendChild(createElement2(content, translate_fn));\n } else {\n for (let child of content) {\n // Check if the child is an array description or an HTMLElement\n if (Array.isArray(child) && child.length > 0) {\n el.appendChild(createElement2(child, translate_fn));\n } else if (child instanceof HTMLElement) {\n el.appendChild(child);\n }\n }\n }\n }\n } else if(content instanceof HTMLElement ||\n content instanceof Text ||\n content instanceof SVGElement)\n {\n el.appendChild(content);\n } else {\n if(content != null) {\n log_error(\"content ignored\");\n trace_json(content);\n }\n }\n\n /*\n * Attach event listeners\n */\n if (events && typeof events === 'object') {\n for(const eventType of Object.keys(events)) {\n el.addEventListener(eventType, events[eventType]);\n }\n }\n\n return el;\n}\n\n/***************************************************************************\n * Code written by ChatGPT\n // Usage example:\n ***************************************************************************/\nfunction getPositionRelativeToBody(element)\n{\n if (!element) {\n return {\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n };\n }\n\n const { top, left, width, height } = element.getBoundingClientRect?.() || { top: 0, left: 0, width: 0, height: 0 };\n\n const isBrowser = typeof window !== \"undefined\";\n const scrollTop = isBrowser ? window.scrollY || document.documentElement?.scrollTop || document.body?.scrollTop || 0 : 0;\n const scrollLeft = isBrowser ? window.scrollX || document.documentElement?.scrollLeft || document.body?.scrollLeft || 0 : 0;\n\n return {\n top: top + scrollTop,\n left: left + scrollLeft,\n right: left + scrollLeft + width,\n bottom: top + scrollTop + height\n };\n}\n\n/***************************************************************************\n * Create SVG element from string code\n ***************************************************************************/\nfunction parseSVG(string)\n{\n return ((new DOMParser().parseFromString(string, 'image/svg+xml')).firstChild);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction refresh_language(element, t)\n{\n if(!is_function(t)) {\n log_error(\"You must supply a translation function\");\n return;\n }\n if(!element) {\n element = document;\n }\n\n /* `querySelectorAll` searches DESCENDANTS: it never returns the\n * element it was called on. So a caller that hands us the very\n * node carrying the key -- which is what happens whenever a widget\n * is built lazily and translated as a unit -- got its children\n * translated and its own attribute left in the source language.\n * Measured on the deployed shell: the toolbar's language dropdown\n * opened as role=\"menu\" aria-label=\"select language\" while its\n * trigger next to it said \"Elegir idioma\". Include the root. */\n const matching = (selector) => {\n let out = [];\n if(typeof element.matches === \"function\" && element.matches(selector)) {\n out.push(element);\n }\n out.push(...element.querySelectorAll(selector));\n return out;\n };\n\n matching('[data-i18n]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n');\n for(let node of elem.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if(!value) {\n value = node.nodeValue;\n }\n node.nodeValue = t(value);\n break; // Stop after updating the first text node\n }\n }\n });\n\n /* Translate the `title` attribute (hover tooltip) for any element\n * carrying `data-i18n-title=\"<canonical key>\"`. Used by lib-yui's\n * nav and toolbar renderers to keep tooltips in sync with the\n * active language, since refresh_language() above only touches\n * text-node content. */\n matching('[data-i18n-title]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n-title');\n if(value) {\n elem.setAttribute('title', t(value));\n }\n });\n\n /* Translate the `aria-label` attribute (assistive-tech name) for\n * any element carrying `data-i18n-aria-label=\"<canonical key>\"`.\n * Same contract as data-i18n-title above — emitted by lib-yui's\n * toolbar and nav renderers next to the static `aria-label` so\n * screen readers track language switches. */\n matching('[data-i18n-aria-label]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n-aria-label');\n if(value) {\n elem.setAttribute('aria-label', t(value));\n }\n });\n\n /* Translate the `placeholder` attribute (inputs/textareas) for\n * any element carrying `data-i18n-placeholder=\"<canonical key>\"`.\n * Same contract as data-i18n-title above — a placeholder is not a\n * text node, so the data-i18n walk cannot reach it. */\n matching('[data-i18n-placeholder]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n-placeholder');\n if(value) {\n elem.setAttribute('placeholder', t(value));\n }\n });\n}\n\n/************************************************************\n * Example Usage\n * const tracker = timeTracker(\"Track1\");\n * tracker.mark(\"Step 1\");\n * tracker.mark(\"Step 2\");\n ************************************************************/\nfunction timeTracker(tracker_name=\"Time Tracker\", verbose=false)\n{\n const name = tracker_name;\n const startTime = performance.now();\n let lastMarkTime = startTime;\n\n if(verbose) {\n log_warning(\n `--> ${name} - starting`\n );\n }\n\n return {\n mark: (label = \"Intermediate\", result=\"\") => {\n const currentTime = performance.now();\n const partial = (currentTime - lastMarkTime) / 1000;\n const total = (currentTime - startTime) / 1000;\n if(verbose) {\n log_warning(\n `--> ${name} ${label} - partial: ${partial} sec, total: ${total} sec, ${result}`\n );\n }\n lastMarkTime = currentTime;\n return {\n partial: partial,\n total: total\n };\n }\n };\n}\n\n/************************************************************\n * Get the current timestamp in ISO 8601 format with milliseconds and time zone.\n * Example Output: \"2024-02-24T14:05:30.123+0200\"\n ************************************************************/\nfunction current_timestamp(now)\n{\n now = now || new Date();\n const pad = (n, w) => String(n).padStart(w, \"0\");\n\n /* LOCAL time, because the offset written after it is the local one:\n * toISOString() is UTC, and \"UTC time +0200\" is a wall clock two\n * hours wrong for anyone reading it (C writes local time too). */\n const timestamp =\n `${now.getFullYear()}-${pad(now.getMonth() + 1, 2)}-${pad(now.getDate(), 2)}` +\n `T${pad(now.getHours(), 2)}:${pad(now.getMinutes(), 2)}:${pad(now.getSeconds(), 2)}`;\n const milliseconds = pad(now.getMilliseconds(), 3);\n\n // Time zone offset in ±HHMM format (getTimezoneOffset() is positive WEST of UTC)\n const offsetMinutes = now.getTimezoneOffset();\n const sign = offsetMinutes > 0 ? \"-\" : \"+\";\n const hours = pad(Math.floor(Math.abs(offsetMinutes) / 60), 2);\n const minutes = pad(Math.abs(offsetMinutes) % 60, 2);\n\n return `${timestamp}.${milliseconds}${sign}${hours}${minutes}`;\n}\n\n/********************************************\n * Return UTC time of right now\n ********************************************/\nfunction get_now()\n{\n return Math.floor(Date.now() / 1000);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction index_in_list(list, elm) {\n if(!list) {\n throw \"ERROR: index_in_list() list empty\";\n }\n for(let i=0; i<list.length; i++) {\n if(elm === list[i]) {\n return i;\n }\n }\n return -1;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction node_uuid()\n{\n let uuid = \"\";\n\n if (typeof window !== \"undefined\" && window.localStorage) {\n uuid = window.localStorage.getItem(\"host_uuid\");\n if (!uuid && window.crypto?.randomUUID) {\n uuid = window.crypto.randomUUID(); // Generate a new UUID\n window.localStorage.setItem(\"host_uuid\", uuid);\n }\n } else if (typeof globalThis !== \"undefined\" && globalThis.crypto?.randomUUID) {\n uuid = globalThis.crypto.randomUUID(); // Node.js environment (if available)\n } else {\n uuid = \"00000000-0000-0000-0000-000000000000\"; // Fallback UUID (if crypto is unavailable)\n }\n\n return uuid;\n}\n\n/************************************************************\n * Build a cleaned name\n ************************************************************/\nfunction clean_name(name)\n{\n return name.replace(/[?# ^:]/g, '_');\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction get_function_name(func)\n{\n let fName = null;\n if (typeof func === \"function\" || typeof func === \"object\") {\n fName = (\"\" + func).match(/function\\s*([\\w\\$]*)\\s*\\(/);\n }\n if (fName !== null) {\n return fName[1] + \"()\";\n }\n return \"\";\n}\n\n/***************************************************************************\n * implement a debounce or throttle mechanism to limit the number\n * of times the callback function is executed\n\n const fn = debounce(() => window.console.log('Called!'), 1000);\n\n // Start debounce timer\n fn();\n\n // Execute immediately (if pending)\n fn.flush();\n\n // Cancel the pending call\n fn.cancel();\n\n ***************************************************************************/\nfunction debounce(func, wait = 0, immediate = false)\n{\n let timeout = null;\n let args = null;\n let context = null;\n\n const debounced = (..._args) => {\n context = this;\n args = _args;\n\n const later = () => {\n timeout = null;\n if (!immediate) {\n func.apply(context, args);\n }\n };\n\n const callNow = immediate && !timeout;\n\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n\n if (callNow) {\n func.apply(context, args);\n }\n };\n\n // Immediately invoke the pending function\n debounced.flush = () => {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n func.apply(context, args);\n }\n };\n\n // Cancel the pending execution\n debounced.cancel = () => {\n clearTimeout(timeout);\n timeout = null;\n args = null;\n context = null;\n };\n\n return debounced;\n}\n\n/************************************************************\n * Build a URL/path from segments, ensuring exactly one '/'\n * between each part.\n *\n * - The first segment keeps its leading '/' (absolute) or\n * not (relative).\n * - Trailing '/' is stripped from every segment.\n * - Leading '/' is stripped from every segment except the first.\n * - Empty/null/undefined segments are skipped.\n *\n * Mirrors the C helper build_path() from gobj-c/src/helpers.c.\n ************************************************************/\nfunction build_path(...segments)\n{\n let result = \"\";\n let i = 0;\n\n for(let segment of segments) {\n if(segment == null || segment === \"\") {\n continue;\n }\n segment = String(segment);\n\n if(i === 0) {\n // First segment: keep leading '/', strip trailing '/'\n segment = segment.replace(/\\/+$/, \"\");\n } else {\n // Subsequent segments: strip both leading and trailing '/'\n segment = segment.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n }\n\n if(segment === \"\") {\n continue;\n }\n\n if(i > 0) {\n result += \"/\";\n }\n result += segment;\n i++;\n }\n\n return result;\n}\n\n\n\n /***************************************\n * Flat json (id -> value)\n ***************************************/\n\n\n\n\n/************************************************************\n * THE FLAT FORM, AND WHY IT IS SHAPED LIKE THIS\n *\n * A json seen as a table: one row per LEAF, the id being the\n * PATH of the item and the value its value. Easier to store,\n * to compare and to diff than the nested form, and the only\n * one a person can read when two configurations disagree.\n *\n * {a: {b: 1}, c: [10, 20]}\n * -> {\"a`b\": 1, \"c`[0]\": 10, \"c`[1]\": 20}\n *\n * Same grammar as the C side (kwid.c), because the point is\n * that a flat json written by either can be read by the other:\n *\n * - segments joined by '`', the SDK's own path delimiter;\n * - a literal '`' in a key is DOUBLED, so no key is\n * forbidden -- a dict keyed by \"1630\" is a dict, not an\n * array of 1631 elements, which is what the first C\n * implementation answered;\n * - an array index is '[N]', canonical, no leading zeros;\n * - a dict key starting with '[' doubles it ('[[0]'), so it\n * can never be read as an index;\n * - AN EMPTY CONTAINER IS A LEAF: {} and [] hold no leaves,\n * and 'properties': {} is everywhere in our configs.\n *\n * flat2json() THROWS instead of guessing: an id used as leaf and\n * as container would depend on the order the ids are read in.\n ************************************************************/\nconst FLAT_MAX_DEPTH = 256;\nconst FLAT_MAX_INDEX = 100000;\n\n/************************************************************\n * Is this raw segment an array index, '[N]'?\n * Returns the index, or null.\n ************************************************************/\nfunction flat_seg_index(seg)\n{\n if(typeof seg !== \"string\" || seg.length < 3 || seg[0] !== \"[\") {\n return null;\n }\n if(seg[seg.length-1] !== \"]\") {\n return null;\n }\n const body = seg.slice(1, -1);\n if(!/^[0-9]+$/.test(body)) {\n return null;\n }\n if(body.length > 1 && body[0] === \"0\") {\n return null; // canonical: '[00]' is malformed, not a second '[0]'\n }\n return parseInt(body, 10);\n}\n\n/************************************************************\n * Escape one dict key.\n ************************************************************/\nfunction flat_escape_key(key)\n{\n const s = String(key).replace(/`/g, \"``\");\n return s[0] === \"[\" ? \"[\" + s : s;\n}\n\n/************************************************************\n * Compose a flat id from its segments.\n *\n * A STRING segment is a dict key and gets escaped; a NUMBER is\n * an array index and is written '[N]'. They are two types and\n * not two spellings: as strings, the key \"[0]\" and the index 0\n * would both be \"[0]\", which is the ambiguity '[N]' removes.\n ************************************************************/\nfunction flat_key_join(segments)\n{\n if(!Array.isArray(segments) || segments.length === 0) {\n return \"\";\n }\n return segments.map(\n (seg) => (typeof seg === \"number\" ? `[${seg}]` : flat_escape_key(seg))\n ).join(\"`\");\n}\n\n/************************************************************\n * Split a flat id into its segments, undoing the escapes.\n *\n * An index comes back as a NUMBER and a dict key as a STRING.\n ************************************************************/\nfunction flat_key_split(key)\n{\n if(typeof key !== \"string\") {\n return null;\n }\n\n let raw = [];\n let cur = \"\";\n for(let i = 0; i < key.length; i++) {\n if(key[i] === \"`\") {\n if(key[i+1] === \"`\") {\n cur += \"`\";\n i++;\n continue;\n }\n raw.push(cur);\n cur = \"\";\n continue;\n }\n cur += key[i];\n }\n raw.push(cur);\n\n /* Decide what each segment IS before undoing the bracket escape:\n * the other way round, '[[0]' would become '[0]' and read as an\n * index. */\n return raw.map((seg) => {\n const idx = flat_seg_index(seg);\n if(idx !== null) {\n return idx;\n }\n if(seg[0] === \"[\" && seg[1] === \"[\") {\n return seg.slice(1);\n }\n return seg;\n });\n}\n\n/************************************************************\n * Nested -> flat.\n ************************************************************/\nfunction json2flat(jn)\n{\n const flat = {};\n\n const walk = (value, path, depth) => {\n if(depth > FLAT_MAX_DEPTH) {\n throw new Error(`json2flat: deeper than ${FLAT_MAX_DEPTH}`);\n }\n if(value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const keys = Object.keys(value);\n if(keys.length > 0) {\n for(const key of keys) {\n const seg = flat_escape_key(key);\n walk(value[key], depth === 0 ? seg : path + \"`\" + seg, depth+1);\n }\n return;\n }\n } else if(Array.isArray(value) && value.length > 0) {\n value.forEach((child, index) => {\n const seg = `[${index}]`;\n walk(child, depth === 0 ? seg : path + \"`\" + seg, depth+1);\n });\n return;\n }\n /* A leaf: a scalar, or an EMPTY container, which has no leaves\n * of its own and would otherwise vanish. Depth, not the length\n * of the path: {\"\": 1} is a json whose only id is \"\". */\n if(depth === 0) {\n return; // a scalar root has no path\n }\n flat[path] = value;\n };\n\n if(jn === undefined || jn === null) {\n return flat;\n }\n walk(jn, \"\", 0);\n return flat;\n}\n\n/************************************************************\n * Flat -> nested. Throws on the FIRST id that does not fit:\n * rebuilding \"most of it\" is how a configuration comes back\n * subtly different from the one that was saved.\n ************************************************************/\nfunction flat2json(flat)\n{\n if(flat === null || typeof flat !== \"object\" || Array.isArray(flat)) {\n throw new Error(\"flat2json: a flat json is an object of id -> value\");\n }\n\n let root = null;\n\n for(const key of Object.keys(flat)) {\n const segments = flat_key_split(key);\n if(!segments || segments.length === 0) {\n throw new Error(`flat2json: malformed flat id: '${key}'`);\n }\n if(segments.length > FLAT_MAX_DEPTH) {\n throw new Error(`flat2json: '${key}' deeper than ${FLAT_MAX_DEPTH}`);\n }\n\n const first_is_index = (typeof segments[0] === \"number\");\n if(root === null) {\n root = first_is_index ? [] : {};\n } else if(first_is_index !== Array.isArray(root)) {\n throw new Error(\n `flat2json: '${key}' does not fit a ` +\n `${Array.isArray(root)? \"array\": \"object\"} root`\n );\n }\n\n let current = root;\n for(let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const is_index = (typeof seg === \"number\");\n const is_last = (i === segments.length - 1);\n const next_is_index = is_last? false: (typeof segments[i+1] === \"number\");\n\n if(is_index && seg > FLAT_MAX_INDEX) {\n throw new Error(\n `flat2json: array index ${seg} over the limit ` +\n `(${FLAT_MAX_INDEX}) in '${key}'`\n );\n }\n if(is_index !== Array.isArray(current)) {\n throw new Error(\n `flat2json: '${key}' uses a ${is_index? \"array index\": \"key\"} ` +\n `where the tree already has a ` +\n `${Array.isArray(current)? \"array\": \"object\"}`\n );\n }\n\n if(is_last) {\n if(Array.isArray(current)) {\n while(current.length <= seg) {\n current.push(null);\n }\n current[seg] = flat[key];\n } else {\n if(Object.prototype.hasOwnProperty.call(current, seg)) {\n throw new Error(\n `flat2json: '${key}' is written twice, or once as a ` +\n `value and once as a container`\n );\n }\n current[seg] = flat[key];\n }\n break;\n }\n\n let child;\n if(Array.isArray(current)) {\n while(current.length <= seg) {\n current.push(null);\n }\n child = current[seg];\n if(child === null || child === undefined) {\n child = next_is_index? []: {};\n current[seg] = child;\n }\n } else {\n child = current[seg];\n if(child === undefined) {\n child = next_is_index? []: {};\n current[seg] = child;\n }\n }\n\n if(child === null || typeof child !== \"object\") {\n throw new Error(\n `flat2json: '${key}' walks through a value: the same id is ` +\n `a leaf and a container at once`\n );\n }\n if(next_is_index !== Array.isArray(child)) {\n throw new Error(\n `flat2json: '${key}' needs a ${next_is_index? \"array\": \"object\"} ` +\n `where the tree already has a ` +\n `${Array.isArray(child)? \"array\": \"object\"}`\n );\n }\n current = child;\n }\n }\n\n return root === null ? {} : root;\n}\n\n/************************************************************\n * Deep equality, for comparing two leaf values.\n ************************************************************/\nfunction flat_value_equal(a, b)\n{\n if(a === b) {\n return true;\n }\n if(a === null || b === null || typeof a !== \"object\" || typeof b !== \"object\") {\n return false;\n }\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/************************************************************\n * What changed between two flat dicts:\n *\n * {added: {id: value}, removed: {id: value},\n * changed: {id: {from, to}}}\n ************************************************************/\nfunction flat_diff(flat1, flat2)\n{\n const a = (flat1 && typeof flat1 === \"object\")? flat1: {};\n const b = (flat2 && typeof flat2 === \"object\")? flat2: {};\n const diff = {added: {}, removed: {}, changed: {}};\n\n for(const key of Object.keys(a)) {\n if(!Object.prototype.hasOwnProperty.call(b, key)) {\n diff.removed[key] = a[key];\n } else if(!flat_value_equal(a[key], b[key])) {\n diff.changed[key] = {from: a[key], to: b[key]};\n }\n }\n for(const key of Object.keys(b)) {\n if(!Object.prototype.hasOwnProperty.call(a, key)) {\n diff.added[key] = b[key];\n }\n }\n\n return diff;\n}\n\n/************************************************************\n * Apply that diff to a flat dict, which is MUTATED.\n *\n * On the flat form on purpose: there an id addresses one value,\n * so applying is setting and deleting, with nothing to walk and\n * nothing to guess. Nested is json2flat -> flat_apply -> flat2json.\n ************************************************************/\nfunction flat_apply(flat, diff)\n{\n if(flat === null || typeof flat !== \"object\" || Array.isArray(flat)) {\n throw new Error(\"flat_apply: a flat json is an object of id -> value\");\n }\n if(diff === null || typeof diff !== \"object\") {\n throw new Error(\"flat_apply: a diff is the object flat_diff() answers\");\n }\n\n for(const key of Object.keys(diff.removed || {})) {\n delete flat[key];\n }\n for(const key of Object.keys(diff.added || {})) {\n flat[key] = diff.added[key];\n }\n for(const key of Object.keys(diff.changed || {})) {\n const change = diff.changed[key];\n if(!change || !Object.prototype.hasOwnProperty.call(change, \"to\")) {\n throw new Error(`flat_apply: changed '${key}' without a 'to'`);\n }\n flat[key] = change.to;\n }\n\n return flat;\n}\n\n\nexport {\n kw_flag_t,\n json_deep_copy,\n duplicate_objects,\n json_is_identical,\n json_object_update,\n json_object_update_existing,\n json_object_update_missing,\n json_object_get,\n json_object_set,\n json_object_set_new,\n json_object_del,\n json_array_append,\n json_array_append_new,\n json_array_remove,\n json_array_extend,\n json_object_size,\n json_array_size,\n json_size,\n empty_json,\n\n is_object,\n is_array,\n is_string,\n is_number,\n is_boolean,\n is_null,\n is_pure_number,\n is_date,\n is_function,\n is_gobj,\n\n parseBoolean,\n empty_string,\n strncmp,\n strcmp,\n strcasecmp,\n cmp_two_simple_json,\n strstr,\n\n is_metadata_key,\n is_private_key,\n kw_pop,\n kw_has_key,\n kw_find_path,\n kw_delete,\n kw_get_bool,\n kw_get_int,\n kw_get_real,\n kw_get_str,\n kw_get_pointer,\n kw_get_dict,\n kw_get_list,\n kw_get_dict_value,\n kw_set_dict_value,\n kw_set_subdict_value,\n kw_match_simple,\n kw_find_json_in_list,\n kw_select,\n kw_collect,\n kw_clone_by_keys,\n kw_clone_by_not_keys,\n\n kw_get_local_storage_value,\n kw_set_local_storage_value,\n kw_remove_local_storage_value,\n\n kwid_match_id,\n kwid_collect,\n kwid_new_dict,\n kwid_new_list,\n kwid_find_one_record,\n kwid_get_ids,\n list2options,\n\n id_index_in_obj_list,\n str_in_list,\n strs_in_list,\n delete_from_list,\n\n msg_iev_push_stack,\n msg_iev_get_stack,\n msg_iev_set_msg_type,\n msg_iev_get_msg_type,\n msg_iev_write_key,\n msg_iev_read_key,\n load_json_file,\n send_http_json_post,\n\n jdb_init,\n jdb_update,\n jdb_delete,\n jdb_get_topic,\n jdb_get,\n jdb_get_by_idx,\n\n create_json_record,\n\n set_remote_log_functions,\n set_log_callback,\n set_console_log_enabled,\n set_console_log_filter,\n log_error,\n log_warning,\n log_info,\n log_debug,\n trace_msg,\n trace_json,\n\n jwtDecode,\n jwt2json,\n\n escapeHtml,\n safeSrc,\n createOneHtml,\n createElement2,\n getPositionRelativeToBody,\n parseSVG,\n refresh_language,\n\n timeTracker,\n current_timestamp,\n get_now,\n index_in_list,\n node_uuid,\n clean_name,\n get_function_name,\n debounce,\n build_path,\n\n json2flat,\n flat2json,\n flat_key_join,\n flat_key_split,\n flat_diff,\n flat_apply,\n};\n","/*********************************************************************************\n * dbsimple.js\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025, ArtGins.\n *********************************************************************************/\n\nimport {\n kw_get_local_storage_value,\n kw_remove_local_storage_value,\n kw_set_local_storage_value,\n is_object,\n kw_clone_by_keys,\n json_object_update_missing,\n kw_clone_by_not_keys,\n json_object_size,\n} from \"./helpers.js\";\n\nimport {\n sdata_flag_t,\n gobj_read_attrs,\n gobj_short_name,\n gobj_write_attrs,\n} from \"./gobj.js\";\n\n/************************************************************\n *\n ************************************************************/\nfunction _get_persistent_path(gobj)\n{\n return \"persistent-attrs-\" + gobj_short_name(gobj);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction db_load_persistent_attrs(\n gobj,\n keys // str, list or dict.\n)\n{\n let jn_attrs = gobj_read_attrs(gobj, sdata_flag_t.SDF_PERSIST, 0);\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n if(jn_file && is_object(jn_file)) {\n let attrs = kw_clone_by_keys(\n gobj,\n jn_file, // owned\n keys, // owned\n false\n );\n attrs = kw_clone_by_keys( // Remove attrs removed\n gobj,\n attrs, // owned\n jn_attrs, // owned\n false\n );\n\n gobj_write_attrs(gobj, attrs, sdata_flag_t.SDF_PERSIST, 0);\n }\n}\n\n/************************************************************\n * Returns 0 on success, -1 when the attrs did NOT reach the store\n * (quota exceeded, private mode, storage disabled). Callers must check\n * it: a discarded write with a UI that shows the value as saved is the\n * worst of both worlds.\n ************************************************************/\nfunction db_save_persistent_attrs(\n gobj,\n keys // str, list or dict.\n)\n{\n let jn_attrs = gobj_read_attrs(gobj, sdata_flag_t.SDF_PERSIST, 0);\n let attrs = kw_clone_by_keys(\n gobj,\n jn_attrs, // owned\n keys, // owned\n false\n );\n\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n if(jn_file && is_object(jn_file)) {\n json_object_update_missing(attrs, jn_file);\n }\n\n return kw_set_local_storage_value(\n _get_persistent_path(gobj),\n attrs\n );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction db_remove_persistent_attrs(\n gobj,\n keys // str, list or dict.\n)\n{\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n\n let attrs = kw_clone_by_not_keys(\n gobj,\n jn_file,\n keys,\n false\n );\n\n if(json_object_size(attrs)===0) {\n kw_remove_local_storage_value(_get_persistent_path(gobj));\n } else {\n kw_set_local_storage_value(\n _get_persistent_path(gobj),\n attrs\n );\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction db_list_persistent_attrs(gobj, keys)\n{\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n let attrs = {};\n if(jn_file && is_object(jn_file)) {\n attrs = kw_clone_by_keys(\n gobj,\n jn_file, // owned\n keys, // owned\n false\n );\n }\n return attrs;\n}\n\n//=======================================================================\n// Expose the class via the global object\n//=======================================================================\nexport {\n db_load_persistent_attrs,\n db_save_persistent_attrs,\n db_remove_persistent_attrs,\n db_list_persistent_attrs,\n};\n","/***********************************************************************\n * ui_lib_treedb.js\n *\n * Treedb common helpers\n *\n * - El treedb center se registra,\n *\n * - Los formtable con treedb_name\n * se suscriben masivamente a las tablas de los hooks y fkeys.\n *\n * - Los hook se subscriben a todos las modificaciones-z de los hijos,\n * ( solo de los create y delete realmente, solo se necesita el id del que existe)\n * en cada una redefinirán sus option2list, así un padre puede cortar el link.\n * pero puede ser un proceso lento.\n *\n * - Los fkeys se subscriben a todas las modificaciones de los padres,\n * realmente solo se necesita a las creaciones y deletes de los registros de la tabla,\n * updates y link/unlink le da igual. Con cada publicación redefinirán sus option2list.\n *\n * OJO con los unsubscribe!! necesarios!\n *\n * El formtable publicará los eventos: CREATE_NODE, DELETE_NODE, UPDATE_NODE\n * en el UPDATE_NODE irá un reseteo/creación de los links.\n * OJO que un link/unlink implica un update de dos nodos, el padre y el hijo. Quién primero?\n *\n *\n * Version\n * -------\n * 1.0 Initial release\n * 2.0\n *\n * Copyright (c) 2020-2024 Niyamaka.\n * All Rights Reserved.\n ***********************************************************************/\nimport {\n kw_get_dict_value,\n is_array,\n kw_set_dict_value,\n kw_has_key,\n log_error,\n is_string,\n is_object,\n json_object_size,\n json_size,\n str_in_list,\n kwid_new_dict,\n} from \"./helpers.js\";\n\n/********************************************\n * Data\n ********************************************/\nlet treedb_register = { // Dictionary with data of registered global topics\n};\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_formtable(treedb_name, topic_name, gobj_formtable)\n{\n let treedb = kw_get_dict_value(null, treedb_register, treedb_name, {}, true);\n let gobjs = kw_get_dict_value(null, treedb, \"gobjs\", {}, true);\n kw_set_dict_value(null, gobjs, gobj_formtable.name, gobj_formtable);\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_unregister_formtable(treedb_name, topic_name, gobj_formtable)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let gobjs = kw_get_dict_value(treedb, \"gobjs\", {}, true);\n if(kw_has_key(gobjs, gobj_formtable.name)) {\n delete gobjs[gobj_formtable.name];\n } else {\n log_error(\"treedb_unregister_formtable() gobj not found: \" + gobj_formtable.name);\n }\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_nodes(treedb_name, topic_name, nodes)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let data = kw_get_dict_value(treedb, \"data\", {}, true);\n kw_set_dict_value(data, topic_name, kwid_new_dict(nodes));\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_update_node(treedb_name, topic_name, node)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let data = kw_get_dict_value(treedb, \"data\", {}, true);\n let topic_data = kw_get_dict_value(data, topic_name, {}, true);\n\n kw_set_dict_value(topic_data, node.id, node);\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_del_node(treedb_name, topic_name, node)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let data = kw_get_dict_value(treedb, \"data\", {}, true);\n let topic_data = kw_get_dict_value(data, topic_name, {}, true);\n\n delete topic_data[node.id];\n}\n\n/********************************************\n * Used by ui_treedb to update options\n ********************************************/\nfunction treedb_get_register(treedb_name)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, false);\n return treedb;\n}\n\n/********************************************\n * Used by formtable to get combo options\n ********************************************/\nfunction treedb_get_topic_data(treedb_name, topic_name)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, false);\n let data = kw_get_dict_value(treedb, \"data\", {}, false);\n return kw_get_dict_value(data, topic_name, {}, false);\n}\n\n/********************************************\n * Used by formtable to get combo options\n ********************************************/\nfunction treedb_get_topic_field_data(treedb_name, topic_name)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, false);\n let data = kw_get_dict_value(treedb, \"data\", {}, false);\n return kw_get_dict_value(data, topic_name, {}, false);\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_hook_data_size(value)\n{\n if(is_array(value) && json_size(value)===1) {\n let o = value[0];\n if(kw_has_key(o, \"size\")) {\n return o.size;\n }\n return 1;\n }\n return json_size(value);\n}\n\n/************************************************************\n * fkey can be:\n *\n * \"$id\"\n *\n * \"$topic_name^$id^$hook_name\n *\n * {\n * topic_name: $topic_name,\n * id: $id,\n * hook_name: $hook_name\n * }\n *\n * Return\n * {\n * topic_name:\n * id:\n * hook_name:\n * }\n ************************************************************/\nfunction treedb_decoder_fkey(col, fkey)\n{\n if(is_string(fkey)) {\n if(fkey.indexOf(\"^\") === -1) {\n // \"$id\"\n let fkey_desc = col.fkey;\n if(json_object_size(fkey_desc)!==1) {\n log_error(\"bad fkey 1\");\n log_error(col);\n log_error(fkey);\n return null;\n }\n\n let topic_name;\n let hook_name;\n for(const k of Object.keys(fkey_desc)) {\n topic_name = k;\n hook_name = fkey_desc[k];\n break;\n }\n\n return {\n topic_name: topic_name,\n id: fkey,\n hook_name: hook_name\n };\n\n } else {\n // \"$topic_name^$id^$hook_name\n let tt = fkey.split(\"^\");\n if(tt.length !== 3) {\n log_error(\"bad fkey 2\");\n log_error(col);\n log_error(fkey);\n return null;\n }\n return {\n topic_name: tt[0],\n id: tt[1],\n hook_name: tt[2]\n };\n }\n\n } else if(is_object(fkey)) {\n return {\n topic_name: fkey.topic_name,\n id: fkey.id,\n hook_name: fkey.hook_name\n };\n\n } else {\n log_error(\"bad fkey 3\");\n log_error(col);\n log_error(fkey);\n return null;\n }\n}\n\n/************************************************************\n * Encode a fkey (any format) to canonical string:\n * \"$topic_name^$id^$hook_name\"\n *\n * Returns null on error.\n ************************************************************/\nfunction treedb_encoder_fkey(col, fkey)\n{\n let decoded = treedb_decoder_fkey(col, fkey);\n if(!decoded) {\n return null;\n }\n return decoded.topic_name + \"^\" + decoded.id + \"^\" + decoded.hook_name;\n}\n\n/********************************************\n * hook can be:\n *\n * \"$id\"\n *\n * \"$topic_name^$id\n *\n * {\n * topic_name: $topic_name,\n * id: $id\n * }\n *\n * Return\n * {\n * topic_name:\n * id:\n * }\n ********************************************/\nfunction treedb_decoder_hook(col, hook)\n{\n if(is_string(hook)) {\n if(hook.indexOf(\"^\") === -1) {\n // \"$id\"\n let hook_desc = col.hook;\n if(json_object_size(hook_desc)!==1) {\n log_error(\"bad hook 1\");\n log_error(col);\n log_error(hook);\n return null;\n }\n\n let topic_name;\n let fkey_name;\n\n for(let k of Object.keys(hook_desc)) {\n topic_name = k;\n fkey_name = hook_desc[k];\n break;\n }\n\n return {\n topic_name: topic_name,\n id: hook\n };\n\n } else {\n // \"$topic_name^$id\n let tt = hook.split(\"^\");\n if(tt.length !== 2) {\n log_error(\"bad hook 2\");\n log_error(col);\n log_error(hook);\n return null;\n }\n return {\n topic_name: tt[0],\n id: tt[1]\n };\n }\n\n } else if(is_object(hook)) {\n return {\n topic_name: hook.topic_name,\n id: hook.id\n };\n\n } else {\n log_error(\"bad hook 3\");\n log_error(col);\n log_error(hook);\n return null;\n }\n}\n\n/************************************************************\n * Return [\n * name, // name/id of field (table column name)\n * header, // header of field\n * type, // yuneta type (basic and tranger/treedb types)\n * real_type, // json type\n * enum_list, // List of options to <select> or template or table or ...\n * is_required, // field required\n * is_writable // field writable (no readonly)\n * default_value\n * placeholder\n * fkey // fkey mapping {topic_name: hook_name}, null if none\n * ]\n *\n * The template is recursive, in values you can set dictionaries, or arrays,\n * in some context will define the real_type,\n * in other will define a subform.\n *\n ************************************************************/\nconst treedb_real_types = [ // WARNING check tr_treedb.h to update new real types\n \"string\",\n \"integer\",\n \"object\", \"dict\",\n \"array\",\"list\",\n \"real\",\n \"boolean\",\n \"blob\"\n];\n\nconst treedb_field_attributes = [ // WARNING check tr_treedb.h to update new types\n \"persistent\", // stored on disk; implicit readable, NOT writable\n // (see tr_treedb.h: unlike SDF_PERSIST of a gobj attr)\n \"required\",\n \"notnull\",\n \"wild\",\n \"inherit\",\n\n // For use in gobj attributes\n \"readable\", // Field readable by user\n \"writable\", // Field writable by user implicit \"readable\"\n \"hidden\", // Field hidden to user\n \"stats\", // field with stats implicit \"readable\"\n \"rstats\", // field with resettable stats implicit \"stats\"\n \"pstats\" // field with persistent stats implicit \"stats\"\n];\n\nconst treedb_field_types = [ // WARNING check tr_treedb.h to update new types\n \"hook\", // special field types\n \"fkey\",\n \"enum\",\n\n \"template\", // normal field types\n \"uuid\",\n \"rowid\",\n \"qualified\",\n \"password\",\n \"email\",\n \"url\",\n \"time\",\n \"now\",\n \"date\",\n \"color\",\n \"image\",\n \"icon\",\n \"file\", // an fkey into __assets__: the bytes on disk under the treedb\n \"tel\",\n \"table\",\n \"id\",\n \"currency\",\n \"hex\",\n \"binary\",\n \"percent\",\n \"base64\",\n \"coordinates\",\n \"gbuffer\"\n];\n\nfunction treedb_get_field_desc(col)\n{\n let field_desc = {\n name: col.id,\n header: col.header,\n real_type: col.type,\n type: col.type, // By default, is basic type\n enum_list: null,\n is_required: false,\n is_writable: false, // Must be explicitly writable\n is_hidden: false,\n default_value: col.default,\n placeholder: col.placeholder,\n fillspace: col.fillspace || 4,\n fkey: col.fkey || null, // fkey mapping {topic_name: hook_name} (fkey cols)\n is_file: false, // ['fkey','file']: an fkey into __assets__\n };\n\n if(!col.flag) {\n // It can happen if col is not a column descriptor\n return field_desc;\n }\n\n for(let i=0; i<col.flag.length; i++) {\n let f = col.flag[i];\n\n if(str_in_list(treedb_field_types, f)) {\n switch(f) {\n case \"enum\":\n field_desc.enum_list = col.enum;\n break;\n case \"template\":\n field_desc.enum_list = col.template;\n break;\n case \"table\":\n field_desc.enum_list = col.table;\n break;\n case \"file\":\n field_desc.is_file = true;\n break;\n }\n field_desc.type = f;\n\n } else if(str_in_list(treedb_field_attributes, f)) {\n switch(f) {\n case \"writable\":\n field_desc.is_writable = true;\n break;\n case \"notnull\":\n field_desc.is_required = true;\n break;\n case \"required\":\n field_desc.is_required = true;\n break;\n case \"hidden\":\n field_desc.is_hidden = true;\n break;\n }\n }\n }\n\n /*\n * A `file` column is flagged ['fkey','file'] -- `file` QUALIFIES the\n * fkey, it does not replace it -- and the loop above takes the LAST\n * type word it meets, so the ORDER of the flag array would decide\n * what this answers. The C side does not care about the order\n * (derive_file_hooks() asks for both words with kw_has_word), so\n * neither may this: `file` wins wherever it sits.\n */\n if(field_desc.is_file) {\n field_desc.type = \"file\";\n }\n\n return field_desc;\n}\n\nfunction template_get_field_desc(key, value)\n{\n let field_desc = {\n name : key,\n header: key,\n real_type: null,\n type: null,\n enum_list: null,\n is_required: false,\n is_writable: false, // Must be explicitly writable\n is_hidden: false,\n default_value: undefined,\n placeholder: undefined,\n fkey: null, // a string spec cannot express the fkey mapping\n };\n\n /*---------------------------*\n * process value\n *---------------------------*/\n if(is_string(value)) {\n let values = value.split('.');\n for(let i=0; i<values.length; i++) {\n let f = values[i];\n\n if(str_in_list(treedb_real_types, f)) {\n if(!field_desc.real_type) {\n field_desc.real_type = f;\n }\n } else if(str_in_list(treedb_field_types, f)) {\n if(!field_desc.type) {\n field_desc.type = f;\n }\n } else if(str_in_list(treedb_field_attributes, f)) {\n switch(f) {\n case \"writable\":\n field_desc.is_writable = true;\n break;\n case \"notnull\":\n field_desc.is_required = true;\n break;\n case \"required\":\n field_desc.is_required = true;\n break;\n case \"hidden\":\n field_desc.is_hidden = true;\n break;\n }\n }\n }\n if(!field_desc.real_type) {\n field_desc.real_type = \"string\";\n }\n\n } else if(is_object(value)) {\n field_desc = treedb_get_field_desc(value);\n if(!field_desc.name) {\n field_desc.name = key;\n }\n if(!field_desc.header) {\n field_desc.header = key;\n }\n\n } else if(is_array(value)) {\n // TODO case impossible?\n field_desc.real_type = \"array\";\n field_desc.enum_list = value;\n }\n\n if(!field_desc.type) {\n field_desc.type = field_desc.real_type;\n }\n return field_desc;\n}\n\n/********************************************\n *\n ********************************************/\nfunction create_template_record(template, kw)\n{\n let new_record = {};\n if(!kw) {\n kw = {};\n }\n\n Object.entries(template).forEach(([field, col]) => {\n /* col is either a dot-token spec (string) or a column\n * descriptor (object); only the object form carries a default */\n let default_value;\n if(is_object(col)) {\n default_value = col.default;\n }\n let value = kw_get_dict_value(null, kw, field, default_value);\n new_record[field] = value;\n });\n\n return new_record;\n}\n\nexport {\n treedb_hook_data_size,\n treedb_decoder_fkey,\n treedb_encoder_fkey,\n treedb_decoder_hook,\n treedb_get_field_desc,\n template_get_field_desc,\n create_template_record,\n};\n","/****************************************************************************\n * c_timer.js\n *\n * GClass Timer\n * High-level timer, fed by the browser's own timer service\n *\n * Don't use gobj_start()/gobj_stop(), USE set_timeout..(), clear_timeout()\n *\n * The CONTRACT is the C one (see c_timer.h), and it is the whole\n * public surface: set_timeout() arms, clear_timeout() disarms, and\n * a one-shot is done once it fires. Whether the gobj is running is\n * an INTERNAL matter of this gclass -- nobody asking for a timeout\n * has to know it exists, and no caller should have to pair a\n * set_timeout() with a gobj_start() to make it work.\n *\n * What feeds the timer is the only thing that differs from C, and\n * it is deliberately invisible from outside: there the gobj rides\n * the yuno's one-second heartbeat, here it is a native setTimeout().\n *\n * Copyright (c) 2025-2026, ArtGins.\n * All Rights Reserved.\n ****************************************************************************/\n\nimport {\n SDATA,\n SDATA_END,\n data_type_t,\n gclass_flag_t,\n event_flag_t,\n GObj,\n gclass_create,\n gobj_parent,\n gobj_send_event,\n gobj_publish_event,\n gobj_start,\n gobj_stop,\n gobj_is_running,\n gobj_read_bool_attr,\n gobj_read_integer_attr,\n gobj_read_pointer_attr,\n gobj_subscribe_event,\n gobj_is_pure_child,\n gobj_gclass_name,\n gobj_write_bool_attr,\n gobj_write_integer_attr,\n} from \"./gobj.js\";\n\nimport {\n log_error,\n} from \"./helpers.js\";\n\n\n/***************************************************************\n * Constants\n ***************************************************************/\nconst GCLASS_NAME = \"C_TIMER\";\n\n/***************************************************************\n * Data\n ***************************************************************/\n/*---------------------------------------------*\n * Attributes\n *---------------------------------------------*/\nconst attrs_table = [\nSDATA(data_type_t.DTP_POINTER, \"subscriber\", 0, null, \"Subscriber of output events\"),\nSDATA(data_type_t.DTP_BOOLEAN, \"periodic\", 0, 0, \"True for periodic timeouts\"),\nSDATA(data_type_t.DTP_INTEGER, \"msec\", 0, 0, \"Timeout in milliseconds\"),\nSDATA_END()\n];\n\nlet PRIVATE_DATA = {\n periodic: false,\n msec: 0,\n timer_id: -1,\n};\n\nlet __gclass__ = null;\n\n\n\n\n /******************************\n * Framework Methods\n ******************************/\n\n\n\n\n/***************************************************************\n * Framework Method: Create\n ***************************************************************/\nfunction mt_create(gobj)\n{\n let priv = gobj.priv;\n\n /*\n * SERVICE subscription model\n */\n const subscriber = gobj_read_pointer_attr(gobj, \"subscriber\");\n if(subscriber) {\n gobj_subscribe_event(gobj, null, {}, subscriber);\n }\n\n priv.periodic = gobj_read_bool_attr(gobj, \"periodic\");\n priv.msec = gobj_read_integer_attr(gobj, \"msec\");\n}\n\n/***************************************************************\n * Framework Method: Writing\n ***************************************************************/\nfunction mt_writing(gobj, path)\n{\n let priv = gobj.priv;\n\n switch(path) {\n case \"periodic\":\n priv.periodic = gobj_read_bool_attr(gobj, \"periodic\");\n break;\n case \"msec\":\n priv.msec = gobj_read_integer_attr(gobj, \"msec\");\n if(priv.timer_id !== -1) {\n clearTimeout(priv.timer_id);\n priv.timer_id = -1;\n }\n if(priv.msec > 0) {\n priv.timer_id = setTimeout(\n function() {\n gobj_send_event(gobj, \"EV_TIMEOUT\", {}, gobj);\n },\n priv.msec\n );\n }\n\n /*\n * The running state follows the timeout, and it follows it HERE,\n * on the attribute write -- not in the set_timeout()/clear_timeout()\n * helpers. The attribute is the real interface; those three PUBLIC\n * functions are an escape from the gclass interface (attributes,\n * events, commands, local methods, stats) that c_timer has carried\n * since C, and sugar must not be the only door that behaves.\n * Writing `msec` by hand has to leave the timer exactly as\n * set_timeout() would.\n *\n * No recursion through gobj_stop(): it clears `running` BEFORE\n * calling mt_stop(), and mt_stop() lands right back here.\n */\n if(priv.msec > 0) {\n if(!gobj_is_running(gobj)) {\n gobj_start(gobj);\n }\n } else {\n if(gobj_is_running(gobj)) {\n gobj_stop(gobj);\n }\n }\n break;\n }\n}\n\n/***************************************************************\n * Framework Method: Start\n ***************************************************************/\nfunction mt_start(gobj)\n{\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Stop\n ***************************************************************/\nfunction mt_stop(gobj)\n{\n gobj_write_integer_attr(gobj, \"msec\", -1); // This write stops any timer\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Destroy\n ***************************************************************/\nfunction mt_destroy(gobj)\n{\n}\n\n\n\n\n /***************************\n * Actions\n ***************************/\n\n\n\n\n/***************************************************************\n * Action: Timeout\n ***************************************************************/\nfunction ac_timeout(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n let ev = priv.periodic ? \"EV_TIMEOUT_PERIODIC\" : \"EV_TIMEOUT\";\n\n /*\n * Re-arm BEFORE delivering, like C does, and for its two reasons:\n * the period must not carry the execution time of the action, and a\n * clear_timeout() made from INSIDE the action has to win. Re-arming\n * afterwards undid that clear and re-armed with the msec the clear\n * had just written -- a negative delay, which setTimeout() serves\n * immediately: a cleared periodic timer turned into a busy loop.\n */\n if(priv.periodic && priv.msec > 0) {\n priv.timer_id = setTimeout(\n function() {\n gobj_send_event(gobj, \"EV_TIMEOUT\", {}, gobj);\n },\n priv.msec\n );\n } else {\n priv.timer_id = -1;\n }\n\n /*\n * SERVICE subscription model\n */\n if (gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), ev, {}, gobj);\n } else {\n gobj_publish_event(gobj, ev, {});\n }\n\n /*\n * A one-shot is spent: it stops itself, so nobody has to stop it.\n * Unless the action just re-armed it -- `timer_id` back from -1 is\n * the same guard C makes on `t_flush`.\n */\n if(!priv.periodic && priv.timer_id === -1) {\n if(gobj_is_running(gobj)) {\n gobj_stop(gobj);\n }\n }\n\n return 0;\n}\n\n\n\n\n /***************************\n * FSM\n ***************************/\n\n\n\n\n/*---------------------------------------------*\n * Global methods table\n *---------------------------------------------*/\nconst gmt = {\n mt_create: mt_create,\n mt_writing: mt_writing,\n mt_start: mt_start,\n mt_stop: mt_stop,\n mt_destroy: mt_destroy,\n};\n\n/***************************************************************\n * Create the GClass\n ***************************************************************/\nfunction create_gclass(gclass_name)\n{\n if (__gclass__) {\n log_error(`GClass ALREADY created: ${gclass_name}`);\n return -1;\n }\n\n /*---------------------------------------------*\n * States\n *---------------------------------------------*/\n const st_idle = [\n [\"EV_TIMEOUT\", ac_timeout, null]\n ];\n\n const states = [\n [\"ST_IDLE\", st_idle]\n ];\n\n /*---------------------------------------------*\n * Events\n *---------------------------------------------*/\n const event_types = [\n [\"EV_TIMEOUT\", event_flag_t.EVF_OUTPUT_EVENT],\n [\"EV_TIMEOUT_PERIODIC\", event_flag_t.EVF_OUTPUT_EVENT],\n [0, 0]\n ];\n\n /*----------------------------------------*\n * Create the gclass\n *----------------------------------------*/\n __gclass__ = gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n 0, // lmt,\n attrs_table,\n PRIVATE_DATA,\n 0, // authz_table,\n 0, // command_table,\n 0, // s_user_trace_level\n gclass_flag_t.gcflag_manual_start // gclass_flag\n );\n if (!__gclass__) {\n // Error already logged\n return -1;\n }\n\n return 0;\n}\n\n/***************************************************************************\n * Register GClass\n ***************************************************************************/\nfunction register_c_timer()\n{\n return create_gclass(GCLASS_NAME);\n}\n\n\n\n\n /***************************\n * Helpers\n ***************************/\n\n\n\n\n/***************************************************************************\n * Set timeout\n ***************************************************************************/\nfunction set_timeout(gobj, msec)\n{\n if(!(gobj instanceof GObj)) {\n log_error(`not GObj TYPE`);\n return -1;\n }\n if(gobj_gclass_name(gobj) !== \"C_TIMER\") {\n log_error(`not C_TIMER GObj`);\n return -1;\n }\n\n gobj_write_bool_attr(gobj, \"periodic\", false);\n gobj_write_integer_attr(gobj, \"msec\", msec); // This write launches the timer\n}\n\n/***************************************************************************\n * Set periodic timeout\n ***************************************************************************/\nfunction set_timeout_periodic(gobj, msec)\n{\n if(!(gobj instanceof GObj)) {\n log_error(`not GObj TYPE`);\n return -1;\n }\n if(gobj_gclass_name(gobj) !== \"C_TIMER\") {\n log_error(`not C_TIMER GObj`);\n return -1;\n }\n\n gobj_write_bool_attr(gobj, \"periodic\", true);\n gobj_write_integer_attr(gobj, \"msec\", msec); // This write launches the timer\n}\n\n/***************************************************************************\n * Clear timeout\n ***************************************************************************/\nfunction clear_timeout(gobj)\n{\n if(!(gobj instanceof GObj)) {\n log_error(`not GObj TYPE`);\n return -1;\n }\n if(gobj_gclass_name(gobj) !== \"C_TIMER\") {\n log_error(`not C_TIMER GObj`);\n return -1;\n }\n\n gobj_write_integer_attr(gobj, \"msec\", -1); // This write stops the timer\n}\n\nexport { register_c_timer, set_timeout, set_timeout_periodic, clear_timeout };\n","/****************************************************************************\n * c_yuno.js\n *\n * The default yuno in js\n *\n * Copyright (c) 2025-2026, ArtGins.\n * All Rights Reserved. ****************************************************************************/\nimport {\n YUNETA_VERSION,\n SDATA,\n SDATA_END,\n data_type_t,\n event_flag_t,\n gclass_create,\n gobj_create_pure_child,\n gobj_start,\n gobj_play,\n gobj_pause,\n gobj_is_playing,\n gobj_is_running,\n gobj_default_service,\n gobj_stop_children,\n gobj_name,\n gobj_read_attr,\n gobj_publish_event,\n gobj_write_str_attr,\n gobj_write_attr,\n gobj_yuno_role,\n gobj_yuno_name,\n gclass_find_by_name,\n gobj_set_global_trace,\n gobj_set_global_no_trace,\n gobj_set_global_trace2,\n gobj_set_global_no_trace2,\n gobj_set_gclass_trace,\n gobj_set_gclass_no_trace,\n gobj_get_global_trace_level,\n gobj_get_global_trace_no_level,\n gobj_get_gclass_trace_level,\n gobj_get_gclass_trace_level2,\n gobj_get_gclass_trace_no_level,\n gobj_save_persistent_attrs,\n sdata_flag_t,\n} from \"./gobj.js\";\n\nimport {\n current_timestamp,\n log_error, node_uuid,\n is_object,\n is_array,\n} from \"./helpers.js\";\n\nimport {\n build_command_response,\n} from \"./command_parser.js\";\n\nimport {\n set_timeout_periodic,\n clear_timeout\n} from \"./c_timer.js\";\n\n/***************************************************************\n * Constants\n ***************************************************************/\nconst GCLASS_NAME = \"C_YUNO\";\n\n/***************************************************************\n * Data\n ***************************************************************/\n/*---------------------------------------------*\n * Attributes\n *---------------------------------------------*/\nconst attrs_table = [\nSDATA(data_type_t.DTP_BOOLEAN, \"changesLost\", 0, false, \"Set true to warn about leaving page\"),\nSDATA(data_type_t.DTP_BOOLEAN, \"browser_beforeunload\", 0, false, \"Set true to refreshing browser\"),\nSDATA(data_type_t.DTP_STRING, \"__username__\", 0, \"\", \"Username\"),\nSDATA(data_type_t.DTP_STRING, \"start_date\", 0, \"\", \"Yuno starting date\"),\nSDATA(data_type_t.DTP_STRING, \"node_uuid\", 0, \"\", \"uuid of node\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_role\", 0, \"\", \"Yuno role\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_id\", 0, \"\", \"Yuno Id. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_name\", 0, \"\", \"Yuno name. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_tag\", 0, \"\", \"Tags of yuno. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_release\", 0, \"\", \"Yuno Release. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_version\", 0, \"\", \"Yuno version (APP_VERSION)\"),\nSDATA(data_type_t.DTP_STRING, \"yuneta_version\", 0, YUNETA_VERSION, \"Yuneta version\"),\nSDATA(data_type_t.DTP_LIST, \"required_services\", 0, \"[]\", \"Required services\"),\nSDATA(data_type_t.DTP_DICT, \"trace_levels\", sdata_flag_t.SDF_PERSIST, \"{}\", \"Trace levels\"),\nSDATA(data_type_t.DTP_DICT, \"no_trace_levels\", sdata_flag_t.SDF_PERSIST, \"{}\", \"No trace levels\"),\nSDATA(data_type_t.DTP_POINTER, \"trace_ievent_callback\",0, null, \"Where the traffic trace goes (C_IEVENT_CLI levels ievents/ievents2); console when null\"),\nSDATA(data_type_t.DTP_BOOLEAN, \"developer\", 0, false, \"Developer mode enabled\"),\nSDATA(data_type_t.DTP_INTEGER, \"periodic_timeout\", 0, \"1000\", \"Timeout periodic, in miliseconds.\"),\nSDATA_END()\n];\n\nlet PRIVATE_DATA = {\n gobj_timer: null,\n};\n\nlet __gclass__ = null;\n\n\n\n\n /******************************\n * Framework Methods\n ******************************/\n\n\n\n\n/***************************************************************\n * Framework Method: Create\n ***************************************************************/\nfunction mt_create(gobj)\n{\n let priv = gobj.priv;\n\n let date = current_timestamp();\n gobj_write_str_attr(gobj, \"start_date\", date);\n gobj_write_str_attr(gobj, \"node_uuid\", node_uuid());\n\n /*\n * Create children\n */\n gobj.priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), \"C_TIMER\", {}, gobj);\n\n priv.periodic_timeout = gobj_read_attr(gobj, \"periodic_timeout\");\n\n /*\n * Traces: what the user persisted wins over what main() set by\n * default. The persistent attrs are already loaded (a yuno is a\n * service), as in the C kernel's C_YUNO.\n */\n set_user_gclass_traces(gobj);\n set_user_gclass_no_traces(gobj);\n}\n\n/***************************************************************\n * Framework Method: Writing\n ***************************************************************/\nfunction mt_writing(gobj, path)\n{\n}\n\n/***************************************************************\n * Framework Method: Start\n ***************************************************************/\nfunction mt_start(gobj)\n{\n set_timeout_periodic(gobj.priv.gobj_timer, gobj.priv.periodic_timeout);\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Stop\n ***************************************************************/\nfunction mt_stop(gobj)\n{\n /*\n * When yuno stops, it's the death of the app\n */\n clear_timeout(gobj.priv.gobj_timer);\n gobj_stop_children(gobj);\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Play\n ***************************************************************/\nfunction mt_play(gobj)\n{\n let default_service = gobj_default_service();\n if(!gobj_is_running(default_service)) {\n gobj_start(default_service);\n }\n if(!gobj_is_playing(default_service)) {\n gobj_play(default_service);\n }\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Pause\n ***************************************************************/\nfunction mt_pause(gobj)\n{\n gobj_pause(gobj_default_service());\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Destroy\n ***************************************************************/\nfunction mt_destroy(gobj)\n{\n}\n\n\n\n\n /***************************\n * Local Methods\n ***************************/\n\n\n\n\n/***************************************************************\n * Restore the trace levels the user persisted.\n *\n * A saved scope REPLACES what is in force: main() sets its defaults\n * (gobj_set_global_no_trace(\"timer_periodic\"), a gclass it wants quiet)\n * before the yuno is created, and a default the user turned off must\n * stay off. A scope is saved whole, empty included (save_global_trace());\n * a scope never saved keeps main()'s. The C kernel's C_YUNO does the same.\n ***************************************************************/\nfunction set_user_gclass_traces(gobj)\n{\n let jn_trace_levels = gobj_read_attr(gobj, \"trace_levels\");\n if(!is_object(jn_trace_levels)) {\n return 0;\n }\n\n let jn_global = jn_trace_levels[\"__global_trace__\"];\n if(is_array(jn_global)) {\n gobj_set_global_trace2(0xFFFFFFFF, false);\n for(let level of jn_global) {\n gobj_set_global_trace(level, true);\n }\n }\n\n for(const [name, jn_levels] of Object.entries(jn_trace_levels)) {\n let gclass = gclass_find_by_name(name);\n if(!gclass) {\n /* Not a gclass (__global_trace__) or one not registered in\n * this app: nothing to restore, and nothing worth a log. */\n continue;\n }\n if(!is_array(jn_levels)) {\n log_error(`${gobj_name(gobj)}: trace_levels of ${name} MUST be a list`);\n continue;\n }\n gobj_set_gclass_trace(gclass, null, false);\n for(let level of jn_levels) {\n gobj_set_gclass_trace(gclass, level, true);\n }\n }\n return 0;\n}\n\n/***************************************************************\n * Restore the no-trace levels, see set_user_gclass_traces()\n ***************************************************************/\nfunction set_user_gclass_no_traces(gobj)\n{\n let jn_no_trace_levels = gobj_read_attr(gobj, \"no_trace_levels\");\n if(!is_object(jn_no_trace_levels)) {\n return 0;\n }\n\n let jn_global = jn_no_trace_levels[\"__global_no_trace__\"];\n if(is_array(jn_global)) {\n gobj_set_global_no_trace2(0xFFFFFFFF, false);\n for(let level of jn_global) {\n gobj_set_global_no_trace(level, true);\n }\n }\n\n for(const [name, jn_levels] of Object.entries(jn_no_trace_levels)) {\n let gclass = gclass_find_by_name(name);\n if(!gclass) {\n continue; // see set_user_gclass_traces()\n }\n if(!is_array(jn_levels)) {\n log_error(`${gobj_name(gobj)}: no_trace_levels of ${name} MUST be a list`);\n continue;\n }\n gobj_set_gclass_no_trace(gclass, null, false);\n for(let level of jn_levels) {\n gobj_set_gclass_no_trace(gclass, level, true);\n }\n }\n return 0;\n}\n\n/***************************************************************\n * Save a scope WHOLE, from the levels in force (see\n * set_user_gclass_traces()): a saved scope replaces main()'s, so it\n * has to carry everything that must be in force.\n ***************************************************************/\nfunction save_trace_scope(gobj, attr, scope, levels)\n{\n let jn_levels = gobj_read_attr(gobj, attr);\n if(!is_object(jn_levels)) {\n jn_levels = {};\n }\n jn_levels[scope] = levels;\n gobj_write_attr(gobj, attr, jn_levels);\n return gobj_save_persistent_attrs(gobj, attr);\n}\n\n/***************************************************************\n * \"set\" as the C command reads it: TRUE / set / 1, FALSE / reset / 0\n ***************************************************************/\nfunction parse_set(value)\n{\n if(value === true || value === false) {\n return value;\n }\n let v = String(value === undefined || value === null ? \"\" : value).toLowerCase();\n if(v === \"true\" || v === \"set\") {\n return true;\n }\n if(v === \"false\" || v === \"reset\") {\n return false;\n }\n if(v === \"\" || isNaN(Number(v))) {\n return null;\n }\n return Number(v) ? true : false;\n}\n\nfunction yuno_prefix()\n{\n return `${gobj_yuno_role()}^${gobj_yuno_name()}`;\n}\n\n\n\n\n /***************************\n * Commands\n ***************************/\n\n\n\n\n/***************************************************************\n * The trace commands of the C kernel's C_YUNO, same names and same\n * parameters (`level`, `set`, `gclass_name` / `gclass`). Setting a\n * level saves its scope.\n ***************************************************************/\nfunction mt_command_parser(gobj, command, kw, src)\n{\n kw = kw || {};\n switch(command) {\n case \"get-global-trace\":\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_level());\n case \"get-global-no-trace\":\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_no_level());\n case \"set-global-trace\":\n case \"set-global-no-trace\":\n {\n let no = (command === \"set-global-no-trace\");\n let level = kw.level;\n let set = parse_set(kw.set);\n if(!level) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: what level?`, null, null);\n }\n if(set === null) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: bitmask set or re-set?`, null, null);\n }\n let ret = no ? gobj_set_global_no_trace(level, set) : gobj_set_global_trace(level, set);\n if(ret < 0) {\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: global trace level not found: ${level}`, null, null\n );\n }\n if(no) {\n save_trace_scope(gobj, \"no_trace_levels\", \"__global_no_trace__\", gobj_get_global_trace_no_level());\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_no_level());\n }\n save_trace_scope(gobj, \"trace_levels\", \"__global_trace__\", gobj_get_global_trace_level());\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_level());\n }\n case \"get-gclass-trace\":\n case \"get-gclass-no-trace\":\n case \"set-gclass-trace\":\n case \"set-gclass-no-trace\":\n {\n let no = command.indexOf(\"no-trace\") >= 0;\n let gclass_name = kw.gclass_name || kw.gclass || \"\";\n let gclass = gclass_find_by_name(gclass_name);\n if(!gclass) {\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: what gclass is '${gclass_name}'?`, null, null\n );\n }\n if(command.indexOf(\"get-\") === 0) {\n return build_command_response(gobj, 0, null, null,\n no ? gobj_get_gclass_trace_no_level(gclass) : gobj_get_gclass_trace_level(gclass)\n );\n }\n let level = kw.level;\n let set = parse_set(kw.set);\n if(!level) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: what level?`, null, null);\n }\n if(set === null) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: bitmask set or re-set?`, null, null);\n }\n let ret = no ? gobj_set_gclass_no_trace(gclass, level, set) : gobj_set_gclass_trace(gclass, level, set);\n if(ret < 0) {\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: trace level of ${gclass_name} not found: ${level}`, null, null\n );\n }\n if(no) {\n save_trace_scope(gobj, \"no_trace_levels\", gclass_name, gobj_get_gclass_trace_no_level(gclass));\n return build_command_response(gobj, 0, null, null, gobj_get_gclass_trace_no_level(gclass));\n }\n save_trace_scope(gobj, \"trace_levels\", gclass_name, gobj_get_gclass_trace_level2(gclass));\n return build_command_response(gobj, 0, null, null, gobj_get_gclass_trace_level(gclass));\n }\n default:\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: command not available: ${command}`, null, null\n );\n }\n}\n\n\n\n\n /***************************\n * Actions\n ***************************/\n\n\n\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_timeout(gobj, event, kw, src)\n{\n gobj_publish_event(gobj, event, kw);\n return 0;\n}\n\n\n\n\n /***************************\n * FSM\n ***************************/\n\n\n\n\n/*---------------------------------------------*\n * Global methods table\n *---------------------------------------------*/\nconst gmt = {\n mt_create: mt_create,\n mt_writing: mt_writing,\n mt_start: mt_start,\n mt_stop: mt_stop,\n mt_destroy: mt_destroy,\n mt_play: mt_play,\n mt_pause: mt_pause,\n mt_command_parser: mt_command_parser,\n};\n\n\n/***************************************************************\n * Create the GClass\n ***************************************************************/\nfunction create_gclass(gclass_name)\n{\n if(__gclass__) {\n log_error(`GClass ALREADY created: ${gclass_name}`);\n return -1;\n }\n\n /*---------------------------------------------*\n * States\n *---------------------------------------------*/\n const st_idle = [\n [\"EV_TIMEOUT_PERIODIC\", ac_timeout, null]\n ];\n\n const states = [\n [\"ST_IDLE\", st_idle]\n ];\n\n /*---------------------------------------------*\n * Events\n *---------------------------------------------*/\n const event_types = [\n [\"EV_TIMEOUT_PERIODIC\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [0, 0]\n ];\n\n /*----------------------------------------*\n * Create the gclass\n *----------------------------------------*/\n __gclass__ = gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n 0, // lmt,\n attrs_table,\n PRIVATE_DATA,\n 0, // authz_table,\n 0, // command_table,\n 0, // s_user_trace_level\n 0 // gclass_flag\n );\n if(!__gclass__) {\n // Error already logged\n return -1;\n }\n\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction register_c_yuno()\n{\n return create_gclass(GCLASS_NAME);\n}\n\nexport { register_c_yuno };\n","/**************************************************************************\n * c_ievent_cli.js\n * Ievent_cli GClass.\n *\n * Inter-event (client side)\n * Simulate a remote service like a local gobj.\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025-2026, ArtGins.\n **************************************************************************/\nimport {\n YUNETA_VERSION,\n SDATA,\n SDATA_END,\n data_type_t,\n gclass_flag_t,\n sdata_flag_t,\n event_flag_t,\n gclass_create,\n gobj_parent,\n gobj_short_name,\n gobj_yuno,\n gobj_trace_level,\n gobj_send_event,\n gobj_publish_event,\n gobj_read_integer_attr,\n gobj_read_str_attr,\n gobj_read_pointer_attr,\n gobj_write_str_attr,\n gobj_subscribe_event,\n gobj_is_pure_child,\n gobj_create_pure_child,\n gobj_name,\n gobj_current_state,\n gobj_is_destroying,\n gobj_yuno_name,\n gobj_yuno_role,\n gobj_find_subscriptions,\n gobj_is_running,\n gobj_is_playing,\n gobj_read_attr,\n gobj_yuno_id,\n gobj_has_event,\n gobj_find_service,\n gobj_change_state,\n gobj_read_bool_attr,\n\n} from \"./gobj.js\";\n\nimport {\n log_error,\n log_debug,\n log_warning,\n current_timestamp,\n empty_string,\n msg_iev_push_stack,\n msg_iev_get_stack,\n kw_get_str,\n kw_get_int,\n kw_get_dict_value,\n node_uuid,\n msg_iev_set_msg_type,\n msg_iev_get_msg_type,\n trace_json,\n json_deep_copy,\n json_object_del,\n set_remote_log_functions, kw_flag_t,\n} from \"./helpers.js\";\n\nimport {\n clear_timeout,\n set_timeout\n} from \"./c_timer.js\";\n\n/***************************************************************\n * Constants\n ***************************************************************/\nconst GCLASS_NAME = \"C_IEVENT_CLI\";\n\nconst IEVENT_STACK_ID = \"ievent_gate_stack\";\nconst COMMAND_STACK_ID = \"command_stack\";\nconst STATS_STACK_ID = \"stats_stack\";\n\n/***************************************************************\n * Data\n ***************************************************************/\n/*---------------------------------------------*\n * Attributes\n *---------------------------------------------*/\nconst attrs_table = [\n/*-ATTR-type--------------------name----------------flag------------------------default-----description---------- */\nSDATA (data_type_t.DTP_STRING, \"wanted_yuno_role\", sdata_flag_t.SDF_RD, \"\", \"wanted yuno role\"),\nSDATA (data_type_t.DTP_STRING, \"wanted_yuno_name\", sdata_flag_t.SDF_RD, \"\", \"wanted yuno name\"),\nSDATA (data_type_t.DTP_STRING, \"wanted_yuno_service\",sdata_flag_t.SDF_RD, \"\", \"wanted yuno service\"),\nSDATA (data_type_t.DTP_STRING, \"remote_yuno_role\", sdata_flag_t.SDF_RD, \"\", \"confirmed remote yuno role\"),\nSDATA (data_type_t.DTP_STRING, \"remote_yuno_name\", sdata_flag_t.SDF_RD, \"\", \"confirmed remote yuno name\"),\nSDATA (data_type_t.DTP_STRING, \"remote_yuno_service\",sdata_flag_t.SDF_RD, \"\", \"confirmed remote yuno service\"),\nSDATA (data_type_t.DTP_STRING, \"url\", sdata_flag_t.SDF_RD, \"\", \"Url to connect\"),\nSDATA (data_type_t.DTP_STRING, \"jwt\", sdata_flag_t.SDF_PERSIST, \"\", \"JWT\"),\nSDATA (data_type_t.DTP_STRING, \"cert_pem\", sdata_flag_t.SDF_PERSIST, \"\", \"SSL server certification, PEM str format\"),\nSDATA (data_type_t.DTP_JSON, \"extra_info\", sdata_flag_t.SDF_RD, \"{}\", \"dict data set by user, added to the identity card msg.\"),\nSDATA (data_type_t.DTP_LIST, \"required_services\",sdata_flag_t.SDF_RD, \"[]\", \"Services this LINK requires (identity card). Empty = the yuno's `required_services`, as before. A yuno with several links to DIFFERENT backends must set it per link: the yuno-wide list is the union, so every backend is told the service names of all the others.\"),\nSDATA (data_type_t.DTP_INTEGER, \"timeout_retry\", sdata_flag_t.SDF_RD, \"5000\", \"First reconnect delay (ms). It BACKS OFF from here, doubling up to timeout_retry_max, and resets when a session is reached\"),\nSDATA (data_type_t.DTP_INTEGER, \"timeout_retry_max\",sdata_flag_t.SDF_RD, \"60000\", \"Cap of the reconnect backoff (ms). Set it equal to timeout_retry for the old fixed-interval behaviour\"),\nSDATA (data_type_t.DTP_INTEGER, \"timeout_idack\", sdata_flag_t.SDF_RD, \"5000\", \"timeout waiting idAck\"),\nSDATA (data_type_t.DTP_POINTER, \"subscriber\", 0, 0, \"subscriber of output-events. If null then subscriber is the parent\"),\nSDATA_END()\n];\n\n/*---------------------------------------------*\n * GClass trace levels\n * HACK strict ascendant value!\n * required paired correlative strings\n * in s_user_trace_level\n *---------------------------------------------*/\nconst TRACE_IEVENTS = 0x0001;\nconst TRACE_IEVENTS2 = 0x0002;\nconst s_user_trace_level = [\n [\"ievents\", \"Trace inter-events with metadata of kw\"],\n [\"ievents2\", \"Trace inter-events with full kw\"],\n [\"identity-card\", \"Trace identity_card messages\"],\n];\n\n/* The traffic trace is this gclass's own level, as in the C kernel\n * (`set-gclass-trace gclass=C_IEVENT_CLI level=ievents`). Where it goes\n * is the yuno's `trace_ievent_callback`, the console when there is none. */\nfunction is_traffic_tracing(gobj)\n{\n return (gobj_trace_level(gobj) & (TRACE_IEVENTS|TRACE_IEVENTS2)) ? true : false;\n}\n\n/*---------------------------------------------*\n * Private data\n *---------------------------------------------*/\nlet PRIVATE_DATA = {\n url: null,\n remote_yuno_name: null,\n remote_yuno_role: null,\n remote_yuno_service:null,\n gobj_timer: null,\n inform_on_close: false,\n websocket: null,\n inside_on_open: false, // avoid duplicates, no subscriptions while in on_open,\n // they will send in resend_subscriptions\n retry_ms: 0, // current backoff (0 = none yet); see next_retry()\n};\n\nlet __gclass__ = null;\n\n\n\n\n /******************************\n * Framework Methods\n ******************************/\n\n\n\n\n/***************************************************************\n * Framework Method: Create\n ***************************************************************/\nfunction mt_create(gobj)\n{\n let priv = gobj.priv;\n\n /*\n * Create children\n */\n priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), \"C_TIMER\", {}, gobj);\n\n priv.url = gobj_read_str_attr(gobj, \"url\");\n priv.remote_yuno_name = gobj_read_str_attr(gobj, \"remote_yuno_name\");\n priv.remote_yuno_role = gobj_read_str_attr(gobj, \"remote_yuno_role\");\n priv.remote_yuno_service = gobj_read_str_attr(gobj, \"remote_yuno_service\");\n\n gobj_write_str_attr(gobj, \"wanted_yuno_name\", priv.remote_yuno_name);\n gobj_write_str_attr(gobj, \"wanted_yuno_role\", priv.remote_yuno_role);\n gobj_write_str_attr(gobj, \"wanted_yuno_service\", priv.remote_yuno_service);\n\n /*\n * SERVICE subscription model\n */\n const subscriber = gobj_read_pointer_attr(gobj, \"subscriber\");\n if(subscriber) {\n gobj_subscribe_event(gobj, null, {}, subscriber);\n }\n}\n\n/***************************************************************\n * Framework Method: Writing\n ***************************************************************/\nfunction mt_writing(gobj, path)\n{\n let priv = gobj.priv;\n\n switch(path) {\n case \"url\":\n priv.url = gobj_read_str_attr(gobj, \"url\");\n break;\n case \"remote_yuno_name\":\n priv.remote_yuno_name = gobj_read_str_attr(gobj, \"remote_yuno_name\");\n break;\n case \"remote_yuno_role\":\n priv.remote_yuno_role = gobj_read_str_attr(gobj, \"remote_yuno_role\");\n break;\n case \"remote_yuno_service\":\n priv.remote_yuno_service = gobj_read_str_attr(gobj, \"remote_yuno_service\");\n break;\n }\n}\n\n/***************************************************************\n * Framework Method: Start\n ***************************************************************/\nfunction mt_start(gobj)\n{\n let priv = gobj.priv;\n\n /* Starting is a deliberate act (the operator pressed connect): it must\n * not inherit the backoff a previous run had escalated to. */\n priv.retry_ms = 0;\n\n priv.websocket = setup_websocket(gobj);\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Stop\n ***************************************************************/\nfunction mt_stop(gobj)\n{\n let priv = gobj.priv;\n\n clear_timeout(priv.gobj_timer);\n\n if(priv.websocket) {\n /*\n * Keep the .onclose handler wired: a deliberate stop that does\n * NOT destroy the gobj (e.g. a frontend that stops\n * __remote_service__ on logout and drives its UI teardown from\n * the published EV_ON_CLOSE) still needs the async onclose to\n * reach the FSM. This mirrors the C kernel, where mt_stop stops\n * the bottom transport and ac_on_close publishes EV_ON_CLOSE.\n * The stop+destroy-in-the-same-turn case is handled in the\n * onclose handler itself (gobj_is_destroying guard).\n */\n close_websocket(gobj);\n }\n\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Destroy\n ***************************************************************/\nfunction mt_destroy(gobj)\n{\n}\n\n/***************************************************************\n * Framework Method: Stats\n * Ask for stats to remote `kw.service` (or wanted_yuno_service)\n ***************************************************************/\nfunction mt_stats(gobj, stats, kw, src)\n{\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n log_error(`Not in session`);\n return null;\n }\n\n if(!kw) {\n kw = {};\n }\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(src),\n kw_get_str(gobj, kw, \"service\", null, 0)\n );\n\n let __md_stats__ = kw_get_dict_value(\n gobj, kw, \"__md_stats__\", null, kw_flag_t.KW_EXTRACT\n );\n if(__md_stats__) {\n //\n } else {\n __md_stats__ = {};\n }\n\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n STATS_STACK_ID,\n {\n \"stats\": stats,\n \"kw\": __md_stats__\n }\n );\n\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id\n );\n\n kw[\"__stats__\"] = stats;\n msg_iev_set_msg_type(gobj, kw, \"__stats__\");\n\n send_static_iev(gobj, \"EV_MT_STATS\", kw, src);\n\n return null; // return null on asynchronous response.\n}\n\n/***************************************************************\n * Framework Method: Command\n * Ask for command to remote `kw.service` (or wanted_yuno_service)\n ***************************************************************/\nfunction mt_command(gobj, command, kw, src)\n{\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n log_error(`Not in session`);\n return null;\n }\n\n if(!kw) {\n kw = {};\n }\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(src),\n kw_get_str(gobj, kw, \"service\", \"\", 0)\n );\n\n let __md_command__ = kw_get_dict_value(\n gobj, kw, \"__md_command__\", null, kw_flag_t.KW_EXTRACT\n );\n if(__md_command__) {\n //\n } else {\n __md_command__ = {};\n }\n\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n COMMAND_STACK_ID,\n {\n \"command\": command,\n \"kw\": __md_command__\n }\n );\n\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id\n );\n\n kw[\"__command__\"] = command;\n msg_iev_set_msg_type(gobj, kw, \"__command__\");\n\n send_static_iev(gobj, \"EV_MT_COMMAND\", kw, src);\n\n return null; // return null on asynchronous response.\n}\n\n/***************************************************************\n * Framework Method: inject_event\n * Send event to remote `kw.service` (or wanted_yuno_service)\n ***************************************************************/\nfunction mt_inject_event(gobj, event, kw, src)\n{\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n window.console.error(`Not in session`); // Don't use log_error\n return -1;\n }\n\n if(!kw) {\n kw = {};\n }\n\n /*\n * __MESSAGE__\n * Put the ievent if it doesn't come with it,\n * if it does come with it, it's because it will be a response\n */\n let jn_request = msg_iev_get_stack(gobj, kw, IEVENT_STACK_ID);\n if(jn_request) {\n /*\n * __RESPONSE__\n */\n } else {\n /*\n * __REQUEST__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(src),\n kw_get_str(gobj, kw, \"__service__\", 0, 0)\n );\n json_object_del(kw, \"__service__\");\n\n msg_iev_push_stack(\n gobj,\n kw,\n \"__message__\",\n event\n );\n\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id\n );\n }\n\n msg_iev_set_msg_type(gobj, kw, \"__message__\");\n\n return send_static_iev(gobj, event, kw, src);\n}\n\n/***************************************************************\n * Framework Method subscription_added\n ***************************************************************/\nfunction mt_subscription_added(gobj, subs)\n{\n let priv = gobj.priv;\n\n if(gobj_current_state(gobj) !== \"ST_SESSION\" || !priv.websocket) {\n /* on_open will send all subscriptions. The !websocket case is the\n * teardown window: mt_stop already closed the socket but the async\n * onclose hasn't moved the FSM out of ST_SESSION yet. */\n return 0;\n }\n\n if(priv.inside_on_open) {\n // avoid duplicates of subscriptions\n return 0;\n }\n return send_remote_subscription(gobj, subs);\n}\n\n/***************************************************************\n * Framework Method subscription_deleted\n ***************************************************************/\nfunction mt_subscription_deleted(gobj, subs)\n{\n let priv = gobj.priv;\n // in C: return 0;\n // TODO hay algo mal, las subscripciones locales se interpretan como remotas\n\n if(gobj_current_state(gobj) !== \"ST_SESSION\" || !priv.websocket) {\n /* Nothing to do: on open this subscription will not be re-sent.\n * The !websocket case is the teardown window (stop+destroy in the\n * same turn): the socket is gone but the async onclose hasn't moved\n * the FSM out of ST_SESSION — the remote side drops the session's\n * subscriptions on close anyway. */\n return 0;\n }\n\n if(priv.inside_on_open) {\n // avoid duplicates of subscriptions\n return 0;\n }\n if(empty_string(subs.event)) {\n // HACK only resend explicit subscriptions\n return 0;\n }\n\n let kw = {};\n\n let __global__ = subs.__global__;\n let __config__ = subs.__config__;\n let __filter__ = subs.__filter__;\n let __service__ = subs.__service__;\n let subscriber = subs.subscriber;\n\n if(__config__) {\n kw[\"__config__\"] = __config__;\n }\n if(__global__) {\n kw[\"__global__\"] = __global__;\n }\n if(__filter__) {\n kw[\"__filter__\"] = __filter__;\n }\n\n /*\n * __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(subscriber),\n __service__\n );\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n IEVENT_STACK_ID,\n jn_ievent_id // owned\n );\n\n msg_iev_set_msg_type(gobj, kw, \"__unsubscribing__\");\n\n return send_static_iev(gobj, subs.event, kw, gobj);\n}\n\n\n\n\n /***************************\n * Local Methods\n ***************************/\n\n\n\n\n/***************************************************************\n * Setup WebSocket\n * Mixin DOM events -> Yuneta events\n ***************************************************************/\nfunction setup_websocket(gobj)\n{\n if(gobj.priv.websocket) {\n log_error(`Websocket ALREADY setup`);\n }\n\n const url = gobj_read_str_attr(gobj, \"url\");\n log_debug(`====> Starting WebSocket to '${url}' (${gobj_short_name(gobj)})`);\n\n let websocket;\n try {\n websocket = new WebSocket(url);\n } catch (e) {\n log_error(`${gobj_short_name(gobj)}: Cannot open WebSocket to '${url}', Error: ${e.message}`);\n return null;\n }\n\n if (!websocket) {\n log_error(`${gobj_short_name(gobj)}: Failed to initialize WebSocket.`);\n return null;\n }\n\n websocket.onopen = () => {\n // log_debug(`${gobj_short_name(gobj)}: WebSocket connection opened.`);\n gobj_send_event(gobj, \"EV_ON_OPEN\", { url }, gobj);\n };\n\n websocket.onmessage = (e) => {\n // log_debug(`${gobj_short_name(gobj)}: Received message: ${event.data}`);\n gobj_send_event(gobj, \"EV_ON_MESSAGE\", { url, data: e.data }, gobj);\n };\n\n // not useful\n // websocket.onerror = (e) => {\n // log_error(`${gobj_short_name(gobj)}: WebSocket error occurred.`);\n // };\n\n websocket.onclose = (e) => {\n /*\n * A stop+destroy in the same turn (e.g. a wrapper tearing its\n * transport down on logout) leaves this async onclose to fire\n * AFTER the gobj is gone. gobj_is_destroying() covers both the\n * destroying and destroyed flags; bail out so we don't send\n * EV_ON_CLOSE to a dead gobj (\"gobj dst DESTROYED\"). A stop that\n * keeps the gobj alive still gets its EV_ON_CLOSE.\n */\n if(gobj_is_destroying(gobj)) {\n return;\n }\n if(!gobj_read_bool_attr(gobj_yuno(), \"browser_beforeunload\")) {\n gobj_send_event(\n gobj,\n \"EV_ON_CLOSE\",\n {\n url, e: e\n },\n gobj\n );\n } else {\n log_warning('Close websocket by unload page');\n }\n };\n\n return websocket; // Return the WebSocket instance\n}\n\n/***************************************************************\n * Closes the WebSocket connection safely.\n ***************************************************************/\nfunction close_websocket(gobj, code = 1000, reason = \"\")\n{\n let priv = gobj.priv;\n\n let websocket = priv.websocket;\n priv.websocket = null;\n\n if (!websocket ||\n websocket.readyState === WebSocket.CLOSED ||\n websocket.readyState === WebSocket.CLOSING)\n {\n log_warning(\"WebSocket is already closed or in the process of closing.\");\n return;\n }\n\n log_debug(`Closing WebSocket (Code: ${code}, Reason: \"${reason}\")`);\n\n try {\n websocket.close(code, reason);\n } catch (e) {\n log_error(\"Error closing WebSocket:\", e.message);\n }\n}\n\n/***************************************************************\n * Trace intra event\n ***************************************************************/\nfunction trace_inter_event(gobj, prefix, iev)\n{\n let hora = current_timestamp();\n try {\n log_debug(\"\\n\" + hora + \" \" + prefix + \"\\n\");\n //trace_msg(JSON.stringify(iev, null, 4));\n trace_json(iev);\n } catch (e) {\n log_debug(\"ERROR in trace_inter_event: \" + e);\n }\n}\n\n/************************************************************\n * inter event container\n ************************************************************/\nclass InterEvent {\n constructor(event, kw) {\n this.event = event;\n this.kw = kw || {};\n }\n}\n\n/************************************************************\n * Create inter-event\n ************************************************************/\nfunction iev_create(\n event,\n kw)\n{\n if(empty_string(event)) {\n log_error(\"iev_create() event NULL\");\n return null;\n }\n\n return new InterEvent(event, kw);\n}\n\n/**************************************\n * Send jsonify inter-event message\n **************************************/\nfunction send_iev(gobj, iev)\n{\n let priv = gobj.priv;\n\n let msg = JSON.stringify(iev);\n\n if(is_traffic_tracing(gobj)) {\n let url = gobj_read_str_attr(gobj, \"url\");\n let prefix = gobj_name(gobj_yuno()) + ' ==> ' + url;\n let trace_ievent_callback = gobj_read_attr(gobj_yuno(), \"trace_ievent_callback\");\n if(trace_ievent_callback) {\n let size = msg.length;\n trace_ievent_callback(prefix, iev, 1, size);\n } else {\n trace_inter_event(gobj, prefix, iev);\n }\n }\n\n if(!priv.websocket || priv.websocket.readyState !== WebSocket.OPEN) {\n /* Socket gone or not open (teardown window, race with a drop):\n * the message cannot be delivered. A warning, not one TypeError\n * bomb per message. */\n log_warning(`${gobj_short_name(gobj)}: send_iev(): websocket not open, message lost`);\n return -1;\n }\n try {\n priv.websocket.send(msg);\n } catch (e) {\n log_error(`${gobj_short_name(gobj)}: send_iev(): ${e}`);\n //log_error(msg);\n }\n return 0;\n}\n\n/**************************************\n *\n **************************************/\nfunction send_static_iev(gobj, event, kw, src)\n{\n let iev = iev_create(\n event,\n kw\n );\n\n return send_iev(gobj, iev);\n}\n\n/***************************************************************\n * __MESSAGE__\n ***************************************************************/\nfunction build_cli_ievent_request(gobj, src_service, dst_service)\n{\n if(empty_string(dst_service)) {\n dst_service = gobj_read_str_attr(gobj, \"wanted_yuno_service\");\n }\n\n return {\n \"dst_yuno\": gobj_read_str_attr(gobj, \"wanted_yuno_name\"),\n \"dst_role\": gobj_read_str_attr(gobj, \"wanted_yuno_role\"),\n \"dst_service\": dst_service,\n\n \"src_yuno\": gobj_yuno_name(),\n \"src_role\": gobj_yuno_role(),\n \"src_service\": src_service,\n \"host\": node_uuid()\n };\n}\n\n/***************************************************************\n * Send identity card\n ***************************************************************/\nfunction send_identity_card(gobj)\n{\n let priv = gobj.priv;\n\n let playing = gobj_is_playing(gobj_yuno());\n let yuno_version = gobj_read_str_attr(gobj_yuno(), \"yuno_version\");\n let yuno_release = gobj_read_str_attr(gobj_yuno(), \"yuno_release\");\n let yuno_tag = gobj_read_str_attr(gobj_yuno(), \"yuno_tag\");\n\n /*\n * The services THIS link needs authorized. A single-link yuno leaves it\n * empty and the yuno-wide list is used, as it always was. A multi-link\n * yuno (one C_IEVENT_CLI per backend) must set it per link: the yuno's\n * list is necessarily the union of every backend's, so each backend would\n * be handed the service names of all the others.\n */\n let required_services = gobj_read_attr(gobj, \"required_services\");\n if(!required_services || !required_services.length) {\n required_services = gobj_read_attr(gobj_yuno(), \"required_services\");\n }\n\n let kw = {\n \"yuno_role\": gobj_yuno_role(),\n \"yuno_id\": gobj_yuno_id(),\n \"yuno_name\": gobj_yuno_name(),\n \"yuno_tag\": yuno_tag,\n \"yuno_version\": yuno_version,\n \"yuno_release\": yuno_release,\n \"yuneta_version\": YUNETA_VERSION,\n \"playing\": playing,\n \"pid\": 0,\n \"watcher_pid\": 0,\n \"jwt\": gobj_read_str_attr(gobj, \"jwt\"),\n \"username\": gobj_read_str_attr(gobj_yuno(), \"__username__\"),\n \"launch_id\": 0,\n \"yuno_startdate\": gobj_read_str_attr(gobj_yuno(), \"start_date\"),\n \"id\": node_uuid(),\n \"user_agent\": typeof window !== \"undefined\" ? window.navigator.userAgent : \"\",\n \"language\": typeof window !== \"undefined\" ? window.navigator.language : \"\",\n \"required_services\": required_services\n };\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(gobj_parent(gobj)), // TODO ??? in C is gobj_name(gobj),\n null\n );\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id // owned\n );\n\n msg_iev_set_msg_type(gobj, kw, \"__identity__\");\n\n set_timeout(priv.gobj_timer, gobj_read_integer_attr(gobj, \"timeout_idack\"));\n\n return send_static_iev(gobj, \"EV_IDENTITY_CARD\", kw, gobj);\n}\n\n/********************************************\n * Create iev from data received\n * on websocket connection\n ********************************************/\nfunction iev_create_from_json(gobj, data)\n{\n let x;\n try {\n x = JSON.parse(data);\n } catch (e) {\n log_error(\"parsing inter_event json: \" + e);\n return null;\n }\n\n if(!(x instanceof Object)) {\n log_error(\"parsing inter_event: websocket data not a json object\");\n return null;\n }\n let event = x['event'];\n if(!event) {\n log_error(\"parsing inter_event: no event\");\n return null;\n }\n if(typeof event !== 'string') {\n log_error(\"parsing inter_event: event not a string\");\n return null;\n }\n\n let kw = x['kw'];\n if(!kw) {\n log_error(\"parsing inter_kw: no kw\");\n return null;\n }\n if(!(kw instanceof Object)) {\n log_error(\"parsing inter_event: kw not a json object\");\n return null;\n }\n\n return {\n event: event,\n kw: kw || {}\n };\n}\n\n/************************************************\n *\n ************************************************/\nfunction send_remote_subscription(gobj, subs)\n{\n if(empty_string(subs.event)) {\n // HACK only resend explicit subscriptions\n return -1;\n }\n\n let kw = {};\n\n let __global__ = subs.__global__;\n let __config__ = subs.__config__;\n let __filter__ = subs.__filter__;\n let __service__ = subs.__service__;\n let subscriber = subs.subscriber;\n\n if(__config__) {\n kw[\"__config__\"] = __config__;\n }\n if(__global__) {\n kw[\"__global__\"] = __global__;\n }\n if(__filter__) {\n kw[\"__filter__\"] = __filter__;\n }\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(subscriber),\n __service__\n );\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n IEVENT_STACK_ID,\n jn_ievent_id // owned\n );\n\n msg_iev_set_msg_type(gobj, kw, \"__subscribing__\");\n\n return send_static_iev(gobj, subs.event, kw, gobj);\n}\n\n/***************************************************************\n * resend subscriptions\n ***************************************************************/\nfunction resend_subscriptions(gobj)\n{\n let dl_subs = gobj_find_subscriptions(\n gobj,\n null, // event,\n null, // kw (__config__, __global__, __local__)\n null // subscriber\n );\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n send_remote_subscription(gobj, subs);\n }\n}\n\n\n\n\n /***************************\n * Actions\n ***************************/\n\n\n\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_timeout_disconnected(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n if(gobj_is_running(gobj)) {\n priv.websocket = setup_websocket(gobj);\n }\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_on_open(gobj, event, kw, src)\n{\n log_debug('Websocket opened: ' + gobj.priv.url);\n send_identity_card(gobj);\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_on_close(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n let e = kw.e;\n let url = kw.url;\n\n set_remote_log_functions(); // clean remote log\n\n log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${e.code}, Reason: \"${e.reason}\", Clean: ${e.wasClean})`);\n\n // Cleanup WebSocket event handlers\n if(priv.websocket) {\n priv.websocket.onopen = null;\n priv.websocket.onmessage = null;\n priv.websocket.onerror = null;\n priv.websocket.onclose = null;\n priv.websocket = null;\n }\n\n if(priv.inform_on_close) {\n /*\n * We had a real session (EV_ON_OPEN was published) and the\n * channel just dropped. Tell the subscribers — both backend\n * FSMs that need to reset their state and any frontend that\n * cares. inform_on_close is one-shot: re-armed by\n * ac_identity_card_ack on the next successful open.\n */\n priv.inform_on_close = false;\n gobj_publish_event(\n gobj,\n 'EV_ON_CLOSE',\n {\n url: url,\n remote_yuno_name: priv.remote_yuno_name,\n remote_yuno_role: priv.remote_yuno_role,\n remote_yuno_service: priv.remote_yuno_service\n }\n );\n } else {\n /*\n * WebSocket closed BEFORE EV_ON_OPEN ever fired — typical\n * causes: bad TLS cert (ERR_CERT_COMMON_NAME_INVALID), port\n * closed, backend not running, firewall. The framework\n * policy is to keep retrying forever while the gobj is\n * running (the operator may fix the issue at any time, the\n * retry counter ends up in the logs and triggers monitors),\n * so we do NOT stop and we do NOT publish EV_ON_CLOSE\n * (would break the EV_ON_OPEN→EV_ON_CLOSE FSM contract on\n * subscribers that only handle close in their connected\n * state). Instead we publish a separate event,\n * EV_ON_OPEN_ERROR, that interactive subscribers (typical:\n * a browser GUI showing a login form) can opt into. The\n * EVF_NO_WARN_SUBS flag keeps the framework quiet for the\n * many subscribers (mostly backend FSMs) that don't care.\n * Mirrors the WebSocket browser API split: .onopen /\n * .onclose / .onerror.\n *\n * log_warning leaves a precise trace per failed attempt so\n * monitors / log aggregators can alert on it (the framework\n * retries forever; without this line the only sign of\n * trouble would be the WebSocket close in the browser\n * console).\n */\n log_warning(\n `${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ` +\n `${url} (Code: ${e.code}, Reason: \"${e.reason}\", ` +\n `Clean: ${e.wasClean})`\n );\n gobj_publish_event(\n gobj,\n 'EV_ON_OPEN_ERROR',\n {\n url: url,\n remote_yuno_name: priv.remote_yuno_name,\n remote_yuno_role: priv.remote_yuno_role,\n remote_yuno_service: priv.remote_yuno_service,\n code: e.code,\n reason: e.reason,\n was_clean: e.wasClean\n }\n );\n }\n\n if(gobj_is_running(gobj)) {\n set_timeout(priv.gobj_timer, next_retry(gobj));\n }\n\n return 0;\n}\n\n/***************************************************************\n * How long to wait before the next reconnect attempt.\n *\n * The delay used to be a constant (`timeout_retry`, 5s), for ever. A\n * backend that is down — or a URL with a typo, which never comes back —\n * was therefore hit every 5 seconds for the whole life of the tab, by\n * EVERY link pointed at it, all in lockstep. It backs off now: from\n * `timeout_retry`, doubling, capped at `timeout_retry_max`.\n *\n * The jitter (±20%) is what breaks the lockstep. Without it, N links that\n * went down together retry together for ever — a thundering herd against a\n * backend that is just coming back up. It is the one place a random number\n * earns its keep.\n *\n * Reset to zero when a session is actually reached\n * (ac_identity_card_ack), so a link that flaps once does not carry a\n * minute-long penalty into its next real drop.\n ***************************************************************/\nfunction next_retry(gobj)\n{\n let priv = gobj.priv;\n\n let base = gobj_read_integer_attr(gobj, \"timeout_retry\");\n let max = gobj_read_integer_attr(gobj, \"timeout_retry_max\");\n if(max < base) {\n max = base; /* equal = the old fixed-interval behaviour */\n }\n\n priv.retry_ms = priv.retry_ms ? Math.min(priv.retry_ms * 2, max) : base;\n\n let jitter = priv.retry_ms * 0.2;\n let ms = priv.retry_ms - jitter + (Math.random() * 2 * jitter);\n return Math.max(1, Math.round(ms));\n}\n\n/********************************************\n *\n ********************************************/\nfunction ac_timeout_wait_idAck(gobj, event, kw, src)\n{\n send_identity_card(gobj);\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_identity_card_ack(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n /*---------------------------------------*\n * Clear timeout\n *---------------------------------------*/\n clear_timeout(priv.gobj_timer);\n\n /*---------------------------------------*\n * Update remote values\n *---------------------------------------*/\n /*\n * Here is the end point of the request.\n * Don't pop the request, because\n * the event can be publishing to more users.\n */\n /*\n * __RESPONSE__ __MESSAGE__\n */\n let event_id = msg_iev_get_stack(gobj, kw, IEVENT_STACK_ID, true);\n let src_yuno = kw_get_str(gobj, event_id, \"src_yuno\", \"\");\n let src_role = kw_get_str(gobj, event_id, \"src_role\", \"\");\n let src_service = kw_get_str(gobj, event_id, \"src_service\", \"\");\n gobj_write_str_attr(gobj, \"remote_yuno_name\", src_yuno);\n gobj_write_str_attr(gobj, \"remote_yuno_role\", src_role);\n gobj_write_str_attr(gobj, \"remote_yuno_service\", src_service);\n\n // WARNING comprueba result, ahora puede venir negativo\n let result = kw_get_int(gobj, kw, \"result\", -1, 0);\n let comment = kw_get_str(gobj, kw, \"comment\", \"\", 0);\n let username_ = kw_get_str(gobj, kw, \"username\", \"\", 0);\n let services_roles = kw_get_dict_value(gobj, kw, \"services_roles\", {});\n if(result < 0) {\n close_websocket(gobj);\n\n let kw_nak = {\n \"url\": gobj_read_str_attr(gobj, \"url\"),\n \"result\": result,\n \"comment\": comment,\n \"username\": username_,\n \"remote_yuno_name\": src_yuno,\n \"remote_yuno_role\": src_role,\n \"remote_yuno_service\": src_service\n };\n\n /*\n * SERVICE subscription model\n */\n if(gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), \"EV_ON_ID_NAK\", kw_nak, gobj);\n } else {\n gobj_publish_event(gobj, \"EV_ON_ID_NAK\", kw_nak);\n }\n\n } else {\n gobj_change_state(gobj, \"ST_SESSION\");\n priv.inside_on_open = true;\n\n /*\n * A session was reached: the backoff starts over. A link that flaps\n * once must not carry a minute-long penalty into its next real drop.\n */\n priv.retry_ms = 0;\n\n if(!priv.inform_on_close) {\n priv.inform_on_close = true;\n let kw_on_open = {\n \"username\": username_,\n \"remote_yuno_name\": src_yuno,\n \"remote_yuno_role\": src_role,\n \"remote_yuno_service\": src_service,\n \"services_roles\": services_roles,\n };\n\n /*\n * SERVICE subscription model\n */\n if(gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), \"EV_ON_OPEN\", kw_on_open, gobj);\n } else {\n gobj_publish_event(gobj, \"EV_ON_OPEN\", kw_on_open);\n }\n }\n\n priv.inside_on_open = false;\n\n /*\n * Resend subscriptions\n */\n resend_subscriptions(gobj);\n }\n\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_on_message(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n let url = priv.url;\n\n /*------------------------------------------*\n * Create inter_event from received data\n *------------------------------------------*/\n let iev_msg = iev_create_from_json(gobj, kw.data);\n\n /*---------------------------------------*\n * trace inter_event\n *---------------------------------------*/\n if(is_traffic_tracing(gobj)) {\n let prefix = gobj_name(gobj_yuno()) + ' <== ' + url;\n let size = kw.data.length;\n let trace_ievent_callback = gobj_read_attr(gobj_yuno(), \"trace_ievent_callback\");\n if(trace_ievent_callback) {\n trace_ievent_callback(prefix, iev_msg, 2, size);\n } else {\n trace_inter_event(gobj, prefix, iev_msg);\n }\n }\n\n /*----------------------------------------*\n *\n *----------------------------------------*/\n let iev_event = iev_msg.event;\n let iev_kw = iev_msg.kw;\n\n /*-----------------------------------------*\n * If state is not in SESSION, send self.\n * Mainly process EV_IDENTITY_CARD_ACK\n *-----------------------------------------*/\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n if(gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {\n /* Handled unless the action says it FAILED. Not `=== 0`: an\n * action that simply returns nothing answers `undefined`, which\n * is not `=== 0`, and the session was then closed on a message\n * that had just been processed fine. */\n let ret = gobj_send_event(gobj, iev_event, iev_kw, gobj);\n if(!(ret < 0)) {\n // iev_kw consumed\n return 0;\n }\n // iev_kw consumed\n } else {\n log_error(`${gobj_short_name(gobj)}: event UNKNOWN in not-session state ${iev_event}`);\n }\n close_websocket(gobj);\n return -1;\n }\n\n iev_msg = null;\n\n /*------------------------------------*\n * Analyze inter_event\n *------------------------------------*/\n let msg_type = msg_iev_get_msg_type(gobj, iev_kw);\n\n /*----------------------------------------*\n * Get inter-event routing information.\n *----------------------------------------*/\n let event_id = msg_iev_get_stack(gobj, iev_kw, IEVENT_STACK_ID);\n\n /*----------------------------------------*\n * Check dst role^name\n *----------------------------------------*/\n let iev_dst_role = kw_get_str(gobj, event_id, \"dst_role\", \"\");\n // Check yuno_name too\n\n if(iev_dst_role.toLowerCase() !== gobj_yuno_role().toLowerCase()) {\n log_error(`\"It's not my role, dst_role: ${iev_dst_role}, my_role: ${gobj_yuno_role()}`);\n return 0;\n }\n\n /*----------------------------------------*\n * Check dst service\n *----------------------------------------*/\n let iev_dst_service = kw_get_str(gobj, event_id, \"dst_service\", \"\");\n\n /*------------------------------------*\n * Is the event a subscription?\n *------------------------------------*/\n if(msg_type === \"__subscribing__\") {\n /*\n * it's a external subscription\n */\n // TODO subscription\n return -1;\n }\n\n /*---------------------------------------*\n * Is the event is a unsubscription?\n *---------------------------------------*/\n if(msg_type === \"__unsubscribing__\") {\n /*\n * it's a external unsubscription\n */\n // TODO unsubscription\n return -1;\n }\n\n /*-------------------------------------------------------*\n * Filter public events of this gobj\n *-------------------------------------------------------*/\n if(gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {\n /*\n * It's mine (I manage inter-command and inter-stats)\n */\n gobj_send_event(gobj, iev_event, iev_kw, gobj);\n return 0;\n }\n\n /*-------------------------------------------------------------*\n * Dispatch the event\n *\n * A MESSAGE THAT NAMES A SERVICE IS ADDRESSED TO IT, and when\n * that service is gone the message is not for anybody else.\n * Delivering it to the fallback below is how a view's private\n * stream ends up on every other subscriber of this transport.\n *\n * In an SPA that is not theoretical, and the shape is always the\n * same: a view mounted under a service name subscribes to a\n * backend event, the user navigates away, the view is destroyed,\n * and the frames already in flight keep arriving addressed to a\n * name nobody answers to. They were then published to everyone,\n * which in practice means the application gobj -- subscribed to\n * this transport with a NULL event, deliberately, because naming\n * EV_ON_OPEN in a subscription forwards it upstream and the\n * remote rejects it -- and a null subscription matches\n * everything. Its FSM does not declare a device frame, so it said\n * so, loudly, once per frame: 38 of them in one 26 ms burst on a\n * node with 38 devices.\n *\n * It is the ordinary end of a view's life and not a broken\n * invariant -- an unsubscribe cannot recall what is already on\n * the wire -- so the message is dropped with a WARNING that names\n * what was lost, not with an error and a stack.\n *-------------------------------------------------------------*/\n if(!empty_string(iev_dst_service)) {\n let gobj_service = gobj_find_service(iev_dst_service, false);\n if(!gobj_service) {\n log_warning(`${gobj_short_name(gobj)}: event for a service that is gone, DROPPED: service '${iev_dst_service}', ev '${iev_event}'`);\n return 0;\n }\n if(!gobj_has_event(gobj_service, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {\n log_error(`${gobj_short_name(gobj)}: Service found but no event or not public, service '${gobj_short_name(gobj_service)}', ev '${iev_event}'`);\n return -1;\n }\n gobj_send_event(gobj_service, iev_event, iev_kw, gobj);\n return 0;\n }\n\n /*\n * SERVICE subscription model: the message names NO destination,\n * so it belongs to whoever subscribed here. This is the path the\n * check above protects, not one it replaces.\n */\n if(gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), iev_event, iev_kw, gobj);\n } else {\n gobj_publish_event(gobj, iev_event, iev_kw);\n }\n\n return 0;\n}\n\n/***************************************************************************\n * remote asking for stats\n ***************************************************************************/\nfunction ac_mt_stats(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return 0;\n}\n\n/***************************************************************************\n * remote asking for command\n ***************************************************************************/\nfunction ac_mt_command(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return 0;\n}\n\n/***************************************************************************\n * remote asking for play yuno\n ***************************************************************************/\nfunction ac_play_yuno(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return -1;\n}\n\n/***************************************************************************\n * remote asking for pause yuno\n ***************************************************************************/\nfunction ac_pause_yuno(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return -1;\n}\n\n\n\n\n /***************************\n * FSM\n ***************************/\n\n\n\n\n/*---------------------------------------------*\n * Global methods table\n *---------------------------------------------*/\nconst gmt = {\n mt_create: mt_create,\n mt_writing: mt_writing,\n mt_start: mt_start,\n mt_stop: mt_stop,\n mt_destroy: mt_destroy,\n mt_stats: mt_stats,\n mt_command_parser: mt_command,\n mt_inject_event: mt_inject_event,\n mt_subscription_added: mt_subscription_added,\n mt_subscription_deleted: mt_subscription_deleted,\n};\n\n\n/***************************************************************\n * Create the GClass\n ***************************************************************/\nfunction create_gclass(gclass_name)\n{\n if(__gclass__) {\n log_error(`GClass ALREADY created: ${gclass_name}`);\n return -1;\n }\n\n /*---------------------------------------------*\n * States\n *---------------------------------------------*/\n const st_disconnected = [\n [\"EV_ON_OPEN\", ac_on_open, \"ST_WAIT_IDENTITY_CARD_ACK\"],\n [\"EV_ON_CLOSE\", ac_on_close, null],\n [\"EV_TIMEOUT\", ac_timeout_disconnected,null],\n [null, null, null]\n ];\n const st_wait_identity_card_ack = [\n [\"EV_ON_MESSAGE\", ac_on_message, null],\n [\"EV_IDENTITY_CARD_ACK\", ac_identity_card_ack, null],\n [\"EV_ON_CLOSE\", ac_on_close, \"ST_DISCONNECTED\"],\n [\"EV_TIMEOUT\", ac_timeout_wait_idAck, null],\n [null, null, null]\n ];\n const st_session = [\n [\"EV_ON_MESSAGE\", ac_on_message, null],\n [\"EV_MT_STATS\", ac_mt_stats, null],\n [\"EV_MT_COMMAND\", ac_mt_command, null],\n [\"EV_ON_CLOSE\", ac_on_close, \"ST_DISCONNECTED\"],\n [null, null, null]\n ];\n\n const states = [\n [\"ST_DISCONNECTED\", st_disconnected],\n [\"ST_WAIT_IDENTITY_CARD_ACK\", st_wait_identity_card_ack],\n [\"ST_SESSION\", st_session],\n [null, null]\n ];\n\n /*---------------------------------------------*\n * Events\n *---------------------------------------------*/\n const event_types = [\n [\"EV_ON_MESSAGE\", event_flag_t.EVF_OUTPUT_EVENT],\n [\"EV_IDENTITY_CARD_ACK\", event_flag_t.EVF_PUBLIC_EVENT],\n [\"EV_ON_ID_NAK\", event_flag_t.EVF_PUBLIC_EVENT|event_flag_t.EVF_OUTPUT_EVENT],\n\n [\"EV_MT_STATS\", event_flag_t.EVF_PUBLIC_EVENT],\n [\"EV_MT_COMMAND\", event_flag_t.EVF_PUBLIC_EVENT],\n\n [\"EV_ON_OPEN\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [\"EV_ON_CLOSE\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [\"EV_ON_OPEN_ERROR\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [\"EV_TIMEOUT\", 0],\n [null, 0]\n ];\n\n /*----------------------------------------*\n * Create the gclass\n *----------------------------------------*/\n __gclass__ = gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n 0, // lmt,\n attrs_table,\n PRIVATE_DATA,\n 0, // authz_table,\n 0, // command_table,\n s_user_trace_level,\n gclass_flag_t.gcflag_no_check_output_events // gclass_flag\n );\n if(!__gclass__) {\n // Error already logged\n return -1;\n }\n\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction register_c_ievent_cli()\n{\n return create_gclass(GCLASS_NAME);\n}\n\nexport { register_c_ievent_cli };\n"],"mappings":"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"}
1
+ {"version":3,"file":"gobj-js.umd.min.js","names":["GCLASS_NAME","attrs_table","PRIVATE_DATA","__gclass__","mt_create","mt_writing","mt_start","mt_stop","mt_destroy","ac_timeout","gmt","create_gclass","GCLASS_NAME","attrs_table","PRIVATE_DATA","__gclass__","mt_create","mt_writing","mt_start","mt_stop","mt_destroy","gmt","create_gclass"],"sources":["../src/sprintf.js","../src/command_parser.js","../src/stats_parser.js","../src/gobj.js","../src/helpers.js","../src/dbsimple.js","../src/lib_treedb.js","../src/c_timer.js","../src/c_yuno.js","../src/c_ievent_cli.js"],"sourcesContent":["/*\n https://github.com/alexei/sprintf.js/blob/master/src/sprintf.js\n Copyright (c) 2007-present, Alexandru Mărășteanu <hello@alexei.ro>\n */\n\nlet re = {\n not_string: /[^s]/,\n not_bool: /[^t]/,\n not_type: /[^T]/,\n not_primitive: /[^v]/,\n number: /[diefg]/,\n numeric_arg: /[bcdiefguxX]/,\n json: /[j]/,\n not_json: /[^j]/,\n text: /^[^\\x25]+/,\n modulo: /^\\x25{2}/,\n placeholder: /^\\x25(?:([1-9]\\d*)\\$|\\(([^)]+)\\))?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-gijostTuvxX])/,\n key: /^([a-z_][a-z_\\d]*)/i,\n key_access: /^\\.([a-z_][a-z_\\d]*)/i,\n index_access: /^\\[(\\d+)\\]/,\n sign: /^[+-]/\n};\n\nfunction sprintf(key) {\n // `arguments` is not an array, but should be fine for this call\n return sprintf_format(sprintf_parse(key), arguments);\n}\n\nfunction vsprintf(fmt, argv) {\n return sprintf.apply(null, [fmt].concat(argv || []));\n}\n\nfunction sprintf_format(parse_tree, argv) {\n var cursor = 1, tree_length = parse_tree.length, arg, output = '', i, k, ph, pad, pad_character, pad_length, is_positive, sign;\n for (i = 0; i < tree_length; i++) {\n if (typeof parse_tree[i] === 'string') {\n output += parse_tree[i];\n }\n else if (typeof parse_tree[i] === 'object') {\n ph = parse_tree[i]; // convenience purposes only\n if (ph.keys) { // keyword argument\n arg = argv[cursor];\n for (k = 0; k < ph.keys.length; k++) {\n if (arg == undefined) {\n throw new Error(sprintf('[sprintf] Cannot access property \"%s\" of undefined value \"%s\"', ph.keys[k], ph.keys[k-1]));\n }\n arg = arg[ph.keys[k]];\n }\n }\n else if (ph.param_no) { // positional argument (explicit)\n arg = argv[ph.param_no];\n }\n else { // positional argument (implicit)\n arg = argv[cursor++];\n }\n\n if (re.not_type.test(ph.type) && re.not_primitive.test(ph.type) && arg instanceof Function) {\n arg = arg();\n }\n\n if (re.numeric_arg.test(ph.type) && (typeof arg !== 'number' && isNaN(arg))) {\n throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg));\n }\n\n if (re.number.test(ph.type)) {\n is_positive = arg >= 0;\n }\n\n switch (ph.type) {\n case 'b':\n arg = parseInt(arg, 10).toString(2);\n break;\n case 'c':\n arg = String.fromCharCode(parseInt(arg, 10));\n break;\n case 'd':\n case 'i':\n arg = parseInt(arg, 10);\n break;\n case 'j':\n arg = JSON.stringify(arg, null, ph.width ? parseInt(ph.width) : 0);\n break;\n case 'e':\n arg = ph.precision ? parseFloat(arg).toExponential(ph.precision) : parseFloat(arg).toExponential();\n break;\n case 'f':\n arg = ph.precision ? parseFloat(arg).toFixed(ph.precision) : parseFloat(arg);\n break;\n case 'g':\n arg = ph.precision ? String(Number(arg.toPrecision(ph.precision))) : parseFloat(arg);\n break;\n case 'o':\n arg = (parseInt(arg, 10) >>> 0).toString(8);\n break;\n case 's':\n arg = String(arg);\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 't':\n arg = String(!!arg);\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 'T':\n arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase();\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 'u':\n arg = parseInt(arg, 10) >>> 0;\n break;\n case 'v':\n arg = arg.valueOf();\n arg = (ph.precision ? arg.substring(0, ph.precision) : arg);\n break;\n case 'x':\n arg = (parseInt(arg, 10) >>> 0).toString(16);\n break;\n case 'X':\n arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase();\n break;\n }\n if (re.json.test(ph.type)) {\n output += arg;\n }\n else {\n if (re.number.test(ph.type) && (!is_positive || ph.sign)) {\n sign = is_positive ? '+' : '-';\n arg = arg.toString().replace(re.sign, '');\n }\n else {\n sign = '';\n }\n pad_character = ph.pad_char ? ph.pad_char === '0' ? '0' : ph.pad_char.charAt(1) : ' ';\n pad_length = ph.width - (sign + arg).length;\n pad = ph.width ? (pad_length > 0 ? pad_character.repeat(pad_length) : '') : '';\n output += ph.align ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg);\n }\n }\n }\n return output;\n}\n\nlet sprintf_cache = Object.create(null);\n\nfunction sprintf_parse(fmt) {\n if (sprintf_cache[fmt]) {\n return sprintf_cache[fmt];\n }\n\n let _fmt = fmt, match, parse_tree = [], arg_names = 0;\n while (_fmt) {\n if ((match = re.text.exec(_fmt)) !== null) {\n parse_tree.push(match[0]);\n }\n else if ((match = re.modulo.exec(_fmt)) !== null) {\n parse_tree.push('%');\n }\n else if ((match = re.placeholder.exec(_fmt)) !== null) {\n if (match[2]) {\n arg_names |= 1;\n var field_list = [], replacement_field = match[2], field_match = [];\n if ((field_match = re.key.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {\n if ((field_match = re.key_access.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n }\n else if ((field_match = re.index_access.exec(replacement_field)) !== null) {\n field_list.push(field_match[1]);\n }\n else {\n throw new SyntaxError('[sprintf] failed to parse named argument key');\n }\n }\n }\n else {\n throw new SyntaxError('[sprintf] failed to parse named argument key');\n }\n match[2] = field_list;\n }\n else {\n arg_names |= 2;\n }\n if (arg_names === 3) {\n throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported');\n }\n\n parse_tree.push(\n {\n placeholder: match[0],\n param_no: match[1],\n keys: match[2],\n sign: match[3],\n pad_char: match[4],\n align: match[5],\n width: match[6],\n precision: match[7],\n type: match[8]\n }\n );\n }\n else {\n throw new SyntaxError('[sprintf] unexpected placeholder');\n }\n _fmt = _fmt.substring(match[0].length);\n }\n return sprintf_cache[fmt] = parse_tree;\n}\n\nexport { sprintf, vsprintf };\n","/****************************************************************************\n * command_parser.js\n *\n * Command parser\n *\n * Copyright (c) 2025, ArtGins.\n * All Rights Reserved. ****************************************************************************/\n\n/***************************************************************\n *\n ***************************************************************/\nfunction command_parser(\n gobj,\n command,\n kw,\n src\n) {\n\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction build_command_response(\n gobj,\n result,\n comment,\n schema,\n data\n) {\n return {\n result: result,\n comment: comment || {},\n schema: schema || {},\n data: data || []\n };\n}\n\nexport {\n command_parser,\n build_command_response,\n};\n","/****************************************************************************\n * stats_parser.js\n *\n * Stats parser\n *\n * Copyright (c) 2025, ArtGins.\n * All Rights Reserved. ****************************************************************************/\n\n/***************************************************************\n *\n ***************************************************************/\nfunction stats_parser(\n gobj,\n stats,\n kw,\n src\n) {\n\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction build_stats_response(\n gobj,\n result,\n comment,\n schema,\n data\n) {\n return {\n result: result,\n comment: comment || {},\n schema: schema || {},\n data: data || []\n };\n}\n\nexport {\n stats_parser,\n build_stats_response,\n};\n","/*********************************************************************************\n * Objects with a simple Finite State Machine.\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025-2026, ArtGins.\n *********************************************************************************/\n/* jshint bitwise: false */\n\nimport {\n kw_flag_t,\n is_string,\n is_object,\n is_array,\n is_number,\n log_error,\n log_warning,\n empty_string,\n json_deep_copy,\n json_object_update,\n json_object_get,\n json_object_del,\n json_object_set,\n json_object_set_new,\n index_in_list,\n json_array_size,\n strcasecmp,\n kw_get_dict,\n kw_get_bool,\n kw_match_simple,\n kw_get_int,\n json_array_append,\n kw_get_dict_value,\n trace_json,\n json_array_remove,\n kw_get_str,\n kw_has_key,\n kw_pop,\n kw_get_pointer,\n json_object_size,\n log_debug,\n json_array_append_new,\n parseBoolean,\n is_gobj,\n json_size,\n json_is_identical,\n get_function_name,\n} from \"./helpers.js\";\n\nimport {sprintf} from \"./sprintf.js\";\nimport {build_command_response} from \"./command_parser.js\";\nimport {build_stats_response} from \"./stats_parser.js\";\n\n/**************************************************************************\n * Constants\n **************************************************************************/\nlet YUNETA_VERSION = \"7.0.0a\";\n\n/**************************************************************************\n * Private data\n **************************************************************************/\nlet __jn_global_settings__ = null;\nlet __global_load_persistent_attrs_fn__ = null;\nlet __global_save_persistent_attrs_fn__ = null;\nlet __global_remove_persistent_attrs_fn__ = null;\nlet __global_list_persistent_attrs_fn__ = null;\nlet __global_command_parser_fn__ = null;\nlet __global_stats_parser_fn__ = null;\n\n/*\n * System (gobj) output events\n */\nlet dl_global_event_types = [];\n\nlet _gclass_register = Object.create(null);\nlet __jn_services__ = {};\n\nlet __yuno__ = null;\nlet __default_service__ = null;\nlet __inside__ = 0;\n\n/**************************************************************************\n * SData - Structured Data\n **************************************************************************/\nconst data_type_t = Object.freeze({\n DTP_STRING: 1,\n DTP_BOOLEAN: 2,\n DTP_INTEGER: 3,\n DTP_REAL: 4,\n DTP_LIST: 5,\n DTP_DICT: 6,\n DTP_JSON: 7,\n DTP_POINTER: 8\n});\n\n// Macros as functions\nconst DTP_IS_STRING = (type) => type === data_type_t.DTP_STRING;\nconst DTP_IS_BOOLEAN = (type) => type === data_type_t.DTP_BOOLEAN;\nconst DTP_IS_INTEGER = (type) => type === data_type_t.DTP_INTEGER;\nconst DTP_IS_REAL = (type) => type === data_type_t.DTP_REAL;\nconst DTP_IS_LIST = (type) => type === data_type_t.DTP_LIST;\nconst DTP_IS_DICT = (type) => type === data_type_t.DTP_DICT;\nconst DTP_IS_JSON = (type) => type === data_type_t.DTP_JSON;\nconst DTP_IS_POINTER = (type) => type === data_type_t.DTP_POINTER;\nconst DTP_IS_SCHEMA = (type) => type === DTP_SCHEMA;\nconst DTP_SCHEMA = data_type_t.DTP_POINTER;\nconst DTP_IS_NUMBER = (type) => DTP_IS_INTEGER(type) || DTP_IS_REAL(type) || DTP_IS_BOOLEAN(type);\n\nconst sdata_flag_t = Object.freeze({\n SDF_NOTACCESS: 0x00000001,\n SDF_RD: 0x00000002,\n SDF_WR: 0x00000004,\n SDF_REQUIRED: 0x00000008,\n SDF_PERSIST: 0x00000010,\n SDF_VOLATIL: 0x00000020,\n SDF_RESOURCE: 0x00000040,\n SDF_PKEY: 0x00000080,\n SDF_DEPRECATED: 0x00000100,\n SDF_FUTURE2: 0x00000200,\n SDF_WILD_CMD: 0x00000400,\n SDF_STATS: 0x00000800,\n SDF_FKEY: 0x00001000,\n SDF_RSTATS: 0x00002000,\n SDF_PSTATS: 0x00004000,\n SDF_AUTHZ_R: 0x00008000,\n SDF_AUTHZ_W: 0x00010000,\n SDF_AUTHZ_X: 0x00020000,\n SDF_AUTHZ_P: 0x00040000,\n SDF_AUTHZ_S: 0x00080000,\n SDF_AUTHZ_RS: 0x00100000\n});\n\nconst SDF_PUBLIC_ATTR = sdata_flag_t.SDF_RD | sdata_flag_t.SDF_WR | sdata_flag_t.SDF_STATS |\n sdata_flag_t.SDF_PERSIST | sdata_flag_t.SDF_VOLATIL |\n sdata_flag_t.SDF_RSTATS | sdata_flag_t.SDF_PSTATS;\nconst ATTR_WRITABLE = sdata_flag_t.SDF_WR | sdata_flag_t.SDF_PERSIST;\nconst ATTR_READABLE = SDF_PUBLIC_ATTR;\n\nclass SDataDesc {\n constructor(type, name, flag = 0, default_value = null, description = \"\",\n alias = null, header = null, fillspace = 0, json_fn = null, schema = null, authpth = null) {\n this.type = type;\n this.name = name;\n this.alias = alias;\n this.flag = flag;\n this.default_value= default_value;\n this.header = header;\n this.fillspace = fillspace;\n this.description = description;\n this.json_fn = json_fn;\n this.schema = schema;\n this.authpth = authpth;\n }\n}\n\nconst SDATA_END = () => new SDataDesc(0, null);\nconst SDATA = (type, name, flag, default_value, description) => new SDataDesc(type, name, flag, default_value, description);\nconst SDATACM = (type, name, alias, items, json_fn, description) => new SDataDesc(type, name, 0, null, description, alias, null, 0, json_fn, items, null);\nconst SDATACM2 = (type, name, flag, alias, items, json_fn, description) => new SDataDesc(type, name, flag, null, description, alias, null, 0, json_fn, items, null);\nconst SDATAPM = (type, name, flag, default_value, description) => new SDataDesc(type, name, flag, default_value, description);\nconst SDATAAUTHZ = (type, name, flag, alias, items, description) => new SDataDesc(type, name, flag, null, description, alias, null, 0, null, items, null);\nconst SDATAPM0 = (type, name, flag, authpth, description) => new SDataDesc(type, name, flag, null, description, null, null, 0, null, null, authpth);\nconst SDATADF = (type, name, flag, header, fillspace, description) => new SDataDesc(type, name, flag, null, description, null, header, fillspace);\n\n/***************************************************************\n * Structures\n ***************************************************************/\nclass GClass {\n constructor(\n gclass_name,\n gmt,\n lmt,\n attrs_table,\n priv,\n authz_table,\n command_table,\n s_user_trace_level,\n gclass_flag\n ) {\n this.gclass_name = gclass_name;\n this.dl_states = []; // FSM list states and their ev/action/next\n this.dl_events = []; // FSM list of events (gobj_event_t, event_flag_t)\n this.gmt = gmt; // Global methods\n this.lmt = lmt;\n\n this.attrs_table = attrs_table;\n this.priv = priv;\n this.authz_table = authz_table; // acl\n this.command_table = command_table; // if it exits then mt_command is not used.\n\n this.s_user_trace_level = s_user_trace_level;\n this.gclass_flag = Number(gclass_flag) || 0;\n\n this.instances = 0; // instances of this gclass\n this.trace_level = 0;\n this.no_trace_level = 0;\n this.jn_trace_filter = null;\n this.fsm_checked = false;\n }\n}\n\nclass GObj {\n constructor(gobj_name, gclass, kw, parent, gobj_flag) {\n this.__refs__ = 0;\n this.gclass = gclass;\n this.parent = null; // assign in _add_child()\n this.dl_children = [];\n this.dl_subscriptions = []; // subscriptions of this gobj to events of others gobj.\n this.dl_subscribings = []; // subscribed events\n this.current_state = gclass.dl_states[0];\n this.last_state = null;\n this.obflag = 0;\n this.gobj_flag = Number(gobj_flag) || 0;\n\n // Data allocated\n this.gobj_name = gobj_name;\n this.jn_attrs = null;\n this.jn_stats = {};\n this.jn_user_data = {};\n this.full_name = null;\n this.short_name = null;\n this.priv = json_deep_copy(gclass.priv);\n\n this.running = false; // set by gobj_start/gobj_stop\n this.playing = false; // set by gobj_play/gobj_pause\n this.disabled = false; // set by gobj_enable/gobj_disable\n this.bottom_gobj = null;\n\n this.trace_level = 0;\n this.no_trace_level = 0;\n }\n}\n\n/*\n * gclass_flag_t\n * Features of the gclass\n *\n // Example usage:\n\n let flags = gclass_flag_t.gcflag_manual_start | gclass_flag_t.gcflag_singleton;\n\n if (flags & gclass_flag_t.gcflag_manual_start) {\n console.log(\"Manual start flag is set\");\n }\n\n */\n\nconst gclass_flag_t = Object.freeze({\n gcflag_manual_start: 0x0001, // gobj_start_tree() doesn't start automatically\n gcflag_no_check_output_events: 0x0002, // When publishing, don't check events in output_event_list\n gcflag_ignore_unknown_attrs: 0x0004, // When creating a gobj, ignore non-existing attrs\n gcflag_required_start_to_play: 0x0008, // Don't play if start wasn't done\n gcflag_singleton: 0x0010, // Can only have one instance\n});\n\n/*\n * gobj_flag_t\n * Features of the gobj\n *\n // Example usage:\n\n let gobj_flag = gobj_flag_t.gobj_flag_yuno | gobj_flag_t.gobj_flag_service;\n\n // Check if a flag is set\n\n if (gobj_flag & gobj_flag_t.gobj_flag_service) {\n console.log(\"Service flag is set\");\n }\n\n // Convert to array of names for debugging\n\n function print_gobj_flags(flagValue) {\n return Object.keys(gobj_flag_t).filter(key => flagValue & gobj_flag_t[key]);\n }\n\n */\nconst gobj_flag_t = Object.freeze({\n gobj_flag_yuno: 0x0001,\n gobj_flag_default_service: 0x0002,\n gobj_flag_service: 0x0004, // Interface (events, attrs, commands, stats)\n gobj_flag_volatil: 0x0008,\n gobj_flag_pure_child: 0x0010, // Pure child sends events directly to parent\n gobj_flag_autostart: 0x0020, // Set by gobj_create_tree0 too\n gobj_flag_autoplay: 0x0040, // Set by gobj_create_tree0 too\n});\n\n/*\n * obflag_t\n * Features realtime of the gobj\n */\nconst obflag_t = Object.freeze({\n obflag_destroying: 0x0001,\n obflag_destroyed: 0x0002,\n obflag_created: 0x0004,\n});\n\nconst event_flag_t = Object.freeze({\n EVF_NO_WARN_SUBS : 0x0001, // Don't warn of \"Publish event WITHOUT subscribers\"\n EVF_OUTPUT_EVENT : 0x0002, // Output Event\n EVF_SYSTEM_EVENT : 0x0004, // System Event\n EVF_PUBLIC_EVENT : 0x0008, // You should document a public event, it's the API\n});\n\nconst walk_type_t = Object.freeze({\n /*\n * One must be selected\n */\n WALK_TOP2BOTTOM : 0x0001,\n WALK_BOTTOM2TOP : 0x0002,\n WALK_BYLEVEL : 0x0004,\n\n /*\n * One must be selected when WALK_BYLEVEL is selected.\n */\n WALK_FIRST2LAST : 0x0010,\n WALK_LAST2FIRST : 0x0020,\n});\n\n\n/*---------------------------*\n * FSM\n *---------------------------*/\nclass Event_Action { // C event_action_t\n constructor(event_name, action, next_state) {\n this.event_name = event_name;\n this.action = action;\n this.next_state = next_state;\n }\n}\n\nclass State { // C state_t\n constructor(state_name) {\n this.state_name = state_name;\n this.dl_actions = [];\n }\n}\n\nclass Event_Type { // C event_type_t\n constructor(event_name, event_flag) {\n this.event_name = event_name;\n this.event_flag = Number(event_flag) || 0;\n }\n}\n\n/*\n * Indent a trace line by its nesting depth, the same as the C kernel's\n * tab() (gobj.c): TWO spaces per level of `__inside__`, and never zero\n * — it writes bf[0] before the loop, so even at depth 0 a line starts\n * one space in. This was `2n - 1` here, one short at every level, so a\n * trace read side by side with a node's did not line up.\n */\nfunction tab()\n{\n return ' '.repeat(Math.max(1, __inside__ * 2));\n}\n\n/* Machine (automata) trace format, mirroring the C kernel:\n * 0 = legacy (\"🔄 mach(gclass^name), st: STATE, ev: EVENT, ac: …, from(…)\"\n * + a \"🔀🔀 new st(…)\" line + a \"<- mach(…) ret: N\" line —\n * THREE lines for one transition)\n * 1 = simpler (\"🔄 EVENT dst STATE from src\") — one line per transition,\n * no return line and no state-change line.\n *\n * DEFAULT 1, which is the C kernel's default (`trace_machine_format` in\n * gobj.c: \"0 legacy, 1 simpler, 2 full\"). The JS port shipped 0 and so read\n * three lines a transition where a node read one — the same trace, three\n * times the wall, and the two sides did not look alike. */\nlet __trace_machine_format__ = 1;\n\nfunction gobj_set_trace_machine_format(format)\n{\n __trace_machine_format__ = (Number(format) === 1) ? 1 : 0;\n}\n\nfunction gobj_trace_machine_format()\n{\n return __trace_machine_format__;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction trace_machine(msg)\n{\n if(is_object(msg)) {\n msg = JSON.stringify(msg);\n }\n log_debug(tab() + String(msg));\n}\n\n\n/***************************************************************\n * Trace levels\n *\n * The SAME names and the SAME bits as the C kernel (gobj.h's\n * enum + gobj.c's s_global_trace_level), so a level means one\n * thing across the two implementations and a habit learned on\n * one side transfers to the other. The levels that only exist\n * on a node (fs, liburing, gbuffers) keep their bit anyway:\n * dropping them would shift every bit above and break exactly\n * that alignment.\n *\n * 16 higher bits are global, 16 lower bits are per-gclass user\n * levels (`s_user_trace_level` in gclass_create).\n ***************************************************************/\nconst trace_level_t = Object.freeze({\n TRACE_MACHINE: 0x00010000,\n TRACE_CREATE_DELETE: 0x00020000,\n TRACE_CREATE_DELETE2: 0x00040000,\n TRACE_SUBSCRIPTIONS: 0x00080000,\n TRACE_START_STOP: 0x00100000,\n TRACE_EV_KW: 0x00200000,\n TRACE_AUTHZS: 0x00400000,\n TRACE_STATES: 0x00800000,\n TRACE_GBUFFERS: 0x01000000,\n TRACE_TIMER: 0x02000000,\n TRACE_FS: 0x04000000,\n TRACE_URING: 0x08000000,\n TRACE_TIMER_PERIODIC: 0x10000000,\n TRACE_URING_TIME: 0x20000000,\n TRACE_COMMANDS: 0x40000000\n});\n\nconst TRACE_USER_LEVEL = 0x0000FFFF;\nconst TRACE_GLOBAL_LEVEL1 = 0x0FFF0000;\n\n/* Name → bit, in the C table's order. */\nconst s_global_trace_level = [\n [\"machine\", trace_level_t.TRACE_MACHINE, \"Trace machine\"],\n [\"create_delete\", trace_level_t.TRACE_CREATE_DELETE, \"Trace create/delete of gobjs\"],\n [\"create_delete2\", trace_level_t.TRACE_CREATE_DELETE2, \"Trace create/delete of gobjs level 2: with kw\"],\n [\"subscriptions\", trace_level_t.TRACE_SUBSCRIPTIONS, \"Trace subscriptions of gobjs\"],\n [\"start_stop\", trace_level_t.TRACE_START_STOP, \"Trace start/stop of gobjs\"],\n [\"ev_kw\", trace_level_t.TRACE_EV_KW, \"Trace event keywords\"],\n [\"authzs\", trace_level_t.TRACE_AUTHZS, \"Trace authorizations\"],\n [\"states\", trace_level_t.TRACE_STATES, \"Trace change of states\"],\n [\"gbuffers\", trace_level_t.TRACE_GBUFFERS, \"Trace gbuffers\"],\n [\"timer\", trace_level_t.TRACE_TIMER, \"Trace timers\"],\n [\"fs\", trace_level_t.TRACE_FS, \"Trace file system\"],\n [\"liburing\", trace_level_t.TRACE_URING, \"Trace liburing mixins\"],\n [\"timer_periodic\", trace_level_t.TRACE_TIMER_PERIODIC, \"Trace periodic timers\"],\n [\"liburing_timer\", trace_level_t.TRACE_URING_TIME, \"Trace liburing timer\"],\n [\"commands\", trace_level_t.TRACE_COMMANDS, \"Trace commands\"]\n];\n\nlet __global_trace_level__ = 0;\nlet __global_trace_no_level__ = 0;\nlet __deep_trace__ = 0;\n\n/*\n * A gclass's own levels, `s_user_trace_level` in gclass_create: a list of\n * [name, description], in bit order -- the first is 0x0001, like the C\n * table of {name, description}.\n */\nfunction level2bit(level, s_user_trace_level)\n{\n for(const [name, bit] of s_global_trace_level) {\n if(name === level) {\n return bit;\n }\n }\n if(Array.isArray(s_user_trace_level)) {\n for(let i = 0; i < s_user_trace_level.length && i < 16; i++) {\n if(s_user_trace_level[i] && s_user_trace_level[i][0] === level) {\n return 1 << i;\n }\n }\n }\n return 0;\n}\n\n/* The names of the bits set in `bitmask`, global and the gclass's own. */\nfunction bit2level(bitmask, s_user_trace_level)\n{\n let levels = [];\n for(const [name, bit] of s_global_trace_level) {\n if(bitmask & bit) {\n levels.push(name);\n }\n }\n if(Array.isArray(s_user_trace_level)) {\n for(let i = 0; i < s_user_trace_level.length && i < 16; i++) {\n if(s_user_trace_level[i] && (bitmask & (1 << i))) {\n levels.push(s_user_trace_level[i][0]);\n }\n }\n }\n return levels;\n}\n\n/*\n * A level name, a decimal bitmask as a string, or empty for \"all\": all the\n * global levels, or, with a gclass, all of its own (the C kernel's \"\").\n */\nfunction trace_bitmask(level, who, s_user_trace_level)\n{\n if(empty_string(level)) {\n return s_user_trace_level === undefined ? TRACE_GLOBAL_LEVEL1 : TRACE_USER_LEVEL;\n }\n if(/^[0-9]+$/.test(String(level))) {\n const n = Number(level);\n if(n) {\n return n;\n }\n }\n const bit = level2bit(String(level), s_user_trace_level);\n if(!bit) {\n log_error(`${who}: trace level NOT FOUND: ${level}`);\n return 0;\n }\n return bit;\n}\n\n/************************************************************\n * The levels in force for a gobj: global, plus its gclass's,\n * plus its own — the union, exactly as the C kernel computes\n * it in gobj_trace_level().\n ************************************************************/\nfunction gobj_trace_level(gobj)\n{\n if(__deep_trace__) {\n return 0xFFFFFFFF;\n }\n let bitmask = __global_trace_level__;\n if(gobj) {\n bitmask |= gobj.trace_level || 0;\n if(gobj.gclass) {\n bitmask |= gobj.gclass.trace_level || 0;\n }\n }\n return bitmask;\n}\n\nfunction gobj_trace_no_level(gobj)\n{\n let bitmask = __global_trace_no_level__;\n if(gobj) {\n bitmask |= gobj.no_trace_level || 0;\n if(gobj.gclass) {\n bitmask |= gobj.gclass.no_trace_level || 0;\n }\n }\n return bitmask;\n}\n\nfunction __trace_gobj_create_delete__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_CREATE_DELETE;\n}\n\nfunction __trace_gobj_subscriptions__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_SUBSCRIPTIONS;\n}\n\nfunction __trace_gobj_start_stop__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_START_STOP;\n}\n\nfunction __trace_gobj_ev_kw__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_EV_KW;\n}\n\nfunction __trace_gobj_states__(gobj)\n{\n return gobj_trace_level(gobj) & trace_level_t.TRACE_STATES;\n}\n\n/************************************************************\n * Must trace a command? — the C kernel's is_commands_tracing()\n ************************************************************/\nfunction is_commands_tracing(gobj)\n{\n if(__deep_trace__ > 1) {\n return true;\n }\n if(!gobj) {\n return false;\n }\n return (gobj_trace_level(gobj) & trace_level_t.TRACE_COMMANDS) ? true : false;\n}\n\n/************************************************************\n * Must trace? — the C kernel's is_machine_tracing(), including\n * the two event-specific levels: `timer` and `timer_periodic`\n * light up only for their own event.\n ************************************************************/\nfunction is_machine_tracing(gobj, event)\n{\n if(__deep_trace__ > 1) {\n return true;\n }\n if(!gobj) {\n return false;\n }\n const level = gobj_trace_level(gobj);\n const trace =\n (level & trace_level_t.TRACE_MACHINE) ||\n ((level & trace_level_t.TRACE_TIMER_PERIODIC) && event === \"EV_TIMEOUT_PERIODIC\") ||\n ((level & trace_level_t.TRACE_TIMER) && event === \"EV_TIMEOUT\");\n\n return trace ? true : false;\n}\n\n/************************************************************\n * Must NOT trace? Asked of the SOURCE, so a noisy sender can\n * be silenced without turning the destination off.\n ************************************************************/\nfunction is_machine_not_tracing(gobj, event)\n{\n if(__deep_trace__ > 1) {\n return false;\n }\n if(!gobj) {\n return true;\n }\n const level = gobj_trace_no_level(gobj);\n const no_trace =\n (level & trace_level_t.TRACE_MACHINE) ||\n ((level & trace_level_t.TRACE_TIMER_PERIODIC) && event === \"EV_TIMEOUT_PERIODIC\") ||\n ((level & trace_level_t.TRACE_TIMER) && event === \"EV_TIMEOUT\");\n\n return no_trace ? true : false;\n}\n\n/************************************************************\n * The setters — same signatures as the C kernel\n ************************************************************/\nfunction gobj_set_global_trace(level, set)\n{\n const bitmask = trace_bitmask(level, \"gobj_set_global_trace\");\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n __global_trace_level__ |= bitmask;\n } else {\n __global_trace_level__ &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_set_global_no_trace(level, set)\n{\n const bitmask = trace_bitmask(level, \"gobj_set_global_no_trace\");\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n __global_trace_no_level__ |= bitmask;\n } else {\n __global_trace_no_level__ &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_global_trace_level()\n{\n return __global_trace_level__;\n}\n\nfunction gobj_global_trace_no_level()\n{\n return __global_trace_no_level__;\n}\n\n/* By bitmask, the C kernel's gobj_set_global_trace2(): 0xFFFFFFFF clears all. */\nfunction gobj_set_global_trace2(bitmask, set)\n{\n if(set) {\n __global_trace_level__ = (__global_trace_level__ | bitmask) >>> 0;\n } else {\n __global_trace_level__ = (__global_trace_level__ & ~bitmask) >>> 0;\n }\n return 0;\n}\n\nfunction gobj_set_global_no_trace2(bitmask, set)\n{\n if(set) {\n __global_trace_no_level__ = (__global_trace_no_level__ | bitmask) >>> 0;\n } else {\n __global_trace_no_level__ = (__global_trace_no_level__ & ~bitmask) >>> 0;\n }\n return 0;\n}\n\n/*\n * The levels in force, by NAME -- the C kernel's getters, same names.\n * gobj_get_gclass_trace_level() includes the global levels, as in C;\n * gobj_get_gclass_trace_level2() is the gclass's own only.\n */\nfunction gobj_get_global_trace_level()\n{\n return bit2level(__global_trace_level__, null);\n}\n\nfunction gobj_get_global_trace_no_level()\n{\n return bit2level(__global_trace_no_level__, null);\n}\n\nfunction gobj_get_gclass_trace_level(gclass)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_get_gclass_trace_level: gclass NOT FOUND: ${gclass}`);\n return [];\n }\n return bit2level(gclass_.trace_level | __global_trace_level__, gclass_.s_user_trace_level);\n}\n\nfunction gobj_get_gclass_trace_level2(gclass)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_get_gclass_trace_level2: gclass NOT FOUND: ${gclass}`);\n return [];\n }\n return bit2level(gclass_.trace_level, gclass_.s_user_trace_level);\n}\n\nfunction gobj_get_gclass_trace_no_level(gclass)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_get_gclass_trace_no_level: gclass NOT FOUND: ${gclass}`);\n return [];\n }\n return bit2level(gclass_.no_trace_level, gclass_.s_user_trace_level);\n}\n\n/* Everything at once, for a session that is chasing something. */\nfunction gobj_set_deep_trace(value)\n{\n __deep_trace__ = Number(value) || 0;\n return 0;\n}\n\n/*\n * Per gclass: `gclass` is the gclass object or its name, so the\n * caller does not need a handle it may not have.\n */\nfunction gobj_set_gclass_trace(gclass, level, set)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_set_gclass_trace: gclass NOT FOUND: ${gclass}`);\n return -1;\n }\n const bitmask = (level === null) ? 0xFFFFFFFF :\n trace_bitmask(level, \"gobj_set_gclass_trace\", gclass_.s_user_trace_level || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gclass_.trace_level |= bitmask;\n } else {\n gclass_.trace_level &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_set_gobj_trace(gobj, level, set)\n{\n if(!gobj) {\n log_error(`gobj_set_gobj_trace: gobj NULL`);\n return -1;\n }\n const bitmask = trace_bitmask(level, \"gobj_set_gobj_trace\", (gobj.gclass && gobj.gclass.s_user_trace_level) || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gobj.trace_level |= bitmask;\n } else {\n gobj.trace_level &= ~bitmask;\n }\n return 0;\n}\n\n/*\n * Per gclass, the SILENCING side. What every C main() uses to keep\n * the timers out of a `machine` trace:\n *\n * gobj_set_gclass_no_trace(\"C_TIMER\", \"machine\", true);\n * gobj_set_global_no_trace(\"timer_periodic\", true);\n *\n * `machine` traces every event by design, timers included, so without\n * this a one-second tick buries whatever you were following.\n */\nfunction gobj_set_gclass_no_trace(gclass, level, set)\n{\n const gclass_ = is_string(gclass) ? gclass_find_by_name(gclass) : gclass;\n if(!gclass_) {\n log_error(`gobj_set_gclass_no_trace: gclass NOT FOUND: ${gclass}`);\n return -1;\n }\n const bitmask = (level === null) ? 0xFFFFFFFF :\n trace_bitmask(level, \"gobj_set_gclass_no_trace\", gclass_.s_user_trace_level || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gclass_.no_trace_level |= bitmask;\n } else {\n gclass_.no_trace_level &= ~bitmask;\n }\n return 0;\n}\n\nfunction gobj_set_gobj_no_trace(gobj, level, set)\n{\n if(!gobj) {\n log_error(`gobj_set_gobj_no_trace: gobj NULL`);\n return -1;\n }\n const bitmask = trace_bitmask(level, \"gobj_set_gobj_no_trace\", (gobj.gclass && gobj.gclass.s_user_trace_level) || null);\n if(!bitmask) {\n return -1; /* Error already logged */\n }\n if(set) {\n gobj.no_trace_level |= bitmask;\n } else {\n gobj.no_trace_level &= ~bitmask;\n }\n return 0;\n}\n\n/* The catalogue, for a dev panel or a \"what can I turn on?\" list. */\nfunction gobj_repr_global_trace_levels()\n{\n return s_global_trace_level.map(([name, bit, description]) => ({\n name: name, bit: bit, description: description,\n set: (__global_trace_level__ & bit) ? true : false\n }));\n}\n\n/************************************************************\n * Start up\n ************************************************************/\nfunction gobj_start_up(\n jn_global_settings,\n load_persistent_attrs_fn,\n save_persistent_attrs_fn,\n remove_persistent_attrs_fn,\n list_persistent_attrs_fn,\n global_command_parser_fn,\n global_stats_parser_fn\n)\n{\n __jn_global_settings__ = jn_global_settings;\n __global_load_persistent_attrs_fn__ = load_persistent_attrs_fn;\n __global_save_persistent_attrs_fn__ = save_persistent_attrs_fn;\n __global_remove_persistent_attrs_fn__ = remove_persistent_attrs_fn;\n __global_list_persistent_attrs_fn__ = list_persistent_attrs_fn;\n __global_command_parser_fn__ = global_command_parser_fn;\n __global_stats_parser_fn__ = global_stats_parser_fn;\n\n /*----------------------------------------*\n * Build Global Events\n *----------------------------------------*/\n const global_events = [\n [\"EV_STATE_CHANGED\", event_flag_t.EVF_SYSTEM_EVENT|\n event_flag_t.EVF_OUTPUT_EVENT|\n event_flag_t.EVF_NO_WARN_SUBS],\n [0, 0]\n ];\n\n for (let i = 0; i < global_events.length; i++) {\n let event_name = global_events[i][0];\n let event_flag = global_events[i][1];\n\n _add_event_type(dl_global_event_types, event_name, event_flag);\n }\n\n\n return 0;\n}\n\n/************************************************************\n * Register gclass\n ************************************************************/\nfunction _register_gclass(\n gclass,\n gclass_name\n)\n{\n if(!gclass || !(gclass instanceof GClass)) {\n log_error(`gclass undefined`);\n return -1;\n }\n if(!gclass_name) {\n log_error(`gclass_name undefined`);\n return -1;\n }\n\n let gclass_ = _gclass_register[gclass_name];\n if (gclass_) {\n log_error(`gclass ALREADY REGISTERED: ${gclass_name}`);\n return -1;\n }\n _gclass_register[gclass_name] = gclass;\n return 0;\n}\n\n/***************************************************************************\n * Build default values\n ***************************************************************************/\nfunction sdata_create(gobj, sdata_desc)\n{\n let sdata = {};\n\n if(!is_array(sdata_desc)) {\n log_error(`sdata_desc MUST be an array`);\n trace_json(sdata_desc);\n return sdata;\n }\n for(let i=0; i < sdata_desc.length; i++) {\n const it = sdata_desc[i];\n if(!it.name) {\n continue;\n }\n set_default(gobj, sdata, it);\n }\n\n return sdata;\n}\n\n/***************************************************************************\n * Set array values to sdata, from json or binary\n ***************************************************************************/\nfunction set_default(gobj, sdata, it)\n{\n let jn_value;\n let svalue = it.default_value;\n\n switch(it.type) {\n case data_type_t.DTP_STRING:\n jn_value = String(svalue);\n break;\n case data_type_t.DTP_BOOLEAN:\n jn_value = parseBoolean(svalue);\n break;\n case data_type_t.DTP_INTEGER:\n jn_value = parseInt(svalue);\n if(isNaN(jn_value)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_REAL:\n jn_value = Number(svalue);\n if(isNaN(jn_value)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_LIST:\n if(is_string(svalue)) {\n try {\n jn_value = JSON.parse(svalue);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value = svalue;\n }\n if(!is_array(jn_value)) {\n jn_value = [];\n }\n break;\n case data_type_t.DTP_DICT:\n if(is_string(svalue)) {\n try {\n jn_value = JSON.parse(svalue);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value = svalue;\n }\n if(!is_object(jn_value)) {\n jn_value = {};\n }\n break;\n case data_type_t.DTP_JSON:\n if(is_string(svalue)) {\n try {\n jn_value = JSON.parse(svalue);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value = svalue;\n }\n break;\n case data_type_t.DTP_POINTER:\n jn_value = svalue;\n break;\n }\n\n if(jn_value === undefined) {\n log_error(`default_value WRONG, it: ${it.name}, value: ${it.default_value}`);\n jn_value = null;\n }\n\n sdata[it.name] = jn_value;\n return 0;\n}\n\n/***************************************************************************\n * Set array values to sdata, from json or binary\n ***************************************************************************/\nfunction json2item(gobj, sdata, it, jn_value_)\n{\n let jn_value2;\n\n switch(it.type) {\n case data_type_t.DTP_STRING:\n if(jn_value_ === null || jn_value_ === undefined) {\n /*\n * C parity: a DTP_STRING attr cannot hold a null\n * pointer, the convention is empty string. Without\n * this branch JSON.stringify(null) below produced the\n * literal 4-char string \"null\", which then leaks into\n * IEvent payloads (e.g. IDENTITY_CARD's jwt) and\n * silently breaks empty-string checks on the wire.\n */\n jn_value2 = \"\";\n } else if(is_string(jn_value_)) {\n jn_value2 = String(jn_value_);\n } else {\n let s = JSON.stringify(jn_value_);\n if(s) {\n jn_value2 = String(s);\n }\n }\n break;\n case data_type_t.DTP_BOOLEAN:\n jn_value2 = parseBoolean(jn_value_);\n break;\n case data_type_t.DTP_INTEGER:\n jn_value2 = parseInt(jn_value_);\n if(isNaN(jn_value2)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_REAL:\n jn_value2 = Number(jn_value_);\n if(isNaN(jn_value2)) {\n log_error(`${gobj_short_name(gobj)}: attr NaN: ${it.name}`);\n }\n break;\n case data_type_t.DTP_LIST:\n if(is_string(jn_value_)) {\n try {\n jn_value2 = JSON.parse(jn_value_);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value2 = jn_value_;\n }\n if(!is_array(jn_value2)) {\n log_error(`attr must be an array: ${it.name}`);\n return -1;\n }\n break;\n\n case data_type_t.DTP_DICT:\n if(is_string(jn_value_)) {\n try {\n jn_value2 = JSON.parse(jn_value_);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value2 = jn_value_;\n }\n if(!is_object(jn_value2)) {\n log_error(`attr must be an object: ${it.name}`);\n return -1;\n }\n break;\n\n case data_type_t.DTP_JSON:\n if(is_string(jn_value_)) {\n try {\n jn_value2 = JSON.parse(jn_value_);\n } catch (error) {\n log_error(`JSON parse error: ${error.message}`);\n }\n } else {\n jn_value2 = jn_value_;\n }\n if(!is_array(jn_value2) && !is_object(jn_value2)) {\n log_error(`attr must be a json dict/list: ${it.name}`);\n return -1;\n }\n break;\n\n case data_type_t.DTP_POINTER:\n jn_value2 = jn_value_;\n break;\n }\n\n if(jn_value2 === undefined) {\n log_error(`${gobj_short_name(gobj)}: attr undefined: ${it.name}`);\n }\n\n sdata[it.name] = jn_value2;\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) {\n gobj.priv[it.name] = jn_value2;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, it.name);\n }\n }\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_hsdata(gobj)\n{\n return gobj.jn_attrs;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_hsdata2(gobj, name, verbose)\n{\n if(gobj_has_attr(gobj, name)) {\n return gobj_hsdata(gobj);\n } else if(gobj && gobj.bottom_gobj) {\n return gobj_hsdata2(gobj.bottom_gobj, name, verbose);\n }\n if(verbose) {\n log_error(`GClass Attribute NOT FOUND: ${gobj_short_name(gobj)}, attr ${name}`);\n }\n return null;\n}\n\n/***************************************************************************\n * Return the data description of the attribute `attr`\n * If `attr` is null returns full attr's table\n ***************************************************************************/\nfunction gclass_attr_desc(gclass, attr, verbose)\n{\n if(!gclass || !(gclass instanceof GClass)) {\n if(verbose) {\n log_error(`gclass NULL`);\n }\n return null;\n }\n\n if(!attr) {\n return gclass.attrs_table;\n }\n\n for(let i=0; i < gclass.attrs_table.length; i++) {\n const it = gclass.attrs_table[i];\n if (it.name && it.name === attr) {\n return it;\n }\n }\n\n if(verbose) {\n log_error(`${gclass.gclass_name}: GClass Attribute NOT FOUND: ${attr}`);\n }\n return null;\n}\n\n/************************************************************\n * create and register gclass\n ************************************************************/\nfunction gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n lmt,\n attrs_table,\n priv,\n authz_table,\n command_table,\n s_user_trace_level,\n gclass_flag\n) {\n if(empty_string(gclass_name)) {\n log_error(`gclass_name EMPTY`);\n return null;\n }\n if (gclass_name.includes('`') ||\n gclass_name.includes('^') ||\n gclass_name.includes('.'))\n {\n log_error(`GClass name CANNOT have '.' or '^' or '\\`' char: ${gclass_name}`);\n return null;\n }\n if(gclass_find_by_name(gclass_name)) {\n log_error(`GClass ALREADY exists: ${gclass_name}`);\n return null;\n }\n let gclass = new GClass(\n gclass_name,\n gmt,\n lmt,\n attrs_table,\n priv,\n authz_table,\n command_table,\n s_user_trace_level,\n gclass_flag\n );\n\n _register_gclass(gclass, gclass_name);\n\n /*----------------------------------------*\n * Build States\n *----------------------------------------*/\n const states_size = states.length;\n for (let i = 0; i < states_size; i++) {\n let state_name = states[i][0]; // First element is state name\n let ev_action_list = states[i][1]; // Second element is the array of actions\n\n if(empty_string(state_name)) {\n continue;\n }\n if(gclass_add_state(gclass, state_name)<0) {\n // Error already logged\n gclass_unregister(gclass);\n return null;\n }\n\n const ev_action_size = ev_action_list.length;\n for (let j = 0; j < ev_action_size; j++) {\n let event_name = ev_action_list[j][0];\n let action = ev_action_list[j][1];\n let next_state = ev_action_list[j][2];\n\n if(empty_string(event_name)) {\n continue;\n }\n gclass_add_ev_action(\n gclass,\n state_name,\n event_name,\n action,\n next_state\n );\n }\n }\n\n /*----------------------------------------*\n * Build Events\n *----------------------------------------*/\n for (let i = 0; i < event_types.length; i++) {\n let event_name = event_types[i][0];\n let event_type = event_types[i][1];\n\n if(empty_string(event_name)) {\n continue;\n }\n if(gclass_event_type(gclass, event_name)) {\n log_error(`SMachine: event repeated in input_events: ${event_name}`);\n gclass_unregister(gclass);\n return null;\n }\n\n gclass_add_event_type(gclass, event_name, event_type);\n }\n\n /*----------------------------------------*\n * Check FSM\n *----------------------------------------*/\n if(!gclass.fsm_checked) {\n if(gclass_check_fsm(gclass)<0) {\n gclass_unregister(gclass);\n return null;\n }\n gclass.fsm_checked = true;\n }\n\n return gclass;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_unregister(gclass)\n{\n let gclass_name;\n if(is_string(gclass)) {\n gclass_name = gclass;\n } else if(gclass instanceof GClass) {\n gclass_name = gclass.gclass_name;\n } else {\n log_error(`Cannot unregister gclass, type unknown`);\n return -1;\n }\n\n let gclass_ = _gclass_register[gclass_name];\n if(!gclass_) {\n log_error(`Cannot unregister gclass, not found: ${gclass_name}`);\n return -1;\n }\n if(gclass_.instances > 0) {\n log_error(`Cannot unregister gclass, instances in use: ${gclass_name}`);\n return -1;\n }\n\n delete _gclass_register[gclass_name];\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction _find_state(gclass, state_name)\n{\n const size = gclass.dl_states.length;\n const dl = gclass.dl_states;\n\n for(let i=0; i<size; i++) {\n let state = dl[i];\n if(state.state_name && state.state_name === state_name) {\n return state;\n }\n }\n return null;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction _find_event_action(state, event_name)\n{\n const size = state.dl_actions.length;\n const dl = state.dl_actions;\n\n for(let i=0; i<size; i++) {\n let event_action = dl[i];\n if(event_action.event_name && event_action.event_name === event_name) {\n return event_action;\n }\n }\n return null;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_add_state(gclass, state_name)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n if(_find_state(gclass, state_name)) {\n log_error(`state already exists: ${state_name}`);\n return -1;\n }\n\n gclass.dl_states.push(new State(state_name));\n\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_add_ev_action(\n gclass,\n state_name,\n event_name,\n action,\n next_state\n)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n if(empty_string(state_name)) {\n log_error(`state_name EMPTY`);\n return -1;\n }\n\n let state = _find_state(gclass, state_name);\n if(!state) {\n log_error(`state not found: ${state_name}`);\n return -1;\n }\n\n if(_find_event_action(state, event_name)) {\n log_error(`event already exists: gclass ${gclass.gclass_name}, state ${state_name}, event ${event_name}`);\n return -1;\n }\n\n state.dl_actions.push(new Event_Action(event_name, action, next_state));\n\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction _add_event_type(dl, event_name, event_flag)\n{\n if(!empty_string(event_name)) {\n dl.push(new Event_Type(event_name, event_flag));\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_add_event_type(gclass, event_name, event_flag)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n return _add_event_type(gclass.dl_events, event_name, event_flag);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_event_type(gclass, event_name)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return 0;\n }\n\n const size = gclass.dl_events.length;\n const dl = gclass.dl_events;\n\n for(let i=0; i<size; i++) {\n let event_type = dl[i];\n if(event_type.event_name && event_type.event_name === event_name) {\n return event_type;\n }\n }\n\n return null;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gclass_check_fsm(gclass)\n{\n if(!(gclass instanceof GClass)) {\n log_error(`Cannot add state, typeof not GClass`);\n return -1;\n }\n\n let ret = 0;\n\n /*\n * check states\n */\n if(!json_array_size(gclass.dl_states)) {\n log_error(`GClass without states: ${gclass.gclass_name}`);\n ret += -1;\n }\n\n /*\n * check state's event in input_list\n */\n for(let i=0; i<gclass.dl_states.length; i++) {\n let state = gclass.dl_states[i];\n if(empty_string(state.state_name)) {\n continue;\n }\n // gobj_state_t state_name;\n // dl_list_t dl_actions;\n\n for(let j=0; j<state.dl_actions.length; j++) {\n let event_action = state.dl_actions[j];\n if(empty_string(event_action.event_name)) {\n continue;\n }\n // gobj_event_t event_name;\n // gobj_action_fn action;\n // gobj_state_t next_state;\n let event_type = gclass_event_type(gclass, event_action.event_name);\n if(!event_type) {\n log_error(`SMachine: state's event NOT in input_events: gclass ${gclass.gclass_name}, state ${state.state_name}, event ${event_action.event_name}`);\n ret += -1;\n }\n\n if(event_action.next_state) {\n let next_state = _find_state(gclass, event_action.next_state);\n if(!next_state) {\n log_error(`SMachine: next state NOT in state names: gclass ${gclass.gclass_name}, state ${state.state_name}, next_state ${event_action.next_state}`);\n ret += -1;\n }\n }\n }\n }\n\n /*\n * check input_list's event in state\n */\n for(let i=0; i<gclass.dl_events.length; i++) {\n let event_type = gclass.dl_events[i];\n if(empty_string(event_type.event_name)) {\n continue;\n }\n // gobj_event_t event_type.event_name;\n // event_flag_t event_type.event_flag;\n if(!is_number(event_type.event_flag)) {\n log_error(`SMachine: event flag is NOT number: gclass ${gclass.gclass_name}, event ${event_type.event_name}`);\n ret += -1;\n }\n if(!(event_type.event_flag & event_flag_t.EVF_OUTPUT_EVENT)) {\n let found = false;\n\n for(let j=0; j<gclass.dl_states.length; j++) {\n let state = gclass.dl_states[j];\n if(empty_string(state.state_name)) {\n continue;\n }\n let event_action = _find_event_action(state, event_type.event_name);\n if(event_action) {\n found = true;\n }\n }\n\n if(!found) {\n log_error(`SMachine: input_list's event NOT in state: gclass ${gclass.gclass_name}, event ${event_type.event_name}`);\n ret += -1;\n }\n }\n }\n\n return ret;\n}\n\n/************************************************************\n * Find gclass\n ************************************************************/\nfunction gclass_find_by_name(gclass_name, verbose)\n{\n let gclass = null;\n try {\n gclass = _gclass_register[gclass_name];\n } catch (e) {\n }\n if(!gclass) {\n if(verbose) {\n log_error(`gclass not found: ${gclass_name}`);\n }\n /*\n * NULL, not undefined: a missing key answers `undefined`, and a\n * caller writing the obvious `gclass_find_by_name(\"X\") === null`\n * then gets FALSE for a gclass that is not there. gobj-ui had four\n * guards written exactly like that -- one of them the \"not\n * registered by the app\" message that could therefore never print,\n * leaving a missing gclass to surface as \"can't access property\n * jn_attrs, e is null\" from whoever used what gobj_create refused\n * to build.\n */\n return null;\n }\n return gclass;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_services()\n{\n let jn_register = [];\n\n for(const key of Object.keys(__jn_services__)) {\n json_array_append_new(jn_register, key);\n }\n\n return jn_register;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_default_service()\n{\n if(!__default_service__ || (__default_service__.obflag & obflag_t.obflag_destroyed)) {\n return null;\n }\n return __default_service__;\n}\n\n/************************************************************\n * find a service\n ************************************************************/\nfunction gobj_find_service(\n service_name,\n verbose\n)\n{\n service_name = service_name.toLowerCase();\n let service_gobj = __jn_services__[service_name];\n if(!service_gobj) {\n if(verbose) {\n log_error(`gobj service not found: ${service_name}`);\n }\n /*\n * Same contract as gclass_find_by_name: ALWAYS null when there is\n * no service. It used to answer `null` with verbose and `undefined`\n * without it -- the same absent service giving a different falsy\n * value depending on a logging flag -- and handing that undefined\n * to a DTP_POINTER attr logs \"attr undefined\" on every use.\n */\n return null;\n }\n return service_gobj;\n}\n\n/************************************************************\n * register a service\n ************************************************************/\nfunction _register_service(gobj)\n{\n let service_name = gobj_name(gobj);\n service_name = service_name.toLowerCase();\n if(__jn_services__[service_name]) {\n log_error(`service ALREADY REGISTERED: ${service_name}. Will be UPDATED`);\n }\n __jn_services__[service_name] = gobj;\n return 0;\n}\n\n/************************************************************\n * deregister a service\n ************************************************************/\nfunction _deregister_service(gobj)\n{\n let service_name = gobj_name(gobj);\n service_name = service_name.toLowerCase();\n if(!__jn_services__[service_name]) {\n log_error(`\"service NOT found in register\": ${service_name}`);\n return -1;\n }\n delete __jn_services__[service_name];\n return 0;\n}\n\n/************************************************************\n * add child.\n ************************************************************/\nfunction _add_child(parent, child)\n{\n if(child.parent) {\n log_error(`_add_child() ALREADY HAS PARENT: ${child.gobj_name}`);\n }\n parent.dl_children.push(child);\n child.parent = parent;\n}\n\n/************************************************************\n * remove child\n ************************************************************/\nfunction _remove_child(parent, child)\n{\n let index = index_in_list(parent.dl_children, child);\n if (index >= 0) {\n json_array_remove(parent.dl_children, index);\n child.parent = null;\n }\n}\n\n/************************************************************\n * Example how change CONFIG of a gclass (temporarily)\n *\n let CONFIG = gobj_get_gclass_config(\"Ka_scrollview\", true);\n let old_dragging = CONFIG.draggable;\n CONFIG.draggable = true;\n\n let gobj_ka_scrollview = self.yuno.gobj_create(\n \"xxx\",\n Ka_scrollview,\n {\n ...\n },\n self // this will provoke EV_SHOWED,EV_KEYDOWN\n );\n\n CONFIG.draggable = old_dragging;\n\n ************************************************************/\nfunction gobj_get_gclass_config(gclass_name, verbose)\n{\n let gclass = gclass_find_by_name(gclass_name, verbose);\n if(gclass && gclass.gmt.mt_get_gclass_config) {\n return gclass.gmt.mt_get_gclass_config.call();\n } else {\n if(verbose) {\n log_error(sprintf(\n \"gobj_get_gclass_config: '%s' gclass without mt_get_gclass_config\", gclass_name\n ));\n }\n return null;\n }\n}\n\n/************************************************************\n * Only gobj services can load/save persistent attrs.\n * WARNING: persistent attrs are loaded automatically in the creation of gobjs\n ************************************************************/\nfunction gobj_load_persistent_attrs(\n gobj,\n keys // str, list or dict.\n) {\n if(!gobj_is_service(gobj)) {\n log_error(`${gobj_short_name(gobj)}: Only gobj services can load/save writable-persistent`);\n return -1;\n }\n if(__global_load_persistent_attrs_fn__) {\n return __global_load_persistent_attrs_fn__(gobj, keys);\n }\n return -1;\n}\n\n/************************************************************\n * Only gobj services can load/save persistent attrs.\n ************************************************************/\nfunction gobj_save_persistent_attrs(\n gobj,\n keys // str, list or dict.\n) {\n if(!gobj_is_service(gobj)) {\n log_error(`${gobj_short_name(gobj)}: Only gobj services can load/save writable-persistent`);\n return -1;\n }\n if(__global_save_persistent_attrs_fn__) {\n return __global_save_persistent_attrs_fn__(gobj, keys);\n }\n return -1;\n}\n\n/************************************************************\n * Only gobj services can load/save persistent attrs.\n ************************************************************/\nfunction gobj_remove_persistent_attrs(\n gobj,\n keys // str, list or dict.\n) {\n\n if(!gobj_is_service(gobj)) {\n log_error(`${gobj_short_name(gobj)}: Only gobj services can load/save writable-persistent`);\n return -1;\n }\n if(!__global_remove_persistent_attrs_fn__) {\n return -1;\n }\n return __global_remove_persistent_attrs_fn__(gobj, keys);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_list_persistent_attrs(gobj, keys)\n{\n if(!__global_list_persistent_attrs_fn__) {\n return null;\n }\n return __global_list_persistent_attrs_fn__(gobj, keys);\n}\n\n/************************************************************\n * Update existing in first level, and all in next levels\n ************************************************************/\nfunction _json_object_update_config(destination, source) {\n if(!source) {\n return destination;\n }\n for (let property in source) {\n if (source.hasOwnProperty(property) && destination.hasOwnProperty(property)) {\n if(is_object(destination[property]) && is_object(source[property])) {\n json_object_update(\n destination[property],\n source[property]\n );\n } else {\n destination[property] = source[property];\n }\n }\n }\n return destination;\n}\n\n/***************************************************************************\n * ATTR:\n ***************************************************************************/\nfunction print_attr_not_found(gobj, name)\n{\n if(name !== \"__json_config_variables__\") {\n log_error(`GClass Attribute NOT FOUND: ${gobj_short_name(gobj)}, attr ${name}`);\n }\n}\n\n/***************************************************************************\n * Update sdata fields from a json dict.\n * Constraint: if flag is -1\n * => all fields!\n * else\n * => matched flag\n ***************************************************************************/\nfunction json2sdata(\n hsdata,\n kw, // not owned\n flag,\n not_found_cb, // Called when the key not exist in hsdata\n gobj)\n{\n if(!hsdata || !kw) {\n log_error(`hsdata or kw NULL`);\n return -1;\n }\n let ret = 0;\n\n for (const [key, jn_value] of Object.entries(kw)) {\n const it = gclass_attr_desc(gobj.gclass, key, false);\n if(!it) {\n if(not_found_cb) {\n not_found_cb(gobj, key);\n ret--;\n }\n continue;\n }\n if(!(flag === -1 || (it.flag & flag))) {\n continue;\n }\n if(it.flag & sdata_flag_t.SDF_DEPRECATED) {\n log_warning(`${gobj_short_name(gobj)}: Deprecated attribute used in gobj creation: ${key}`);\n }\n ret += json2item(gobj, hsdata, it, jn_value);\n }\n\n return ret;\n}\n\n/************************************************************\n * ATTR:\n * Get data from json kw parameter,\n * and put the data in config sdata.\n ************************************************************/\nfunction write_json_parameters(gobj, kw, jn_global)\n{\n let hs = gobj_hsdata(gobj);\n let new_kw = kw; // kw_apply_json_config_variables(kw, jn_global_mine);\n\n let ret = json2sdata(\n hs,\n new_kw,\n -1,\n (gobj.gclass.gclass_flag & gclass_flag_t.gcflag_ignore_unknown_attrs)?0:print_attr_not_found,\n gobj\n );\n if(ret < 0) {\n log_error(`${gobj_short_name(gobj)} json2data() FAILED`);\n trace_json(new_kw);\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag\n) {\n /*--------------------------------*\n * Check parameters\n *--------------------------------*/\n if(gobj_flag & (gobj_flag_t.gobj_flag_yuno)) {\n if(__yuno__) {\n log_error(`__yuno__ already created`);\n return null;\n }\n gobj_flag |= gobj_flag_t.gobj_flag_service;\n\n } else {\n if(!parent) {\n log_error(`gobj NEEDS a parent!`);\n return null;\n }\n\n if(!(typeof parent === 'string' || parent instanceof GObj)) {\n log_error(`BAD TYPE of parent: ${parent}`);\n return null;\n }\n\n if(is_string(parent)) {\n // find the named gobj\n parent = gobj_find_service(parent);\n if (!parent) {\n log_warning(`parent service not found: ${parent}`);\n return null;\n }\n }\n }\n\n if(gobj_flag & (gobj_flag_t.gobj_flag_service)) {\n if(gobj_find_service(gobj_name, false)) {\n log_error(`service ALREADY registered: ${gclass_name}^${gobj_name}`);\n return null;\n }\n }\n\n if(gobj_flag & (gobj_flag_t.gobj_flag_default_service)) {\n if(__default_service__) {\n log_error(`default service ALREADY registered: ${gclass_name}^${gobj_name}`);\n return null;\n }\n gobj_flag |= gobj_flag_t.gobj_flag_service;\n }\n\n if(empty_string(gclass_name)) {\n log_error(`gclass_name must be a string`);\n return null;\n }\n let gclass = gclass_find_by_name(gclass_name, false);\n if(!gclass) {\n log_error(`GClass not registered: ${gclass_name}^${gobj_name}`);\n return null;\n }\n if(!is_string(gobj_name)) {\n log_error(`gobj_name must be a string: ${gclass_name}`);\n return null;\n }\n\n if(!empty_string(gobj_name)) {\n /*\n * Check that the gobj_name: cannot contain `\n */\n if(gobj_name.includes('`')) {\n log_error(`gobj_name cannot contain char \\': ${gclass_name}^${gobj_name}`);\n return null;\n }\n /*\n * Check that the gobj_name: cannot contain ^\n */\n if(gobj_name.includes('^')) {\n log_error(`gobj_name cannot contain char ^: ${gclass_name}^${gobj_name}`);\n return null;\n }\n }\n\n /*--------------------------------*\n * Alloc memory\n * Initialize variables\n *--------------------------------*/\n let gobj = new GObj(gobj_name, gclass, kw, parent, gobj_flag);\n gobj.jn_attrs = sdata_create(gobj, gclass.attrs_table);\n\n // Now mt_writing is only informative, not needed to update priv\n for(const [key, value] of Object.entries(gobj.jn_attrs)) {\n if(key in gobj.priv) {\n gobj.priv[key] = value;\n }\n }\n\n let trace_creation = __trace_gobj_create_delete__(gobj);\n if(trace_creation) {\n trace_machine(sprintf(\"💙💙⏩ creating: %s^%s\",\n gclass.gclass_name, gobj_name\n ));\n }\n\n /*--------------------------*\n * Register service\n *--------------------------*/\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_service)) {\n _register_service(gobj);\n }\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_yuno)) {\n __yuno__ = gobj;\n }\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_default_service)) {\n __default_service__ = gobj;\n }\n\n /*--------------------------------------*\n * Add to parent\n *--------------------------------------*/\n if(!(gobj.gobj_flag & (gobj_flag_t.gobj_flag_yuno))) {\n _add_child(parent, gobj);\n }\n\n /*--------------------------------*\n * Mark as created\n *--------------------------------*/\n gobj.obflag |= obflag_t.obflag_created;\n gobj.gclass.instances++;\n\n /*--------------------------------*\n * Write configuration\n * WARNING collateral damage:\n * write_json_parameters was before Mark as created!\n *--------------------------------*/\n write_json_parameters(gobj, kw, __jn_global_settings__);\n\n /*--------------------------------------*\n * Load writable and persistent attrs\n * of services and __root__\n *--------------------------------------*/\n if(gobj.gobj_flag & (gobj_flag_t.gobj_flag_service)) {\n if(__global_load_persistent_attrs_fn__) {\n __global_load_persistent_attrs_fn__(gobj, null);\n }\n }\n\n /*--------------------------------*\n * Exec mt_create\n *--------------------------------*/\n if(gobj.gclass.gmt.mt_create2) {\n gobj.gclass.gmt.mt_create2(gobj, kw);\n } else if(gobj.gclass.gmt.mt_create) {\n gobj.gclass.gmt.mt_create(gobj);\n }\n\n /*--------------------------------------*\n * Inform to parent\n * when the child is full operative\n *-------------------------------------*/\n if(parent && parent.gclass.gmt.mt_child_added) {\n if(trace_creation) {\n trace_machine(sprintf(\n \"👦👦🔵 child_added(%s): %s\",\n gobj_full_name(parent),\n gobj_short_name(gobj)\n ));\n }\n parent.gclass.gmt.mt_child_added(parent, gobj);\n }\n\n if(trace_creation) {\n trace_machine(sprintf(\"💙💙⏪ created: %s\", gobj_full_name(gobj)));\n }\n\n return gobj;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_create_yuno(\n gobj_name,\n gclass_name,\n kw\n) {\n return gobj_create2(gobj_name, gclass_name, kw, null, gobj_flag_t.gobj_flag_yuno);\n}\n\nfunction gobj_create_service(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(gobj_name, gclass_name, kw, parent, gobj_flag_t.gobj_flag_service);\n}\n\nfunction gobj_create_default_service(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag_t.gobj_flag_default_service|gobj_flag_t.gobj_flag_autostart\n );\n}\n\nfunction gobj_create_volatil(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag_t.gobj_flag_volatil\n );\n}\n\nfunction gobj_create_pure_child(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n gobj_flag_t.gobj_flag_pure_child\n );\n}\n\nfunction gobj_create(\n gobj_name,\n gclass_name,\n kw,\n parent\n) {\n return gobj_create2(\n gobj_name,\n gclass_name,\n kw,\n parent,\n 0\n );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_destroy(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return;\n }\n\n /*--------------------------------*\n * Check parameters\n *--------------------------------*/\n if(gobj.__refs__ > 0) {\n log_error(`${gobj_short_name(gobj)}: gobj DESTROYING with references: ${gobj.__refs__}`);\n }\n /*--------------------------------------------------------*\n * Pause and Stop\n *\n * BEFORE raising obflag_destroying, and that order is the\n * whole point: gobj_pause() and gobj_stop() refuse a gobj\n * that is already destroying -- rightly so, nobody OUTSIDE\n * may stop something already being dismantled -- so doing\n * this after the flag logged \"gobj NULL or DESTROYED\" and\n * quietly skipped mt_pause / mt_stop: the gobj was taken\n * apart without ever releasing its timers, subscriptions\n * and DOM listeners. The two errors below are still loud:\n * destroying a live gobj remains the CALLER's bug, and the\n * fix there is gobj_stop_tree() before gobj_destroy().\n * What changed is that the rescue now runs instead of\n * pretending to.\n *\n * Quiescing first also means mt_stop() sees exactly what an\n * orderly stop sees -- it matters for a gclass that stops\n * its children there, since that path carries the same\n * destroying guard.\n *--------------------------------------------------------*/\n if(gobj.playing) {\n log_error(`Destroying a PLAYING gobj: ${gobj_full_name(gobj)}`);\n gobj_pause(gobj);\n }\n if(gobj.running) {\n log_error(`Destroying a RUNNING gobj: ${gobj_full_name(gobj)}`);\n gobj_stop(gobj);\n }\n\n gobj.obflag |= obflag_t.obflag_destroying;\n\n /*\n * AFTER the flag, so it also takes what mt_stop() may have posted\n * above: from here on gobj_post_event() refuses this gobj.\n */\n purge_posted_events(gobj);\n\n let trace_creation = __trace_gobj_create_delete__(gobj);\n if(trace_creation) {\n trace_machine(sprintf(\"💔💔⏩ destroying: %s\", gobj_full_name(gobj)));\n }\n\n /*----------------------------------------------*\n * Inform to parent now,\n * when the child is NOT still full operative\n *----------------------------------------------*/\n let parent = gobj_parent(gobj);\n if(parent && parent.gclass.gmt.mt_child_removed) {\n if(trace_creation) {\n trace_machine(sprintf(\"👦👦🔴 child_removed(%s): %s\",\n gobj_full_name(parent),\n gobj_short_name(gobj)\n ));\n }\n parent.gclass.gmt.mt_child_removed(parent, gobj);\n }\n\n /*--------------------------------*\n * Deregister if service\n *--------------------------------*/\n if(gobj.gobj_flag & gobj_flag_t.gobj_flag_service) {\n _deregister_service(gobj);\n }\n\n /*--------------------------------*\n * Delete subscriptions\n *--------------------------------*/\n gobj_unsubscribe_list(gobj, gobj.dl_subscriptions, true);\n gobj_unsubscribe_list(gobj, gobj.dl_subscribings, true);\n\n /*--------------------------------*\n * Delete from parent\n *--------------------------------*/\n if(parent) {\n _remove_child(parent, gobj);\n if(gobj_is_volatil(gobj)) {\n if(gobj_bottom_gobj(parent) === gobj &&\n !gobj_is_destroying(parent))\n {\n gobj_set_bottom_gobj(parent, null);\n }\n }\n }\n\n /*--------------------------------*\n * Delete children\n *--------------------------------*/\n gobj_destroy_children(gobj);\n\n /*-------------------------------------------------*\n * Exec mt_destroy\n * Call this after all children are destroyed.\n * Then you can delete resources used by children\n * (example: event_loop in main/threads)\n *-------------------------------------------------*/\n if(gobj.obflag & obflag_t.obflag_created) {\n if(gobj.gclass.gmt.mt_destroy) {\n gobj.gclass.gmt.mt_destroy(gobj);\n }\n }\n\n /*--------------------------------*\n * Mark as destroyed\n *--------------------------------*/\n if(trace_creation) {\n trace_machine(sprintf(\"💔💔⏪ destroyed: %s\", gobj_full_name(gobj)));\n }\n gobj.obflag |= obflag_t.obflag_destroyed;\n\n /*--------------------------------*\n * Dealloc data\n *--------------------------------*/\n if(gobj.obflag & obflag_t.obflag_created) {\n gobj.gclass.instances--;\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_destroy_children(gobj)\n{\n let dl_children = gobj.dl_children.slice();\n\n for(let i=0; i < dl_children.length; i++) {\n let child = dl_children[i];\n if (!gobj_is_destroying(child)) {\n gobj_destroy(child);\n }\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_start(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(gobj.running) {\n log_error(`${gobj_short_name(gobj)}: GObj ALREADY RUNNING`);\n return -1;\n }\n if(gobj.disabled) {\n log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);\n return -1;\n }\n\n /*\n * TODO Check required attributes.\n */\n // json_t *jn_required_attrs = gobj_check_required_attrs(gobj);\n // if(jn_required_attrs) {\n // gobj_log_error(gobj, LOG_OPT_TRACE_STACK,\n // \"function\", \"%s\", __FUNCTION__,\n // \"msgset\", \"%s\", MSGSET_OPERATIONAL_ERROR,\n // \"msg\", \"%s\", \"Cannot start without all required attributes\",\n // \"attrs\", \"%j\", jn_required_attrs,\n // NULL\n // );\n // JSON_DECREF(jn_required_attrs)\n // return -1;\n // }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏺ ⏺ start: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.running = true;\n\n let ret = 0;\n if(gobj.gclass.gmt.mt_start) {\n ret = gobj.gclass.gmt.mt_start(gobj);\n }\n return ret;\n}\n\n/***************************************************************************\n * Start all children of the gobj.\n ***************************************************************************/\nfunction cb_start_child(child, user_data, user_data2)\n{\n if(child.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start) {\n return 0;\n }\n if(!gobj_is_destroying(child) && !gobj_is_running(child) && !gobj_is_disabled(child)) {\n gobj_start(child);\n }\n return 0;\n}\nfunction gobj_start_children(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n return gobj_walk_gobj_children(gobj, walk_type_t.WALK_FIRST2LAST, cb_start_child, 0, 0);\n}\n\n/***************************************************************************\n * Start this gobj and all children tree of the gobj.\n ***************************************************************************/\nfunction cb_start_child_tree(child, user_data, user_data2)\n{\n if(child.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start) {\n return 1;\n }\n if(gobj_is_disabled(child)) {\n return 1;\n }\n if(!gobj_is_running(child)) {\n gobj_start(child);\n }\n return 0;\n}\nfunction gobj_start_tree(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏺ ⏺ ⏺ ⏺ start_tree: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n if((gobj.gclass.gclass_flag & gclass_flag_t.gcflag_manual_start)) {\n return 0;\n } else if(gobj.disabled) {\n return 0;\n } else {\n if(!gobj.running) {\n gobj_start(gobj);\n }\n }\n return gobj_walk_gobj_children_tree(gobj, walk_type_t.WALK_TOP2BOTTOM, cb_start_child_tree, 0, 0);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_stop(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(!gobj.running) {\n log_error(`${gobj_short_name(gobj)}: GObj NOT RUNNING`);\n return -1;\n }\n if(gobj.playing) {\n // It's auto-stopping but display error (magic but warn!).\n log_warning(`${gobj_short_name(gobj)}: GObj stopping without previous pause`);\n gobj_pause(gobj);\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏹ ⏹ stop: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.running = false;\n\n let ret = 0;\n if(gobj.gclass.gmt.mt_stop) {\n ret = gobj.gclass.gmt.mt_stop(gobj);\n }\n\n return ret;\n}\n\n/***************************************************************************\n * Stop all children of the gobj.\n ***************************************************************************/\nfunction cb_stop_child(child, user_data, user_data2)\n{\n if(gobj_is_running(child)) {\n gobj_stop(child);\n }\n return 0;\n}\nfunction gobj_stop_children(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n return gobj_walk_gobj_children(gobj, walk_type_t.WALK_FIRST2LAST, cb_stop_child, 0, 0);\n}\n\n/***************************************************************************\n * Stop this gobj and all children tree of the gobj.\n ***************************************************************************/\nfunction gobj_stop_tree(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏹ ⏹ ⏹ ⏹ stop_tree: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n if(gobj_is_running(gobj)) {\n gobj_stop(gobj);\n }\n return gobj_walk_gobj_children_tree(gobj, walk_type_t.WALK_TOP2BOTTOM, cb_stop_child, 0, 0);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_play(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(`gobj NULL or DESTROYED: ${gobj_short_name(gobj)}`);\n return -1;\n }\n if(gobj.playing) {\n log_error(`${gobj_short_name(gobj)}: GObj ALREADY PLAYING`);\n return -1;\n }\n if(gobj.disabled) {\n log_error(`${gobj_short_name(gobj)}: GObj DISABLED`);\n return -1;\n }\n if(!gobj_is_running(gobj)) {\n if(!(gobj.gclass.gclass_flag & gclass_flag_t.gcflag_required_start_to_play)) {\n // Default: It's auto-starting but display error (magic but warn!).\n log_warning(`${gobj_short_name(gobj)}: GObj playing without previous start`);\n gobj_start(gobj);\n } else {\n log_error(`${gobj_short_name(gobj)}: Cannot play, start not done`);\n return -1;\n }\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏯ ⏯ play: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.playing = true;\n\n let ret = 0;\n if(gobj.gclass.gmt.mt_play) {\n ret = gobj.gclass.gmt.mt_play(gobj);\n /* `ret === false` too: the C contract is an int and -1 is the\n * failure, but a javascript mt_play says it with `false` — and\n * `false < 0` is FALSE, so the gobj was left PLAYING after a play\n * that failed. */\n if(ret < 0 || ret === false) {\n gobj.playing = false;\n }\n }\n return ret;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_pause(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(!gobj.playing) {\n log_error(`${gobj_short_name(gobj)}: GObj NOT PLAYING`);\n return -1;\n }\n\n let tracea = __trace_gobj_start_stop__(gobj);\n if(tracea) {\n trace_machine(sprintf(\"⏸ ⏸ pause: %s\",\n gobj_full_name(gobj)\n ));\n }\n\n gobj.playing = false;\n\n if(gobj.gclass.gmt.mt_pause) {\n return gobj.gclass.gmt.mt_pause(gobj);\n } else {\n return 0;\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_running(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n return false;\n }\n return gobj.running;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_disabled(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n return true;\n }\n return gobj.disabled;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_service(gobj)\n{\n if(gobj && (gobj.gobj_flag & (gobj_flag_t.gobj_flag_service))) {\n return true;\n } else {\n return false;\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_playing(gobj)\n{\n if(gobj_is_destroying(gobj)) {\n return false;\n }\n return gobj.playing;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno()\n{\n if(!__yuno__ || (__yuno__.obflag & obflag_t.obflag_destroyed)) {\n return null;\n }\n return __yuno__;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno_name()\n{\n let yuno = gobj_yuno();\n if(!yuno) {\n return \"\";\n }\n return gobj_name(yuno);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno_role()\n{\n let yuno = gobj_yuno();\n if(!yuno) {\n return \"\";\n }\n return gobj_read_str_attr(yuno, \"yuno_role\");\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_yuno_id()\n{\n let yuno = gobj_yuno();\n if(!yuno) {\n return \"\";\n }\n return gobj_read_str_attr(yuno, \"yuno_id\");\n}\n\n/***************************************************************************\n * Return name\n ***************************************************************************/\nfunction gobj_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj bad type`);\n return null;\n }\n\n return gobj.gobj_name;\n}\n\n/***************************************************************************\n * Return mach name. Same as gclass name.\n ***************************************************************************/\nfunction gobj_gclass_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n return gobj.gclass.gclass_name;\n}\n\n/************************************************************\n * get short name (gclass^name)\n ************************************************************/\nfunction gobj_short_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj bad type`);\n return null;\n }\n\n return gobj.gclass.gclass_name + '^' + gobj_name(gobj);\n}\n\n/************************************************************\n * Get full name\n ************************************************************/\nfunction gobj_full_name(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n let full_name = gobj_short_name(gobj);\n let parent = gobj_parent(gobj);\n while(parent) {\n let prefix = gobj_short_name(parent);\n full_name = prefix + '`' + full_name;\n parent = gobj_parent(parent);\n }\n return full_name;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_parent(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n return gobj.parent;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_volatil(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(gobj.gobj_flag & gobj_flag_t.gobj_flag_volatil) {\n return true;\n }\n return false;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_is_pure_child(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(gobj.gobj_flag & gobj_flag_t.gobj_flag_pure_child) {\n return true;\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_is_destroying(gobj)\n{\n if(!is_gobj(gobj)) {\n return true;\n }\n\n if(gobj.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n return true;\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_bottom_gobj(gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n return gobj.bottom_gobj;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_set_bottom_gobj(gobj, bottom_gobj)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(gobj.bottom_gobj) {\n log_warning(`${gobj_short_name(gobj)}: bottom_gobj already set`);\n }\n gobj.bottom_gobj = bottom_gobj;\n}\n\n/***************************************************************************\n * Return the data description of the attribute `attr`\n * If `attr` is null returns full attr's table\n ***************************************************************************/\nfunction gobj_attr_desc(gobj, attr, verbose)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n if(!attr) {\n return gobj.gclass.attrs_table;\n }\n\n return gclass_attr_desc(gobj.gclass, attr, verbose);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_walk_gobj_children(\n gobj,\n walk_type, // walk_type_t\n cb_walking,\n user_data,\n user_data2\n) {\n if(gobj_is_destroying(gobj)) {\n log_error(`gobj NULL, destroying, or bad type`);\n return 0;\n }\n\n return rc_walk_by_list(gobj.dl_children, walk_type, cb_walking, user_data, user_data2);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_walk_gobj_children_tree(\n gobj,\n walk_type, // walk_type_t\n cb_walking,\n user_data,\n user_data2\n) {\n if(gobj_is_destroying(gobj)) {\n log_error(`gobj NULL, destroying, or bad type`);\n return 0;\n }\n\n return rc_walk_by_tree(gobj.dl_children, walk_type, cb_walking, user_data, user_data2);\n}\n\n/***************************************************************\n * Walking\n ***************************************************************/\n/***************************************************************\n * What a WALK CALLBACK answered, as the number the contract is\n * written in: -1 stop the walk, 0 descend into the children,\n * >0 do not descend.\n *\n * A javascript callback that simply RETURNS NOTHING is the common\n * case, and `undefined` is neither `< 0` nor `=== 0`, so the walk\n * used to read it as \"do not descend\" and skipped the subtree in\n * silence. Nothing is 0 here — the neutral answer, the one C gives\n * when an action has nothing to say.\n *\n * A boolean is NOT guessed: `true`/`false` could mean either half of\n * this contract, so it is reported and taken as 0. A walk that\n * silently loses a subtree is the thing this whole function exists\n * to stop.\n ***************************************************************/\nfunction walk_ret(ret)\n{\n if(typeof ret === \"number\" && isFinite(ret)) {\n return ret;\n }\n if(ret === undefined || ret === null) {\n return 0;\n }\n log_error(\n `walk callback must return a NUMBER (-1 stop, 0 descend, >0 skip children), ` +\n `got ${typeof ret}: taken as 0`\n );\n return 0;\n}\n\nfunction rc_walk_by_list(\n iter_, // dl_list_t\n walk_type, // walk_type_t\n cb_walking, // cb_walking_t\n user_data,\n user_data2\n) {\n /*\n * This let destroy the current item\n */\n let iter = [...iter_];\n\n let child;\n if(walk_type & walk_type_t.WALK_LAST2FIRST) {\n for(let i=iter.length; i>0; i--) {\n child = iter[i-1];\n let ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n }\n }\n } else {\n for(let i=0; i<iter.length; i++) {\n child = iter[i];\n let ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n }\n }\n }\n\n return 0;\n}\n\n/***************************************************************\n * Walking\n * If cb_walking return negative, the iter will stop.\n * Valid options:\n * WALK_BYLEVEL:\n * WALK_FIRST2LAST\n * or\n * WALK_LAST2FIRST\n ***************************************************************/\nfunction rc_walk_by_level(\n iter, // dl_list_t\n walk_type, // walk_type_t\n cb_walking, // cb_walking_t\n user_data,\n user_data2\n) {\n /*\n * First my children\n */\n let ret = rc_walk_by_list(iter, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n\n /*\n * Now child's children\n */\n let child;\n if(walk_type & walk_type_t.WALK_LAST2FIRST) {\n for(let i=iter.length; i>0; i--) {\n child = iter[i-1];\n\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_level(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n }\n } else {\n for(let i=0; i<iter.length; i++) {\n child = iter[i];\n\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_level(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n }\n }\n\n return ret;\n}\n\n/***************************************************************\n * Walking\n * If cb_walking return negative, the iter will stop.\n * return 0, continue\n * return positive, step current branch (only in WALK_TOP2BOTTOM)\n * Valid options:\n * WALK_TOP2BOTTOM\n * or\n * WALK_BOTTOM2TOP\n * or\n * WALK_BYLEVEL:\n * WALK_FIRST2LAST\n * or\n * WALK_LAST2FIRST\n ***************************************************************/\nfunction rc_walk_by_tree(\n iter, // dl_list_t\n walk_type, // walk_type_t\n cb_walking, // cb_walking_t\n user_data,\n user_data2\n) {\n if(walk_type & walk_type_t.WALK_BYLEVEL) {\n return rc_walk_by_level(iter, walk_type, cb_walking, user_data, user_data2);\n }\n\n let ret;\n let child;\n if(walk_type & walk_type_t.WALK_BOTTOM2TOP) {\n for(let i=iter.length; i>0; i--) {\n child = iter[i-1];\n\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_tree(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n\n ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n }\n\n }\n } else {\n for(let i=0; i<iter.length; i++) {\n child = iter[i];\n\n ret = walk_ret((cb_walking)(child, user_data, user_data2));\n if(ret < 0) {\n return ret;\n } else if(ret === 0) {\n let dl_child_list = [...child.dl_children];\n ret = rc_walk_by_tree(dl_child_list, walk_type, cb_walking, user_data, user_data2);\n if(ret < 0) {\n return ret;\n }\n } else {\n // positive, continue next\n }\n }\n }\n\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction its_me(gobj, shortname)\n{\n let n = shortname.split(\"^\");\n let gobj_name_ =null;\n let gclass_name_ = null;\n if(n.length === 2) {\n gclass_name_ = n[0];\n gobj_name_ = n[1];\n if(gclass_name_ !== gobj_gclass_name(gobj)) {\n return false;\n }\n } else if(n.length === 1) {\n gobj_name_ = n[0];\n } else {\n return false;\n }\n return gobj_name_ === gobj_name(gobj);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_find_gobj(gobj, path)\n{\n if(empty_string(path)) {\n return null;\n }\n /*\n * WARNING code repeated\n */\n const path_ = path.toLowerCase();\n if(path_ === \"__default_service__\") {\n return __default_service__;\n }\n if(path_ === \"__yuno__\" || path_ === \"__root__\") {\n return __yuno__;\n }\n\n return gobj_search_path(__yuno__, path);\n}\n\n/***************************************************************************\n * Match child.\n ***************************************************************************/\nfunction gobj_match_gobj(gobj, jn_filter)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return false;\n }\n\n let __gclass_name__ = jn_filter.__gclass_name__;\n let __gobj_name__ = jn_filter.__gobj_name__;\n let __prefix_gobj_name__ = jn_filter.__prefix_gobj_name__;\n let __disabled__ = jn_filter.__disabled__;\n let __state__ = jn_filter.__state__;\n\n /*\n * Check the system keys of the jn_filter used in find loop\n */\n if(__gclass_name__) {\n if(__gclass_name__ !== gobj_gclass_name(gobj)) {\n return false;\n }\n }\n if(__gobj_name__) {\n if(__gobj_name__ !== gobj_name(gobj)) {\n return false;\n }\n }\n if(__prefix_gobj_name__) {\n let l = __prefix_gobj_name__.length;\n let name = gobj_name(gobj).substring(0, l);\n if(__prefix_gobj_name__ !== name) {\n return false;\n }\n }\n if(__state__) {\n let state = gobj_current_state(gobj);\n if(__state__ !== state) {\n return false;\n }\n }\n\n let jn_attrs = gobj.jn_attrs;\n\n for(const key of Object.keys(jn_filter)) {\n if(key === \"__gclass_name__\" ||\n key === \"__gobj_name__\" ||\n key === \"__prefix_gobj_name__\" ||\n key === \"__disabled__\" ||\n key === \"__state__\") {\n continue;\n }\n if(gobj_has_attr(gobj, key)) {\n if(jn_attrs[key] !== jn_filter[key]) {\n return false;\n }\n }\n }\n return true;\n}\n\n/***************************************************************************\n * Returns the first matched child.\n ***************************************************************************/\nfunction gobj_find_child(gobj, jn_filter)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n\n const dl_children = gobj.dl_children;\n for(let i=0; i < dl_children.length; i++) {\n const child = dl_children[i];\n if(gobj_match_gobj(child, jn_filter)) {\n return child;\n }\n }\n\n return null;\n}\n\n/************************************************************\n * Return child's list matched with kw attributes\n ************************************************************/\nfunction gobj_match_children(gobj, jn_filter)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n\n jn_filter = jn_filter || {};\n let children = [];\n\n const dl_children = gobj.dl_children;\n for(let i=0; i < dl_children.length; i++) {\n const child = dl_children[i];\n if(gobj_match_gobj(child, jn_filter)) {\n children.push(child);\n }\n }\n\n return children;\n}\n\n/************************************************************\n * Returns the matched children searching in the tree.\n ************************************************************/\nfunction gobj_match_children_tree(gobj, jn_filter)\n{\n jn_filter = jn_filter || {};\n\n function _walk_child_tree(d, o)\n {\n let dl_children = o.dl_children;\n for (let i=0; i < dl_children.length; i++) {\n let child = dl_children[i];\n if(gobj_match_gobj(child, jn_filter)) {\n d.push(child);\n }\n _walk_child_tree(d, child);\n }\n }\n\n let list = [];\n _walk_child_tree(list, gobj);\n return list;\n}\n\n/***************************************************************************\n * Return the object searched by path.\n * The separator of tree's gobj must be '`'\n ***************************************************************************/\nfunction gobj_search_path(gobj, path)\n{\n if(!path) {\n return null;\n }\n /*\n * Get node and compare with this\n */\n let p = path.split(\"`\");\n let shortname = p[0];\n if(!its_me(gobj, shortname)) {\n return null;\n }\n if(p.length===1) {\n // No more nodes\n return gobj;\n }\n\n /*\n * Get next node and compare with children\n */\n let n = p[1];\n let nn = n.split(\"^\");\n let filter = {};\n if(nn.length === 1) {\n filter.__gobj_name__ = nn;\n } else {\n filter.__gclass_name__ = nn[0];\n filter.__gobj_name__ = nn[1];\n }\n\n /*\n * Search in children\n */\n let child = gobj_find_child(gobj, filter);\n if(!child) {\n return null;\n }\n p.splice(0, 1);\n p = p.join(\"`\");\n return gobj_search_path(child, p);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_has_attr(gobj, name)\n{\n if(empty_string(name)) {\n return false; // WARNING must be a silence function!\n }\n return !!gclass_attr_desc(gobj.gclass, name, false);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_read_attr(gobj, name, src)\n{\n let jn_attrs = gobj.jn_attrs;\n\n // TODO implement inherited attributes\n // TODO if attribute not found then find in bottom gobj\n if(name in jn_attrs) {\n if(jn_attrs.hasOwnProperty(name)) {\n // TODO must be a item2json, to call mt_reading\n let value = jn_attrs[name];\n if(gobj.gclass.gmt.mt_reading) {\n return gobj.gclass.gmt.mt_reading(gobj, name, value);\n }\n return value;\n }\n }\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return null;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_attrs(\n gobj,\n include_flag, // sdata_flag_t\n src\n) {\n let jn_attrs = {};\n\n let sdata_desc = gobj.gclass.attrs_table;\n\n for(let i=0; i < sdata_desc.length; i++) {\n const it = sdata_desc[i];\n if(!it.name) {\n continue;\n }\n\n if(include_flag === -1 || (it.flag & include_flag)) {\n let value;\n if(gobj.gclass.gmt.mt_reading &&\n !(gobj.obflag & obflag_t.obflag_destroyed)) {\n value = gobj.gclass.gmt.mt_reading(gobj, it.name);\n if(value === undefined) {\n value = json_object_get(gobj.jn_attrs, it.name);\n }\n } else {\n value = json_object_get(gobj.jn_attrs, it.name);\n }\n json_object_set(jn_attrs, it.name, value);\n }\n }\n\n return jn_attrs;\n}\n\n/***************************************************************************\n * ATTR: read bool\n ***************************************************************************/\nfunction gobj_read_bool_attr(gobj, name)\n{\n if(name) {\n if(strcasecmp(name, \"__disabled__\")===0) {\n return gobj_is_disabled(gobj);\n } else if(strcasecmp(name, \"__running__\")===0) {\n return gobj_is_running(gobj);\n } else if(strcasecmp(name, \"__playing__\")===0) {\n return gobj_is_playing(gobj);\n } else if(strcasecmp(name, \"__service__\")===0) {\n return gobj_is_service(gobj);\n }\n }\n\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_integer_attr(gobj, name)\n{\n if(name && strcasecmp(name, \"__trace_level__\")===0) {\n // TODO return gobj_trace_level(gobj);\n }\n\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_str_attr(gobj, name)\n{\n if(name && strcasecmp(name, \"__state__\")===0) {\n return gobj_current_state(gobj);\n }\n\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/***************************************************************************\n * ATTR: read\n ***************************************************************************/\nfunction gobj_read_pointer_attr(gobj, name)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n if(gobj.gclass.gmt.mt_reading) {\n if(!(gobj.obflag & obflag_t.obflag_destroyed)) {\n return gobj.gclass.gmt.mt_reading(gobj, name);\n }\n }\n return json_object_get(hs, name);\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction gobj_write_attr(\n gobj,\n path, // If it has ` then segments are gobj and leaf is the attribute (+bottom)\n value,\n src\n) {\n // TODO implement inherited attributes\n // TODO if attribute not found then find in bottom gobj\n\n if(!is_string(path)) {\n log_error(sprintf(\n \"gobj_write_attr(%s): path must be a string\",\n gobj_short_name(gobj))\n );\n return -1;\n }\n let jn_attrs = gobj.jn_attrs;\n\n let ss = path.split(\"`\");\n if(ss.length<=1) {\n let key = path;\n if(key in jn_attrs) {\n if(jn_attrs.hasOwnProperty(key)) {\n jn_attrs[key] = value;\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) {\n gobj.priv[key] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, key);\n }\n }\n return 0;\n }\n }\n log_error(sprintf(\"gobj_write_attr(%s): attr not found '%s'\", gobj_short_name(gobj), key));\n return -1;\n }\n\n let key;\n let len = ss.length;\n for(let i=0; i<len; i++) {\n key = ss[i];\n let child = gobj_find_child(gobj, {\"__gobj_name__\": key});\n if(child && i<len-1) {\n gobj = child;\n continue;\n }\n\n // TODO this write in childs, is not well checked!\n let jn_attrs = gobj.jn_attrs;\n\n if(key in jn_attrs) {\n if(jn_attrs.hasOwnProperty(key)) {\n jn_attrs[key] = value;\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(key)) {\n gobj.priv[key] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.mt_writing) {\n gobj.mt_writing(gobj, key);\n }\n }\n return 0;\n }\n }\n break;\n }\n\n log_error(sprintf(\"gobj_write_attr(%s): attr not found '%s'\", gobj_short_name(gobj), key));\n return -1;\n}\n\n/***************************************************************************\n * WRITE - high level\n ***************************************************************************/\nfunction sdata_write_default_values(\n gobj,\n include_flag, // sdata_flag_t\n exclude_flag // sdata_flag_t\n)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n let sdata_desc = gobj.gclass.attrs_table;\n\n for(let i=0; i < sdata_desc.length; i++) {\n const it = sdata_desc[i];\n if(!it.name) {\n continue;\n }\n\n if(exclude_flag && (it.flag & exclude_flag)) {\n continue;\n }\n if(include_flag === -1 || (it.flag & include_flag)) {\n const value = set_default(gobj, gobj.jn_attrs, it);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(it.name)) {\n gobj.priv[it.name] = value;\n }\n\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, it.name);\n }\n }\n }\n return 0;\n}\n\n/***************************************************************************\n * ATTR: write\n * Reset volatile attributes\n ***************************************************************************/\nfunction gobj_reset_volatil_attrs(gobj)\n{\n return sdata_write_default_values(\n gobj,\n sdata_flag_t.SDF_VOLATIL, // include_flag\n 0 // exclude_flag\n );\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_attrs(\n gobj,\n kw,\n include_flag, // sdata_flag_t\n src\n) {\n let hs = gobj_hsdata(gobj);\n let ret = 0;\n for (const [attr, jn_value] of Object.entries(kw)) {\n let it = gobj_attr_desc(gobj, attr, true);\n if(!it) {\n continue;\n }\n if(!(include_flag === -1 || (it.flag & include_flag))) {\n continue;\n }\n ret += json2item(gobj, hs, it, jn_value);\n }\n\n return ret;\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_bool_attr(gobj, name, value)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n hs[name] = parseBoolean(value);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) {\n gobj.priv[name] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, name);\n }\n }\n return 0;\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return -1;\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_integer_attr(gobj, name, value)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n hs[name] = parseInt(value);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) {\n gobj.priv[name] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, name);\n }\n }\n return 0;\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return -1;\n}\n\n/***************************************************************************\n * ATTR: write\n ***************************************************************************/\nfunction gobj_write_str_attr(gobj, name, value)\n{\n let hs = gobj_hsdata2(gobj, name, false);\n if(hs) {\n hs[name] = String(value);\n\n // New, write automatically the defined private data, in JS is possible do it\n if(is_object(gobj.priv) && gobj.priv.hasOwnProperty(name)) {\n gobj.priv[name] = value;\n }\n\n // Avoid call to mt_writing before mt_create or destroyed!\n if((gobj.obflag & obflag_t.obflag_created) && !(gobj.obflag & obflag_t.obflag_destroyed)) {\n // Now mt_writing is only informative, not needed to update priv\n if(gobj.gclass.gmt.mt_writing) {\n gobj.gclass.gmt.mt_writing(gobj, name);\n }\n }\n return 0;\n }\n\n log_error(`${gobj_short_name(gobj)}: GClass Attribute NOT FOUND, attr ${name}`);\n return -1;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_change_state(gobj, state_name)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n\n if(gobj.current_state.state_name === state_name) {\n return false;\n }\n let new_state = _find_state(gobj.gclass, state_name);\n if(!new_state) {\n log_error(`${gobj_short_name(gobj)}: state unknown, state ${state_name}`);\n return false;\n }\n gobj.last_state = gobj.current_state;\n gobj.current_state = new_state;\n\n let tracea = is_machine_tracing(gobj, \"EV_STATE_CHANGED\");\n let tracea_states = __trace_gobj_states__(gobj) ? true : false;\n if(tracea || tracea_states) {\n if(__trace_machine_format__ === 1) {\n /* No state line, like the C kernel: in the simpler shape the\n * transition line already carries the state it ran in, and a\n * second line per change doubles the trace to say it again. */\n } else {\n trace_machine(sprintf(\"🔀🔀 mach(%s%s^%s), new st(%s), prev st(%s)\",\n (!gobj.running)?\"!!\":\"\",\n gobj_gclass_name(gobj), gobj_name(gobj),\n gobj_current_state(gobj),\n gobj.last_state.state_name\n ));\n }\n }\n\n // TODO let kw_st = {};\n // kw_st[\"previous_state\"] = gobj.last_state.state_name;\n // kw_st[\"current_state\"] = gobj.current_state.state_name;\n //\n // if(gobj.gclass.gmt.mt_state_changed) {\n // gobj.gclass.gmt.mt_state_changed(gobj, \"EV_STATE_CHANGED\", kw_st);\n // } else {\n // gobj_publish_event(gobj, \"EV_STATE_CHANGED\", kw_st);\n // }\n\n return true;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_current_state(gobj)\n{\n /*\n * Aligned with the C kernel's gobj_current_state(): only NULL-guard\n * and return the state name. A gobj being destroyed still has a\n * valid current_state, and reporting it is harmless — callers test\n * it against a state string. (Do NOT log on obflag_destroying here:\n * destroy tears down subscriptions, which calls mt_subscription_*\n * whose first line reads this; a log there is a false positive.)\n */\n if(!is_gobj(gobj)) {\n log_error(\"hgobj NULL\");\n return \"\";\n }\n\n return gobj.current_state.state_name;\n}\n\n/************************************************************\n * Change parent\n ************************************************************/\nfunction gobj_change_parent(gobj, parent)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return null;\n }\n if(!(parent instanceof GObj)) {\n log_error(`${gobj_short_name(gobj)}: gobj_change_parent() BAD TYPE of parent`);\n return -1;\n }\n\n /*--------------------------------------*\n * Remove from current parent\n *--------------------------------------*/\n if (gobj.parent && gobj.parent.mt_child_removed) {\n gobj.parent.mt_child_removed(gobj.parent, gobj);\n }\n if (gobj.parent) {\n _remove_child(gobj.parent, gobj);\n gobj.parent = null;\n }\n\n /*--------------------------------------*\n * Add to new parent\n *--------------------------------------*/\n _add_child(parent, gobj);\n\n /*--------------------------------------*\n * Inform to parent\n *-------------------------------------*/\n if(parent.mt_child_added) {\n let trace_creation = __trace_gobj_create_delete__(gobj);\n if(trace_creation) {\n log_debug(sprintf(\"👦👦🔵 child_added(%s): %s\", gobj_full_name(parent), gobj_short_name(gobj)));\n }\n parent.mt_child_added(parent, gobj);\n }\n\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_event_type( // silent function\n gobj,\n event,\n include_system_events\n)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj NULL of bad type`);\n return null;\n }\n\n let event_type = gclass_event_type(gobj.gclass, event);\n if(event_type) {\n return event_type;\n }\n\n if(include_system_events) {\n /*\n * Check global (gobj) output events\n */\n const size = dl_global_event_types.length;\n const dl = dl_global_event_types;\n\n for(let i=0; i<size; i++) {\n let event_type = dl[i];\n if(event_type.event_name && event_type.event_name === event) {\n return event_type;\n }\n }\n }\n\n return null;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_has_event(gobj, event, event_flag)\n{\n let event_type = gobj_event_type(gobj, event, false);\n if(!event_type) {\n return false;\n }\n\n if(event_flag && !(event_type.event_flag & event_flag)) {\n return false;\n }\n\n return true;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_has_output_event(gobj, event, event_flag)\n{\n let event_type = gobj_event_type(gobj, event, false);\n if(!event_type) {\n return false;\n }\n\n if(event_flag && !(event_type.event_flag & event_flag)) {\n return false;\n }\n\n if(!(event_type.event_flag & event_flag_t.EVF_OUTPUT_EVENT)) {\n return false;\n }\n\n return true;\n}\n\n/************************************************************\n * Posted events: gobj_send_event(), but on the next turn\n *\n * Same contract as the C side (see gobj.h). It exists to get out of the\n * stack you are standing on: gobj_publish_event() dispatches synchronously,\n * so a subscriber action runs inside the publisher's own stack, and\n * destroying that publisher there dismantles what is still iterating.\n *\n * The queue is drained with setTimeout(0) and NOT with queueMicrotask():\n * a microtask runs before the browser can paint or handle an input, so a\n * chain of posted events would hold the page exactly the way it used to\n * hold the event loop in C. A macrotask gives the browser its turn between\n * one event and the next.\n *\n * Delivery is a SNAPSHOT: the events queued when the drain begins are the\n * ones delivered in it, and whatever an action posts while it runs waits\n * for the following turn.\n ************************************************************/\nconst MAX_POSTED_EVENTS = 10000;\nlet __dl_posted_events__ = [];\nlet __posted_events_scheduled__ = false;\n\nfunction gobj_post_event(dst, event, kw, src)\n{\n if(!dst || !(dst instanceof GObj)) {\n log_error(`gobj_post_event(): gobj dst NULL, event ${event}`);\n return -1;\n }\n if(dst.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n log_error(`gobj_post_event(): gobj dst DESTROYING, event ${event}`);\n return -1;\n }\n if(empty_string(event)) {\n log_error(`gobj_post_event(): event EMPTY`);\n return -1;\n }\n\n /*\n * Checked now, not when it is delivered: otherwise the\n * \"Event NOT DEFINED in state\" arrives a turn later, with a stack that\n * points at the drain instead of at whoever posted it.\n */\n if(!gobj_has_event(dst, event, 0)) {\n log_error(\n `gobj_post_event(): event NOT DEFINED in gclass ` +\n `${gobj_gclass_name(dst)}, event ${event}`\n );\n return -1;\n }\n\n if(__dl_posted_events__.length >= MAX_POSTED_EVENTS) {\n log_error(\n `gobj_post_event(): too many posted events, this is NOT a work ` +\n `queue, event ${event}, pending ${__dl_posted_events__.length}`\n );\n return -1;\n }\n\n __dl_posted_events__.push({dst: dst, event: event, kw: kw, src: src});\n\n if(is_machine_tracing(dst, event) && !is_machine_not_tracing(src, event)) {\n trace_machine(sprintf(\"📬 posted(%s%s), ev: %s, pending: %d\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n event,\n __dl_posted_events__.length\n ));\n }\n\n if(!__posted_events_scheduled__) {\n __posted_events_scheduled__ = true;\n setTimeout(gobj_deliver_posted_events, 0);\n }\n\n return 0;\n}\n\n/************************************************************\n * How many posted events wait for delivery\n ************************************************************/\nfunction gobj_posted_events_size()\n{\n return __dl_posted_events__.length;\n}\n\n/************************************************************\n * Deliver the posted events. One turn, one snapshot.\n ************************************************************/\nfunction gobj_deliver_posted_events()\n{\n __posted_events_scheduled__ = false;\n\n let snapshot = __dl_posted_events__;\n __dl_posted_events__ = [];\n\n let delivered = 0;\n for(let msg of snapshot) {\n if(msg.dst.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n continue; // destroyed after it was queued, in this same snapshot\n }\n gobj_send_event(msg.dst, msg.event, msg.kw, msg.src);\n delivered++;\n }\n\n /*\n * What the actions posted while this ran is already in the new list.\n */\n if(__dl_posted_events__.length > 0 && !__posted_events_scheduled__) {\n __posted_events_scheduled__ = true;\n setTimeout(gobj_deliver_posted_events, 0);\n }\n\n return delivered;\n}\n\n/************************************************************\n * Take a gobj out of the queue of posted events.\n *\n * Called from gobj_destroy(), and the two halves are not the same thing:\n * as DESTINATION the entry is dropped, as SOURCE only the pointer is\n * cleared -- the destination still wants its event, and it arrives with\n * src null, which every action already has to accept.\n ************************************************************/\nfunction purge_posted_events(gobj)\n{\n if(__dl_posted_events__.length === 0) {\n return;\n }\n for(let msg of __dl_posted_events__) {\n if(msg.src === gobj) {\n msg.src = null;\n }\n }\n __dl_posted_events__ = __dl_posted_events__.filter(msg => msg.dst !== gobj);\n}\n\n/************************************************************\n * send_event\n ************************************************************/\nfunction gobj_send_event(dst, event, kw, src)\n{\n if(!dst || !(dst instanceof GObj)) {\n log_error(`gobj dst NULL`);\n return -1;\n }\n\n if(dst.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n log_error(`gobj dst DESTROYED`);\n return -1;\n }\n\n let state = dst.current_state;\n if(!state) {\n log_error(`${gobj_short_name(dst)}: current_state NULL`);\n return -1;\n }\n\n /*----------------------------------*\n * Find the event/action in state\n *----------------------------------*/\n let tracea = is_machine_tracing(dst, event) && !is_machine_not_tracing(src, event);\n\n __inside__ ++;\n\n let event_action = _find_event_action(state, event);\n if(!event_action) {\n if(dst.gclass.gmt.mt_inject_event) {\n __inside__ --;\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n trace_machine(sprintf(\"🔜 %s %s%s %s\",\n event?event:\"\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n state.state_name\n ));\n } else {\n trace_machine(sprintf(\"🔃 mach(%s%s), st: %s, ev: %s, from(%s%s)\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n state.state_name,\n event?event:\"\",\n (src && !src.running)?\"!!\":\"\",\n gobj_short_name(src)\n ));\n }\n if(kw) {\n if(__trace_gobj_ev_kw__(dst)) {\n if(json_object_size(kw)) {\n trace_json(kw);\n }\n }\n }\n }\n return dst.gclass.gmt.mt_inject_event(dst, event, kw, src);\n }\n\n if(tracea) {\n trace_machine(sprintf(\n \"📛 mach(%s%s^%s), st: %s, ev: %s, 📛📛ERROR Event NOT DEFINED in state📛📛, from(%s%s^%s)\",\n (!dst.running)?\"!!\":\"\",\n gobj_gclass_name(dst), gobj_name(dst),\n state.state_name,\n event?event:\"\",\n (src && !src.running)?\"!!\":\"\",\n gobj_gclass_name(src), gobj_name(src)\n ));\n }\n log_error(`📛📛 Event NOT DEFINED in state 📛📛: ${gobj_short_name(dst)}, ${state.state_name}, ${event}`);\n\n __inside__ --;\n\n return -1;\n }\n\n /*----------------------------------*\n * Check AUTHZ\n *----------------------------------*/\n// if(ev_desc.authz & EV_AUTHZ_INJECT) {\n// }\n\n /*----------------------------------*\n * Exec the event\n *----------------------------------*/\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n /* Compact one-liner, like the C kernel's trace_machine_format==1. */\n trace_machine(sprintf(\"🔄 %s %s%s %s from %s%s\",\n event?event:\"\",\n (!dst.running)?\"!!\":\"\",\n gobj_short_name(dst),\n state.state_name,\n (src && !src.running)?\"!!\":\"\",\n gobj_short_name(src)\n ));\n } else {\n let action_name = \"\";\n if(event_action.action) {\n action_name = get_function_name(event_action.action);\n }\n trace_machine(sprintf(\"🔄 mach(%s%s^%s), st: %s, ev: %s%s%s, ac: %s, from(%s%s^%s)\",\n (!dst.running)?\"!!\":\"\",\n gobj_gclass_name(dst), gobj_name(dst),\n state.state_name,\n \"\", //On_Black RBlue,\n event?event:\"\",\n \"\", //Color_Off,\n action_name,\n (src && !src.running)?\"!!\":\"\",\n gobj_gclass_name(src), gobj_name(src)\n ));\n }\n if(kw) {\n if(__trace_gobj_ev_kw__(dst)) {\n if(json_object_size(kw)) {\n trace_json(kw);\n }\n }\n }\n }\n\n /*\n * IMPORTANT HACK\n * Set new state BEFORE run 'action'\n *\n * The next state is changed before executing the action.\n * If you don’t like this behavior, set the next-state to NULL\n * and use change_state() to change the state inside the actions.\n */\n if(event_action.next_state) {\n gobj_change_state(dst, event_action.next_state);\n }\n\n let ret = -1;\n try {\n if(event_action.action) {\n // Execute the action\n ret = (event_action.action)(dst, event, kw, src);\n } else {\n // No action, there is nothing amiss!.\n }\n } finally {\n }\n\n if(tracea && __trace_machine_format__ !== 1 && !(dst.obflag & obflag_t.obflag_destroyed)) {\n trace_machine(sprintf(\"<- mach(%s%s^%s), st: %s, ev: %s, ret: %d\",\n (!dst.running)?\"!!\":\"\",\n gobj_gclass_name(dst), gobj_name(dst),\n dst.current_state.state_name,\n event?event:\"\",\n is_number(ret)?ret:0\n ));\n }\n\n __inside__ --;\n\n return ret;\n}\n\nconst subs_flag_t = Object.freeze({\n__hard_subscription__ : 0x00000001,\n__own_event__ : 0x00000002, // If gobj_send_event return -1 don't continue publishing\n});\n\n/*\n *\n */\nconst subscription_desc = [\n/*-ATTR-type--------------------name-----------flag-default-description---------- */\nSDATA(data_type_t.DTP_POINTER, \"publisher\", 0, null, \"publisher gobj\"),\nSDATA(data_type_t.DTP_POINTER, \"subscriber\", 0, null, \"subscriber gobj\"),\nSDATA(data_type_t.DTP_STRING, \"event\", 0, \"\", \"event name subscribed\"),\nSDATA(data_type_t.DTP_STRING, \"renamed_event\",0, \"\", \"rename event name\"),\nSDATA(data_type_t.DTP_INTEGER, \"subs_flag\", 0, 0, \"subscription flag\"),\nSDATA(data_type_t.DTP_JSON, \"__config__\", 0, null, \"subscription config\"),\nSDATA(data_type_t.DTP_JSON, \"__global__\", 0, null, \"global kw, merge in publishing\"),\nSDATA(data_type_t.DTP_JSON, \"__local__\", 0, null, \"local kw, remove in publishing\"),\nSDATA(data_type_t.DTP_JSON, \"__filter__\", 0, null, \"filter kw, filter in publishing\"),\nSDATA(data_type_t.DTP_STRING, \"__service__\", 0, \"\", \"subscription service\"),\nSDATA_END()\n];\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction _create_subscription(\n publisher,\n event,\n kw,\n subscriber)\n{\n let subs = sdata_create(publisher, subscription_desc);\n json_object_set_new(subs, \"event\", event);\n json_object_set_new(subs, \"subscriber\", subscriber);\n json_object_set_new(subs, \"publisher\", publisher);\n\n let subs_flag = 0;\n\n if(kw) {\n let __config__ = kw_get_dict(publisher, kw, \"__config__\", null);\n let __global__ = kw_get_dict(publisher, kw, \"__global__\", null);\n let __local__ = kw_get_dict(publisher, kw, \"__local__\", null);\n let __filter__ = kw_get_dict_value(publisher, kw, \"__filter__\", null);\n let __service__ = kw_get_str(publisher, kw, \"__service__\", \"\");\n\n if(json_size(__global__)>0) {\n let kw_clone = json_deep_copy(__global__);\n json_object_set_new(subs, \"__global__\", kw_clone);\n }\n if(json_size(__config__)>0) {\n let kw_clone = json_deep_copy(__config__);\n json_object_set_new(subs, \"__config__\", kw_clone);\n\n// TODO\n// if(kw_has_key(kw_clone, \"__rename_event_name__\")) {\n// const char *renamed_event = kw_get_str(gobj?, kw_clone, \"__rename_event_name__\", 0, 0);\n// sdata_write_str(subs, \"renamed_event\", renamed_event);\n// json_object_del(kw_clone, \"__rename_event_name__\");\n// subs_flag |= __rename_event_name__;\n//\n// // Get/Create __global__\n// json_t *kw_global = sdata_read_json(subs, \"__global__\");\n// if(!kw_global) {\n// kw_global = json_object();\n// sdata_write_json(subs, \"__global__\", kw_global);\n// kw_decref(kw_global); // Incref above\n// }\n// kw_set_dict_value(\n// kw_global,\n// \"__original_event_name__\",\n// json_string(event)\n// );\n// }\n\n if(kw_has_key(kw_clone, \"__hard_subscription__\")) {\n let hard_subscription = kw_get_bool(publisher,\n kw_clone, \"__hard_subscription__\", false\n );\n json_object_del(kw_clone, \"__hard_subscription__\");\n if(hard_subscription) {\n subs_flag |= subs_flag_t.__hard_subscription__;\n }\n }\n if(kw_has_key(kw_clone, \"__own_event__\")) {\n let own_event= kw_get_bool(publisher,\n kw_clone, \"__own_event__\", false\n );\n json_object_del(kw_clone, \"__own_event__\");\n if(own_event) {\n subs_flag |= subs_flag_t.__own_event__;\n }\n }\n }\n if(json_size(__local__)>0) {\n let kw_clone = json_deep_copy(__local__);\n json_object_set_new(subs, \"__local__\", kw_clone);\n }\n if(json_size(__filter__)>0) {\n let kw_clone = json_deep_copy(__filter__);\n json_object_set_new(subs, \"__filter__\", kw_clone);\n }\n if(!empty_string(__service__)) {\n json_object_set_new(subs, \"__service__\", __service__);\n }\n }\n json_object_set_new(subs, \"subs_flag\", subs_flag);\n\n return subs;\n}\n\n/***************************************************************************\n * Match subscription\n ***************************************************************************/\nfunction _match_subscription(\n subs,\n publisher,\n event,\n kw,\n subscriber\n) {\n let __config__ = kw_get_dict(publisher, kw, \"__config__\", null);\n let __global__ = kw_get_dict(publisher, kw, \"__global__\", null);\n let __local__ = kw_get_dict(publisher, kw, \"__local__\", null);\n let __filter__ = kw_get_dict_value(publisher, kw, \"__filter__\", null);\n\n let match = true;\n\n if(publisher) {\n let publisher_ = kw_get_pointer(null, subs, \"publisher\", null);\n if(publisher !== publisher_) {\n match = false;\n }\n }\n\n if(subscriber) {\n let subscriber_ = kw_get_pointer(null, subs, \"subscriber\", null);\n if(subscriber !== subscriber_) {\n match = false;\n }\n }\n\n if(event) {\n let event_ = kw_get_str(null, subs, \"event\", \"\");\n if(event !== event_) {\n match = false;\n }\n }\n\n if(json_size(__config__)>0) {\n let kw_config = kw_get_dict(null, subs, \"__config__\", null);\n if(json_size(kw_config)>0) {\n if(!json_is_identical(kw_config, __config__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n if(json_size(__global__)>0) {\n let kw_global = kw_get_dict(null, subs, \"__global__\", null);\n if(json_size(kw_global)>0) {\n if(!json_is_identical(kw_global, __global__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n if(json_size(__local__)>0) {\n let kw_local = kw_get_dict(null, subs, \"__local__\", null);\n if(json_size(kw_local)>0) {\n if(!json_is_identical(kw_local, __local__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n if(json_size(__filter__)>0) {\n let kw_filter = kw_get_dict_value(null, subs, \"__filter__\", null);\n if(json_size(kw_filter)>0) {\n if(!json_is_identical(kw_filter, __filter__)) {\n match = false;\n }\n } else {\n match = false;\n }\n }\n\n return match;\n}\n\n/***************************************************************************\n * Return a list of subscriptions in the list dl_subs\n * filtering by matching:\n * publisher\n * event,\n * kw (__config__, __global__, __local__, __filter__),\n * subscriber\n ***************************************************************************/\nfunction _find_subscriptions(\n dl_subs,\n publisher,\n event,\n kw,\n subscriber\n) {\n let iter = [];\n\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n if(_match_subscription(\n subs,\n publisher,\n event,\n kw, // NOT owned\n subscriber\n )) {\n json_array_append(iter, subs);\n }\n }\n\n return iter;\n}\n\n/***************************************************************************\n * Find idx of subscription in dl_subs, -1 not found\n ***************************************************************************/\nfunction _get_subs_idx(\n dl_subs,\n publisher,\n event,\n kw,\n subscriber\n) {\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n if(_match_subscription(\n subs,\n publisher,\n event,\n kw, // NOT owned\n subscriber\n )) {\n return i;\n }\n }\n\n return -1;\n}\n\n/***************************************************************************\n * Delete subscription in publisher and subscriber\n ***************************************************************************/\nfunction _delete_subscription(\n gobj,\n subs,\n force,\n not_inform\n) {\n let publisher = kw_get_pointer(gobj, subs, \"publisher\", null, kw_flag_t.KW_REQUIRED);\n let subscriber = kw_get_pointer(gobj, subs, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n let event = kw_get_str(gobj, subs, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n let subs_flag = kw_get_int(gobj, subs, \"subs_flag\", null, kw_flag_t.KW_REQUIRED);\n let hard_subscription = (subs_flag & subs_flag_t.__hard_subscription__)?1:0;\n\n /*-------------------------------*\n * Check if hard subscription\n *-------------------------------*/\n if(hard_subscription) {\n if(!force) {\n return -1;\n }\n }\n\n /*-----------------------------*\n * Trace\n *-----------------------------*/\n let tracea = __trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher);\n if(tracea) {\n trace_machine(sprintf(\n \"💜💜👎 unsubscribing event '%s': publisher %s, subscriber'%s'\",\n event?event:\"\",\n gobj_short_name(publisher),\n gobj_short_name(subscriber)\n ));\n trace_json(subs);\n }\n\n /*------------------------------------------------*\n * Inform (BEFORE) of subscription removed\n *------------------------------------------------*/\n if(!(publisher.obflag & obflag_t.obflag_destroyed)) {\n if(!not_inform) {\n if(publisher.gclass.gmt.mt_subscription_deleted) {\n publisher.gclass.gmt.mt_subscription_deleted(\n publisher,\n subs\n );\n }\n }\n }\n\n /*--------------------------------*\n * Delete subscription\n *--------------------------------*/\n let idx = _get_subs_idx(\n publisher.dl_subscriptions,\n publisher,\n event,\n subs,\n subscriber\n );\n\n if(idx >= 0) {\n json_array_remove(publisher.dl_subscriptions, idx);\n } else {\n log_error(`${gobj_short_name(gobj)}: subscription in publisher not found`);\n trace_json(subs);\n }\n\n idx = _get_subs_idx(\n subscriber.dl_subscribings,\n publisher,\n event,\n subs,\n subscriber\n );\n if(idx >= 0) {\n json_array_remove(subscriber.dl_subscribings, idx);\n } else {\n log_error(`${gobj_short_name(gobj)}: subscription in subscriber not found`);\n trace_json(subs);\n }\n\n return 0;\n}\n\n/***************************************************************************\n * Subscribe to an event\n *\n * event is only one event (not a string list like ginsfsm).\n *\n * See .h\n ***************************************************************************/\nfunction gobj_subscribe_event(\n publisher,\n event,\n kw,\n subscriber)\n{\n if(kw == null) {\n kw = {};\n }\n\n /*---------------------*\n * Check something\n *---------------------*/\n if(!publisher) {\n log_error(`publisher NULL: ev ${event}`);\n return 0;\n }\n if(!subscriber) {\n log_error(`subscriber NULL: ev ${event}`);\n return 0;\n }\n\n const IGNORED_KEYS = new Set(\n [\"__config__\", \"__global__\", \"__local__\", \"__filter__\", \"__service__\"]\n );\n Object.keys(kw).forEach(key => {\n if (!IGNORED_KEYS.has(key)) {\n log_error(`${gobj_short_name(publisher)}: key ignored in subscription (key: ${key}, event: ${event})`);\n }\n });\n\n /*--------------------------------------------------------------*\n * Event must be in output event list\n * You can avoid this with gcflag_no_check_output_events flag\n *--------------------------------------------------------------*/\n if(!empty_string(event)) {\n if(!gobj_has_output_event(publisher, event, event_flag_t.EVF_OUTPUT_EVENT)) {\n if(!(publisher.gclass.gclass_flag & gclass_flag_t.gcflag_no_check_output_events)) {\n log_error(`event NOT in output event list: ${gobj_short_name(publisher)}, ${event}`);\n return 0;\n }\n }\n } else {\n event = \"\"; // In C use NULL, in JS or others use \"\"\n }\n\n /*-------------------------------------------------*\n * Check AUTHZ\n *-------------------------------------------------*/\n\n /*------------------------------*\n * Find repeated subscription\n *------------------------------*/\n let dl_subs = _find_subscriptions(\n publisher.dl_subscriptions,\n publisher,\n event,\n kw,\n subscriber\n );\n if(json_array_size(dl_subs) > 0) {\n log_error(`${gobj_short_name(publisher)}: ${json_array_size(dl_subs)} subscription(s) REPEATED, will be deleted and override`);\n trace_json(dl_subs, \"subscription REPEATED\");\n gobj_unsubscribe_list(publisher, dl_subs, false);\n }\n\n /*-----------------------------*\n * Create subscription\n *-----------------------------*/\n let subs = _create_subscription(\n publisher,\n event,\n kw,\n subscriber\n );\n if(!subs) {\n log_error(`${gobj_short_name(publisher)}: _create_subscription() FAILED`);\n return 0;\n }\n\n json_array_append(publisher.dl_subscriptions, subs);\n json_array_append(subscriber.dl_subscribings, subs);\n\n /*-----------------------------*\n * Trace\n *-----------------------------*/\n let tracea = __trace_gobj_subscriptions__(subscriber) || __trace_gobj_subscriptions__(publisher);\n if(tracea) {\n trace_machine(sprintf(\n \"💜💜👍 subscribing event '%s', publisher '%s', subscriber %s\",\n event?event:\"\",\n gobj_short_name(publisher),\n gobj_short_name(subscriber)\n ));\n if(kw && (__trace_gobj_ev_kw__(subscriber) || __trace_gobj_ev_kw__(publisher))) {\n trace_json(kw);\n }\n }\n\n /*--------------------------------*\n * Inform new subscription\n *--------------------------------*/\n if(publisher.gclass.gmt.mt_subscription_added) {\n let result = publisher.gclass.gmt.mt_subscription_added(\n publisher,\n subs\n );\n /* `false` as well as a negative: the hook refuses the subscription,\n * and in javascript that is how it says so. */\n if(result < 0 || result === false) {\n _delete_subscription(publisher, subs, true, true);\n subs = 0;\n }\n }\n\n return subs;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_unsubscribe_event(\n publisher,\n event,\n kw,\n subscriber)\n{\n if(kw == null) {\n kw = {};\n }\n\n /*---------------------*\n * Check something\n *---------------------*/\n if(!publisher) {\n log_error(`publisher NULL: ev ${event}`);\n return 0;\n }\n if(!subscriber) {\n log_error(`subscriber NULL: ev ${event}`);\n return 0;\n }\n\n const IGNORED_KEYS = new Set(\n [\"__config__\", \"__global__\", \"__local__\", \"__filter__\", \"__service__\"]\n );\n Object.keys(kw).forEach(key => {\n if (!IGNORED_KEYS.has(key)) {\n log_error(`${gobj_short_name(publisher)}: key ignored in subscription (key: ${key}, event: ${event})`);\n }\n });\n\n /*--------------------------------------------------------------*\n * Event must be in output event list\n * You can avoid this with gcflag_no_check_output_events flag\n *--------------------------------------------------------------*/\n if(!empty_string(event)) {\n if(!gobj_has_output_event(publisher, event, event_flag_t.EVF_OUTPUT_EVENT)) {\n if(!(publisher.gclass.gclass_flag & gclass_flag_t.gcflag_no_check_output_events)) {\n log_error(`event NOT in output event list: ${gobj_short_name(publisher)}, ev ${event}`);\n return 0;\n }\n }\n } else {\n event = \"\"; // In C use NULL, in JS or others use \"\"\n }\n\n /*-----------------------------*\n * Find subscription\n *-----------------------------*/\n let dl_subs = _find_subscriptions(\n publisher.dl_subscriptions,\n publisher,\n event,\n kw,\n subscriber\n );\n\n let deleted = 0;\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n _delete_subscription(publisher, subs, false, false);\n deleted++;\n }\n\n if(!deleted) {\n log_warning(`${gobj_short_name(publisher)}: No subscription found`);\n trace_json(kw, \"No subscription found\");\n }\n\n return 0;\n}\n\n/***************************************************************************\n * Unsubscribe a list of subscription hsdata\n ***************************************************************************/\nfunction gobj_unsubscribe_list(\n gobj,\n dl_subs,\n force // delete hard_subscription subs too\n)\n{\n let dl = [...dl_subs];\n for(let i=0; i<dl.length; i++) {\n let subs = dl[i];\n _delete_subscription(gobj, subs, force, false);\n }\n return 0;\n}\n\n/***************************************************************************\n * Return a list of subscriptions in the publisher gobj,\n * filtering by matching:\n * event,\n * kw (__config__, __global__, __local__, __filter__),\n * subscriber\n ***************************************************************************/\nfunction gobj_find_subscriptions(\n publisher,\n event,\n kw,\n subscriber)\n{\n if(kw == null) {\n kw = {};\n }\n return _find_subscriptions(\n publisher.dl_subscriptions,\n publisher,\n event,\n kw,\n subscriber\n );\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction gobj_list_subscriptions(gobj2view)\n{\n let subscriptions = gobj_find_subscriptions(\n gobj2view,\n null, // event,\n null, // kw (__config__, __global__, __local__)\n null // subscriber\n );\n for(let i=0; i<subscriptions.length; i++) {\n let sub = subscriptions[i];\n let publisher = kw_get_pointer(gobj2view, sub, \"publisher\", null, kw_flag_t.KW_REQUIRED);\n let subscriber = kw_get_pointer(gobj2view, sub, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n let event_ = kw_get_str(gobj2view, sub, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n\n json_object_set_new(sub, \"s_event\", event_);\n json_object_set_new(sub, \"s_publisher\", gobj_short_name(publisher));\n json_object_set_new(sub, \"s_subscriber\", gobj_short_name(subscriber));\n }\n\n let subscribings = gobj_find_subscribings( // Return is YOURS\n gobj2view,\n 0, // event,\n null, // kw (__config__, __global__, __local__)\n 0 // subscriber\n );\n for(let i=0; i<subscribings.length; i++) {\n let sub = subscribings[i];\n let publisher = kw_get_pointer(gobj2view, sub, \"publisher\", null, kw_flag_t.KW_REQUIRED);\n let subscriber = kw_get_pointer(gobj2view, sub, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n let event_ = kw_get_str(gobj2view, sub, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n\n json_object_set_new(sub, \"s_event\", event_);\n json_object_set_new(sub, \"s_publisher\", gobj_short_name(publisher));\n json_object_set_new(sub, \"s_subscriber\", gobj_short_name(subscriber));\n }\n\n return {\n \"subscriptions\": subscriptions,\n \"subscribings\": subscribings,\n \"total subscriptions\": json_array_size(subscriptions),\n \"total_subscribings\": json_array_size(subscribings)\n };\n}\n\n/***************************************************************************\n * Return a list of subscribings\n * filtering by matching:\n * event,\n * kw (__config__, __global__, __local__, __filter__),\n * subscriber\n ***************************************************************************/\nfunction gobj_find_subscribings(\n subscriber,\n event,\n kw, // kw (__config__, __global__, __local__, __filter__)\n publisher\n)\n{\n return _find_subscriptions(\n subscriber.dl_subscribings,\n publisher,\n event,\n kw,\n subscriber\n );\n}\n\n/***************************************************************************\n * Return the sum of returns of gobj_send_event\n ***************************************************************************/\nfunction gobj_publish_event(\n publisher,\n event,\n kw)\n{\n if(!is_object(kw)) {\n kw = {};\n }\n\n /*---------------------*\n * Check something\n *---------------------*/\n if(!publisher || publisher.obflag & (obflag_t.obflag_destroyed|obflag_t.obflag_destroying)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n if(empty_string(event)) {\n log_error(`${gobj_short_name(publisher)}: event EMPTY`);\n return -1;\n }\n\n /*--------------------------------------------------------------*\n * Event must be in output event list\n * You can avoid this with gcflag_no_check_output_events flag\n *--------------------------------------------------------------*/\n let ev = gobj_event_type(publisher, event, true);\n if(!(ev && (ev.event_flag & (event_flag_t.EVF_SYSTEM_EVENT|event_flag_t.EVF_OUTPUT_EVENT)))) {\n /*\n * HACK ev can be null,\n * there are gclasses like c_iogate that are intermediate of other events.\n */\n if(!(publisher.gclass.gclass_flag & gclass_flag_t.gcflag_no_check_output_events)) {\n log_error(`event NOT in output event list: ${gobj_short_name(publisher)}, ev ${event}`);\n return -1;\n }\n }\n\n let tracea = (__trace_gobj_subscriptions__(publisher) || is_machine_tracing(publisher, event)) &&\n !is_machine_not_tracing(publisher, event);\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n trace_machine(sprintf(\"🔝🔝 %s %s%s %s\",\n event?event:\"\",\n (!publisher.running)?\"!!\":\"\",\n gobj_short_name(publisher),\n publisher.current_state.state_name\n ));\n } else {\n trace_machine(sprintf(\"🔝🔝 mach(%s%s^%s), st: %s, ev: %s%s%s\",\n (!publisher.running)?\"!!\":\"\",\n gobj_gclass_name(publisher), gobj_name(publisher),\n publisher.current_state.state_name,\n \"\", //On_Black BBlue,\n event?event:\"\",\n \"\" //Color_Off\n ));\n }\n /* The kw only with `ev_kw`, and only with something IN it, like the\n * C kernel: the `machine` trace alone printed the payload of every\n * publication, in the console and in any monitor. */\n if(__trace_gobj_ev_kw__(publisher) && json_object_size(kw)) {\n trace_json(kw);\n }\n }\n\n /*----------------------------------------------------------*\n * Own publication method\n * Return:\n * -1 broke . return\n * 0 continue without publish . return\n * 1 publish and continue . continue below\n *----------------------------------------------------------*/\n if(publisher.gclass.gmt.mt_publish_event) {\n let topublish = publisher.gclass.gmt.mt_publish_event(\n publisher,\n event,\n kw // not owned\n );\n if(topublish<=0) {\n return topublish;\n }\n }\n\n /*--------------------------------------------------------------*\n * Default publication method\n *--------------------------------------------------------------*/\n let dl_subs = [...publisher.dl_subscriptions]; // Create a shallow copy\n let sent_count = 0;\n let ret = 0;\n\n for(let idx=0; idx<dl_subs.length; idx++) {\n let subs = dl_subs[idx];\n /*-------------------------------------*\n * Pre-filter\n * kw NOT owned! you can modify the publishing kw\n * Return:\n * -1 broke\n * 0 continue without publish\n * 1 continue to publish\n *-------------------------------------*/\n if(publisher.gclass.gmt.mt_publication_pre_filter) {\n let topublish = publisher.gclass.gmt.mt_publication_pre_filter(\n publisher,\n subs,\n event,\n kw // not owned\n );\n if(topublish<0) {\n break;\n } else if(!topublish) {\n /* `!topublish` and not `=== 0`: this hook is written in\n * javascript, where the natural way to say \"do not publish\"\n * is `false` — and `false === 0` is FALSE, so it published.\n * Same trap as the `__filter__` guard below. */\n continue;\n }\n }\n let subscriber = kw_get_pointer(publisher, subs, \"subscriber\", null, kw_flag_t.KW_REQUIRED);\n if(!(subscriber && !gobj_is_destroying(subscriber))) {\n continue;\n }\n\n /*\n * Check if event null or event in event_list\n */\n let subs_flag = kw_get_int(publisher, subs, \"subs_flag\", 0, kw_flag_t.KW_REQUIRED);\n let event_ = kw_get_str(publisher, subs, \"event\", \"\", kw_flag_t.KW_REQUIRED);\n if(empty_string(event_) || strcasecmp(event_, event)===0) {\n let __config__ = kw_get_dict(publisher, subs, \"__config__\", null, 0);\n let __global__ = kw_get_dict(publisher, subs, \"__global__\", null, 0);\n let __local__ = kw_get_dict(publisher, subs, \"__local__\", null, 0);\n let __filter__ = kw_get_dict_value(publisher, subs, \"__filter__\", null, 0);\n\n /*\n * Check renamed_event\n */\n// TODO review const char *event_name = sdata_read_str(subs, \"renamed_event\");\n// if(empty_string(event_name)) {\n// event_name = event;\n// }\n\n /*\n * Duplicate the kw to publish if not shared\n * NOW always shared\n */\n let kw2publish = kw;\n\n /*-------------------------------------*\n * User filter method or filter parameter\n * Return:\n * -1 (broke),\n * 0 continue without publish,\n * 1 continue and publish\n *-------------------------------------*/\n let topublish = 1;\n if(publisher.gclass.gmt.mt_publication_filter) {\n topublish = publisher.gclass.gmt.mt_publication_filter(\n publisher,\n event,\n kw2publish, // not owned\n subscriber\n );\n } else if(json_size(__filter__)>0) {\n /* `kw_match_simple()` answers a BOOLEAN, and what is\n * compared below is `topublish === 0`. `false === 0` is\n * FALSE in javascript, so a filter that did not match fell\n * straight through the guard and published anyway: the\n * trace said 👎 and the subscriber got the event all the\n * same. Normalize to the 1/0 the contract is written in\n * (-1 break, 0 skip, 1 publish), which is what the C side\n * passes around. */\n topublish = kw_match_simple(kw2publish , __filter__) ? 1 : 0;\n if(tracea) {\n trace_machine(sprintf(\n \"💜💜🔄%s publishing with filter, event '%s', subscriber'%s', publisher %s\",\n topublish?\"👍\":\"👎\",\n event?event:\"\",\n gobj_short_name(subscriber),\n gobj_short_name(publisher)\n ));\n trace_json(__filter__);\n }\n }\n\n if(topublish<0) {\n break;\n } else if(!topublish) {\n /*\n * Must not be published\n * Next subs\n *\n * `!topublish` and not `=== 0`: a filter or an\n * mt_publication_filter that answers `false` means the same\n * as 0, and a strict comparison with the number let it\n * through.\n */\n continue;\n }\n\n /*\n * Check if System event: don't send it if subscriber has not it\n */\n let ev_ = gobj_event_type(subscriber, event, true);\n if(ev_) {\n if(ev_.event_flag & event_flag_t.EVF_SYSTEM_EVENT) {\n if(!gobj_has_event(subscriber, ev_.event_name, 0)) {\n continue;\n }\n }\n }\n\n /*\n * Remove local keys\n */\n if(__local__) {\n kw_pop(kw2publish,\n __local__ // not owned\n );\n }\n\n /*\n * Apply transformation filters\n * TODO review, I think it was used only from c_agent\n */\n if(__config__) {\n// json_t *jn_trans_filters = kw_get_dict_value(\n// publisher, __config__, \"__trans_filter__\", 0, 0\n// );\n// if(jn_trans_filters) {\n// kw2publish = apply_trans_filters(publisher, kw2publish, jn_trans_filters);\n// }\n }\n\n /*\n * Add global keys\n */\n if(__global__) {\n json_object_update(kw2publish, __global__);\n }\n\n /*\n * Send event\n */\n if(tracea) {\n if(__trace_machine_format__ === 1) {\n /* The event as PUBLISHED and the one the subscriber is\n * sent, which a `__rename_event_name__` can make\n * different -- the C kernel prints both, and the pair is\n * the only place the rename is visible. */\n trace_machine(sprintf(\"🔝🔄 %s (%s) %s%s\",\n event?event:\"\",\n event?event:\"\",\n (!subscriber.running)?\"!!\":\"\",\n gobj_short_name(subscriber)\n ));\n } else {\n trace_machine(sprintf(\"🔝🔄 mach(%s%s), st: %s, ev: %s, from(%s%s)\",\n (!subscriber.running)?\"!!\":\"\",\n gobj_short_name(subscriber),\n gobj_current_state(subscriber),\n event?event:\"\",\n (publisher && !publisher.running)?\"!!\":\"\",\n gobj_short_name(publisher)\n ));\n }\n if(__trace_gobj_ev_kw__(publisher) && json_object_size(kw2publish)) {\n trace_json(kw2publish);\n }\n }\n\n let ret_ = gobj_send_event(\n subscriber,\n event,\n kw2publish,\n publisher\n );\n if(ret_ < 0 && (subs_flag & subs_flag_t.__own_event__)) {\n sent_count = -1; // Return of -1 indicates that someone owned the event\n break;\n }\n ret += ret_;\n sent_count++;\n\n if(gobj_is_destroying(publisher)) {\n /*\n * break all, self publisher deleted\n */\n break;\n }\n }\n }\n\n if(!sent_count) {\n if(!ev || !(ev.event_flag & event_flag_t.EVF_NO_WARN_SUBS)) {\n log_warning(`${gobj_short_name(publisher)}: Publish event WITHOUT subscribers, ev ${event}`);\n // if(__trace_gobj_ev_kw__(publisher)) {\n // if(json_object_size(kw)) {\n // gobj_trace_json(publisher, kw, \"Publish event WITHOUT subscribers\");\n // }\n // }\n }\n }\n\n return ret;\n}\n\n/************************************************************\n * Exec gobj command. Return a webix\n ************************************************************/\nfunction gobj_command(gobj, command, kw, src)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n /*-----------------------------------------------*\n * Trace\n *-----------------------------------------------*/\n let tracea = is_commands_tracing(gobj) ||\n (is_machine_tracing(gobj, null) && !is_machine_not_tracing(src, null));\n if(tracea) {\n trace_machine(sprintf(\"🌀🌀 mach(%s%s), cmd: %s, src: %s\",\n (!gobj_is_running(gobj))?\"!!\":\"\",\n gobj_short_name(gobj),\n command,\n gobj_short_name(src)\n ));\n if(__trace_gobj_ev_kw__(gobj)) {\n trace_json(kw);\n }\n }\n\n /*-----------------------------------------------*\n * The local mt_command_parser has preference\n *-----------------------------------------------*/\n if(gobj.gclass.gmt.mt_command_parser) {\n return gobj.gclass.gmt.mt_command_parser(gobj, command, kw, src);\n }\n\n /*-----------------------------------------------*\n * If it has command_table\n * then use the global command parser\n *-----------------------------------------------*/\n if(gobj.gclass.command_table) {\n if(__global_command_parser_fn__) {\n return __global_command_parser_fn__(gobj, command, kw, src);\n } else {\n return build_command_response(\n gobj,\n -1, // result\n sprintf(\"%s: global command parser not available\", gobj_short_name(gobj)), // jn_comment\n 0, // jn_schema\n 0 // jn_data\n );\n }\n } else {\n return build_command_response(\n gobj,\n -1, // result\n sprintf(\"%s: command table not available\",gobj_short_name(gobj)), // jn_comment\n 0, // jn_schema\n 0 // jn_data\n );\n }\n}\n\n/************************************************************\n * Exec gobj stats. Return a webix\n ************************************************************/\nfunction gobj_stats(gobj, stats, kw, src)\n{\n if(gobj_is_destroying(gobj)) {\n log_error(\"gobj NULL or DESTROYED\");\n return -1;\n }\n\n /*--------------------------------------*\n * The local mt_stats has preference\n *--------------------------------------*/\n if(gobj.gclass.gmt.mt_stats) {\n return gobj.gclass.gmt.mt_stats(gobj, stats, kw, src);\n }\n\n /*-----------------------------------------------*\n * Then use the global stats parser\n *-----------------------------------------------*/\n if(__global_stats_parser_fn__) {\n return __global_stats_parser_fn__(gobj, stats, kw, src);\n } else {\n return build_stats_response(\n gobj,\n -1, // result\n sprintf(\"%s, stats parser not available\", gobj_short_name(gobj)),// jn_comment\n 0, // jn_schema\n 0 // jn_data\n );\n }\n}\n\n\n//=======================================================================\n// Expose the class via the global object\n//=======================================================================\nexport {\n __yuno__,\n YUNETA_VERSION,\n data_type_t,\n sdata_flag_t,\n SDataDesc,\n SDATA,\n SDATACM,\n SDATACM2,\n SDATAPM,\n SDATAAUTHZ,\n SDATAPM0,\n SDATADF,\n SDATA_END,\n gobj_flag_t,\n gclass_flag_t,\n event_flag_t,\n walk_type_t,\n GObj,\n gobj_start_up,\n gobj_hsdata,\n gclass_create,\n gclass_unregister,\n gclass_add_state,\n gclass_add_ev_action,\n gclass_event_type,\n gclass_add_event_type,\n gclass_check_fsm,\n gclass_find_by_name,\n gobj_services,\n gobj_default_service,\n gobj_find_service,\n gobj_load_persistent_attrs,\n gobj_save_persistent_attrs,\n gobj_remove_persistent_attrs,\n gobj_list_persistent_attrs,\n gobj_create2,\n gobj_create_yuno,\n gobj_create_service,\n gobj_create_default_service,\n gobj_create_volatil,\n gobj_create_pure_child,\n gobj_create,\n gobj_destroy,\n gobj_start,\n gobj_start_children,\n gobj_start_tree,\n gobj_stop,\n gobj_stop_children,\n gobj_stop_tree,\n gobj_play,\n gobj_pause,\n gobj_is_running,\n gobj_is_playing,\n gobj_is_service,\n gobj_yuno,\n gobj_yuno_name,\n gobj_yuno_role,\n gobj_yuno_id,\n gobj_name,\n gobj_gclass_name,\n gobj_short_name,\n trace_level_t,\n gobj_set_global_trace,\n gobj_set_global_no_trace,\n gobj_global_trace_level,\n gobj_global_trace_no_level,\n gobj_set_global_trace2,\n gobj_set_global_no_trace2,\n gobj_get_global_trace_level,\n gobj_get_global_trace_no_level,\n gobj_get_gclass_trace_level,\n gobj_get_gclass_trace_level2,\n gobj_get_gclass_trace_no_level,\n gobj_set_gclass_trace,\n gobj_set_gobj_trace,\n gobj_set_gclass_no_trace,\n gobj_set_gobj_no_trace,\n gobj_set_deep_trace,\n gobj_trace_level,\n gobj_trace_no_level,\n gobj_repr_global_trace_levels,\n gobj_set_trace_machine_format,\n gobj_trace_machine_format,\n gobj_full_name,\n gobj_parent,\n gobj_is_volatil,\n gobj_is_pure_child,\n gobj_is_destroying,\n gobj_bottom_gobj,\n gobj_set_bottom_gobj,\n gobj_walk_gobj_children,\n gobj_walk_gobj_children_tree,\n gobj_find_gobj,\n gobj_match_gobj,\n gobj_find_child,\n gobj_match_children,\n gobj_match_children_tree,\n gobj_search_path,\n gobj_has_attr,\n gobj_read_attr,\n gobj_read_attrs,\n gobj_write_attr,\n gobj_write_attrs,\n gobj_read_bool_attr,\n gobj_read_integer_attr,\n gobj_read_str_attr,\n gobj_read_pointer_attr,\n gobj_write_bool_attr,\n gobj_write_integer_attr,\n gobj_write_str_attr,\n gobj_reset_volatil_attrs,\n gobj_change_state,\n gobj_current_state,\n gobj_change_parent,\n\n gobj_has_event,\n gobj_has_output_event,\n gobj_post_event,\n gobj_posted_events_size,\n gobj_deliver_posted_events,\n gobj_send_event,\n\n gobj_subscribe_event,\n gobj_unsubscribe_event,\n gobj_unsubscribe_list,\n gobj_find_subscriptions,\n gobj_list_subscriptions,\n gobj_find_subscribings,\n gobj_publish_event,\n gobj_command,\n gobj_stats,\n};\n","/*********************************************************************************\n * Helper functions\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025, ArtGins.\n *********************************************************************************/\nimport {\n GObj,\n gobj_short_name,\n} from \"./gobj.js\";\n\nimport {sprintf} from \"./sprintf.js\";\n\nconst kw_flag_t = Object.freeze({\n KW_REQUIRED : 0x0001, // Log error message if not exist.\n KW_CREATE : 0x0002, // Create if not exist\n KW_WILD_NUMBER : 0x0004, // For numbers work with real/int/bool/string without error logging\n KW_EXTRACT : 0x0008, // Extract (delete) the key on read from dictionary.\n KW_BACKWARD : 0x0010, // Search backward in lists or arrays\n KW_VERBOSE : 0x0020, //\n KW_LOWER : 0x0040, //\n KW_RECURSIVE : 0x0080, //\n});\n\nconst json_type = Object.freeze({\n JSON_OBJECT: 1,\n JSON_ARRAY: 2,\n JSON_STRING: 3,\n JSON_INTEGER: 4,\n JSON_REAL: 5,\n JSON_TRUE: 6,\n JSON_FALSE: 7,\n JSON_NULL: 8\n});\n\n/************************************************************\n * log function\n ************************************************************/\n\n/********************************************\n * Log functions\n ********************************************/\n/* jshint node: true */\nconst _console = typeof window !== \"undefined\" ? window.console : console;\nlet f_error = _console.error;\nlet f_warning = _console.warn;\nlet f_info = _console.info;\nlet f_debug = _console.debug;\n\n/* Optional sink that mirrors every framework log line (error / warning /\n * info / debug / msg) somewhere else — e.g. a GUI dev monitor that shows the\n * browser console inside the app. It runs IN ADDITION to the console; null\n * (default) leaves behaviour unchanged. Called as (level, msg, hora).\n * CONTRACT: `msg` is a string for every text level, EXCEPT level \"json\"\n * (trace_json payloads), where it is the raw object so the sink can\n * pretty-print it — a sink must handle both. */\nlet __log_callback__ = null;\n\n/* The lines the log helpers wrote since the page loaded, bounded. A sink is\n * installed by application code, well after the first lines are written\n * (gobj_start_up, the yuno, the first services): without this, a monitor\n * would start mid-way through what the browser console shows whole. A new\n * sink is handed this backlog first, so both show the same session. A json\n * line is kept as text, because the object it came from goes on changing. */\nconst LOG_BACKLOG_MAX = 600;\nconst __log_backlog__ = [];\n\nfunction keep_in_backlog(level, msg, hora)\n{\n let m = msg;\n if(level === \"json\") {\n try {\n m = JSON.stringify(msg);\n } catch(e) {\n m = String(msg);\n }\n }\n __log_backlog__.push([level, m, hora]);\n if(__log_backlog__.length > LOG_BACKLOG_MAX) {\n __log_backlog__.shift();\n }\n}\n\nfunction set_log_callback(fn)\n{\n fn = (typeof fn === \"function\") ? fn : null;\n if(fn && fn !== __log_callback__) {\n /* The same sink installed again (an app that re-applies its dev\n * setup) is not replayed to, or it would see every line twice. */\n __log_callback__ = fn;\n for(const [level, m, hora] of __log_backlog__.slice()) {\n let msg = m;\n if(level === \"json\") {\n try {\n msg = JSON.parse(m);\n } catch(e) {\n msg = m;\n }\n }\n __deliver_log__(level, msg, hora);\n }\n return;\n }\n __log_callback__ = fn;\n}\n\n/* Master switch for the DIRECT browser-console writes of the log helpers\n * (log_error/log_warning/log_info/log_debug, trace_msg, trace_json).\n * Default on: the framework logs to the console as it always has. A GUI dev\n * monitor can turn it off to route output to its own window only (see\n * gobj-ui's yui_dev.js \"Output\" selector). Orthogonal to everything else:\n * the log-sink callback (set_log_callback) still fires — so the monitor keeps\n * receiving lines while the console stays clean — and remote log functions\n * (set_remote_log_functions) still fire too. */\nlet __console_output_enabled__ = true;\n\nfunction set_console_log_enabled(enabled)\n{\n __console_output_enabled__ = enabled ? true : false;\n}\n\n/* A per-LINE say over the console writes, on top of the master switch above.\n * `fn(level, msg)` returns true to let the line through; null (default)\n * lets everything through, which is the behaviour there has always been.\n *\n * It exists because the console write happens BEFORE the log sink is\n * called, so nothing downstream can un-print a line: a consumer that wants\n * to silence a class of lines on the console -- gobj-ui's dev monitor\n * silencing the timer traffic of the `machine` trace, which is two lines a\n * second for ever -- has no way to do it except here. The alternative was\n * for the monitor to turn this console off entirely and reprint everything\n * itself, which duplicates the format of every helper below.\n *\n * It filters the CONSOLE only. The log sink still receives every line, so a\n * monitor keeps its own complete record and decides separately what to show. */\nlet __console_log_filter__ = null;\n\nfunction set_console_log_filter(fn)\n{\n __console_log_filter__ = (typeof fn === \"function\") ? fn : null;\n}\n\n/* Does the console want this line? A filter that throws is ignored: a\n * broken one must never be able to silence the log. */\nfunction console_wants(level, msg)\n{\n if(!__console_output_enabled__) {\n return false;\n }\n if(!__console_log_filter__) {\n return true;\n }\n try {\n return __console_log_filter__(level, msg) ? true : false;\n } catch(e) {\n return true;\n }\n}\n\nlet __in_log_callback__ = false;\n\nfunction emit_log_callback(level, msg, hora)\n{\n if(__in_log_callback__) {\n return; /* a line logged BY the sink is not part of the session */\n }\n keep_in_backlog(level, msg, hora);\n __deliver_log__(level, msg, hora);\n}\n\nfunction __deliver_log__(level, msg, hora)\n{\n if(__log_callback__ && !__in_log_callback__) {\n /* Re-entrancy guard: a sink that itself logs (directly or through any\n * framework helper) must not loop back into itself. */\n __in_log_callback__ = true;\n try {\n /* Pass msg as-is: text levels already send a string; \"json\" sends\n * the raw object so the sink can pretty-print it. */\n __log_callback__(level, msg, hora);\n } catch(e) {\n /* A broken sink must never break the framework's own logging. */\n } finally {\n __in_log_callback__ = false;\n }\n }\n}\n\nfunction set_remote_log_functions(remote_log_fn)\n{\n if(remote_log_fn) {\n f_error = remote_log_fn;\n f_warning = remote_log_fn;\n } else {\n f_error = _console.error;\n f_warning = _console.warn;\n }\n}\n\nfunction format_log(format)\n{\n const args = Array.prototype.slice.call(arguments);\n let output = \"\";\n\n if (typeof format === 'string') {\n let i = 1;\n output = format.replace(/%[sdifoO]/g, match => {\n const val = args[i++];\n switch (match) {\n case '%s': return String(val);\n case '%d':\n case '%i': return parseInt(val);\n case '%f': return parseFloat(val);\n case '%o':\n case '%O':\n return typeof val === 'object' ? JSON.stringify(val) : String(val);\n default: return match;\n }\n });\n\n // Append any remaining arguments (e.g. raw objects or extra messages)\n const rest = args.slice(i).map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg) : String(arg)\n );\n\n if (rest.length > 0) {\n output += \" \" + rest.join(\" \");\n }\n } else {\n // If no format string, join all args\n output = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg) : String(arg)\n ).join(\" \");\n }\n\n return output;\n}\n\nfunction log_error(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_error) {\n if(f_error === _console.error) {\n if(console_wants(\"error\", msg)) {\n f_error(\"%c\" + hora + \" ERROR: \" + String(msg), \"color:red\");\n }\n } else {\n if(console_wants(\"error\", msg)) {\n _console.error(\"%c\" + hora + \" ERROR: \" + String(msg), \"color:red\");\n }\n f_error(`${hora} ERROR: ${String(msg)}`);\n }\n }\n emit_log_callback(\"error\", msg, hora);\n}\n\nfunction log_warning(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_warning) {\n if(f_warning === _console.warn) {\n if(console_wants(\"warning\", msg)) {\n f_warning(\"%c\" + hora + \" WARNING: \" + String(msg), \"color:yellow\");\n }\n } else {\n if(console_wants(\"warning\", msg)) {\n _console.warn(\"%c\" + hora + \" WARNING: \" + String(msg), \"color:yellow\");\n }\n f_warning(`${hora} WARNING: ${String(msg)}`);\n }\n }\n emit_log_callback(\"warning\", msg, hora);\n}\n\nfunction log_info(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_info) {\n if(console_wants(\"info\", msg)) {\n f_info(\"%c\" + hora + \" INFO: \" + String(msg), \"color:cyan\");\n }\n }\n emit_log_callback(\"info\", msg, hora);\n}\n\nfunction log_debug(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_debug) {\n if(console_wants(\"debug\", msg)) {\n f_debug(\"%c\" + hora + \" DEBUG: \" + String(msg), \"color:silver\");\n }\n }\n emit_log_callback(\"debug\", msg, hora);\n}\n\nfunction trace_msg(format)\n{\n let msg = format_log(format);\n let hora = current_timestamp();\n\n if(f_debug) {\n if(console_wants(\"msg\", msg)) {\n f_debug(\"%c\" + hora + \" MSG: \" + String(msg), \"color:cyan\");\n }\n }\n emit_log_callback(\"msg\", msg, hora);\n}\n\nfunction trace_json(jn, msg)\n{\n if(console_wants(\"json\", msg)) {\n if(msg) {\n _console.warn(\"=====> \" + msg);\n }\n _console.dir(jn);\n }\n /* Also mirror it to the log sink (e.g. the dev monitor) so the payload\n * shows next to the trace that dumped it — console.dir stays in the\n * browser console only. */\n emit_log_callback(\"json\", jn, current_timestamp());\n}\n\n/************************************************************\n * Duplicate an object (new references)\n * using the modern structuredClone (Deep copy of a single object)\n ************************************************************/\nfunction json_deep_copy(obj) // old __duplicate__,\n{\n return structuredClone(obj); // jshint ignore:line\n}\n\n/************************************************************\n * Duplicate objects (new references) in a new object\n * using the modern structuredClone\n ************************************************************/\nfunction duplicate_objects(...sourceObjects)\n{\n const result = {};\n for (const obj of sourceObjects) {\n const clonedObj = structuredClone(obj); // jshint ignore:line\n Object.assign(result, clonedObj); // Merge into the result object\n }\n return result;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction json_is_identical(kw1, kw2)\n{\n if(kw1 === kw2) {\n return true;\n }\n if(kw1 === null || kw2 === null) {\n return kw1 === kw2;\n }\n if(typeof kw1 !== typeof kw2) {\n return false;\n }\n if(Array.isArray(kw1) !== Array.isArray(kw2)) {\n return false;\n }\n if(Array.isArray(kw1)) {\n if(kw1.length !== kw2.length) {\n return false;\n }\n for(let i = 0; i < kw1.length; i++) {\n if(!json_is_identical(kw1[i], kw2[i])) {\n return false;\n }\n }\n return true;\n }\n if(typeof kw1 === \"object\") {\n let keys1 = Object.keys(kw1).sort();\n let keys2 = Object.keys(kw2).sort();\n if(keys1.length !== keys2.length) {\n return false;\n }\n for(let i = 0; i < keys1.length; i++) {\n if(keys1[i] !== keys2[i]) {\n return false;\n }\n if(!json_is_identical(kw1[keys1[i]], kw2[keys2[i]])) {\n return false;\n }\n }\n return true;\n }\n return kw1 === kw2;\n}\n\n/************************************************************\n * Extend a dict with another dict (NOT recursive),\n * adding new keys and overwriting existing keys.\n ************************************************************/\nfunction json_object_update(destination, source) // old __extend_dict__\n{\n if(!source) {\n return destination;\n }\n for (let property of Object.keys(source)) {\n destination[property] = source[property];\n }\n return destination;\n}\n\n/************************************************************\n * Update a dict with another dict:\n * ONLY existing items!! (NOT recursive)\n ************************************************************/\nfunction json_object_update_existing(destination, source) // old __update_dict__\n{\n if(!source) {\n return destination;\n }\n for (let property in source) {\n if(source.hasOwnProperty(property) && destination.hasOwnProperty(property)) {\n destination[property] = source[property];\n }\n }\n return destination;\n}\n\n/************************************************************\n * Update a dict with another dict:\n * ONLY missing items!! (NOT recursive)\n ************************************************************/\nfunction json_object_update_missing(destination, source)\n{\n if(!source) {\n return destination;\n }\n for (let property in source) {\n if(source.hasOwnProperty(property) && !destination.hasOwnProperty(property)) {\n destination[property] = source[property];\n }\n }\n return destination;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_get(o, key)\n{\n if(o && o.hasOwnProperty(key)) {\n return o[key];\n }\n return undefined;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_del(o, k)\n{\n if(o && o.hasOwnProperty(k)) {\n delete o[k];\n }\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_set(o, k, v)\n{\n o[k] = v;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_object_set_new(o, k, v)\n{\n o[k] = v;\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_get(a, i)\n{\n if(!is_array(a)) {\n return undefined;\n }\n return a[i];\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_append(a, v)\n{\n a.push(v);\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_append_new(a, v)\n{\n a.push(v);\n}\n\n/************************************************************\n * Simulate jansson function\n ************************************************************/\nfunction json_array_remove(a, idx)\n{\n a.splice(idx, 1);\n}\n\n/************************************************************\n * Extend array\n ************************************************************/\nfunction json_array_extend(destination, source) // old __extend_list__\n{\n if(!source) {\n return destination;\n }\n Array.prototype.push.apply(destination, source);\n return destination;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction json_object_size(a)\n{\n if(is_object(a)) {\n return Object.keys(a).length;\n }\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction json_array_size(a)\n{\n if(is_array(a)) {\n return a.length;\n }\n return 0;\n}\n\n/************************************************************\n * How much content a json carries: elements of a container,\n * 1 for a non-empty string, 0 for everything else\n * (null/undefined, scalars). C twin: json_size() in helpers.h.\n ************************************************************/\nfunction json_size(a)\n{\n if(is_object(a)) {\n return Object.keys(a).length;\n } else if(is_array(a)) {\n return a.length;\n } else if(is_string(a) && a.length > 0) {\n return 1;\n } else {\n return 0;\n }\n}\n\n/************************************************************\n * \"There is nothing usable here\": null/undefined, {}, [],\n * \"\" and any scalar. C twin: empty_json() in helpers.h,\n * where it is the guard to write instead of `if(!jn)` --\n * there an absent DTP_JSON is json_null(), a valid pointer.\n * Here `if(!x)` happens to work, and that difference is what\n * a port across the two runtimes gets wrong: write the same\n * question in both.\n *\n * The other question -- \"absent or explicitly null\", C's\n * json_absent() -- is is_null() here, since javascript has\n * no second null to tell apart.\n ************************************************************/\nfunction empty_json(a)\n{\n return json_size(a) === 0;\n}\n\n/************************************************************\n * json_equal (like jansson library)\n * Returns 1 if value1 and value2 are equal.\n * Returns 0 if they are unequal\n ************************************************************/\nfunction json_equal(json1, json2)\n{\n if (!json1 || !json2) {\n return 0;\n }\n\n if (json_typeof(json1) !== json_typeof(json2)) {\n return 0;\n }\n\n /* this covers true, false and null as they are singletons */\n if (json1 === json2) {\n return 1;\n }\n\n switch (json_typeof(json1)) {\n case json_type.JSON_OBJECT:\n return json_object_equal(json1, json2);\n case json_type.JSON_ARRAY:\n return json_array_equal(json1, json2);\n case json_type.JSON_STRING:\n return json_string_equal(json1, json2);\n case json_type.JSON_INTEGER:\n return json_integer_equal(json1, json2);\n case json_type.JSON_REAL:\n return json_real_equal(json1, json2);\n default:\n return 0;\n }\n}\n\nfunction json_object_equal(object1, object2) {\n let value2;\n\n if (json_object_size(object1) !== json_object_size(object2)) {\n return 0;\n }\n\n //json_object_foreach((json_t *)object1, key, value1) {\n for (const [key, value1] of Object.entries(object1)) {\n value2 = json_object_get(object2, key);\n\n if (!json_equal(value1, value2)) {\n return 0;\n }\n }\n\n return 1;\n}\n\nfunction json_array_equal(array1, array2) {\n let i, size;\n\n size = json_array_size(array1);\n if (size !== json_array_size(array2)) {\n return 0;\n }\n\n for (i = 0; i < size; i++) {\n let value1, value2;\n\n value1 = json_array_get(array1, i);\n value2 = json_array_get(array2, i);\n\n if (!json_equal(value1, value2)) {\n return 0;\n }\n }\n\n return 1;\n}\n\nfunction json_string_equal(string1, string2) {\n return string1 === string2?1:0;\n}\n\nfunction json_integer_equal(integer1, integer2) {\n return integer1 === integer2?1:0;\n}\n\nfunction json_real_equal(real1, real2) {\n return real1 === real2?1:0;\n}\n\nfunction json_typeof(jn)\n{\n if(is_object(jn)) {\n return json_type.JSON_OBJECT;\n }\n if(is_array(jn)) {\n return json_type.JSON_ARRAY;\n }\n if(is_string(jn)) {\n return json_type.JSON_STRING;\n }\n if(is_pure_number(jn)) {\n return json_type.JSON_INTEGER;\n }\n if(is_number(jn)) {\n return json_type.JSON_REAL;\n }\n if(is_boolean(jn)) {\n if(Boolean(jn)===true) {\n return json_type.JSON_TRUE;\n } else {\n return json_type.JSON_FALSE;\n }\n }\n if(is_null(jn)) {\n return json_type.JSON_NULL;\n }\n\n log_error(`Not a json type`);\n return 0;\n}\n\n/************************************************************\n * Return if a value is an object (excluding arrays & null)\n ************************************************************/\nfunction is_object(value) {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/************************************************************\n * Return if a value is an array\n ************************************************************/\nfunction is_array(value) {\n return Array.isArray(value);\n}\n\n/************************************************************\n * Return if a value is a string\n ************************************************************/\nfunction is_string(value) {\n return typeof value === \"string\";\n}\n\n/************************************************************\n * Return if a value is a number (excluding NaN & Infinity)\n ************************************************************/\nfunction is_number(value) {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n/************************************************************\n * Return if a value is a boolean\n ************************************************************/\nfunction is_boolean(value) {\n return typeof value === \"boolean\";\n}\n\n/************************************************************\n * Return if a value is null or undefined\n ************************************************************/\nfunction is_null(value) {\n return value == null; // Covers both `null` and `undefined`\n}\n\n/************************************************************\n * Check if a string is a number\n * The function correctly identifies both integer and floating-point numbers.\n * It handles special cases like scientific notation (e.g., \"1.2e3\"),\n * positive/negative numbers, and fractional numbers without leading digits.\n * It returns false for non-numeric strings, empty strings,\n * and strings with only whitespace.\n ************************************************************/\nfunction is_pure_number(str)\n{\n if(is_number(str)) {\n return true;\n }\n if(!is_string(str)) {\n return false;\n }\n\n // Convert the string to a number\n const num = Number(str);\n\n // Check if the result is NaN (Not-a-Number)\n if (isNaN(num)) {\n return false; // The string is not a number\n }\n\n // Optionally, you can check if the input is exactly equal to the parsed number\n // This ensures that the input is a valid number string\n return str.trim() !== '' && !isNaN(num);\n}\n\n/************************************************************\n * Return if a value is a Date object\n ************************************************************/\nfunction is_date(value) {\n return value instanceof Date && !isNaN(value);\n}\n\n/************************************************************\n * Return if a value is a function\n ************************************************************/\nfunction is_function(value) {\n return typeof value === \"function\";\n}\n\n/************************************************************\n * Return if a value is an instance of GObj\n ************************************************************/\nfunction is_gobj(value) {\n return value instanceof GObj;\n}\n\n/************************************************************\n * Return if a value is an empty string or not a string\n ************************************************************/\nfunction empty_string(value) {\n return !is_string(value) || value.length === 0;\n}\n\n/*\n * Converts a string to a bool.\n *\n * This conversion will:\n *\n * - match 'true', 'on', or '1' as true.\n * - ignore all white-space padding\n * - ignore capitalization (case).\n *\n * ' tRue ','ON', and '1 ' will all evaluate as true.\n *\n */\nfunction parseBoolean(s)\n{\n if(is_number(s)) {\n return Boolean(s);\n }\n\n // will match one and only one of the string 'true','1', or 'on' rerardless\n // of capitalization and regardless off surrounding white-space.\n //\n let regex=/^\\s*(true|1|on)\\s*$/i;\n\n return regex.test(s);\n}\n\n/************************************************************\n * Like C functions\n ************************************************************/\nfunction strncmp(str1, str2, lgth)\n{\n // Binary safe string comparison\n //\n // version: 909.322\n // discuss at: http://phpjs.org/functions/strncmp\n // + original by: Waldo Malqui Silva\n // + input by: Steve Hilder\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + revised by: gorthaur\n // + reimplemented by: Brett Zamir (http://brett-zamir.me)\n // * example 1: strncmp(\"aaa\", \"aab\", 2);\n // * returns 1: 0\n // * example 2: strncmp(\"aaa\", \"aab\", 3 );\n // * returns 2: -1\n var s1 = (str1+\"\").substring(0, lgth);\n var s2 = (str2+\"\").substring(0, lgth);\n\n return ( ( s1 === s2 ) ? 0 : ( ( s1 > s2 ) ? 1 : -1 ) );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strcmp(str1, str2)\n{\n // http://kevin.vanzonneveld.net\n // + original by: Waldo Malqui Silva\n // + input by: Steve Hilder\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + revised by: gorthaur\n // * example 1: strcmp( \"waldo\", \"owald\" );\n // * returns 1: 1\n // * example 2: strcmp( \"owald\", \"waldo\" );\n // * returns 2: -1\n\n return ( ( str1 === str2 ) ? 0 : ( ( str1 > str2 ) ? 1 : -1 ) );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strcasecmp(str1, str2)\n{\n // http://kevin.vanzonneveld.net\n // + original by: Waldo Malqui Silva\n // + input by: Steve Hilder\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + revised by: gorthaur\n // * example 1: strcmp( \"waldo\", \"owald\" );\n // * returns 1: 1\n // * example 2: strcmp( \"owald\", \"waldo\" );\n // * returns 2: -1\n let s1 = str1.toLowerCase();\n let s2 = str2.toLowerCase();\n\n return ( ( s1 === s2 ) ? 0 : ( ( s1 > s2 ) ? 1 : -1 ) );\n}\n\n/***************************************************************************\n Only compare str/int/real/bool items\n Complex types are done as matched\n Return lower, iqual, higher (-1, 0, 1), like strcmp\n***************************************************************************/\nfunction cmp_two_simple_json(jn_var1, jn_var2)\n{\n /*\n * Discard complex types, done as matched\n */\n if(is_object(jn_var1) ||\n is_object(jn_var2) ||\n is_array(jn_var1) ||\n is_array(jn_var2)) {\n return 0;\n }\n\n /*\n * First try number\n */\n if(is_number(jn_var1) || is_number(jn_var2)) {\n let val1 = Number(jn_var1);\n let val2 = Number(jn_var2);\n if(val1 > val2) {\n return 1;\n } else if(val1 < val2) {\n return -1;\n } else {\n return 0;\n }\n }\n\n /*\n * Try boolean\n */\n if(is_boolean(jn_var1) || is_boolean(jn_var2)) {\n let val1 = Number(jn_var1);\n let val2 = Number(jn_var2);\n if(val1 > val2) {\n return 1;\n } else if(val1 < val2) {\n return -1;\n } else {\n return 0;\n }\n }\n\n /*\n * Try string\n */\n let val1 = String(jn_var1);\n let val2 = String(jn_var2);\n return strcmp(val1, val2);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strstr(haystack, needle, bool)\n{\n // Finds first occurrence of a string within another\n //\n // version: 1103.1210\n // discuss at: http://phpjs.org/functions/strstr\n // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // + bugfixed by: Onno Marsman\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n // * example 1: strstr(‘Kevin van Zonneveld’, ‘van’);\n // * returns 1: ‘van Zonneveld’\n // * example 2: strstr(‘Kevin van Zonneveld’, ‘van’, true);\n // * returns 2: ‘Kevin ‘\n // * example 3: strstr(‘name@example.com’, ‘@’);\n // * returns 3: ‘@example.com’\n // * example 4: strstr(‘name@example.com’, ‘@’, true);\n // * returns 4: ‘name’\n var pos = 0;\n\n haystack += \"\";\n pos = haystack.indexOf(needle);\n if (pos === -1) {\n return false;\n } else {\n if (bool) {\n return haystack.substring(0, pos);\n } else {\n return haystack.slice(pos);\n }\n }\n}\n\n/***************************************************************************\n * Metadata key (variable) has a prefix of 2 underscore\n ***************************************************************************/\nfunction is_metadata_key(key)\n{\n if(!is_string(key)) {\n return false;\n }\n let i;\n for(i = 0; i < key.length; i++) {\n if (key[i] !== '_') {\n break;\n }\n if(i > 2) {\n break;\n }\n }\n return (i === 2);\n}\n\n/***************************************************************************\n * Private key (variable) has a prefix of 1 underscore\n ***************************************************************************/\nfunction is_private_key(key)\n{\n if(!is_string(key)) {\n return false;\n }\n let i;\n for(i = 0; i < key.length; i++) {\n if (key[i] !== '_') {\n break;\n }\n if(i > 2) {\n break;\n }\n }\n return (i === 1);\n}\n\n/************************************************************\n * Remove from `kw1` all keys in `kw2`.\n * `kw2` can be a string, object, or array.\n ************************************************************/\nfunction kw_pop(kw1, kw2)\n{\n if (typeof kw2 === \"object\" && !Array.isArray(kw2)) {\n // If kw2 is an object, remove its keys from kw1\n for (const key of Object.keys(kw2)) {\n delete kw1[key];\n }\n } else if (Array.isArray(kw2)) {\n // If kw2 is an array, recursively remove each element from kw1\n for (const item of kw2) {\n kw_pop(kw1, item);\n }\n } else if (typeof kw2 === \"string\") {\n // If kw2 is a string, remove it as a key from kw1\n delete kw1[kw2];\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_has_key(kw, key)\n{\n if(key in kw) {\n if (kw.hasOwnProperty(key)) {\n return true;\n }\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_find_path(gobj, kw, path, verbose)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n if(!(is_object(kw) || is_array(kw))) {\n log_error(`${gobj_short_name(gobj)}: kw must be list or dict`);\n return 0;\n }\n if(!is_string(path)) {\n log_error(`${gobj_short_name(gobj)}: path must be a string: ${String(path)}`);\n return 0;\n }\n let ss = path.split('`');\n if(ss.length<=1) {\n return kw[path];\n }\n let len = ss.length;\n for(let i=0; i<len; i++) {\n let key = ss[i];\n kw = kw[key];\n if(kw === undefined) {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: path not found: ${String(path)}`);\n }\n return undefined;\n }\n }\n return kw;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strrchr_split(str, char)\n{\n let index = str.lastIndexOf(char);\n if(index === -1) {\n return [str, \"\"]; // If char is not found, return whole string as first part and empty second part\n }\n return [str.substring(0, index), str.substring(index + 1)];\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_delete(gobj, kw, path)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let [path_, k] = strrchr_split(path, '`');\n if(!empty_string(k)) {\n let v = kw_find_path(gobj, kw, path_, true);\n json_object_del(v, k);\n } else {\n json_object_del(kw, path);\n }\n return 0;\n}\n\n/************************************************************\n * As the C kw_get_bool(): a boolean found is the answer, and\n * anything else gives the default back, LOGGED (\"path MUST BE a\n * json boolean\", required or not) -- unless KW_WILD_NUMBER asks\n * to read a number (0 is false), a string (\"true\"/\"false\" in any\n * case, else its integer) or null (false); a list or a dict is\n * then false, logged too. Before gobj-js 7.25.2 the value went\n * through Boolean(), so \"false\" was TRUE; before 7.25.3 a value\n * of the wrong type gave the default back in silence.\n ************************************************************/\nfunction kw_get_bool(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let b = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n const wild = flag && (flag & kw_flag_t.KW_WILD_NUMBER);\n\n if(b === undefined) {\n if(create) {\n let v = Boolean(default_value);\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return Boolean(default_value);\n }\n\n let value;\n if(is_boolean(b)) {\n value = b;\n } else if(wild && is_number(b)) {\n value = (b !== 0);\n } else if(wild && is_string(b)) {\n if(b.toLowerCase() === \"true\") {\n value = true;\n } else if(b.toLowerCase() === \"false\") {\n value = false;\n } else {\n value = (parseInt(b) || 0) !== 0;\n }\n } else if(wild && b === null) {\n value = false;\n } else if(wild) {\n log_error(`${gobj ? gobj_short_name(gobj) + \": \" : \"\"}` +\n `path MUST BE a simple json element: '${path}'`);\n trace_json(kw);\n return false;\n } else {\n log_error(`${gobj ? gobj_short_name(gobj) + \": \" : \"\"}` +\n `path MUST BE a json boolean: '${path}'`);\n trace_json(kw);\n return Boolean(default_value);\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n return value;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_int(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = parseInt(default_value);\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return parseInt(default_value);\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n if(!is_number(v)) {\n if(required) {\n log_error(`path value MUST BE a number: ${path}`);\n trace_msg(kw);\n }\n return parseInt(default_value);\n }\n\n return parseInt(v);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_real(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = Number(default_value);\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return Number(default_value);\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n if(!is_number(v)) {\n if(required) {\n log_error(`path value MUST BE a number: ${path}`);\n trace_msg(kw);\n }\n return Number(default_value);\n }\n\n return Number(v);\n}\n\n/************************************************************\n * The default comes back AS GIVEN, as in the C kw_get_str()\n * (`const char *default_value`, where 0 is NULL). Turned into\n * a string, a default of 0 or null was \"0\" or \"null\", which is\n * TRUE: an `if(value)` on the answer took an absent key for a\n * present one. KW_CREATE stores a string default, and null for\n * any other, as C stores json_null() for a NULL default.\n ************************************************************/\nfunction kw_get_str(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n kw_set_dict_value(gobj, kw, path,\n is_string(default_value)? default_value : null);\n return default_value;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n if(!is_string(v)) {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE a string: ${path}`);\n trace_msg(kw);\n }\n return default_value;\n }\n\n return v;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_pointer(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = default_value;\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n * As the C kw_get_dict(): a dict found is the answer, and\n * anything else gives the default back AS GIVEN (null stays\n * null). KW_CREATE stores a dict default, never a null one.\n * Before gobj-js 7.25.2 the answer went through Object(), so a\n * null default came back as {} and a 0 as a Number object.\n ************************************************************/\nfunction kw_get_dict(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create && is_object(default_value) && kw) {\n kw_set_dict_value(gobj, kw, path, default_value);\n return default_value;\n }\n if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(!is_object(v)) {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE a dict: ${path}`);\n trace_msg(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_get_dict_value(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create) {\n let v = default_value;\n kw_set_dict_value(gobj, kw, path, v);\n return v;\n\n } else if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n * As the C kw_get_list(): a list found is the answer, and\n * anything else gives the default back AS GIVEN. KW_CREATE\n * stores a list default, never a null one. Before gobj-js\n * 7.25.2 the answer went through Array(), which WRAPS its\n * argument: a list found came back as [list], a default of []\n * as [[]] and a null one as [null].\n ************************************************************/\nfunction kw_get_list(gobj, kw, path, default_value, flag)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n let v = kw_find_path(gobj, kw, path, false);\n\n const required = flag && (flag & kw_flag_t.KW_REQUIRED);\n const create = flag && (flag & kw_flag_t.KW_CREATE);\n const extract = flag && (flag & kw_flag_t.KW_EXTRACT);\n\n if(v === undefined) {\n if(create && is_array(default_value) && kw) {\n kw_set_dict_value(gobj, kw, path, default_value);\n return default_value;\n }\n if(required) {\n log_error(`path not found: '${path}'`);\n trace_json(kw);\n }\n return default_value;\n }\n\n if(!is_array(v)) {\n if(required) {\n log_error(`${gobj_short_name(gobj)}: path value MUST BE an array: ${path}`);\n trace_msg(kw);\n }\n return default_value;\n }\n\n if(extract) {\n kw_delete(gobj, kw, path);\n }\n\n return v;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_set_dict_value(gobj, kw, path, value)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n if(!is_object(kw)) {\n log_error(\"kw is not an object\");\n return -1;\n }\n\n let ss = path.split('`');\n if(ss.length<=1) {\n kw[path] = value;\n return 0;\n }\n\n let len = ss.length;\n for(let i=0; i<len; i++) {\n let key = ss[i];\n if(i === len-1) {\n /* last segment */\n kw[key] = value;\n\n } else {\n let seg = kw[key];\n if(seg === undefined) {\n kw[key] = {};\n }\n kw = kw[key];\n }\n }\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction kw_set_subdict_value(gobj, kw, path, key, value)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n\n if(!is_object(kw)) {\n log_error(\"kw is not an object\");\n return -1;\n }\n\n let subdict = kw_get_dict(gobj, kw, path, {}, kw_flag_t.KW_CREATE);\n if(!is_object(subdict)) {\n log_error(\"subdict is not an object\");\n return -1;\n }\n subdict[key] = value;\n\n return 0;\n}\n\n/***************************************************************************\n Match a json dict with a json filter (only compare str/number)\n ***************************************************************************/\nfunction _kw_match_simple(\n kw, // not owned\n jn_filter, // owned\n prefix_path\n)\n{\n let path = \"\";\n let matched = false;\n\n if(is_array(jn_filter)) {\n // Empty array evaluate as false, until a match condition occurs.\n matched = false;\n for(let idx = 0; idx < jn_filter.length; idx++) {\n let jn_filter_value = jn_filter[idx];\n /*\n * Complex variable, recursive\n */\n if(empty_string(prefix_path)) {\n path = sprintf(\"%s\", prefix_path);\n } else {\n path = sprintf(\"%s`%d\", prefix_path, idx);\n }\n\n matched = _kw_match_simple(\n kw, // not owned\n jn_filter_value, // owned\n path\n );\n if(matched) {\n break;\n }\n }\n\n } else if(is_object(jn_filter)) {\n // Object evaluate as true, until a NOT match condition occurs.\n matched = true;\n let keys = Object.keys(jn_filter);\n for(let i=0; i<keys.length; i++) {\n let key = keys[i];\n let jn_filter_value = jn_filter[key];\n if(empty_string(prefix_path)) {\n path = sprintf(\"%s\", key);\n } else {\n path = sprintf(\"%s`%s\", prefix_path, key);\n }\n\n if(is_array(jn_filter_value) || is_object(jn_filter_value)) {\n /*\n * Complex variable, recursive\n */\n matched = _kw_match_simple(\n kw, // not owned\n jn_filter_value, // owned\n path\n );\n if(!matched) {\n break;\n }\n continue;\n }\n\n /*\n * Get the record value, firstly by path else by name\n */\n // Firstly try the key as pointers\n let jn_record_value = kw_get_dict_value(0, kw, path, 0, 0);\n if(!jn_record_value) {\n // Secondly try the key with points (.) as full key\n jn_record_value = json_object_get(kw, path);\n }\n if(!jn_record_value) {\n matched = false;\n break;\n }\n\n /*\n * Do simple operation\n */\n let cmp = cmp_two_simple_json(jn_record_value, jn_filter_value);\n if(cmp!==0) {\n matched = false;\n break;\n }\n }\n }\n\n return matched;\n}\n\n/***************************************************************************\n Match a json dict with a json filter (only compare str/number)\n ***************************************************************************/\nfunction kw_match_simple(\n kw, // not owned\n jn_filter // owned\n)\n{\n if(json_size(jn_filter)===0) {\n // No filter, or an empty object or empty array evaluates as true.\n return true;\n }\n\n return _kw_match_simple(kw, jn_filter, \"\");\n}\n\n/***************************************************************************\n Get a the idx of simple json item in a json list.\n Return -1 if not found\n ***************************************************************************/\nfunction kw_find_json_in_list(\n gobj,\n kw_list,\n item,\n flag\n)\n{\n if(!item || !is_array(kw_list)) {\n if(flag) {\n log_error(`item NULL or kw_list is not a list`);\n }\n return -1;\n }\n\n for(let i=0; i<kw_list.length; i++) {\n let jn_item = kw_list[i];\n if(json_is_identical(item, jn_item)) {\n return i;\n }\n }\n\n if(flag) {\n log_error(`item not found in this list`);\n }\n return -1;\n}\n\n/*************************************************************\n Being `kw` a row's list or list of dicts [{},...],\n return a new list of **duplicated** kw filtering the rows by `jn_filter` (where),\n If match_fn is 0 then kw_match_simple is used.\n *************************************************************/\nfunction kw_select(gobj, kw, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!kw) {\n return null;\n }\n if(!match_fn) {\n match_fn = kw_match_simple;\n }\n let kw_new = [];\n\n if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let jn_value = kw[i];\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(json_deep_copy(jn_value));\n }\n }\n } else if(is_object(kw)) {\n if(match_fn(kw, jn_filter)) {\n kw_new.push(json_deep_copy(kw));\n }\n } else {\n log_error(\"kw_select() BAD kw parameter\");\n return null;\n }\n\n return kw_new;\n}\n\n/*************************************************************\n Being `kw` a row's list or list of dicts [{},...],\n return a new list of incref (clone) kw filtering the rows by `jn_filter` (where)\n If match_fn is 0 then kw_match_simple is used.\n *************************************************************/\nfunction kw_collect(gobj, kw, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!kw) {\n return null;\n }\n if(!match_fn) {\n match_fn = kw_match_simple;\n }\n let kw_new = [];\n\n if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let jn_value = kw[i];\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(jn_value);\n }\n }\n } else if(is_object(kw)) {\n if(match_fn(kw, jn_filter)) {\n kw_new.push(kw);\n }\n } else {\n log_error(\"kw_select() BAD kw parameter\");\n return null;\n }\n\n return kw_new;\n}\n\n/*************************************************************\n Return a new kw only with the keys got by dict's keys or list's keys (strings).\n Keys:\n \"$key\"\n [\"$key1\", \"$key2\", ...]\n {\"$key1\":*, \"$key2\":*, ...}\n\n It's not a deep copy, new keys are the paths.\n If paths are empty return kw\n *************************************************************/\nfunction kw_clone_by_keys(gobj, kw, keys, verbose) // old filter_dict\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let kw_clone = {};\n if(is_string(keys) && !empty_string(keys)) {\n let key = keys;\n if(kw.hasOwnProperty(key)) {\n kw_clone[key] = kw[key];\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n } else if(is_object(keys) && json_object_size(keys)>0) {\n for(let key of Object.keys(keys)) {\n if(kw.hasOwnProperty(key)) {\n kw_clone[key] = kw[key];\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else if(is_array(keys) && json_array_size(keys)>0) {\n for(let j=0; j<keys.length; j++) {\n let key = keys[j];\n if(kw.hasOwnProperty(key)) {\n kw_clone[key] = kw[key];\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else {\n return kw;\n }\n return kw_clone;\n}\n\n/***************************************************************************\n Return a new kw except the keys got by dict's keys or list's keys (strings).\n Keys:\n \"$key\"\n [\"$key1\", \"$key2\", ...]\n {\"$key1\":*, \"$key2\":*, ...}\n\n It's not a deep copy, new keys are the paths.\n If paths are empty return empty\n ***************************************************************************/\nfunction kw_clone_by_not_keys(\n gobj,\n kw,\n keys,\n verbose\n)\n{\n let kw_clone = {};\n json_object_update(kw_clone, kw);\n\n if(is_string(keys) && !empty_string(keys)) {\n let key = keys;\n let jn_value = kw_get_dict_value(gobj, kw, key, 0, 0);\n if(jn_value) {\n json_object_del(kw_clone, key);\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n } else if(is_object(keys) && json_object_size(keys)>0) {\n for(let key of Object.keys(keys)) {\n if(kw.hasOwnProperty(key)) {\n json_object_del(kw_clone, key);\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else if(is_array(keys) && json_array_size(keys)>0) {\n for(let j=0; j<keys.length; j++) {\n let key = keys[j];\n if(kw.hasOwnProperty(key)) {\n json_object_del(kw_clone, key);\n } else {\n if(verbose) {\n log_error(`${gobj_short_name(gobj)}: key not found: ${key}`);\n }\n }\n }\n } else {\n return {};\n }\n\n return kw_clone;\n}\n\n/********************************************\n * Get a local attribute\n ********************************************/\nfunction kw_get_local_storage_value(key, default_value, create = false)\n{\n if (typeof window === \"undefined\" || !window.localStorage) {\n return undefined; // Avoid errors in Node.js\n }\n\n try {\n let value = window.localStorage.getItem(key);\n\n if (value === null) { // `null` means key doesn't exist\n if (create) {\n kw_set_local_storage_value(key, default_value);\n }\n return default_value;\n }\n\n return JSON.parse(value); // Try parsing JSON\n } catch (e) {\n window.console.warn(`Error reading localStorage key \"${key}\":`, e);\n return default_value;\n }\n}\n\n/********************************************\n * Save a local attribute\n *\n * Returns 0 on success, -1 when the value did NOT reach the store.\n * It used to return nothing and only console.warn, so every caller up the\n * chain (db_save_persistent_attrs -> gobj_save_persistent_attrs -> the app)\n * reported success on a store that had rejected the write: a full or blocked\n * localStorage (quota, private mode) silently discarded the change while the\n * UI showed it as saved.\n ********************************************/\nfunction kw_set_local_storage_value(key, value)\n{\n if (typeof window === \"undefined\" || !window.localStorage) {\n return 0; // No store outside the browser: not a failure\n }\n if (!key || value === undefined) {\n log_error(`kw_set_local_storage_value(): invalid key or value: key=${key}`);\n return -1;\n }\n\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n return 0;\n } catch (e) {\n log_error(`kw_set_local_storage_value(): cannot save \"${key}\" ` +\n `(storage full or blocked?): ${e && e.message ? e.message : e}`);\n return -1;\n }\n}\n\n/********************************************\n * Remove local attribute\n ********************************************/\nfunction kw_remove_local_storage_value(key)\n{\n if (typeof window === \"undefined\" || !window.localStorage) {\n return; // Prevents errors in Node.js\n }\n if (!key) {\n window.console.warn(`Invalid key for localStorage removal: ${key}`);\n return;\n }\n\n try {\n window.localStorage.removeItem(key);\n } catch (e) {\n window.console.warn(`Error removing localStorage key \"${key}\":`, e);\n }\n}\n\n/*************************************************************\n Utility for databases.\n Return true if `id` is in the list/dict/str `ids`\n *************************************************************/\nfunction kwid_match_id(ids, id)\n{\n if(is_null(ids) || is_null(id)) {\n // No filter: everything passes.\n return true;\n }\n\n if(is_array(ids)) {\n if(ids.length===0) {\n // An empty list at the first level evaluates as true.\n return true;\n }\n for(let i=0; i<ids.length; i++) {\n let value = ids[i];\n if(value === id) {\n return true;\n }\n }\n\n } else if(is_object(ids)) {\n if(Object.keys(ids).length===0) {\n // An empty object at the first level evaluates as true.\n return true;\n }\n for(let key in ids) {\n if(key === id) {\n return true;\n }\n }\n\n } else if(is_string(ids)) {\n if(ids === id) {\n return true;\n }\n }\n\n return false;\n}\n\n/*************************************************************\n Utility for databases.\n Being `kw` a:\n - list of strings [s,...]\n - list of dicts [{},...]\n - dict of dicts {id:{},...}\n return a NEW list holding the rows that match `ids` and the\n `jn_filter` (where). If match_fn is 0 then kw_match_simple is used.\n\n WARNING the LIST is new; its elements are THE SAME objects, not\n copies. The C twin increfs each one and says \"clone\", which this\n comment repeated for years: javascript has no refcount, so a write\n through a collected row writes into `kw`. Copy what you mean to\n modify.\n\n Returns null -- not an empty list -- for a `kw` that is neither a\n list nor a dict, so a caller that reads `.length` off the answer\n must check it first (kwid_find_one_record does).\n *************************************************************/\nfunction kwid_collect(gobj, kw, ids, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!kw) {\n return null;\n }\n if(!match_fn) {\n match_fn = kw_match_simple;\n }\n let kw_new = [];\n\n if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let jn_value = kw[i];\n\n let id;\n if(is_object(jn_value)) {\n id = kw_get_str(gobj, jn_value, \"id\", \"\", 0);\n } else if(is_string(jn_value)) {\n id = jn_value;\n } else {\n continue;\n }\n\n if(!kwid_match_id(ids, id)) {\n continue;\n }\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(jn_value);\n }\n }\n } else if(is_object(kw)) {\n for(let id of Object.keys(kw)) {\n let jn_value = kw[id];\n\n if(!kwid_match_id(ids, id)) {\n continue;\n }\n if(match_fn(jn_value, jn_filter)) {\n kw_new.push(jn_value);\n }\n }\n\n } else {\n log_error(\"kw_collect() BAD kw parameter\");\n return null;\n }\n\n return kw_new;\n}\n\n/*************************************************************\n Utility for databases.\n Return a dict from a \"dict of records\" or \"list of records\".\n WARNING the \"id\" of a dict's record is hardcoded to its key.\n Convention:\n - all arrays are lists of records (dicts) with \"id\" as primary key\n - delimiter is '`' and '.'\n If path is empty then use kw\n\n WARNING \"new\" is the C twin's word, where it means a new REFERENCE:\n handed a dict, both return THAT dict and not a copy of it. Only the\n list case builds something new, and even then the records inside it\n are the same objects.\n *************************************************************/\nfunction kwid_new_dict(gobj, kw, path)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let new_dict = {};\n if(!empty_string(path)) {\n kw = kw_find_path(gobj, kw, path);\n }\n if(is_object(kw)) {\n new_dict = kw;\n\n } else if(is_array(kw)) {\n for(let i=0; i<kw.length; i++) {\n let kv = kw[i];\n /* KW_REQUIRED, as the C twin passes: under the rule this\n * file serves -- the key of a data record is its `id` -- a\n * record without one is broken, and it used to be dropped\n * in silence. The dict then came back short, and nothing\n * said which row had gone or why. */\n let id = kw_get_str(gobj, kv, \"id\", \"\", kw_flag_t.KW_REQUIRED);\n if(!empty_string(id)) {\n new_dict[id] = kv;\n }\n }\n\n } else {\n log_error(`${gobj_short_name(gobj)} kwid_new_dict: data type unknown`);\n }\n\n return new_dict;\n}\n\n/*************************************************************\n Utility for databases.\n Return a list from a \"dict of records\" or \"list of records\".\n The NORMALIZING function of this family: whatever shape the data\n arrives in, what comes back is the shape a table indexed and\n sorted by `id` wants.\n Convention:\n - all arrays are lists of records (dicts) with \"id\" as primary key\n - delimiter is '`' and '.'\n If path is empty then use kw\n\n WARNING handed a DICT it writes each record's key into the record\n as its `id`, OVERWRITING one that differs -- in the source records,\n which it does not copy. That is the C twin's behaviour\n (`json_object_set_new(v, \"id\", ...)` in kwid.c) and it is the point:\n a dict keyed by id whose records disagree with their own key is\n exactly what this is for. Handed a LIST it returns that same list,\n untouched, as C returns a new reference to it.\n *************************************************************/\nfunction kwid_new_list(gobj, kw, path)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!empty_string(path)) {\n kw = kw_find_path(gobj, kw, path);\n }\n\n if(is_array(kw)) {\n return kw;\n }\n\n if(is_object(kw)) {\n let new_list = [];\n for(let id of Object.keys(kw)) {\n let record = kw[id];\n if(!is_object(record)) {\n log_error(\n `${gobj_short_name(gobj)} kwid_new_list: ` +\n `not a record: '${id}'`\n );\n continue;\n }\n record[\"id\"] = id; // WARNING id hardcoded, as in C\n new_list.push(record);\n }\n return new_list;\n }\n\n log_error(`${gobj_short_name(gobj)} kwid_new_list: wrong type for list`);\n return [];\n}\n\n/*************************************************************\n * Utility for databases. See kwid_collect parameters\n *************************************************************/\nfunction kwid_find_one_record(gobj, kw, ids, jn_filter, match_fn)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n let list = kwid_collect(gobj, kw, ids, jn_filter, match_fn);\n /* kwid_collect() answers null -- not an empty list -- for a kw that\n * is neither a list nor a dict, and for a kw that is missing\n * altogether. Reading `.length` off that is a TypeError thrown at\n * the caller, which is how a command answer with no data crashed a\n * view instead of finding nothing. */\n if(!list || list.length === 0) {\n return null;\n }\n return list[0];\n}\n\n/*************************************************************\n Utility for databases.\n Being `ids` a:\n\n \"$id\"\n\n {\n \"$id\": {\n \"id\": \"$id\",\n ...\n }\n ...\n }\n\n [\"$id\", ...]\n\n [\n \"$id\",\n {\n \"id\":$id,\n ...\n },\n ...\n ]\n\n return a list of all ids\n*************************************************************/\nfunction kwid_get_ids(gobj, ids)\n{\n if(gobj && !is_gobj(gobj)) {\n log_error(`GObj bad instanceof`);\n }\n if(!ids) {\n return [];\n }\n\n let new_ids = [];\n\n if(is_string(ids)) {\n /*\n \"$id\"\n */\n new_ids.push(ids);\n } else if(is_object(ids)) {\n /*\n {\n \"$id\": {\n \"id\": \"$id\",\n ...\n }\n ...\n }\n */\n for(let id in ids) {\n if (ids.hasOwnProperty(id)) {\n new_ids.push(id);\n }\n }\n } else if(is_array(ids)) {\n ids.forEach(function(item) {\n if(is_string(item)) {\n /*\n [\"$id\", ...]\n */\n if(!empty_string(item)) {\n new_ids.push(item);\n }\n } else if(is_object(item)) {\n /*\n [\n {\n \"id\":$id,\n ...\n },\n ...\n ]\n */\n let id = kw_get_str(gobj, item, \"id\", 0, 0);\n if(id) {\n new_ids.push(id);\n }\n }\n });\n }\n\n return new_ids;\n}\n\n/********************************************************\n * Convert [s] or [{}] or {}\n * in a webix list options:\n * [{id:\"\", value:\"\"}, ...]\n ********************************************************/\nfunction list2options(list, field_id, field_value)\n{\n field_id = field_id?field_id:\"id\";\n field_value = field_value?field_value:\"value\";\n\n let options = [];\n\n if(is_array(list)) {\n for(let i=0; i<list.length; i++) {\n let v = list[i];\n if(is_string(v)) {\n options.push({\n id: list[i],\n value: list[i]\n });\n } else if(is_object(v)) {\n let vv = {};\n if(!kw_has_key(v, field_id)) {\n /* If not exist, then get the first entry */\n if(json_size(v)>0) {\n field_id = Object.keys(v)[0];\n } else {\n log_error(\"list2options(): object without field id: \" + field_id);\n continue;\n }\n vv[\"id\"] = field_id;\n vv[\"value\"] = v[field_id];\n } else {\n if(!kw_has_key(v, field_value)) {\n /* If not exist, then get the first entry */\n if(json_size(v)>0) {\n field_value = Object.keys(v)[0];\n } else {\n log_error(\"list2options(): object without field value: \" + field_value);\n continue;\n }\n\n }\n vv[\"id\"] = v[field_id];\n vv[\"value\"] = v[field_value];\n }\n options.push(vv);\n\n } else {\n log_error(\"list2options(): case1 not implemented\");\n }\n }\n } else if(is_object(list)) {\n for(let k of Object.keys(list)) {\n options.push({\n id: k,\n value: k\n });\n }\n } else {\n log_error(\"list2options(): case2 not implemented\");\n }\n\n return options;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction id_index_in_obj_list(list, id) {\n if(!list) {\n return -1;\n }\n for(let i=0; i<list.length; i++) {\n if(list[i] && list[i].id === id) {\n return i;\n }\n }\n return -1;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction str_in_list(list, str, ignore_case)\n{\n if(!list || !str) {\n log_error(\"ERROR: str_in_list() list or str empty\");\n return false;\n }\n\n let len = list.length;\n\n if(ignore_case) {\n str = str.toLowerCase();\n\n for(let i = 0; i < len; i++) {\n let item = list[i];\n if(item && item.toLowerCase() === str) {\n return true;\n }\n }\n\n } else {\n for(let i = 0; i < len; i++) {\n if(list[i] === str) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction strs_in_list(list, strs, ignore_case)\n{\n if(!list) {\n log_error(\"ERROR: strs_in_list() list empty\");\n return false;\n }\n if(!strs) {\n log_error(\"ERROR: strs_in_list() str empty\");\n return false;\n }\n\n for(let i=0; i<strs.length; i++) {\n let str = strs[i];\n if(str_in_list(list, str, ignore_case)) {\n return true;\n }\n }\n return false;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction delete_from_list(list, elm)\n{\n for(let i=0; i<list.length; i++) {\n if(elm === list[i]) {\n list.splice(i, 1);\n return true;\n }\n }\n return false; // elm does not exist!\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_read_key(kw, key)\n{\n try {\n let __md_iev__ = kw[\"__md_iev__\"];\n if(__md_iev__) {\n return __md_iev__[key];\n }\n } catch (e) {\n return undefined;\n }\n return undefined;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_write_key(kw, key, value)\n{\n let __md_iev__ = kw[\"__md_iev__\"];\n if(!__md_iev__) {\n __md_iev__ = {};\n kw[\"__md_iev__\"] = __md_iev__;\n }\n __md_iev__[key] = value;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_push_stack(gobj, kw, stack, jn_data)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj is not a GObj`);\n return null;\n }\n if(!kw) {\n return;\n }\n\n let jn_stack = msg_iev_read_key(kw, stack);\n if(!jn_stack) {\n jn_stack = [];\n msg_iev_write_key(kw, stack, jn_stack);\n }\n try {\n // Code throwing an exception\n if(is_array(jn_stack)) {\n jn_stack.unshift(jn_data);\n }\n } catch(e) {\n log_error(e);\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_get_stack(gobj, kw, stack, verbose)\n{\n if(!is_gobj(gobj)) {\n log_error(`gobj is not a GObj`);\n return null;\n }\n if(!is_object(kw)) {\n log_error(`kw is not a dict`);\n return null;\n }\n\n let jn_stack = msg_iev_read_key(kw, stack);\n if(!jn_stack) {\n if(verbose) {\n log_error(`stack NOT FOUND: ${stack}`);\n }\n return null;\n }\n\n if(jn_stack.length === 0) {\n if(verbose) {\n log_error(`stack empty: ${stack}`);\n }\n return null;\n }\n return jn_stack[0];\n}\n\n/************************************************************\n *\n msg_type_list = [\n \"__identity__\", // Used in identity card\n \"__command__\", // Used in commands\n \"__stats__\", // Used in stats\n \"__subscribing__\", // Used in subscribing events\n \"__unsubscribing__\", // Used in unsubscribing events\n \"__message__\", // Used in messages\n\n \"__publishing__\",\n \"__query__\",\n \"__answer__\",\n \"__request__\",\n \"__response__\",\n \"__order__\",\n \"__poll__\",\n \"__first_shot__\"\n ];\n\n ************************************************************/\nfunction msg_iev_set_msg_type(\n gobj,\n kw,\n msg_type // empty string to delete the key\n)\n{\n if(!empty_string(msg_type)) {\n kw_set_subdict_value(gobj, kw, \"__md_iev__\", \"__msg_type__\", msg_type);\n } else {\n kw_delete(gobj, kw, \"__md_iev__`__msg_type__\");\n }\n return 0;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction msg_iev_get_msg_type(gobj, kw)\n{\n return kw_get_str(gobj, kw, \"__md_iev__`__msg_type__\", \"\", 0);\n}\n\n/************************************************************\n * Load json file from server\n ************************************************************/\nfunction _fileLoaded(xhr) {\n return xhr.status === 0 && xhr.responseText && xhr.responseURL.startsWith(\"file:\");\n}\nfunction load_json_file(url, on_success, on_error)\n{\n let req = new XMLHttpRequest();\n req.open(\"GET\", url, true);\n req.setRequestHeader(\"Accept\", \"application/json\");\n\n req.onreadystatechange = function () {\n if (req.readyState === 4) {\n if (req.status === 200 || _fileLoaded(req)) {\n try {\n let json = JSON.parse(req.responseText);\n on_success(json);\n } catch (error) {\n if (on_error) {\n log_error(`JSON parse status ${req.status}, error: ${error.message}`);\n on_error(req.status);\n }\n }\n } else {\n if (on_error) {\n on_error(req.status);\n }\n }\n }\n };\n\n req.send();\n}\n\n/************************************************************\n * Post http\n * function on_response(status, response_data)\n ************************************************************/\nfunction send_http_json_post(url, data, on_response) {\n\n let xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url);\n xhr.setRequestHeader(\"Accept\", \"application/json\");\n xhr.setRequestHeader(\"Content-Type\", \"application/json\");\n\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n on_response(xhr.status, xhr.responseText);\n }\n };\n xhr.send(data);\n}\n\n/************************************************************\n * callback (obj, key, value, full_path)\n ************************************************************/\nfunction _traverse_dict(obj, callback, full_path)\n{\n if(full_path === undefined || !is_string(full_path)) {\n full_path = \"\";\n }\n for (let key of Object.keys(obj)) {\n if(!obj.hasOwnProperty(key)) {\n continue;\n }\n let sufix = (full_path.length? '`':'') + key;\n full_path += sufix;\n\n callback.apply(this, [obj, key, obj[key], full_path]);\n\n if(is_object(obj[key])) {\n //going one step down in the object tree!!\n _traverse_dict(obj[key], callback, full_path);\n }\n\n full_path = full_path.slice(0, -sufix.length);\n }\n}\n\n/************************************************************\n * Init json database\n * Hierarchical tree. To use in webix style.\n * If a record has children,\n * the own record has the key 'data' with the array of child records\n *\n * Initialization\n * --------------\n var jdb = {\n \"type\": [], // Can be [] or {}\n \"hook\": \"data\",\n \"schema\": { // topics\n \"app_menu\": [],\n \"account_menu\": []\n }\n };\n\n jdb_init(jdb);\n\n *\n * Inside example\n * --------------\n * jdb: {\n * hook: \"data\",\n * type: []\n * schema:{\n * app_menu: [],\n * account_menu: [],\n * ...\n * }\n * topics: {\n * app_menu: [\n * {\n * id: // Mandatory field\n * icon: // Remains: optional fields\n * value:\n * action:\n * },\n * {\n * id:\n * icon:\n * value:\n * action:\n * data: [\n * {\n * id:\n * icon:\n * value:\n * action:\n * },\n *\n * ]\n * },\n * ...\n * ]\n * }\n * }\n ************************************************************/\nfunction jdb_init(jdb, prefix, duplicate)\n{\n if(duplicate) {\n jdb = json_deep_copy(jdb);\n }\n let type = kw_get_dict_value(null, jdb, \"type\", [], 1);\n let hook = kw_get_str(null, jdb, \"hook\", \"data\", 1);\n let schema = kw_get_dict_value(null, jdb, \"schema\", {}, 1);\n let topics = kw_get_dict_value(null, jdb, \"topics\", {}, 1);\n\n // Create topics defined in schema\n let walk = function(obj, key, value, full_path) {\n if(key.substring(0, 2) !== \"__\") {\n kw_get_dict_value(null, topics, full_path, json_deep_copy(type), 1);\n //trace_msg(sprintf(\"full_path: '%s', key: %s, value: %j\", full_path, key, value));\n }\n };\n _traverse_dict(schema, walk, prefix);\n\n return jdb;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_update(jdb, topic_name, path, kw)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_update: topic not found: \" + topic_name);\n return null;\n }\n if(empty_string(kw[\"id\"])) {\n log_error(\"jdb_update: record without id: \" + kw);\n trace_msg(kw);\n return null;\n }\n\n let ids = path.split('`');\n\n let id;\n let v = topic;\n while((id = ids.shift())) {\n if(empty_string(id) || !v) {\n break;\n }\n if(is_object(v)) {\n v = kw_get_dict_value(null, v, jdb.hook, [], 1);\n }\n v = _jdb_get(v, null, id, false);\n }\n\n if(ids.length===0 && v) {\n if(is_array(v)) {\n v.push(kw);\n } else {\n if(v[\"id\"]===kw[\"id\"]) {\n Object.assign(v, kw);\n } else {\n let v_ = kw_get_dict_value(null, v, jdb.hook, [], 1);\n let v__ = _jdb_get(v_, jdb.hook, kw[\"id\"], false);\n if(v__) {\n Object.assign(v__, kw);\n } else {\n v_.push(kw);\n }\n }\n }\n }\n\n //trace_msg(JSON.stringify(topic, null, 4));\n\n return topic;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_delete(jdb, topic_name, path, kw)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_delete: topic not found: \" + topic_name);\n return null;\n }\n if(empty_string(kw[\"id\"])) {\n log_error(\"jdb_delete: record without id: \" + kw);\n trace_msg(kw);\n return null;\n }\n\n let ids = path.split('`');\n\n let id;\n let v = topic;\n while((id = ids.shift())) {\n if(empty_string(id) || !v) {\n break;\n }\n if(is_object(v)) {\n v = kw_get_dict_value(null, v, jdb.hook, null, 0);\n }\n v = _jdb_get(v, null, id, false);\n }\n\n if(ids.length===0 && v) {\n if(is_array(v)) {\n let idx = id_index_in_obj_list(v, kw[\"id\"]);\n if(idx >= 0) {\n v.splice(idx, 1);\n }\n } else {\n let v_ = kw_get_dict_value(null, v, jdb.hook, null, 0);\n let idx = id_index_in_obj_list(v_, kw[\"id\"]);\n if(idx >= 0) {\n v_.splice(idx, 1);\n }\n }\n }\n\n //trace_msg(JSON.stringify(topic, null, 4));\n\n return topic;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_get_topic(jdb, topic_name)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0, false);\n if(!topics) {\n log_error(\"jdb topics section not found\");\n trace_msg(jdb);\n return null;\n }\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0, false);\n if(!topic) {\n log_error(\"jdb topic not found: \" + topic_name);\n trace_msg(topics);\n return null;\n }\n return topic;\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_get(jdb, topic_name, id, recursive)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_get: topic not found: \" + topic_name);\n return null;\n }\n if(recursive === undefined) {\n recursive = true;\n }\n return _jdb_get(topic, jdb.hook, id, recursive);\n}\n\n/********************************************\n *\n ********************************************/\nfunction jdb_get_by_idx(jdb, topic_name, idx)\n{\n let topics = kw_get_dict_value(null, jdb, \"topics\", null, 0);\n let topic = kw_get_dict_value(null, topics, topic_name, null, 0);\n if(!topic) {\n log_error(\"jdb_get_by_idx: topic not found: \" + topic_name);\n return null;\n }\n if(idx < topic.length) {\n return topic[idx];\n } else {\n return {};\n }\n}\n\n/**************************************************\n * Busca el id en el arbol.\n * Los id deben ser únicos, como requiere webix\n **************************************************/\nfunction _jdb_get(v, hook, id, recursive)\n{\n if(!v) {\n return null;\n }\n let j;\n let ln = v.length;\n for(j=0; j<ln; j++) {\n let v_ = v[j];\n if(v_) {\n let id_ = v_[\"id\"];\n if(id_ && (id_ === id)) {\n return v_;\n }\n if(recursive) {\n if(kw_has_key(v_, hook)) {\n let v__ = _jdb_get(v_[hook], hook, id, recursive);\n if(v__) {\n return v__;\n }\n }\n }\n }\n }\n return null;\n}\n\n/***************************************************************************\n *\n * type can be: str, int, real, bool, null, dict, list\n * Example:\n\n static json_desc_t jn_xxx_desc[] = {\n // Name Type Default\n {\"string\", \"str\", \"\"},\n {\"string2\", \"str\", \"Pepe\"},\n {\"integer\", \"int\", \"0660\"}, // beginning with \"0\":octal,\"x\":hexa, others: integer\n {\"boolean\", \"bool\", \"false\"},\n {0} // HACK important, final null\n };\n\n ***************************************************************************/\nfunction create_json_record(json_desc, value) // here in js `json_desc` it's a dictionary with the defaults.\n{\n let record = json_deep_copy(json_desc); // Get fields and default values from json_desc\n json_object_update_existing(record, value); // Update (only with service fields) with user data\n\n return record;\n}\n\n/************************************************************\n * https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library\n ************************************************************/\nfunction jwtDecode(jwt)\n{\n function b64DecodeUnicode(str) {\n return decodeURIComponent(atob(str).replace(/(.)/g, function (m, p) {\n let code = p.charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = '0' + code;\n }\n return '%' + code;\n }));\n }\n\n function decode(str) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw \"Illegal base64url string!\";\n }\n\n try {\n return b64DecodeUnicode(output);\n } catch (err) {\n return atob(output);\n }\n }\n\n let jwtArray = jwt.split('.');\n\n return {\n header: decode(jwtArray[0]),\n payload: decode(jwtArray[1]),\n signature: decode(jwtArray[2])\n };\n}\n\n/************************************************************\n * Decoded jwt and return in json\n * 'what' can be \"header\", \"payload\" or \"signature\"\n * default is \"payload\"\n ************************************************************/\nfunction jwt2json(jwt, what)\n{\n try {\n let jwt_decoded = jwtDecode(jwt);\n switch(what) {\n case \"header\":\n return JSON.parse(jwt_decoded.header);\n case \"signature\":\n return JSON.parse(jwt_decoded.signature);\n case \"payload\":\n default:\n return JSON.parse(jwt_decoded.payload);\n }\n } catch (e) {\n return null;\n }\n}\n\n/***************************************************************************\n * Escape a value for safe insertion into an HTML context.\n * Use this whenever user- or server-supplied strings are interpolated\n * into an innerHTML / style.innerHTML template literal.\n ***************************************************************************/\nfunction escapeHtml(str)\n{\n if(str == null) {\n return '';\n }\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n/***************************************************************************\n * Validate and escape a URL for use as an image/media src attribute.\n * Blocks javascript: and data: URIs that could be used for XSS.\n * Returns an empty string for any disallowed scheme.\n ***************************************************************************/\nfunction safeSrc(url)\n{\n if(!url) {\n return '';\n }\n const s = String(url).trim();\n if(/^javascript:/i.test(s) || /^data:/i.test(s)) {\n return '';\n }\n return escapeHtml(s);\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction createOneHtml(htmlString)\n{\n // Convert the HTML string to DOM nodes\n const template = document.createElement('template');\n template.innerHTML = htmlString.trim(); // Trim to avoid extra text nodes\n\n return template.content.firstChild;\n}\n\n/***************************************************************************\n * Code written by ChatGPT\n Example usage:\n\n function makeDraggable(handle, target) {\n let offsetX = 0;\n let offsetY = 0;\n\n // Called when the drag starts\n const onMouseDown = (e) => {\n // Calculate the initial offset\n offsetX = e.clientX - target.getBoundingClientRect().left;\n offsetY = e.clientY - target.getBoundingClientRect().top;\n\n // Attach the listeners to the document to allow for free movement\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseup', onMouseUp);\n };\n\n // Called when the mouse is moved\n const onMouseMove = (e) => {\n // Calculate the new position\n const x = e.clientX - offsetX;\n const y = e.clientY - offsetY;\n\n // Update the position of the target\n target.style.left = `${x}px`;\n target.style.top = `${y}px`;\n };\n\n // Called when the mouse button is released\n const onMouseUp = () => {\n // Remove the listeners from the document\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseup', onMouseUp);\n };\n\n // Attach the mousedown listener to the handle\n handle.addEventListener('mousedown', onMouseDown);\n }\n\n function addResizeFunctionality(resizeHandle, windowElement) {\n let startX, startY, startWidth, startHeight;\n\n const onMouseDown = (e) => {\n // Prevent default action (like text selection) during resize\n e.preventDefault();\n\n startX = e.clientX;\n startY = e.clientY;\n startWidth = parseInt(document.defaultView.getComputedStyle(windowElement).width, 10);\n startHeight = parseInt(document.defaultView.getComputedStyle(windowElement).height, 10);\n\n document.documentElement.addEventListener('mousemove', onMouseMove, false);\n document.documentElement.addEventListener('mouseup', onMouseUp, false);\n };\n\n const onMouseMove = (e) => {\n // Calculate new size\n const newWidth = startWidth + e.clientX - startX;\n const newHeight = startHeight + e.clientY - startY;\n\n // Update window size\n windowElement.style.width = `${newWidth}px`;\n windowElement.style.height = `${newHeight}px`;\n };\n\n const onMouseUp = () => {\n // Remove the listeners when resizing is done\n document.documentElement.removeEventListener('mousemove', onMouseMove, false);\n document.documentElement.removeEventListener('mouseup', onMouseUp, false);\n };\n\n // Attach the mousedown listener to the resize handle\n resizeHandle.addEventListener('mousedown', onMouseDown, false);\n }\n\n\n function createWindow({ title, x, y, width, height, parent }) {\n const windowEl = createElement2([\n 'div',\n {\n class: 'window',\n // style: `position: absolute; left: ${x}px; top: ${y}px; width: ${width}px; height: ${height}px; display: flex; flex-direction: column; border: 1px solid black;`\n style: {\n position: \"absolute\",\n left: `${x}px`,\n top: `${y}px`,\n width: `${width}px`,\n height: `${height}px`,\n display: \"flex\",\n \"flex-direction\": \"column\",\n border: \"1px solid black\",\n }\n },\n [\n ['div', { class: 'window-top', style: 'display: flex; justify-content: space-between; padding: 5px; border-bottom: 1px solid black;cursor:move;' },\n [\n ['span', {}, title],\n ['button', {}, 'Close', {\n click: (e) => {\n e.target.closest('.window').remove();\n }\n }]\n ]\n ],\n ['div', { class: 'window-content', style: 'flex-grow: 1; padding: 5px;' }, 'This is the content area.'],\n ['div', { class: 'window-bottom', style: 'padding: 5px; border-top: 1px solid black; display: flex; justify-content: flex-end;' },\n [\n ['div', { class: 'resize-handle', style: 'width: 20px; height: 20px; cursor: nwse-resize;' }, '', {\n mousedown: (e) => {\n // Resize logic here\n }\n }]\n ]\n ]\n ]\n ]);\n\n const resizeHandle = windowEl.querySelector('.resize-handle');\n\n makeDraggable(windowEl.querySelector('.window-top'), windowEl);\n addResizeFunctionality(resizeHandle, windowEl);\n\n parent.appendChild(windowEl);\n }\n\n\n // Example usage\n createWindow({\n title: 'My Draggable Window',\n x: 100,\n y: 100,\n width: 400,\n height: 300,\n parent: document.body\n });\n ***************************************************************************/\n\n\n/***************************************************************************\n * Create a HTMLElement:\n * [tag, attrs, content, events]\n *\n * tag -> string\n *\n * attrs -> {key:string}\n * Special case for key=='style'\n * could be `style:'string'`\n * or `style:{k:s}`\n * Special case for key=='i18n' (or 'data-i18n' or 'data_i18next')\n * will be 'data-i18n' attr\n *\n * content -> string | [createElement2() or parameters of createElement2]\n * if string begins with '<' then\n * it will be converted to HTMLElement\n * content = createOneHtml(string)\n * if attrs['i18n'] is not empty then (or 'data-i18n' or 'data_i18next')\n* it will be overridden with the translation\n * content = translate(attrs['i18n']));\n *\n * events -> {event: ()}\n *\n * Return the created element\n *\n * Examples:\n * ['div', { class: 'window-top', style: 'border-bottom: 1px solid black;' },\n * [\n * ['span', {}, 'title'],\n * ['button', {}, 'Close', {\n * click: (e) => {\n * e.target.closest('.window').remove();\n * }\n * }]\n * ]\n * ]\n *\n * ['span', {style: {position: 'absolute'} }, 'title'],\n *\n ***************************************************************************/\nfunction createElement2(description, translate_fn) {\n let [tag, attrs, content, events] = description;\n\n /*\n * Create the html element\n */\n if (!tag) {\n log_error(\"Tag must be a valid HTML element.\");\n return;\n }\n let el = document.createElement(tag);\n\n /*\n * Append attributes\n */\n let data_i18next = '';\n\n if(attrs && typeof attrs === 'object') {\n for (let attr of Object.keys(attrs)) {\n if (attr === 'style' && typeof attrs[attr] === 'object') {\n // Convert the style object to a CSS string\n let styleString = '';\n\n for(const prop of Object.keys(attrs[attr])) {\n styleString += `${prop}: ${attrs[attr][prop]};`;\n }\n el.style.cssText = styleString;\n } else if (attr === 'style') {\n el.style.cssText = attrs[attr];\n } else {\n if(attr === 'i18n' || attr === 'data-i18n' ||\n attr === 'data_i18next' || attr === 'data-i18next') {\n /*\n * A nullish i18n key would render the literal\n * data-i18n=\"undefined\" and block translation\n * (e.g. a field whose `header` is undefined).\n * Skip the attribute instead of poisoning it.\n * An explicit empty string is still honoured.\n */\n if(attrs[attr] !== null && attrs[attr] !== undefined) {\n data_i18next = attrs[attr];\n el.setAttribute('data-i18n', data_i18next);\n }\n } else {\n el.setAttribute(attr, attrs[attr]);\n }\n }\n }\n }\n\n /*\n * Append content, it can be a string or another kids\n */\n if(is_string(content)) {\n content = content.trim();\n if(content.length > 0 && content[0] === '<') {\n el.appendChild(createOneHtml(content));\n } else {\n if(translate_fn && data_i18next) {\n let translated = translate_fn(data_i18next);\n el.textContent = translated?translated:content;\n } else {\n el.textContent = content;\n }\n }\n } else if(is_array(content)) {\n if(content.length > 0) {\n if(is_string(content[0])) {\n el.appendChild(createElement2(content, translate_fn));\n } else {\n for (let child of content) {\n // Check if the child is an array description or an HTMLElement\n if (Array.isArray(child) && child.length > 0) {\n el.appendChild(createElement2(child, translate_fn));\n } else if (child instanceof HTMLElement) {\n el.appendChild(child);\n }\n }\n }\n }\n } else if(content instanceof HTMLElement ||\n content instanceof Text ||\n content instanceof SVGElement)\n {\n el.appendChild(content);\n } else {\n if(content != null) {\n log_error(\"content ignored\");\n trace_json(content);\n }\n }\n\n /*\n * Attach event listeners\n */\n if (events && typeof events === 'object') {\n for(const eventType of Object.keys(events)) {\n el.addEventListener(eventType, events[eventType]);\n }\n }\n\n return el;\n}\n\n/***************************************************************************\n * Code written by ChatGPT\n // Usage example:\n ***************************************************************************/\nfunction getPositionRelativeToBody(element)\n{\n if (!element) {\n return {\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n };\n }\n\n const { top, left, width, height } = element.getBoundingClientRect?.() || { top: 0, left: 0, width: 0, height: 0 };\n\n const isBrowser = typeof window !== \"undefined\";\n const scrollTop = isBrowser ? window.scrollY || document.documentElement?.scrollTop || document.body?.scrollTop || 0 : 0;\n const scrollLeft = isBrowser ? window.scrollX || document.documentElement?.scrollLeft || document.body?.scrollLeft || 0 : 0;\n\n return {\n top: top + scrollTop,\n left: left + scrollLeft,\n right: left + scrollLeft + width,\n bottom: top + scrollTop + height\n };\n}\n\n/***************************************************************************\n * Create SVG element from string code\n ***************************************************************************/\nfunction parseSVG(string)\n{\n return ((new DOMParser().parseFromString(string, 'image/svg+xml')).firstChild);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction refresh_language(element, t)\n{\n if(!is_function(t)) {\n log_error(\"You must supply a translation function\");\n return;\n }\n if(!element) {\n element = document;\n }\n\n /* `querySelectorAll` searches DESCENDANTS: it never returns the\n * element it was called on. So a caller that hands us the very\n * node carrying the key -- which is what happens whenever a widget\n * is built lazily and translated as a unit -- got its children\n * translated and its own attribute left in the source language.\n * Measured on the deployed shell: the toolbar's language dropdown\n * opened as role=\"menu\" aria-label=\"select language\" while its\n * trigger next to it said \"Elegir idioma\". Include the root. */\n const matching = (selector) => {\n let out = [];\n if(typeof element.matches === \"function\" && element.matches(selector)) {\n out.push(element);\n }\n out.push(...element.querySelectorAll(selector));\n return out;\n };\n\n matching('[data-i18n]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n');\n for(let node of elem.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if(!value) {\n value = node.nodeValue;\n }\n node.nodeValue = t(value);\n break; // Stop after updating the first text node\n }\n }\n });\n\n /* Translate the `title` attribute (hover tooltip) for any element\n * carrying `data-i18n-title=\"<canonical key>\"`. Used by lib-yui's\n * nav and toolbar renderers to keep tooltips in sync with the\n * active language, since refresh_language() above only touches\n * text-node content. */\n matching('[data-i18n-title]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n-title');\n if(value) {\n elem.setAttribute('title', t(value));\n }\n });\n\n /* Translate the `aria-label` attribute (assistive-tech name) for\n * any element carrying `data-i18n-aria-label=\"<canonical key>\"`.\n * Same contract as data-i18n-title above — emitted by lib-yui's\n * toolbar and nav renderers next to the static `aria-label` so\n * screen readers track language switches. */\n matching('[data-i18n-aria-label]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n-aria-label');\n if(value) {\n elem.setAttribute('aria-label', t(value));\n }\n });\n\n /* Translate the `placeholder` attribute (inputs/textareas) for\n * any element carrying `data-i18n-placeholder=\"<canonical key>\"`.\n * Same contract as data-i18n-title above — a placeholder is not a\n * text node, so the data-i18n walk cannot reach it. */\n matching('[data-i18n-placeholder]').forEach(function(elem) {\n let value = elem.getAttribute('data-i18n-placeholder');\n if(value) {\n elem.setAttribute('placeholder', t(value));\n }\n });\n}\n\n/************************************************************\n * Example Usage\n * const tracker = timeTracker(\"Track1\");\n * tracker.mark(\"Step 1\");\n * tracker.mark(\"Step 2\");\n ************************************************************/\nfunction timeTracker(tracker_name=\"Time Tracker\", verbose=false)\n{\n const name = tracker_name;\n const startTime = performance.now();\n let lastMarkTime = startTime;\n\n if(verbose) {\n log_warning(\n `--> ${name} - starting`\n );\n }\n\n return {\n mark: (label = \"Intermediate\", result=\"\") => {\n const currentTime = performance.now();\n const partial = (currentTime - lastMarkTime) / 1000;\n const total = (currentTime - startTime) / 1000;\n if(verbose) {\n log_warning(\n `--> ${name} ${label} - partial: ${partial} sec, total: ${total} sec, ${result}`\n );\n }\n lastMarkTime = currentTime;\n return {\n partial: partial,\n total: total\n };\n }\n };\n}\n\n/************************************************************\n * Get the current timestamp in ISO 8601 format with milliseconds and time zone.\n * Example Output: \"2024-02-24T14:05:30.123+0200\"\n ************************************************************/\nfunction current_timestamp(now)\n{\n now = now || new Date();\n const pad = (n, w) => String(n).padStart(w, \"0\");\n\n /* LOCAL time, because the offset written after it is the local one:\n * toISOString() is UTC, and \"UTC time +0200\" is a wall clock two\n * hours wrong for anyone reading it (C writes local time too). */\n const timestamp =\n `${now.getFullYear()}-${pad(now.getMonth() + 1, 2)}-${pad(now.getDate(), 2)}` +\n `T${pad(now.getHours(), 2)}:${pad(now.getMinutes(), 2)}:${pad(now.getSeconds(), 2)}`;\n const milliseconds = pad(now.getMilliseconds(), 3);\n\n // Time zone offset in ±HHMM format (getTimezoneOffset() is positive WEST of UTC)\n const offsetMinutes = now.getTimezoneOffset();\n const sign = offsetMinutes > 0 ? \"-\" : \"+\";\n const hours = pad(Math.floor(Math.abs(offsetMinutes) / 60), 2);\n const minutes = pad(Math.abs(offsetMinutes) % 60, 2);\n\n return `${timestamp}.${milliseconds}${sign}${hours}${minutes}`;\n}\n\n/********************************************\n * Return UTC time of right now\n ********************************************/\nfunction get_now()\n{\n return Math.floor(Date.now() / 1000);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction index_in_list(list, elm) {\n if(!list) {\n throw \"ERROR: index_in_list() list empty\";\n }\n for(let i=0; i<list.length; i++) {\n if(elm === list[i]) {\n return i;\n }\n }\n return -1;\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction node_uuid()\n{\n let uuid = \"\";\n\n if (typeof window !== \"undefined\" && window.localStorage) {\n uuid = window.localStorage.getItem(\"host_uuid\");\n if (!uuid && window.crypto?.randomUUID) {\n uuid = window.crypto.randomUUID(); // Generate a new UUID\n window.localStorage.setItem(\"host_uuid\", uuid);\n }\n } else if (typeof globalThis !== \"undefined\" && globalThis.crypto?.randomUUID) {\n uuid = globalThis.crypto.randomUUID(); // Node.js environment (if available)\n } else {\n uuid = \"00000000-0000-0000-0000-000000000000\"; // Fallback UUID (if crypto is unavailable)\n }\n\n return uuid;\n}\n\n/************************************************************\n * Build a cleaned name\n ************************************************************/\nfunction clean_name(name)\n{\n return name.replace(/[?# ^:]/g, '_');\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction get_function_name(func)\n{\n let fName = null;\n if (typeof func === \"function\" || typeof func === \"object\") {\n fName = (\"\" + func).match(/function\\s*([\\w\\$]*)\\s*\\(/);\n }\n if (fName !== null) {\n return fName[1] + \"()\";\n }\n return \"\";\n}\n\n/***************************************************************************\n * implement a debounce or throttle mechanism to limit the number\n * of times the callback function is executed\n\n const fn = debounce(() => window.console.log('Called!'), 1000);\n\n // Start debounce timer\n fn();\n\n // Execute immediately (if pending)\n fn.flush();\n\n // Cancel the pending call\n fn.cancel();\n\n ***************************************************************************/\nfunction debounce(func, wait = 0, immediate = false)\n{\n let timeout = null;\n let args = null;\n let context = null;\n\n const debounced = (..._args) => {\n context = this;\n args = _args;\n\n const later = () => {\n timeout = null;\n if (!immediate) {\n func.apply(context, args);\n }\n };\n\n const callNow = immediate && !timeout;\n\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n\n if (callNow) {\n func.apply(context, args);\n }\n };\n\n // Immediately invoke the pending function\n debounced.flush = () => {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n func.apply(context, args);\n }\n };\n\n // Cancel the pending execution\n debounced.cancel = () => {\n clearTimeout(timeout);\n timeout = null;\n args = null;\n context = null;\n };\n\n return debounced;\n}\n\n/************************************************************\n * Build a URL/path from segments, ensuring exactly one '/'\n * between each part.\n *\n * - The first segment keeps its leading '/' (absolute) or\n * not (relative).\n * - Trailing '/' is stripped from every segment.\n * - Leading '/' is stripped from every segment except the first.\n * - Empty/null/undefined segments are skipped.\n *\n * Mirrors the C helper build_path() from gobj-c/src/helpers.c.\n ************************************************************/\nfunction build_path(...segments)\n{\n let result = \"\";\n let i = 0;\n\n for(let segment of segments) {\n if(segment == null || segment === \"\") {\n continue;\n }\n segment = String(segment);\n\n if(i === 0) {\n // First segment: keep leading '/', strip trailing '/'\n segment = segment.replace(/\\/+$/, \"\");\n } else {\n // Subsequent segments: strip both leading and trailing '/'\n segment = segment.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n }\n\n if(segment === \"\") {\n continue;\n }\n\n if(i > 0) {\n result += \"/\";\n }\n result += segment;\n i++;\n }\n\n return result;\n}\n\n\n\n /***************************************\n * Flat json (id -> value)\n ***************************************/\n\n\n\n\n/************************************************************\n * THE FLAT FORM, AND WHY IT IS SHAPED LIKE THIS\n *\n * A json seen as a table: one row per LEAF, the id being the\n * PATH of the item and the value its value. Easier to store,\n * to compare and to diff than the nested form, and the only\n * one a person can read when two configurations disagree.\n *\n * {a: {b: 1}, c: [10, 20]}\n * -> {\"a`b\": 1, \"c`[0]\": 10, \"c`[1]\": 20}\n *\n * Same grammar as the C side (kwid.c), because the point is\n * that a flat json written by either can be read by the other:\n *\n * - segments joined by '`', the SDK's own path delimiter;\n * - a literal '`' in a key is DOUBLED, so no key is\n * forbidden -- a dict keyed by \"1630\" is a dict, not an\n * array of 1631 elements, which is what the first C\n * implementation answered;\n * - an array index is '[N]', canonical, no leading zeros;\n * - a dict key starting with '[' doubles it ('[[0]'), so it\n * can never be read as an index;\n * - AN EMPTY CONTAINER IS A LEAF: {} and [] hold no leaves,\n * and 'properties': {} is everywhere in our configs.\n *\n * flat2json() THROWS instead of guessing: an id used as leaf and\n * as container would depend on the order the ids are read in.\n ************************************************************/\nconst FLAT_MAX_DEPTH = 256;\nconst FLAT_MAX_INDEX = 100000;\n\n/************************************************************\n * Is this raw segment an array index, '[N]'?\n * Returns the index, or null.\n ************************************************************/\nfunction flat_seg_index(seg)\n{\n if(typeof seg !== \"string\" || seg.length < 3 || seg[0] !== \"[\") {\n return null;\n }\n if(seg[seg.length-1] !== \"]\") {\n return null;\n }\n const body = seg.slice(1, -1);\n if(!/^[0-9]+$/.test(body)) {\n return null;\n }\n if(body.length > 1 && body[0] === \"0\") {\n return null; // canonical: '[00]' is malformed, not a second '[0]'\n }\n return parseInt(body, 10);\n}\n\n/************************************************************\n * Escape one dict key.\n ************************************************************/\nfunction flat_escape_key(key)\n{\n const s = String(key).replace(/`/g, \"``\");\n return s[0] === \"[\" ? \"[\" + s : s;\n}\n\n/************************************************************\n * Compose a flat id from its segments.\n *\n * A STRING segment is a dict key and gets escaped; a NUMBER is\n * an array index and is written '[N]'. They are two types and\n * not two spellings: as strings, the key \"[0]\" and the index 0\n * would both be \"[0]\", which is the ambiguity '[N]' removes.\n ************************************************************/\nfunction flat_key_join(segments)\n{\n if(!Array.isArray(segments) || segments.length === 0) {\n return \"\";\n }\n return segments.map(\n (seg) => (typeof seg === \"number\" ? `[${seg}]` : flat_escape_key(seg))\n ).join(\"`\");\n}\n\n/************************************************************\n * Split a flat id into its segments, undoing the escapes.\n *\n * An index comes back as a NUMBER and a dict key as a STRING.\n ************************************************************/\nfunction flat_key_split(key)\n{\n if(typeof key !== \"string\") {\n return null;\n }\n\n let raw = [];\n let cur = \"\";\n for(let i = 0; i < key.length; i++) {\n if(key[i] === \"`\") {\n if(key[i+1] === \"`\") {\n cur += \"`\";\n i++;\n continue;\n }\n raw.push(cur);\n cur = \"\";\n continue;\n }\n cur += key[i];\n }\n raw.push(cur);\n\n /* Decide what each segment IS before undoing the bracket escape:\n * the other way round, '[[0]' would become '[0]' and read as an\n * index. */\n return raw.map((seg) => {\n const idx = flat_seg_index(seg);\n if(idx !== null) {\n return idx;\n }\n if(seg[0] === \"[\" && seg[1] === \"[\") {\n return seg.slice(1);\n }\n return seg;\n });\n}\n\n/************************************************************\n * Nested -> flat.\n ************************************************************/\nfunction json2flat(jn)\n{\n const flat = {};\n\n const walk = (value, path, depth) => {\n if(depth > FLAT_MAX_DEPTH) {\n throw new Error(`json2flat: deeper than ${FLAT_MAX_DEPTH}`);\n }\n if(value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const keys = Object.keys(value);\n if(keys.length > 0) {\n for(const key of keys) {\n const seg = flat_escape_key(key);\n walk(value[key], depth === 0 ? seg : path + \"`\" + seg, depth+1);\n }\n return;\n }\n } else if(Array.isArray(value) && value.length > 0) {\n value.forEach((child, index) => {\n const seg = `[${index}]`;\n walk(child, depth === 0 ? seg : path + \"`\" + seg, depth+1);\n });\n return;\n }\n /* A leaf: a scalar, or an EMPTY container, which has no leaves\n * of its own and would otherwise vanish. Depth, not the length\n * of the path: {\"\": 1} is a json whose only id is \"\". */\n if(depth === 0) {\n return; // a scalar root has no path\n }\n flat[path] = value;\n };\n\n if(jn === undefined || jn === null) {\n return flat;\n }\n walk(jn, \"\", 0);\n return flat;\n}\n\n/************************************************************\n * Flat -> nested. Throws on the FIRST id that does not fit:\n * rebuilding \"most of it\" is how a configuration comes back\n * subtly different from the one that was saved.\n ************************************************************/\nfunction flat2json(flat)\n{\n if(flat === null || typeof flat !== \"object\" || Array.isArray(flat)) {\n throw new Error(\"flat2json: a flat json is an object of id -> value\");\n }\n\n let root = null;\n\n for(const key of Object.keys(flat)) {\n const segments = flat_key_split(key);\n if(!segments || segments.length === 0) {\n throw new Error(`flat2json: malformed flat id: '${key}'`);\n }\n if(segments.length > FLAT_MAX_DEPTH) {\n throw new Error(`flat2json: '${key}' deeper than ${FLAT_MAX_DEPTH}`);\n }\n\n const first_is_index = (typeof segments[0] === \"number\");\n if(root === null) {\n root = first_is_index ? [] : {};\n } else if(first_is_index !== Array.isArray(root)) {\n throw new Error(\n `flat2json: '${key}' does not fit a ` +\n `${Array.isArray(root)? \"array\": \"object\"} root`\n );\n }\n\n let current = root;\n for(let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const is_index = (typeof seg === \"number\");\n const is_last = (i === segments.length - 1);\n const next_is_index = is_last? false: (typeof segments[i+1] === \"number\");\n\n if(is_index && seg > FLAT_MAX_INDEX) {\n throw new Error(\n `flat2json: array index ${seg} over the limit ` +\n `(${FLAT_MAX_INDEX}) in '${key}'`\n );\n }\n if(is_index !== Array.isArray(current)) {\n throw new Error(\n `flat2json: '${key}' uses a ${is_index? \"array index\": \"key\"} ` +\n `where the tree already has a ` +\n `${Array.isArray(current)? \"array\": \"object\"}`\n );\n }\n\n if(is_last) {\n if(Array.isArray(current)) {\n while(current.length <= seg) {\n current.push(null);\n }\n current[seg] = flat[key];\n } else {\n if(Object.prototype.hasOwnProperty.call(current, seg)) {\n throw new Error(\n `flat2json: '${key}' is written twice, or once as a ` +\n `value and once as a container`\n );\n }\n current[seg] = flat[key];\n }\n break;\n }\n\n let child;\n if(Array.isArray(current)) {\n while(current.length <= seg) {\n current.push(null);\n }\n child = current[seg];\n if(child === null || child === undefined) {\n child = next_is_index? []: {};\n current[seg] = child;\n }\n } else {\n child = current[seg];\n if(child === undefined) {\n child = next_is_index? []: {};\n current[seg] = child;\n }\n }\n\n if(child === null || typeof child !== \"object\") {\n throw new Error(\n `flat2json: '${key}' walks through a value: the same id is ` +\n `a leaf and a container at once`\n );\n }\n if(next_is_index !== Array.isArray(child)) {\n throw new Error(\n `flat2json: '${key}' needs a ${next_is_index? \"array\": \"object\"} ` +\n `where the tree already has a ` +\n `${Array.isArray(child)? \"array\": \"object\"}`\n );\n }\n current = child;\n }\n }\n\n return root === null ? {} : root;\n}\n\n/************************************************************\n * Deep equality, for comparing two leaf values.\n ************************************************************/\nfunction flat_value_equal(a, b)\n{\n if(a === b) {\n return true;\n }\n if(a === null || b === null || typeof a !== \"object\" || typeof b !== \"object\") {\n return false;\n }\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/************************************************************\n * What changed between two flat dicts:\n *\n * {added: {id: value}, removed: {id: value},\n * changed: {id: {from, to}}}\n ************************************************************/\nfunction flat_diff(flat1, flat2)\n{\n const a = (flat1 && typeof flat1 === \"object\")? flat1: {};\n const b = (flat2 && typeof flat2 === \"object\")? flat2: {};\n const diff = {added: {}, removed: {}, changed: {}};\n\n for(const key of Object.keys(a)) {\n if(!Object.prototype.hasOwnProperty.call(b, key)) {\n diff.removed[key] = a[key];\n } else if(!flat_value_equal(a[key], b[key])) {\n diff.changed[key] = {from: a[key], to: b[key]};\n }\n }\n for(const key of Object.keys(b)) {\n if(!Object.prototype.hasOwnProperty.call(a, key)) {\n diff.added[key] = b[key];\n }\n }\n\n return diff;\n}\n\n/************************************************************\n * Apply that diff to a flat dict, which is MUTATED.\n *\n * On the flat form on purpose: there an id addresses one value,\n * so applying is setting and deleting, with nothing to walk and\n * nothing to guess. Nested is json2flat -> flat_apply -> flat2json.\n ************************************************************/\nfunction flat_apply(flat, diff)\n{\n if(flat === null || typeof flat !== \"object\" || Array.isArray(flat)) {\n throw new Error(\"flat_apply: a flat json is an object of id -> value\");\n }\n if(diff === null || typeof diff !== \"object\") {\n throw new Error(\"flat_apply: a diff is the object flat_diff() answers\");\n }\n\n for(const key of Object.keys(diff.removed || {})) {\n delete flat[key];\n }\n for(const key of Object.keys(diff.added || {})) {\n flat[key] = diff.added[key];\n }\n for(const key of Object.keys(diff.changed || {})) {\n const change = diff.changed[key];\n if(!change || !Object.prototype.hasOwnProperty.call(change, \"to\")) {\n throw new Error(`flat_apply: changed '${key}' without a 'to'`);\n }\n flat[key] = change.to;\n }\n\n return flat;\n}\n\n\nexport {\n kw_flag_t,\n json_deep_copy,\n duplicate_objects,\n json_is_identical,\n json_object_update,\n json_object_update_existing,\n json_object_update_missing,\n json_object_get,\n json_object_set,\n json_object_set_new,\n json_object_del,\n json_array_append,\n json_array_append_new,\n json_array_remove,\n json_array_extend,\n json_object_size,\n json_array_size,\n json_size,\n empty_json,\n\n is_object,\n is_array,\n is_string,\n is_number,\n is_boolean,\n is_null,\n is_pure_number,\n is_date,\n is_function,\n is_gobj,\n\n parseBoolean,\n empty_string,\n strncmp,\n strcmp,\n strcasecmp,\n cmp_two_simple_json,\n strstr,\n\n is_metadata_key,\n is_private_key,\n kw_pop,\n kw_has_key,\n kw_find_path,\n kw_delete,\n kw_get_bool,\n kw_get_int,\n kw_get_real,\n kw_get_str,\n kw_get_pointer,\n kw_get_dict,\n kw_get_list,\n kw_get_dict_value,\n kw_set_dict_value,\n kw_set_subdict_value,\n kw_match_simple,\n kw_find_json_in_list,\n kw_select,\n kw_collect,\n kw_clone_by_keys,\n kw_clone_by_not_keys,\n\n kw_get_local_storage_value,\n kw_set_local_storage_value,\n kw_remove_local_storage_value,\n\n kwid_match_id,\n kwid_collect,\n kwid_new_dict,\n kwid_new_list,\n kwid_find_one_record,\n kwid_get_ids,\n list2options,\n\n id_index_in_obj_list,\n str_in_list,\n strs_in_list,\n delete_from_list,\n\n msg_iev_push_stack,\n msg_iev_get_stack,\n msg_iev_set_msg_type,\n msg_iev_get_msg_type,\n msg_iev_write_key,\n msg_iev_read_key,\n load_json_file,\n send_http_json_post,\n\n jdb_init,\n jdb_update,\n jdb_delete,\n jdb_get_topic,\n jdb_get,\n jdb_get_by_idx,\n\n create_json_record,\n\n set_remote_log_functions,\n set_log_callback,\n set_console_log_enabled,\n set_console_log_filter,\n log_error,\n log_warning,\n log_info,\n log_debug,\n trace_msg,\n trace_json,\n\n jwtDecode,\n jwt2json,\n\n escapeHtml,\n safeSrc,\n createOneHtml,\n createElement2,\n getPositionRelativeToBody,\n parseSVG,\n refresh_language,\n\n timeTracker,\n current_timestamp,\n get_now,\n index_in_list,\n node_uuid,\n clean_name,\n get_function_name,\n debounce,\n build_path,\n\n json2flat,\n flat2json,\n flat_key_join,\n flat_key_split,\n flat_diff,\n flat_apply,\n};\n","/*********************************************************************************\n * dbsimple.js\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025, ArtGins.\n *********************************************************************************/\n\nimport {\n kw_get_local_storage_value,\n kw_remove_local_storage_value,\n kw_set_local_storage_value,\n is_object,\n kw_clone_by_keys,\n json_object_update_missing,\n kw_clone_by_not_keys,\n json_object_size,\n} from \"./helpers.js\";\n\nimport {\n sdata_flag_t,\n gobj_read_attrs,\n gobj_short_name,\n gobj_write_attrs,\n} from \"./gobj.js\";\n\n/************************************************************\n *\n ************************************************************/\nfunction _get_persistent_path(gobj)\n{\n return \"persistent-attrs-\" + gobj_short_name(gobj);\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction db_load_persistent_attrs(\n gobj,\n keys // str, list or dict.\n)\n{\n let jn_attrs = gobj_read_attrs(gobj, sdata_flag_t.SDF_PERSIST, 0);\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n if(jn_file && is_object(jn_file)) {\n let attrs = kw_clone_by_keys(\n gobj,\n jn_file, // owned\n keys, // owned\n false\n );\n attrs = kw_clone_by_keys( // Remove attrs removed\n gobj,\n attrs, // owned\n jn_attrs, // owned\n false\n );\n\n gobj_write_attrs(gobj, attrs, sdata_flag_t.SDF_PERSIST, 0);\n }\n}\n\n/************************************************************\n * Returns 0 on success, -1 when the attrs did NOT reach the store\n * (quota exceeded, private mode, storage disabled). Callers must check\n * it: a discarded write with a UI that shows the value as saved is the\n * worst of both worlds.\n ************************************************************/\nfunction db_save_persistent_attrs(\n gobj,\n keys // str, list or dict.\n)\n{\n let jn_attrs = gobj_read_attrs(gobj, sdata_flag_t.SDF_PERSIST, 0);\n let attrs = kw_clone_by_keys(\n gobj,\n jn_attrs, // owned\n keys, // owned\n false\n );\n\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n if(jn_file && is_object(jn_file)) {\n json_object_update_missing(attrs, jn_file);\n }\n\n return kw_set_local_storage_value(\n _get_persistent_path(gobj),\n attrs\n );\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction db_remove_persistent_attrs(\n gobj,\n keys // str, list or dict.\n)\n{\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n\n let attrs = kw_clone_by_not_keys(\n gobj,\n jn_file,\n keys,\n false\n );\n\n if(json_object_size(attrs)===0) {\n kw_remove_local_storage_value(_get_persistent_path(gobj));\n } else {\n kw_set_local_storage_value(\n _get_persistent_path(gobj),\n attrs\n );\n }\n}\n\n/************************************************************\n *\n ************************************************************/\nfunction db_list_persistent_attrs(gobj, keys)\n{\n let jn_file = kw_get_local_storage_value(_get_persistent_path(gobj), null, false);\n let attrs = {};\n if(jn_file && is_object(jn_file)) {\n attrs = kw_clone_by_keys(\n gobj,\n jn_file, // owned\n keys, // owned\n false\n );\n }\n return attrs;\n}\n\n//=======================================================================\n// Expose the class via the global object\n//=======================================================================\nexport {\n db_load_persistent_attrs,\n db_save_persistent_attrs,\n db_remove_persistent_attrs,\n db_list_persistent_attrs,\n};\n","/***********************************************************************\n * ui_lib_treedb.js\n *\n * Treedb common helpers\n *\n * - El treedb center se registra,\n *\n * - Los formtable con treedb_name\n * se suscriben masivamente a las tablas de los hooks y fkeys.\n *\n * - Los hook se subscriben a todos las modificaciones-z de los hijos,\n * ( solo de los create y delete realmente, solo se necesita el id del que existe)\n * en cada una redefinirán sus option2list, así un padre puede cortar el link.\n * pero puede ser un proceso lento.\n *\n * - Los fkeys se subscriben a todas las modificaciones de los padres,\n * realmente solo se necesita a las creaciones y deletes de los registros de la tabla,\n * updates y link/unlink le da igual. Con cada publicación redefinirán sus option2list.\n *\n * OJO con los unsubscribe!! necesarios!\n *\n * El formtable publicará los eventos: CREATE_NODE, DELETE_NODE, UPDATE_NODE\n * en el UPDATE_NODE irá un reseteo/creación de los links.\n * OJO que un link/unlink implica un update de dos nodos, el padre y el hijo. Quién primero?\n *\n *\n * Version\n * -------\n * 1.0 Initial release\n * 2.0\n *\n * Copyright (c) 2020-2024 Niyamaka.\n * All Rights Reserved.\n ***********************************************************************/\nimport {\n kw_get_dict_value,\n is_array,\n kw_set_dict_value,\n kw_has_key,\n log_error,\n is_string,\n is_object,\n json_object_size,\n json_size,\n str_in_list,\n kwid_new_dict,\n} from \"./helpers.js\";\n\n/********************************************\n * Data\n ********************************************/\nlet treedb_register = { // Dictionary with data of registered global topics\n};\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_formtable(treedb_name, topic_name, gobj_formtable)\n{\n let treedb = kw_get_dict_value(null, treedb_register, treedb_name, {}, true);\n let gobjs = kw_get_dict_value(null, treedb, \"gobjs\", {}, true);\n kw_set_dict_value(null, gobjs, gobj_formtable.name, gobj_formtable);\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_unregister_formtable(treedb_name, topic_name, gobj_formtable)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let gobjs = kw_get_dict_value(treedb, \"gobjs\", {}, true);\n if(kw_has_key(gobjs, gobj_formtable.name)) {\n delete gobjs[gobj_formtable.name];\n } else {\n log_error(\"treedb_unregister_formtable() gobj not found: \" + gobj_formtable.name);\n }\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_nodes(treedb_name, topic_name, nodes)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let data = kw_get_dict_value(treedb, \"data\", {}, true);\n kw_set_dict_value(data, topic_name, kwid_new_dict(nodes));\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_update_node(treedb_name, topic_name, node)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let data = kw_get_dict_value(treedb, \"data\", {}, true);\n let topic_data = kw_get_dict_value(data, topic_name, {}, true);\n\n kw_set_dict_value(topic_data, node.id, node);\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_register_del_node(treedb_name, topic_name, node)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, true);\n let data = kw_get_dict_value(treedb, \"data\", {}, true);\n let topic_data = kw_get_dict_value(data, topic_name, {}, true);\n\n delete topic_data[node.id];\n}\n\n/********************************************\n * Used by ui_treedb to update options\n ********************************************/\nfunction treedb_get_register(treedb_name)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, false);\n return treedb;\n}\n\n/********************************************\n * Used by formtable to get combo options\n ********************************************/\nfunction treedb_get_topic_data(treedb_name, topic_name)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, false);\n let data = kw_get_dict_value(treedb, \"data\", {}, false);\n return kw_get_dict_value(data, topic_name, {}, false);\n}\n\n/********************************************\n * Used by formtable to get combo options\n ********************************************/\nfunction treedb_get_topic_field_data(treedb_name, topic_name)\n{\n let treedb = kw_get_dict_value(treedb_register, treedb_name, {}, false);\n let data = kw_get_dict_value(treedb, \"data\", {}, false);\n return kw_get_dict_value(data, topic_name, {}, false);\n}\n\n/********************************************\n *\n ********************************************/\nfunction treedb_hook_data_size(value)\n{\n if(is_array(value) && json_size(value)===1) {\n let o = value[0];\n if(kw_has_key(o, \"size\")) {\n return o.size;\n }\n return 1;\n }\n return json_size(value);\n}\n\n/************************************************************\n * fkey can be:\n *\n * \"$id\"\n *\n * \"$topic_name^$id^$hook_name\n *\n * {\n * topic_name: $topic_name,\n * id: $id,\n * hook_name: $hook_name\n * }\n *\n * Return\n * {\n * topic_name:\n * id:\n * hook_name:\n * }\n ************************************************************/\nfunction treedb_decoder_fkey(col, fkey)\n{\n if(is_string(fkey)) {\n if(fkey.indexOf(\"^\") === -1) {\n // \"$id\"\n let fkey_desc = col.fkey;\n if(json_object_size(fkey_desc)!==1) {\n log_error(\"bad fkey 1\");\n log_error(col);\n log_error(fkey);\n return null;\n }\n\n let topic_name;\n let hook_name;\n for(const k of Object.keys(fkey_desc)) {\n topic_name = k;\n hook_name = fkey_desc[k];\n break;\n }\n\n return {\n topic_name: topic_name,\n id: fkey,\n hook_name: hook_name\n };\n\n } else {\n // \"$topic_name^$id^$hook_name\n let tt = fkey.split(\"^\");\n if(tt.length !== 3) {\n log_error(\"bad fkey 2\");\n log_error(col);\n log_error(fkey);\n return null;\n }\n return {\n topic_name: tt[0],\n id: tt[1],\n hook_name: tt[2]\n };\n }\n\n } else if(is_object(fkey)) {\n return {\n topic_name: fkey.topic_name,\n id: fkey.id,\n hook_name: fkey.hook_name\n };\n\n } else {\n log_error(\"bad fkey 3\");\n log_error(col);\n log_error(fkey);\n return null;\n }\n}\n\n/************************************************************\n * Encode a fkey (any format) to canonical string:\n * \"$topic_name^$id^$hook_name\"\n *\n * Returns null on error.\n ************************************************************/\nfunction treedb_encoder_fkey(col, fkey)\n{\n let decoded = treedb_decoder_fkey(col, fkey);\n if(!decoded) {\n return null;\n }\n return decoded.topic_name + \"^\" + decoded.id + \"^\" + decoded.hook_name;\n}\n\n/********************************************\n * hook can be:\n *\n * \"$id\"\n *\n * \"$topic_name^$id\n *\n * {\n * topic_name: $topic_name,\n * id: $id\n * }\n *\n * Return\n * {\n * topic_name:\n * id:\n * }\n ********************************************/\nfunction treedb_decoder_hook(col, hook)\n{\n if(is_string(hook)) {\n if(hook.indexOf(\"^\") === -1) {\n // \"$id\"\n let hook_desc = col.hook;\n if(json_object_size(hook_desc)!==1) {\n log_error(\"bad hook 1\");\n log_error(col);\n log_error(hook);\n return null;\n }\n\n let topic_name;\n let fkey_name;\n\n for(let k of Object.keys(hook_desc)) {\n topic_name = k;\n fkey_name = hook_desc[k];\n break;\n }\n\n return {\n topic_name: topic_name,\n id: hook\n };\n\n } else {\n // \"$topic_name^$id\n let tt = hook.split(\"^\");\n if(tt.length !== 2) {\n log_error(\"bad hook 2\");\n log_error(col);\n log_error(hook);\n return null;\n }\n return {\n topic_name: tt[0],\n id: tt[1]\n };\n }\n\n } else if(is_object(hook)) {\n return {\n topic_name: hook.topic_name,\n id: hook.id\n };\n\n } else {\n log_error(\"bad hook 3\");\n log_error(col);\n log_error(hook);\n return null;\n }\n}\n\n/************************************************************\n * Return [\n * name, // name/id of field (table column name)\n * header, // header of field\n * type, // yuneta type (basic and tranger/treedb types)\n * real_type, // json type\n * enum_list, // List of options to <select> or template or table or ...\n * is_required, // field required\n * is_writable // field writable (no readonly)\n * default_value\n * placeholder\n * fkey // fkey mapping {topic_name: hook_name}, null if none\n * ]\n *\n * The template is recursive, in values you can set dictionaries, or arrays,\n * in some context will define the real_type,\n * in other will define a subform.\n *\n ************************************************************/\nconst treedb_real_types = [ // WARNING check tr_treedb.h to update new real types\n \"string\",\n \"integer\",\n \"object\", \"dict\",\n \"array\",\"list\",\n \"real\",\n \"boolean\",\n \"blob\"\n];\n\nconst treedb_field_attributes = [ // WARNING check tr_treedb.h to update new types\n \"persistent\", // stored on disk; implicit readable, NOT writable\n // (see tr_treedb.h: unlike SDF_PERSIST of a gobj attr)\n \"required\",\n \"notnull\",\n \"wild\",\n \"inherit\",\n\n // For use in gobj attributes\n \"readable\", // Field readable by user\n \"writable\", // Field writable by user implicit \"readable\"\n \"hidden\", // Field hidden to user\n \"stats\", // field with stats implicit \"readable\"\n \"rstats\", // field with resettable stats implicit \"stats\"\n \"pstats\" // field with persistent stats implicit \"stats\"\n];\n\nconst treedb_field_types = [ // WARNING check tr_treedb.h to update new types\n \"hook\", // special field types\n \"fkey\",\n \"enum\",\n\n \"template\", // normal field types\n \"uuid\",\n \"rowid\",\n \"qualified\",\n \"password\",\n \"email\",\n \"url\",\n \"time\",\n \"now\",\n \"date\",\n \"color\",\n \"image\",\n \"icon\",\n \"file\", // an fkey into __assets__: the bytes on disk under the treedb\n \"tel\",\n \"table\",\n \"id\",\n \"currency\",\n \"hex\",\n \"binary\",\n \"percent\",\n \"base64\",\n \"coordinates\",\n \"gbuffer\"\n];\n\nfunction treedb_get_field_desc(col)\n{\n let field_desc = {\n name: col.id,\n header: col.header,\n real_type: col.type,\n type: col.type, // By default, is basic type\n enum_list: null,\n is_required: false,\n is_writable: false, // Must be explicitly writable\n is_hidden: false,\n default_value: col.default,\n placeholder: col.placeholder,\n fillspace: col.fillspace || 4,\n fkey: col.fkey || null, // fkey mapping {topic_name: hook_name} (fkey cols)\n is_file: false, // ['fkey','file']: an fkey into __assets__\n };\n\n if(!col.flag) {\n // It can happen if col is not a column descriptor\n return field_desc;\n }\n\n for(let i=0; i<col.flag.length; i++) {\n let f = col.flag[i];\n\n if(str_in_list(treedb_field_types, f)) {\n switch(f) {\n case \"enum\":\n field_desc.enum_list = col.enum;\n break;\n case \"template\":\n field_desc.enum_list = col.template;\n break;\n case \"table\":\n field_desc.enum_list = col.table;\n break;\n case \"file\":\n field_desc.is_file = true;\n break;\n }\n field_desc.type = f;\n\n } else if(str_in_list(treedb_field_attributes, f)) {\n switch(f) {\n case \"writable\":\n field_desc.is_writable = true;\n break;\n case \"notnull\":\n field_desc.is_required = true;\n break;\n case \"required\":\n field_desc.is_required = true;\n break;\n case \"hidden\":\n field_desc.is_hidden = true;\n break;\n }\n }\n }\n\n /*\n * A `file` column is flagged ['fkey','file'] -- `file` QUALIFIES the\n * fkey, it does not replace it -- and the loop above takes the LAST\n * type word it meets, so the ORDER of the flag array would decide\n * what this answers. The C side does not care about the order\n * (derive_file_hooks() asks for both words with kw_has_word), so\n * neither may this: `file` wins wherever it sits.\n */\n if(field_desc.is_file) {\n field_desc.type = \"file\";\n }\n\n return field_desc;\n}\n\nfunction template_get_field_desc(key, value)\n{\n let field_desc = {\n name : key,\n header: key,\n real_type: null,\n type: null,\n enum_list: null,\n is_required: false,\n is_writable: false, // Must be explicitly writable\n is_hidden: false,\n default_value: undefined,\n placeholder: undefined,\n fkey: null, // a string spec cannot express the fkey mapping\n };\n\n /*---------------------------*\n * process value\n *---------------------------*/\n if(is_string(value)) {\n let values = value.split('.');\n for(let i=0; i<values.length; i++) {\n let f = values[i];\n\n if(str_in_list(treedb_real_types, f)) {\n if(!field_desc.real_type) {\n field_desc.real_type = f;\n }\n } else if(str_in_list(treedb_field_types, f)) {\n if(!field_desc.type) {\n field_desc.type = f;\n }\n } else if(str_in_list(treedb_field_attributes, f)) {\n switch(f) {\n case \"writable\":\n field_desc.is_writable = true;\n break;\n case \"notnull\":\n field_desc.is_required = true;\n break;\n case \"required\":\n field_desc.is_required = true;\n break;\n case \"hidden\":\n field_desc.is_hidden = true;\n break;\n }\n }\n }\n if(!field_desc.real_type) {\n field_desc.real_type = \"string\";\n }\n\n } else if(is_object(value)) {\n field_desc = treedb_get_field_desc(value);\n if(!field_desc.name) {\n field_desc.name = key;\n }\n if(!field_desc.header) {\n field_desc.header = key;\n }\n\n } else if(is_array(value)) {\n // TODO case impossible?\n field_desc.real_type = \"array\";\n field_desc.enum_list = value;\n }\n\n if(!field_desc.type) {\n field_desc.type = field_desc.real_type;\n }\n return field_desc;\n}\n\n/********************************************\n *\n ********************************************/\nfunction create_template_record(template, kw)\n{\n let new_record = {};\n if(!kw) {\n kw = {};\n }\n\n Object.entries(template).forEach(([field, col]) => {\n /* col is either a dot-token spec (string) or a column\n * descriptor (object); only the object form carries a default */\n let default_value;\n if(is_object(col)) {\n default_value = col.default;\n }\n let value = kw_get_dict_value(null, kw, field, default_value);\n new_record[field] = value;\n });\n\n return new_record;\n}\n\nexport {\n treedb_hook_data_size,\n treedb_decoder_fkey,\n treedb_encoder_fkey,\n treedb_decoder_hook,\n treedb_get_field_desc,\n template_get_field_desc,\n create_template_record,\n};\n","/****************************************************************************\n * c_timer.js\n *\n * GClass Timer\n * High-level timer, fed by the browser's own timer service\n *\n * Don't use gobj_start()/gobj_stop(), USE set_timeout..(), clear_timeout()\n *\n * The CONTRACT is the C one (see c_timer.h), and it is the whole\n * public surface: set_timeout() arms, clear_timeout() disarms, and\n * a one-shot is done once it fires. Whether the gobj is running is\n * an INTERNAL matter of this gclass -- nobody asking for a timeout\n * has to know it exists, and no caller should have to pair a\n * set_timeout() with a gobj_start() to make it work.\n *\n * What feeds the timer is the only thing that differs from C, and\n * it is deliberately invisible from outside: there the gobj rides\n * the yuno's one-second heartbeat, here it is a native setTimeout().\n *\n * Copyright (c) 2025-2026, ArtGins.\n * All Rights Reserved.\n ****************************************************************************/\n\nimport {\n SDATA,\n SDATA_END,\n data_type_t,\n gclass_flag_t,\n event_flag_t,\n GObj,\n gclass_create,\n gobj_parent,\n gobj_send_event,\n gobj_publish_event,\n gobj_start,\n gobj_stop,\n gobj_is_running,\n gobj_read_bool_attr,\n gobj_read_integer_attr,\n gobj_read_pointer_attr,\n gobj_subscribe_event,\n gobj_is_pure_child,\n gobj_gclass_name,\n gobj_write_bool_attr,\n gobj_write_integer_attr,\n} from \"./gobj.js\";\n\nimport {\n log_error,\n} from \"./helpers.js\";\n\n\n/***************************************************************\n * Constants\n ***************************************************************/\nconst GCLASS_NAME = \"C_TIMER\";\n\n/***************************************************************\n * Data\n ***************************************************************/\n/*---------------------------------------------*\n * Attributes\n *---------------------------------------------*/\nconst attrs_table = [\nSDATA(data_type_t.DTP_POINTER, \"subscriber\", 0, null, \"Subscriber of output events\"),\nSDATA(data_type_t.DTP_BOOLEAN, \"periodic\", 0, 0, \"True for periodic timeouts\"),\nSDATA(data_type_t.DTP_INTEGER, \"msec\", 0, 0, \"Timeout in milliseconds\"),\nSDATA_END()\n];\n\nlet PRIVATE_DATA = {\n periodic: false,\n msec: 0,\n timer_id: -1,\n};\n\nlet __gclass__ = null;\n\n\n\n\n /******************************\n * Framework Methods\n ******************************/\n\n\n\n\n/***************************************************************\n * Framework Method: Create\n ***************************************************************/\nfunction mt_create(gobj)\n{\n let priv = gobj.priv;\n\n /*\n * SERVICE subscription model\n */\n const subscriber = gobj_read_pointer_attr(gobj, \"subscriber\");\n if(subscriber) {\n gobj_subscribe_event(gobj, null, {}, subscriber);\n }\n\n priv.periodic = gobj_read_bool_attr(gobj, \"periodic\");\n priv.msec = gobj_read_integer_attr(gobj, \"msec\");\n}\n\n/***************************************************************\n * Framework Method: Writing\n ***************************************************************/\nfunction mt_writing(gobj, path)\n{\n let priv = gobj.priv;\n\n switch(path) {\n case \"periodic\":\n priv.periodic = gobj_read_bool_attr(gobj, \"periodic\");\n break;\n case \"msec\":\n priv.msec = gobj_read_integer_attr(gobj, \"msec\");\n if(priv.timer_id !== -1) {\n clearTimeout(priv.timer_id);\n priv.timer_id = -1;\n }\n if(priv.msec > 0) {\n priv.timer_id = setTimeout(\n function() {\n gobj_send_event(gobj, \"EV_TIMEOUT\", {}, gobj);\n },\n priv.msec\n );\n }\n\n /*\n * The running state follows the timeout, and it follows it HERE,\n * on the attribute write -- not in the set_timeout()/clear_timeout()\n * helpers. The attribute is the real interface; those three PUBLIC\n * functions are an escape from the gclass interface (attributes,\n * events, commands, local methods, stats) that c_timer has carried\n * since C, and sugar must not be the only door that behaves.\n * Writing `msec` by hand has to leave the timer exactly as\n * set_timeout() would.\n *\n * No recursion through gobj_stop(): it clears `running` BEFORE\n * calling mt_stop(), and mt_stop() lands right back here.\n */\n if(priv.msec > 0) {\n if(!gobj_is_running(gobj)) {\n gobj_start(gobj);\n }\n } else {\n if(gobj_is_running(gobj)) {\n gobj_stop(gobj);\n }\n }\n break;\n }\n}\n\n/***************************************************************\n * Framework Method: Start\n ***************************************************************/\nfunction mt_start(gobj)\n{\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Stop\n ***************************************************************/\nfunction mt_stop(gobj)\n{\n gobj_write_integer_attr(gobj, \"msec\", -1); // This write stops any timer\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Destroy\n ***************************************************************/\nfunction mt_destroy(gobj)\n{\n}\n\n\n\n\n /***************************\n * Actions\n ***************************/\n\n\n\n\n/***************************************************************\n * Action: Timeout\n ***************************************************************/\nfunction ac_timeout(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n let ev = priv.periodic ? \"EV_TIMEOUT_PERIODIC\" : \"EV_TIMEOUT\";\n\n /*\n * Re-arm BEFORE delivering, like C does, and for its two reasons:\n * the period must not carry the execution time of the action, and a\n * clear_timeout() made from INSIDE the action has to win. Re-arming\n * afterwards undid that clear and re-armed with the msec the clear\n * had just written -- a negative delay, which setTimeout() serves\n * immediately: a cleared periodic timer turned into a busy loop.\n */\n if(priv.periodic && priv.msec > 0) {\n priv.timer_id = setTimeout(\n function() {\n gobj_send_event(gobj, \"EV_TIMEOUT\", {}, gobj);\n },\n priv.msec\n );\n } else {\n priv.timer_id = -1;\n }\n\n /*\n * SERVICE subscription model\n */\n if (gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), ev, {}, gobj);\n } else {\n gobj_publish_event(gobj, ev, {});\n }\n\n /*\n * A one-shot is spent: it stops itself, so nobody has to stop it.\n * Unless the action just re-armed it -- `timer_id` back from -1 is\n * the same guard C makes on `t_flush`.\n */\n if(!priv.periodic && priv.timer_id === -1) {\n if(gobj_is_running(gobj)) {\n gobj_stop(gobj);\n }\n }\n\n return 0;\n}\n\n\n\n\n /***************************\n * FSM\n ***************************/\n\n\n\n\n/*---------------------------------------------*\n * Global methods table\n *---------------------------------------------*/\nconst gmt = {\n mt_create: mt_create,\n mt_writing: mt_writing,\n mt_start: mt_start,\n mt_stop: mt_stop,\n mt_destroy: mt_destroy,\n};\n\n/***************************************************************\n * Create the GClass\n ***************************************************************/\nfunction create_gclass(gclass_name)\n{\n if (__gclass__) {\n log_error(`GClass ALREADY created: ${gclass_name}`);\n return -1;\n }\n\n /*---------------------------------------------*\n * States\n *---------------------------------------------*/\n const st_idle = [\n [\"EV_TIMEOUT\", ac_timeout, null]\n ];\n\n const states = [\n [\"ST_IDLE\", st_idle]\n ];\n\n /*---------------------------------------------*\n * Events\n *---------------------------------------------*/\n const event_types = [\n [\"EV_TIMEOUT\", event_flag_t.EVF_OUTPUT_EVENT],\n [\"EV_TIMEOUT_PERIODIC\", event_flag_t.EVF_OUTPUT_EVENT],\n [0, 0]\n ];\n\n /*----------------------------------------*\n * Create the gclass\n *----------------------------------------*/\n __gclass__ = gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n 0, // lmt,\n attrs_table,\n PRIVATE_DATA,\n 0, // authz_table,\n 0, // command_table,\n 0, // s_user_trace_level\n gclass_flag_t.gcflag_manual_start // gclass_flag\n );\n if (!__gclass__) {\n // Error already logged\n return -1;\n }\n\n return 0;\n}\n\n/***************************************************************************\n * Register GClass\n ***************************************************************************/\nfunction register_c_timer()\n{\n return create_gclass(GCLASS_NAME);\n}\n\n\n\n\n /***************************\n * Helpers\n ***************************/\n\n\n\n\n/***************************************************************************\n * Set timeout\n ***************************************************************************/\nfunction set_timeout(gobj, msec)\n{\n if(!(gobj instanceof GObj)) {\n log_error(`not GObj TYPE`);\n return -1;\n }\n if(gobj_gclass_name(gobj) !== \"C_TIMER\") {\n log_error(`not C_TIMER GObj`);\n return -1;\n }\n\n gobj_write_bool_attr(gobj, \"periodic\", false);\n gobj_write_integer_attr(gobj, \"msec\", msec); // This write launches the timer\n}\n\n/***************************************************************************\n * Set periodic timeout\n ***************************************************************************/\nfunction set_timeout_periodic(gobj, msec)\n{\n if(!(gobj instanceof GObj)) {\n log_error(`not GObj TYPE`);\n return -1;\n }\n if(gobj_gclass_name(gobj) !== \"C_TIMER\") {\n log_error(`not C_TIMER GObj`);\n return -1;\n }\n\n gobj_write_bool_attr(gobj, \"periodic\", true);\n gobj_write_integer_attr(gobj, \"msec\", msec); // This write launches the timer\n}\n\n/***************************************************************************\n * Clear timeout\n ***************************************************************************/\nfunction clear_timeout(gobj)\n{\n if(!(gobj instanceof GObj)) {\n log_error(`not GObj TYPE`);\n return -1;\n }\n if(gobj_gclass_name(gobj) !== \"C_TIMER\") {\n log_error(`not C_TIMER GObj`);\n return -1;\n }\n\n gobj_write_integer_attr(gobj, \"msec\", -1); // This write stops the timer\n}\n\nexport { register_c_timer, set_timeout, set_timeout_periodic, clear_timeout };\n","/****************************************************************************\n * c_yuno.js\n *\n * The default yuno in js\n *\n * Copyright (c) 2025-2026, ArtGins.\n * All Rights Reserved. ****************************************************************************/\nimport {\n YUNETA_VERSION,\n SDATA,\n SDATA_END,\n data_type_t,\n event_flag_t,\n gclass_create,\n gobj_create_pure_child,\n gobj_start,\n gobj_play,\n gobj_pause,\n gobj_is_playing,\n gobj_is_running,\n gobj_default_service,\n gobj_stop_children,\n gobj_name,\n gobj_read_attr,\n gobj_publish_event,\n gobj_write_str_attr,\n gobj_write_attr,\n gobj_yuno_role,\n gobj_yuno_name,\n gclass_find_by_name,\n gobj_set_global_trace,\n gobj_set_global_no_trace,\n gobj_set_global_trace2,\n gobj_set_global_no_trace2,\n gobj_set_gclass_trace,\n gobj_set_gclass_no_trace,\n gobj_get_global_trace_level,\n gobj_get_global_trace_no_level,\n gobj_get_gclass_trace_level,\n gobj_get_gclass_trace_level2,\n gobj_get_gclass_trace_no_level,\n gobj_save_persistent_attrs,\n sdata_flag_t,\n} from \"./gobj.js\";\n\nimport {\n current_timestamp,\n log_error, node_uuid,\n is_object,\n is_array,\n} from \"./helpers.js\";\n\nimport {\n build_command_response,\n} from \"./command_parser.js\";\n\nimport {\n set_timeout_periodic,\n clear_timeout\n} from \"./c_timer.js\";\n\n/***************************************************************\n * Constants\n ***************************************************************/\nconst GCLASS_NAME = \"C_YUNO\";\n\n/***************************************************************\n * Data\n ***************************************************************/\n/*---------------------------------------------*\n * Attributes\n *---------------------------------------------*/\nconst attrs_table = [\nSDATA(data_type_t.DTP_BOOLEAN, \"changesLost\", 0, false, \"Set true to warn about leaving page\"),\nSDATA(data_type_t.DTP_BOOLEAN, \"browser_beforeunload\", 0, false, \"Set true to refreshing browser\"),\nSDATA(data_type_t.DTP_STRING, \"__username__\", 0, \"\", \"Username\"),\nSDATA(data_type_t.DTP_STRING, \"start_date\", 0, \"\", \"Yuno starting date\"),\nSDATA(data_type_t.DTP_STRING, \"node_uuid\", 0, \"\", \"uuid of node\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_role\", 0, \"\", \"Yuno role\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_id\", 0, \"\", \"Yuno Id. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_name\", 0, \"\", \"Yuno name. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_tag\", 0, \"\", \"Tags of yuno. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_release\", 0, \"\", \"Yuno Release. Set by agent\"),\nSDATA(data_type_t.DTP_STRING, \"yuno_version\", 0, \"\", \"Yuno version (APP_VERSION)\"),\nSDATA(data_type_t.DTP_STRING, \"yuneta_version\", 0, YUNETA_VERSION, \"Yuneta version\"),\nSDATA(data_type_t.DTP_LIST, \"required_services\", 0, \"[]\", \"Required services\"),\nSDATA(data_type_t.DTP_DICT, \"trace_levels\", sdata_flag_t.SDF_PERSIST, \"{}\", \"Trace levels\"),\nSDATA(data_type_t.DTP_DICT, \"no_trace_levels\", sdata_flag_t.SDF_PERSIST, \"{}\", \"No trace levels\"),\nSDATA(data_type_t.DTP_POINTER, \"trace_ievent_callback\",0, null, \"Where the traffic trace goes (C_IEVENT_CLI levels ievents/ievents2); console when null\"),\nSDATA(data_type_t.DTP_BOOLEAN, \"developer\", 0, false, \"Developer mode enabled\"),\nSDATA(data_type_t.DTP_INTEGER, \"periodic_timeout\", 0, \"1000\", \"Timeout periodic, in miliseconds.\"),\nSDATA_END()\n];\n\nlet PRIVATE_DATA = {\n gobj_timer: null,\n};\n\nlet __gclass__ = null;\n\n\n\n\n /******************************\n * Framework Methods\n ******************************/\n\n\n\n\n/***************************************************************\n * Framework Method: Create\n ***************************************************************/\nfunction mt_create(gobj)\n{\n let priv = gobj.priv;\n\n let date = current_timestamp();\n gobj_write_str_attr(gobj, \"start_date\", date);\n gobj_write_str_attr(gobj, \"node_uuid\", node_uuid());\n\n /*\n * Create children\n */\n gobj.priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), \"C_TIMER\", {}, gobj);\n\n priv.periodic_timeout = gobj_read_attr(gobj, \"periodic_timeout\");\n\n /*\n * Traces: what the user persisted wins over what main() set by\n * default. The persistent attrs are already loaded (a yuno is a\n * service), as in the C kernel's C_YUNO.\n */\n set_user_gclass_traces(gobj);\n set_user_gclass_no_traces(gobj);\n}\n\n/***************************************************************\n * Framework Method: Writing\n ***************************************************************/\nfunction mt_writing(gobj, path)\n{\n}\n\n/***************************************************************\n * Framework Method: Start\n ***************************************************************/\nfunction mt_start(gobj)\n{\n set_timeout_periodic(gobj.priv.gobj_timer, gobj.priv.periodic_timeout);\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Stop\n ***************************************************************/\nfunction mt_stop(gobj)\n{\n /*\n * When yuno stops, it's the death of the app\n */\n clear_timeout(gobj.priv.gobj_timer);\n gobj_stop_children(gobj);\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Play\n ***************************************************************/\nfunction mt_play(gobj)\n{\n let default_service = gobj_default_service();\n if(!gobj_is_running(default_service)) {\n gobj_start(default_service);\n }\n if(!gobj_is_playing(default_service)) {\n gobj_play(default_service);\n }\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Pause\n ***************************************************************/\nfunction mt_pause(gobj)\n{\n gobj_pause(gobj_default_service());\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Destroy\n ***************************************************************/\nfunction mt_destroy(gobj)\n{\n}\n\n\n\n\n /***************************\n * Local Methods\n ***************************/\n\n\n\n\n/***************************************************************\n * Restore the trace levels the user persisted.\n *\n * A saved scope REPLACES what is in force: main() sets its defaults\n * (gobj_set_global_no_trace(\"timer_periodic\"), a gclass it wants quiet)\n * before the yuno is created, and a default the user turned off must\n * stay off. A scope is saved whole, empty included (save_global_trace());\n * a scope never saved keeps main()'s. The C kernel's C_YUNO does the same.\n ***************************************************************/\nfunction set_user_gclass_traces(gobj)\n{\n let jn_trace_levels = gobj_read_attr(gobj, \"trace_levels\");\n if(!is_object(jn_trace_levels)) {\n return 0;\n }\n\n let jn_global = jn_trace_levels[\"__global_trace__\"];\n if(is_array(jn_global)) {\n gobj_set_global_trace2(0xFFFFFFFF, false);\n for(let level of jn_global) {\n gobj_set_global_trace(level, true);\n }\n }\n\n for(const [name, jn_levels] of Object.entries(jn_trace_levels)) {\n let gclass = gclass_find_by_name(name);\n if(!gclass) {\n /* Not a gclass (__global_trace__) or one not registered in\n * this app: nothing to restore, and nothing worth a log. */\n continue;\n }\n if(!is_array(jn_levels)) {\n log_error(`${gobj_name(gobj)}: trace_levels of ${name} MUST be a list`);\n continue;\n }\n gobj_set_gclass_trace(gclass, null, false);\n for(let level of jn_levels) {\n gobj_set_gclass_trace(gclass, level, true);\n }\n }\n return 0;\n}\n\n/***************************************************************\n * Restore the no-trace levels, see set_user_gclass_traces()\n ***************************************************************/\nfunction set_user_gclass_no_traces(gobj)\n{\n let jn_no_trace_levels = gobj_read_attr(gobj, \"no_trace_levels\");\n if(!is_object(jn_no_trace_levels)) {\n return 0;\n }\n\n let jn_global = jn_no_trace_levels[\"__global_no_trace__\"];\n if(is_array(jn_global)) {\n gobj_set_global_no_trace2(0xFFFFFFFF, false);\n for(let level of jn_global) {\n gobj_set_global_no_trace(level, true);\n }\n }\n\n for(const [name, jn_levels] of Object.entries(jn_no_trace_levels)) {\n let gclass = gclass_find_by_name(name);\n if(!gclass) {\n continue; // see set_user_gclass_traces()\n }\n if(!is_array(jn_levels)) {\n log_error(`${gobj_name(gobj)}: no_trace_levels of ${name} MUST be a list`);\n continue;\n }\n gobj_set_gclass_no_trace(gclass, null, false);\n for(let level of jn_levels) {\n gobj_set_gclass_no_trace(gclass, level, true);\n }\n }\n return 0;\n}\n\n/***************************************************************\n * Save a scope WHOLE, from the levels in force (see\n * set_user_gclass_traces()): a saved scope replaces main()'s, so it\n * has to carry everything that must be in force.\n ***************************************************************/\nfunction save_trace_scope(gobj, attr, scope, levels)\n{\n let jn_levels = gobj_read_attr(gobj, attr);\n if(!is_object(jn_levels)) {\n jn_levels = {};\n }\n jn_levels[scope] = levels;\n gobj_write_attr(gobj, attr, jn_levels);\n return gobj_save_persistent_attrs(gobj, attr);\n}\n\n/***************************************************************\n * \"set\" as the C command reads it: TRUE / set / 1, FALSE / reset / 0\n ***************************************************************/\nfunction parse_set(value)\n{\n if(value === true || value === false) {\n return value;\n }\n let v = String(value === undefined || value === null ? \"\" : value).toLowerCase();\n if(v === \"true\" || v === \"set\") {\n return true;\n }\n if(v === \"false\" || v === \"reset\") {\n return false;\n }\n if(v === \"\" || isNaN(Number(v))) {\n return null;\n }\n return Number(v) ? true : false;\n}\n\nfunction yuno_prefix()\n{\n return `${gobj_yuno_role()}^${gobj_yuno_name()}`;\n}\n\n\n\n\n /***************************\n * Commands\n ***************************/\n\n\n\n\n/***************************************************************\n * The trace commands of the C kernel's C_YUNO, same names and same\n * parameters (`level`, `set`, `gclass_name` / `gclass`). Setting a\n * level saves its scope.\n ***************************************************************/\nfunction mt_command_parser(gobj, command, kw, src)\n{\n kw = kw || {};\n switch(command) {\n case \"get-global-trace\":\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_level());\n case \"get-global-no-trace\":\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_no_level());\n case \"set-global-trace\":\n case \"set-global-no-trace\":\n {\n let no = (command === \"set-global-no-trace\");\n let level = kw.level;\n let set = parse_set(kw.set);\n if(!level) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: what level?`, null, null);\n }\n if(set === null) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: bitmask set or re-set?`, null, null);\n }\n let ret = no ? gobj_set_global_no_trace(level, set) : gobj_set_global_trace(level, set);\n if(ret < 0) {\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: global trace level not found: ${level}`, null, null\n );\n }\n if(no) {\n save_trace_scope(gobj, \"no_trace_levels\", \"__global_no_trace__\", gobj_get_global_trace_no_level());\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_no_level());\n }\n save_trace_scope(gobj, \"trace_levels\", \"__global_trace__\", gobj_get_global_trace_level());\n return build_command_response(gobj, 0, null, null, gobj_get_global_trace_level());\n }\n case \"get-gclass-trace\":\n case \"get-gclass-no-trace\":\n case \"set-gclass-trace\":\n case \"set-gclass-no-trace\":\n {\n let no = command.indexOf(\"no-trace\") >= 0;\n let gclass_name = kw.gclass_name || kw.gclass || \"\";\n let gclass = gclass_find_by_name(gclass_name);\n if(!gclass) {\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: what gclass is '${gclass_name}'?`, null, null\n );\n }\n if(command.indexOf(\"get-\") === 0) {\n return build_command_response(gobj, 0, null, null,\n no ? gobj_get_gclass_trace_no_level(gclass) : gobj_get_gclass_trace_level(gclass)\n );\n }\n let level = kw.level;\n let set = parse_set(kw.set);\n if(!level) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: what level?`, null, null);\n }\n if(set === null) {\n return build_command_response(gobj, -1, `${yuno_prefix()}: bitmask set or re-set?`, null, null);\n }\n let ret = no ? gobj_set_gclass_no_trace(gclass, level, set) : gobj_set_gclass_trace(gclass, level, set);\n if(ret < 0) {\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: trace level of ${gclass_name} not found: ${level}`, null, null\n );\n }\n if(no) {\n save_trace_scope(gobj, \"no_trace_levels\", gclass_name, gobj_get_gclass_trace_no_level(gclass));\n return build_command_response(gobj, 0, null, null, gobj_get_gclass_trace_no_level(gclass));\n }\n save_trace_scope(gobj, \"trace_levels\", gclass_name, gobj_get_gclass_trace_level2(gclass));\n return build_command_response(gobj, 0, null, null, gobj_get_gclass_trace_level(gclass));\n }\n default:\n return build_command_response(\n gobj, -1, `${yuno_prefix()}: command not available: ${command}`, null, null\n );\n }\n}\n\n\n\n\n /***************************\n * Actions\n ***************************/\n\n\n\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_timeout(gobj, event, kw, src)\n{\n gobj_publish_event(gobj, event, kw);\n return 0;\n}\n\n\n\n\n /***************************\n * FSM\n ***************************/\n\n\n\n\n/*---------------------------------------------*\n * Global methods table\n *---------------------------------------------*/\nconst gmt = {\n mt_create: mt_create,\n mt_writing: mt_writing,\n mt_start: mt_start,\n mt_stop: mt_stop,\n mt_destroy: mt_destroy,\n mt_play: mt_play,\n mt_pause: mt_pause,\n mt_command_parser: mt_command_parser,\n};\n\n\n/***************************************************************\n * Create the GClass\n ***************************************************************/\nfunction create_gclass(gclass_name)\n{\n if(__gclass__) {\n log_error(`GClass ALREADY created: ${gclass_name}`);\n return -1;\n }\n\n /*---------------------------------------------*\n * States\n *---------------------------------------------*/\n const st_idle = [\n [\"EV_TIMEOUT_PERIODIC\", ac_timeout, null]\n ];\n\n const states = [\n [\"ST_IDLE\", st_idle]\n ];\n\n /*---------------------------------------------*\n * Events\n *---------------------------------------------*/\n const event_types = [\n [\"EV_TIMEOUT_PERIODIC\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [0, 0]\n ];\n\n /*----------------------------------------*\n * Create the gclass\n *----------------------------------------*/\n __gclass__ = gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n 0, // lmt,\n attrs_table,\n PRIVATE_DATA,\n 0, // authz_table,\n 0, // command_table,\n 0, // s_user_trace_level\n 0 // gclass_flag\n );\n if(!__gclass__) {\n // Error already logged\n return -1;\n }\n\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction register_c_yuno()\n{\n return create_gclass(GCLASS_NAME);\n}\n\nexport { register_c_yuno };\n","/**************************************************************************\n * c_ievent_cli.js\n * Ievent_cli GClass.\n *\n * Inter-event (client side)\n * Simulate a remote service like a local gobj.\n *\n * Licence: MIT (http://www.opensource.org/licenses/mit-license)\n * Copyright (c) 2014,2024 Niyamaka.\n * Copyright (c) 2025-2026, ArtGins.\n **************************************************************************/\nimport {\n YUNETA_VERSION,\n SDATA,\n SDATA_END,\n data_type_t,\n gclass_flag_t,\n sdata_flag_t,\n event_flag_t,\n gclass_create,\n gobj_parent,\n gobj_short_name,\n gobj_yuno,\n gobj_trace_level,\n gobj_send_event,\n gobj_publish_event,\n gobj_read_integer_attr,\n gobj_read_str_attr,\n gobj_read_pointer_attr,\n gobj_write_str_attr,\n gobj_subscribe_event,\n gobj_is_pure_child,\n gobj_create_pure_child,\n gobj_name,\n gobj_current_state,\n gobj_is_destroying,\n gobj_yuno_name,\n gobj_yuno_role,\n gobj_find_subscriptions,\n gobj_is_running,\n gobj_is_playing,\n gobj_read_attr,\n gobj_yuno_id,\n gobj_has_event,\n gobj_find_service,\n gobj_change_state,\n gobj_read_bool_attr,\n\n} from \"./gobj.js\";\n\nimport {\n log_error,\n log_debug,\n log_warning,\n current_timestamp,\n empty_string,\n msg_iev_push_stack,\n msg_iev_get_stack,\n kw_get_str,\n kw_get_int,\n kw_get_dict_value,\n node_uuid,\n msg_iev_set_msg_type,\n msg_iev_get_msg_type,\n trace_json,\n json_deep_copy,\n json_object_del,\n set_remote_log_functions, kw_flag_t,\n} from \"./helpers.js\";\n\nimport {\n clear_timeout,\n set_timeout\n} from \"./c_timer.js\";\n\n/***************************************************************\n * Constants\n ***************************************************************/\nconst GCLASS_NAME = \"C_IEVENT_CLI\";\n\nconst IEVENT_STACK_ID = \"ievent_gate_stack\";\nconst COMMAND_STACK_ID = \"command_stack\";\nconst STATS_STACK_ID = \"stats_stack\";\n\n/***************************************************************\n * Data\n ***************************************************************/\n/*---------------------------------------------*\n * Attributes\n *---------------------------------------------*/\nconst attrs_table = [\n/*-ATTR-type--------------------name----------------flag------------------------default-----description---------- */\nSDATA (data_type_t.DTP_STRING, \"wanted_yuno_role\", sdata_flag_t.SDF_RD, \"\", \"wanted yuno role\"),\nSDATA (data_type_t.DTP_STRING, \"wanted_yuno_name\", sdata_flag_t.SDF_RD, \"\", \"wanted yuno name\"),\nSDATA (data_type_t.DTP_STRING, \"wanted_yuno_service\",sdata_flag_t.SDF_RD, \"\", \"wanted yuno service\"),\nSDATA (data_type_t.DTP_STRING, \"remote_yuno_role\", sdata_flag_t.SDF_RD, \"\", \"confirmed remote yuno role\"),\nSDATA (data_type_t.DTP_STRING, \"remote_yuno_name\", sdata_flag_t.SDF_RD, \"\", \"confirmed remote yuno name\"),\nSDATA (data_type_t.DTP_STRING, \"remote_yuno_service\",sdata_flag_t.SDF_RD, \"\", \"confirmed remote yuno service\"),\nSDATA (data_type_t.DTP_STRING, \"url\", sdata_flag_t.SDF_RD, \"\", \"Url to connect\"),\nSDATA (data_type_t.DTP_STRING, \"jwt\", sdata_flag_t.SDF_PERSIST, \"\", \"JWT\"),\nSDATA (data_type_t.DTP_STRING, \"cert_pem\", sdata_flag_t.SDF_PERSIST, \"\", \"SSL server certification, PEM str format\"),\nSDATA (data_type_t.DTP_JSON, \"extra_info\", sdata_flag_t.SDF_RD, \"{}\", \"dict data set by user, added to the identity card msg.\"),\nSDATA (data_type_t.DTP_LIST, \"required_services\",sdata_flag_t.SDF_RD, \"[]\", \"Services this LINK requires (identity card). Empty = the yuno's `required_services`, as before. A yuno with several links to DIFFERENT backends must set it per link: the yuno-wide list is the union, so every backend is told the service names of all the others.\"),\nSDATA (data_type_t.DTP_INTEGER, \"timeout_retry\", sdata_flag_t.SDF_RD, \"5000\", \"First reconnect delay (ms). It BACKS OFF from here, doubling up to timeout_retry_max, and resets when a session is reached\"),\nSDATA (data_type_t.DTP_INTEGER, \"timeout_retry_max\",sdata_flag_t.SDF_RD, \"60000\", \"Cap of the reconnect backoff (ms). Set it equal to timeout_retry for the old fixed-interval behaviour\"),\nSDATA (data_type_t.DTP_INTEGER, \"timeout_idack\", sdata_flag_t.SDF_RD, \"5000\", \"timeout waiting idAck\"),\nSDATA (data_type_t.DTP_POINTER, \"subscriber\", 0, 0, \"subscriber of output-events. If null then subscriber is the parent\"),\nSDATA_END()\n];\n\n/*---------------------------------------------*\n * GClass trace levels\n * HACK strict ascendant value!\n * required paired correlative strings\n * in s_user_trace_level\n *---------------------------------------------*/\nconst TRACE_IEVENTS = 0x0001;\nconst TRACE_IEVENTS2 = 0x0002;\nconst s_user_trace_level = [\n [\"ievents\", \"Trace inter-events with metadata of kw\"],\n [\"ievents2\", \"Trace inter-events with full kw\"],\n [\"identity-card\", \"Trace identity_card messages\"],\n];\n\n/* The traffic trace is this gclass's own level, as in the C kernel\n * (`set-gclass-trace gclass=C_IEVENT_CLI level=ievents`). Where it goes\n * is the yuno's `trace_ievent_callback`, the console when there is none. */\nfunction is_traffic_tracing(gobj)\n{\n return (gobj_trace_level(gobj) & (TRACE_IEVENTS|TRACE_IEVENTS2)) ? true : false;\n}\n\n/*---------------------------------------------*\n * Private data\n *---------------------------------------------*/\nlet PRIVATE_DATA = {\n url: null,\n remote_yuno_name: null,\n remote_yuno_role: null,\n remote_yuno_service:null,\n gobj_timer: null,\n inform_on_close: false,\n websocket: null,\n inside_on_open: false, // avoid duplicates, no subscriptions while in on_open,\n // they will send in resend_subscriptions\n retry_ms: 0, // current backoff (0 = none yet); see next_retry()\n};\n\nlet __gclass__ = null;\n\n\n\n\n /******************************\n * Framework Methods\n ******************************/\n\n\n\n\n/***************************************************************\n * Framework Method: Create\n ***************************************************************/\nfunction mt_create(gobj)\n{\n let priv = gobj.priv;\n\n /*\n * Create children\n */\n priv.gobj_timer = gobj_create_pure_child(gobj_name(gobj), \"C_TIMER\", {}, gobj);\n\n priv.url = gobj_read_str_attr(gobj, \"url\");\n priv.remote_yuno_name = gobj_read_str_attr(gobj, \"remote_yuno_name\");\n priv.remote_yuno_role = gobj_read_str_attr(gobj, \"remote_yuno_role\");\n priv.remote_yuno_service = gobj_read_str_attr(gobj, \"remote_yuno_service\");\n\n gobj_write_str_attr(gobj, \"wanted_yuno_name\", priv.remote_yuno_name);\n gobj_write_str_attr(gobj, \"wanted_yuno_role\", priv.remote_yuno_role);\n gobj_write_str_attr(gobj, \"wanted_yuno_service\", priv.remote_yuno_service);\n\n /*\n * SERVICE subscription model\n */\n const subscriber = gobj_read_pointer_attr(gobj, \"subscriber\");\n if(subscriber) {\n gobj_subscribe_event(gobj, null, {}, subscriber);\n }\n}\n\n/***************************************************************\n * Framework Method: Writing\n ***************************************************************/\nfunction mt_writing(gobj, path)\n{\n let priv = gobj.priv;\n\n switch(path) {\n case \"url\":\n priv.url = gobj_read_str_attr(gobj, \"url\");\n break;\n case \"remote_yuno_name\":\n priv.remote_yuno_name = gobj_read_str_attr(gobj, \"remote_yuno_name\");\n break;\n case \"remote_yuno_role\":\n priv.remote_yuno_role = gobj_read_str_attr(gobj, \"remote_yuno_role\");\n break;\n case \"remote_yuno_service\":\n priv.remote_yuno_service = gobj_read_str_attr(gobj, \"remote_yuno_service\");\n break;\n }\n}\n\n/***************************************************************\n * Framework Method: Start\n ***************************************************************/\nfunction mt_start(gobj)\n{\n let priv = gobj.priv;\n\n /* Starting is a deliberate act (the operator pressed connect): it must\n * not inherit the backoff a previous run had escalated to. */\n priv.retry_ms = 0;\n\n priv.websocket = setup_websocket(gobj);\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Stop\n ***************************************************************/\nfunction mt_stop(gobj)\n{\n let priv = gobj.priv;\n\n clear_timeout(priv.gobj_timer);\n\n if(priv.websocket) {\n /*\n * Keep the .onclose handler wired: a deliberate stop that does\n * NOT destroy the gobj (e.g. a frontend that stops\n * __remote_service__ on logout and drives its UI teardown from\n * the published EV_ON_CLOSE) still needs the async onclose to\n * reach the FSM. This mirrors the C kernel, where mt_stop stops\n * the bottom transport and ac_on_close publishes EV_ON_CLOSE.\n * The stop+destroy-in-the-same-turn case is handled in the\n * onclose handler itself (gobj_is_destroying guard).\n */\n close_websocket(gobj);\n }\n\n return 0;\n}\n\n/***************************************************************\n * Framework Method: Destroy\n ***************************************************************/\nfunction mt_destroy(gobj)\n{\n}\n\n/***************************************************************\n * Framework Method: Stats\n * Ask for stats to remote `kw.service` (or wanted_yuno_service)\n ***************************************************************/\nfunction mt_stats(gobj, stats, kw, src)\n{\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n log_error(`Not in session`);\n return null;\n }\n\n if(!kw) {\n kw = {};\n }\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(src),\n kw_get_str(gobj, kw, \"service\", null, 0)\n );\n\n let __md_stats__ = kw_get_dict_value(\n gobj, kw, \"__md_stats__\", null, kw_flag_t.KW_EXTRACT\n );\n if(__md_stats__) {\n //\n } else {\n __md_stats__ = {};\n }\n\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n STATS_STACK_ID,\n {\n \"stats\": stats,\n \"kw\": __md_stats__\n }\n );\n\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id\n );\n\n kw[\"__stats__\"] = stats;\n msg_iev_set_msg_type(gobj, kw, \"__stats__\");\n\n send_static_iev(gobj, \"EV_MT_STATS\", kw, src);\n\n return null; // return null on asynchronous response.\n}\n\n/***************************************************************\n * Framework Method: Command\n * Ask for command to remote `kw.service` (or wanted_yuno_service)\n ***************************************************************/\nfunction mt_command(gobj, command, kw, src)\n{\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n log_error(`Not in session`);\n return null;\n }\n\n if(!kw) {\n kw = {};\n }\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(src),\n kw_get_str(gobj, kw, \"service\", \"\", 0)\n );\n\n let __md_command__ = kw_get_dict_value(\n gobj, kw, \"__md_command__\", null, kw_flag_t.KW_EXTRACT\n );\n if(__md_command__) {\n //\n } else {\n __md_command__ = {};\n }\n\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n COMMAND_STACK_ID,\n {\n \"command\": command,\n \"kw\": __md_command__\n }\n );\n\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id\n );\n\n kw[\"__command__\"] = command;\n msg_iev_set_msg_type(gobj, kw, \"__command__\");\n\n send_static_iev(gobj, \"EV_MT_COMMAND\", kw, src);\n\n return null; // return null on asynchronous response.\n}\n\n/***************************************************************\n * Framework Method: inject_event\n * Send event to remote `kw.service` (or wanted_yuno_service)\n ***************************************************************/\nfunction mt_inject_event(gobj, event, kw, src)\n{\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n window.console.error(`Not in session`); // Don't use log_error\n return -1;\n }\n\n if(!kw) {\n kw = {};\n }\n\n /*\n * __MESSAGE__\n * Put the ievent if it doesn't come with it,\n * if it does come with it, it's because it will be a response\n */\n let jn_request = msg_iev_get_stack(gobj, kw, IEVENT_STACK_ID);\n if(jn_request) {\n /*\n * __RESPONSE__\n */\n } else {\n /*\n * __REQUEST__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(src),\n kw_get_str(gobj, kw, \"__service__\", 0, 0)\n );\n json_object_del(kw, \"__service__\");\n\n msg_iev_push_stack(\n gobj,\n kw,\n \"__message__\",\n event\n );\n\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id\n );\n }\n\n msg_iev_set_msg_type(gobj, kw, \"__message__\");\n\n return send_static_iev(gobj, event, kw, src);\n}\n\n/***************************************************************\n * Framework Method subscription_added\n ***************************************************************/\nfunction mt_subscription_added(gobj, subs)\n{\n let priv = gobj.priv;\n\n if(gobj_current_state(gobj) !== \"ST_SESSION\" || !priv.websocket) {\n /* on_open will send all subscriptions. The !websocket case is the\n * teardown window: mt_stop already closed the socket but the async\n * onclose hasn't moved the FSM out of ST_SESSION yet. */\n return 0;\n }\n\n if(priv.inside_on_open) {\n // avoid duplicates of subscriptions\n return 0;\n }\n return send_remote_subscription(gobj, subs);\n}\n\n/***************************************************************\n * Framework Method subscription_deleted\n ***************************************************************/\nfunction mt_subscription_deleted(gobj, subs)\n{\n let priv = gobj.priv;\n // in C: return 0;\n // TODO hay algo mal, las subscripciones locales se interpretan como remotas\n\n if(gobj_current_state(gobj) !== \"ST_SESSION\" || !priv.websocket) {\n /* Nothing to do: on open this subscription will not be re-sent.\n * The !websocket case is the teardown window (stop+destroy in the\n * same turn): the socket is gone but the async onclose hasn't moved\n * the FSM out of ST_SESSION — the remote side drops the session's\n * subscriptions on close anyway. */\n return 0;\n }\n\n if(priv.inside_on_open) {\n // avoid duplicates of subscriptions\n return 0;\n }\n if(empty_string(subs.event)) {\n // HACK only resend explicit subscriptions\n return 0;\n }\n\n let kw = {};\n\n let __global__ = subs.__global__;\n let __config__ = subs.__config__;\n let __filter__ = subs.__filter__;\n let __service__ = subs.__service__;\n let subscriber = subs.subscriber;\n\n if(__config__) {\n kw[\"__config__\"] = __config__;\n }\n if(__global__) {\n kw[\"__global__\"] = __global__;\n }\n if(__filter__) {\n kw[\"__filter__\"] = __filter__;\n }\n\n /*\n * __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(subscriber),\n __service__\n );\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n IEVENT_STACK_ID,\n jn_ievent_id // owned\n );\n\n msg_iev_set_msg_type(gobj, kw, \"__unsubscribing__\");\n\n return send_static_iev(gobj, subs.event, kw, gobj);\n}\n\n\n\n\n /***************************\n * Local Methods\n ***************************/\n\n\n\n\n/***************************************************************\n * Setup WebSocket\n * Mixin DOM events -> Yuneta events\n ***************************************************************/\nfunction setup_websocket(gobj)\n{\n if(gobj.priv.websocket) {\n log_error(`Websocket ALREADY setup`);\n }\n\n const url = gobj_read_str_attr(gobj, \"url\");\n log_debug(`====> Starting WebSocket to '${url}' (${gobj_short_name(gobj)})`);\n\n let websocket;\n try {\n websocket = new WebSocket(url);\n } catch (e) {\n log_error(`${gobj_short_name(gobj)}: Cannot open WebSocket to '${url}', Error: ${e.message}`);\n return null;\n }\n\n if (!websocket) {\n log_error(`${gobj_short_name(gobj)}: Failed to initialize WebSocket.`);\n return null;\n }\n\n websocket.onopen = () => {\n // log_debug(`${gobj_short_name(gobj)}: WebSocket connection opened.`);\n gobj_send_event(gobj, \"EV_ON_OPEN\", { url }, gobj);\n };\n\n websocket.onmessage = (e) => {\n // log_debug(`${gobj_short_name(gobj)}: Received message: ${event.data}`);\n gobj_send_event(gobj, \"EV_ON_MESSAGE\", { url, data: e.data }, gobj);\n };\n\n // not useful\n // websocket.onerror = (e) => {\n // log_error(`${gobj_short_name(gobj)}: WebSocket error occurred.`);\n // };\n\n websocket.onclose = (e) => {\n /*\n * A stop+destroy in the same turn (e.g. a wrapper tearing its\n * transport down on logout) leaves this async onclose to fire\n * AFTER the gobj is gone. gobj_is_destroying() covers both the\n * destroying and destroyed flags; bail out so we don't send\n * EV_ON_CLOSE to a dead gobj (\"gobj dst DESTROYED\"). A stop that\n * keeps the gobj alive still gets its EV_ON_CLOSE.\n */\n if(gobj_is_destroying(gobj)) {\n return;\n }\n if(!gobj_read_bool_attr(gobj_yuno(), \"browser_beforeunload\")) {\n gobj_send_event(\n gobj,\n \"EV_ON_CLOSE\",\n {\n url, e: e\n },\n gobj\n );\n } else {\n log_warning('Close websocket by unload page');\n }\n };\n\n return websocket; // Return the WebSocket instance\n}\n\n/***************************************************************\n * Closes the WebSocket connection safely.\n ***************************************************************/\nfunction close_websocket(gobj, code = 1000, reason = \"\")\n{\n let priv = gobj.priv;\n\n let websocket = priv.websocket;\n priv.websocket = null;\n\n if (!websocket ||\n websocket.readyState === WebSocket.CLOSED ||\n websocket.readyState === WebSocket.CLOSING)\n {\n log_warning(\"WebSocket is already closed or in the process of closing.\");\n return;\n }\n\n log_debug(`Closing WebSocket (Code: ${code}, Reason: \"${reason}\")`);\n\n try {\n websocket.close(code, reason);\n } catch (e) {\n log_error(\"Error closing WebSocket:\", e.message);\n }\n}\n\n/***************************************************************\n * Trace intra event\n ***************************************************************/\nfunction trace_inter_event(gobj, prefix, iev)\n{\n let hora = current_timestamp();\n try {\n log_debug(\"\\n\" + hora + \" \" + prefix + \"\\n\");\n //trace_msg(JSON.stringify(iev, null, 4));\n trace_json(iev);\n } catch (e) {\n log_debug(\"ERROR in trace_inter_event: \" + e);\n }\n}\n\n/************************************************************\n * inter event container\n ************************************************************/\nclass InterEvent {\n constructor(event, kw) {\n this.event = event;\n this.kw = kw || {};\n }\n}\n\n/************************************************************\n * Create inter-event\n ************************************************************/\nfunction iev_create(\n event,\n kw)\n{\n if(empty_string(event)) {\n log_error(\"iev_create() event NULL\");\n return null;\n }\n\n return new InterEvent(event, kw);\n}\n\n/**************************************\n * Send jsonify inter-event message\n **************************************/\nfunction send_iev(gobj, iev)\n{\n let priv = gobj.priv;\n\n let msg = JSON.stringify(iev);\n\n if(is_traffic_tracing(gobj)) {\n let url = gobj_read_str_attr(gobj, \"url\");\n let prefix = gobj_name(gobj_yuno()) + ' ==> ' + url;\n let trace_ievent_callback = gobj_read_attr(gobj_yuno(), \"trace_ievent_callback\");\n if(trace_ievent_callback) {\n let size = msg.length;\n trace_ievent_callback(prefix, iev, 1, size);\n } else {\n trace_inter_event(gobj, prefix, iev);\n }\n }\n\n if(!priv.websocket || priv.websocket.readyState !== WebSocket.OPEN) {\n /* Socket gone or not open (teardown window, race with a drop):\n * the message cannot be delivered. A warning, not one TypeError\n * bomb per message. */\n log_warning(`${gobj_short_name(gobj)}: send_iev(): websocket not open, message lost`);\n return -1;\n }\n try {\n priv.websocket.send(msg);\n } catch (e) {\n log_error(`${gobj_short_name(gobj)}: send_iev(): ${e}`);\n //log_error(msg);\n }\n return 0;\n}\n\n/**************************************\n *\n **************************************/\nfunction send_static_iev(gobj, event, kw, src)\n{\n let iev = iev_create(\n event,\n kw\n );\n\n return send_iev(gobj, iev);\n}\n\n/***************************************************************\n * __MESSAGE__\n ***************************************************************/\nfunction build_cli_ievent_request(gobj, src_service, dst_service)\n{\n if(empty_string(dst_service)) {\n dst_service = gobj_read_str_attr(gobj, \"wanted_yuno_service\");\n }\n\n return {\n \"dst_yuno\": gobj_read_str_attr(gobj, \"wanted_yuno_name\"),\n \"dst_role\": gobj_read_str_attr(gobj, \"wanted_yuno_role\"),\n \"dst_service\": dst_service,\n\n \"src_yuno\": gobj_yuno_name(),\n \"src_role\": gobj_yuno_role(),\n \"src_service\": src_service,\n \"host\": node_uuid()\n };\n}\n\n/***************************************************************\n * Send identity card\n ***************************************************************/\nfunction send_identity_card(gobj)\n{\n let priv = gobj.priv;\n\n let playing = gobj_is_playing(gobj_yuno());\n let yuno_version = gobj_read_str_attr(gobj_yuno(), \"yuno_version\");\n let yuno_release = gobj_read_str_attr(gobj_yuno(), \"yuno_release\");\n let yuno_tag = gobj_read_str_attr(gobj_yuno(), \"yuno_tag\");\n\n /*\n * The services THIS link needs authorized. A single-link yuno leaves it\n * empty and the yuno-wide list is used, as it always was. A multi-link\n * yuno (one C_IEVENT_CLI per backend) must set it per link: the yuno's\n * list is necessarily the union of every backend's, so each backend would\n * be handed the service names of all the others.\n */\n let required_services = gobj_read_attr(gobj, \"required_services\");\n if(!required_services || !required_services.length) {\n required_services = gobj_read_attr(gobj_yuno(), \"required_services\");\n }\n\n let kw = {\n \"yuno_role\": gobj_yuno_role(),\n \"yuno_id\": gobj_yuno_id(),\n \"yuno_name\": gobj_yuno_name(),\n \"yuno_tag\": yuno_tag,\n \"yuno_version\": yuno_version,\n \"yuno_release\": yuno_release,\n \"yuneta_version\": YUNETA_VERSION,\n \"playing\": playing,\n \"pid\": 0,\n \"watcher_pid\": 0,\n \"jwt\": gobj_read_str_attr(gobj, \"jwt\"),\n \"username\": gobj_read_str_attr(gobj_yuno(), \"__username__\"),\n \"launch_id\": 0,\n \"yuno_startdate\": gobj_read_str_attr(gobj_yuno(), \"start_date\"),\n \"id\": node_uuid(),\n \"user_agent\": typeof window !== \"undefined\" ? window.navigator.userAgent : \"\",\n \"language\": typeof window !== \"undefined\" ? window.navigator.language : \"\",\n \"required_services\": required_services\n };\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(gobj_parent(gobj)), // TODO ??? in C is gobj_name(gobj),\n null\n );\n msg_iev_push_stack(\n gobj,\n kw,\n IEVENT_STACK_ID,\n jn_ievent_id // owned\n );\n\n msg_iev_set_msg_type(gobj, kw, \"__identity__\");\n\n set_timeout(priv.gobj_timer, gobj_read_integer_attr(gobj, \"timeout_idack\"));\n\n return send_static_iev(gobj, \"EV_IDENTITY_CARD\", kw, gobj);\n}\n\n/********************************************\n * Create iev from data received\n * on websocket connection\n ********************************************/\nfunction iev_create_from_json(gobj, data)\n{\n let x;\n try {\n x = JSON.parse(data);\n } catch (e) {\n log_error(\"parsing inter_event json: \" + e);\n return null;\n }\n\n if(!(x instanceof Object)) {\n log_error(\"parsing inter_event: websocket data not a json object\");\n return null;\n }\n let event = x['event'];\n if(!event) {\n log_error(\"parsing inter_event: no event\");\n return null;\n }\n if(typeof event !== 'string') {\n log_error(\"parsing inter_event: event not a string\");\n return null;\n }\n\n let kw = x['kw'];\n if(!kw) {\n log_error(\"parsing inter_kw: no kw\");\n return null;\n }\n if(!(kw instanceof Object)) {\n log_error(\"parsing inter_event: kw not a json object\");\n return null;\n }\n\n return {\n event: event,\n kw: kw || {}\n };\n}\n\n/************************************************\n *\n ************************************************/\nfunction send_remote_subscription(gobj, subs)\n{\n if(empty_string(subs.event)) {\n // HACK only resend explicit subscriptions\n return -1;\n }\n\n let kw = {};\n\n let __global__ = subs.__global__;\n let __config__ = subs.__config__;\n let __filter__ = subs.__filter__;\n let __service__ = subs.__service__;\n let subscriber = subs.subscriber;\n\n if(__config__) {\n kw[\"__config__\"] = __config__;\n }\n if(__global__) {\n kw[\"__global__\"] = __global__;\n }\n if(__filter__) {\n kw[\"__filter__\"] = __filter__;\n }\n\n /*\n * __REQUEST__ __MESSAGE__\n */\n let jn_ievent_id = build_cli_ievent_request(\n gobj,\n gobj_name(subscriber),\n __service__\n );\n msg_iev_push_stack(\n gobj,\n kw, // not owned\n IEVENT_STACK_ID,\n jn_ievent_id // owned\n );\n\n msg_iev_set_msg_type(gobj, kw, \"__subscribing__\");\n\n return send_static_iev(gobj, subs.event, kw, gobj);\n}\n\n/***************************************************************\n * resend subscriptions\n ***************************************************************/\nfunction resend_subscriptions(gobj)\n{\n let dl_subs = gobj_find_subscriptions(\n gobj,\n null, // event,\n null, // kw (__config__, __global__, __local__)\n null // subscriber\n );\n for(let i=0; i<dl_subs.length; i++) {\n let subs = dl_subs[i];\n send_remote_subscription(gobj, subs);\n }\n}\n\n\n\n\n /***************************\n * Actions\n ***************************/\n\n\n\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_timeout_disconnected(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n if(gobj_is_running(gobj)) {\n priv.websocket = setup_websocket(gobj);\n }\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_on_open(gobj, event, kw, src)\n{\n log_debug('Websocket opened: ' + gobj.priv.url);\n send_identity_card(gobj);\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_on_close(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n let e = kw.e;\n let url = kw.url;\n\n set_remote_log_functions(); // clean remote log\n\n log_warning(`${gobj_short_name(gobj)}: WebSocket closed ${url} (Code: ${e.code}, Reason: \"${e.reason}\", Clean: ${e.wasClean})`);\n\n // Cleanup WebSocket event handlers\n if(priv.websocket) {\n priv.websocket.onopen = null;\n priv.websocket.onmessage = null;\n priv.websocket.onerror = null;\n priv.websocket.onclose = null;\n priv.websocket = null;\n }\n\n if(priv.inform_on_close) {\n /*\n * We had a real session (EV_ON_OPEN was published) and the\n * channel just dropped. Tell the subscribers — both backend\n * FSMs that need to reset their state and any frontend that\n * cares. inform_on_close is one-shot: re-armed by\n * ac_identity_card_ack on the next successful open.\n */\n priv.inform_on_close = false;\n gobj_publish_event(\n gobj,\n 'EV_ON_CLOSE',\n {\n url: url,\n remote_yuno_name: priv.remote_yuno_name,\n remote_yuno_role: priv.remote_yuno_role,\n remote_yuno_service: priv.remote_yuno_service\n }\n );\n } else {\n /*\n * WebSocket closed BEFORE EV_ON_OPEN ever fired — typical\n * causes: bad TLS cert (ERR_CERT_COMMON_NAME_INVALID), port\n * closed, backend not running, firewall. The framework\n * policy is to keep retrying forever while the gobj is\n * running (the operator may fix the issue at any time, the\n * retry counter ends up in the logs and triggers monitors),\n * so we do NOT stop and we do NOT publish EV_ON_CLOSE\n * (would break the EV_ON_OPEN→EV_ON_CLOSE FSM contract on\n * subscribers that only handle close in their connected\n * state). Instead we publish a separate event,\n * EV_ON_OPEN_ERROR, that interactive subscribers (typical:\n * a browser GUI showing a login form) can opt into. The\n * EVF_NO_WARN_SUBS flag keeps the framework quiet for the\n * many subscribers (mostly backend FSMs) that don't care.\n * Mirrors the WebSocket browser API split: .onopen /\n * .onclose / .onerror.\n *\n * log_warning leaves a precise trace per failed attempt so\n * monitors / log aggregators can alert on it (the framework\n * retries forever; without this line the only sign of\n * trouble would be the WebSocket close in the browser\n * console).\n */\n log_warning(\n `${gobj_short_name(gobj)}: EV_ON_OPEN_ERROR cannot open ` +\n `${url} (Code: ${e.code}, Reason: \"${e.reason}\", ` +\n `Clean: ${e.wasClean})`\n );\n gobj_publish_event(\n gobj,\n 'EV_ON_OPEN_ERROR',\n {\n url: url,\n remote_yuno_name: priv.remote_yuno_name,\n remote_yuno_role: priv.remote_yuno_role,\n remote_yuno_service: priv.remote_yuno_service,\n code: e.code,\n reason: e.reason,\n was_clean: e.wasClean\n }\n );\n }\n\n if(gobj_is_running(gobj)) {\n set_timeout(priv.gobj_timer, next_retry(gobj));\n }\n\n return 0;\n}\n\n/***************************************************************\n * How long to wait before the next reconnect attempt.\n *\n * The delay used to be a constant (`timeout_retry`, 5s), for ever. A\n * backend that is down — or a URL with a typo, which never comes back —\n * was therefore hit every 5 seconds for the whole life of the tab, by\n * EVERY link pointed at it, all in lockstep. It backs off now: from\n * `timeout_retry`, doubling, capped at `timeout_retry_max`.\n *\n * The jitter (±20%) is what breaks the lockstep. Without it, N links that\n * went down together retry together for ever — a thundering herd against a\n * backend that is just coming back up. It is the one place a random number\n * earns its keep.\n *\n * Reset to zero when a session is actually reached\n * (ac_identity_card_ack), so a link that flaps once does not carry a\n * minute-long penalty into its next real drop.\n ***************************************************************/\nfunction next_retry(gobj)\n{\n let priv = gobj.priv;\n\n let base = gobj_read_integer_attr(gobj, \"timeout_retry\");\n let max = gobj_read_integer_attr(gobj, \"timeout_retry_max\");\n if(max < base) {\n max = base; /* equal = the old fixed-interval behaviour */\n }\n\n priv.retry_ms = priv.retry_ms ? Math.min(priv.retry_ms * 2, max) : base;\n\n let jitter = priv.retry_ms * 0.2;\n let ms = priv.retry_ms - jitter + (Math.random() * 2 * jitter);\n return Math.max(1, Math.round(ms));\n}\n\n/********************************************\n *\n ********************************************/\nfunction ac_timeout_wait_idAck(gobj, event, kw, src)\n{\n send_identity_card(gobj);\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_identity_card_ack(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n /*---------------------------------------*\n * Clear timeout\n *---------------------------------------*/\n clear_timeout(priv.gobj_timer);\n\n /*---------------------------------------*\n * Update remote values\n *---------------------------------------*/\n /*\n * Here is the end point of the request.\n * Don't pop the request, because\n * the event can be publishing to more users.\n */\n /*\n * __RESPONSE__ __MESSAGE__\n */\n let event_id = msg_iev_get_stack(gobj, kw, IEVENT_STACK_ID, true);\n let src_yuno = kw_get_str(gobj, event_id, \"src_yuno\", \"\");\n let src_role = kw_get_str(gobj, event_id, \"src_role\", \"\");\n let src_service = kw_get_str(gobj, event_id, \"src_service\", \"\");\n gobj_write_str_attr(gobj, \"remote_yuno_name\", src_yuno);\n gobj_write_str_attr(gobj, \"remote_yuno_role\", src_role);\n gobj_write_str_attr(gobj, \"remote_yuno_service\", src_service);\n\n // WARNING comprueba result, ahora puede venir negativo\n let result = kw_get_int(gobj, kw, \"result\", -1, 0);\n let comment = kw_get_str(gobj, kw, \"comment\", \"\", 0);\n let username_ = kw_get_str(gobj, kw, \"username\", \"\", 0);\n let services_roles = kw_get_dict_value(gobj, kw, \"services_roles\", {});\n if(result < 0) {\n close_websocket(gobj);\n\n let kw_nak = {\n \"url\": gobj_read_str_attr(gobj, \"url\"),\n \"result\": result,\n \"comment\": comment,\n \"username\": username_,\n \"remote_yuno_name\": src_yuno,\n \"remote_yuno_role\": src_role,\n \"remote_yuno_service\": src_service\n };\n\n /*\n * SERVICE subscription model\n */\n if(gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), \"EV_ON_ID_NAK\", kw_nak, gobj);\n } else {\n gobj_publish_event(gobj, \"EV_ON_ID_NAK\", kw_nak);\n }\n\n } else {\n gobj_change_state(gobj, \"ST_SESSION\");\n priv.inside_on_open = true;\n\n /*\n * A session was reached: the backoff starts over. A link that flaps\n * once must not carry a minute-long penalty into its next real drop.\n */\n priv.retry_ms = 0;\n\n if(!priv.inform_on_close) {\n priv.inform_on_close = true;\n let kw_on_open = {\n \"username\": username_,\n \"remote_yuno_name\": src_yuno,\n \"remote_yuno_role\": src_role,\n \"remote_yuno_service\": src_service,\n \"services_roles\": services_roles,\n };\n\n /*\n * SERVICE subscription model\n */\n if(gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), \"EV_ON_OPEN\", kw_on_open, gobj);\n } else {\n gobj_publish_event(gobj, \"EV_ON_OPEN\", kw_on_open);\n }\n }\n\n priv.inside_on_open = false;\n\n /*\n * Resend subscriptions\n */\n resend_subscriptions(gobj);\n }\n\n return 0;\n}\n\n/***************************************************************\n *\n ***************************************************************/\nfunction ac_on_message(gobj, event, kw, src)\n{\n let priv = gobj.priv;\n\n let url = priv.url;\n\n /*------------------------------------------*\n * Create inter_event from received data\n *------------------------------------------*/\n let iev_msg = iev_create_from_json(gobj, kw.data);\n\n /*---------------------------------------*\n * trace inter_event\n *---------------------------------------*/\n if(is_traffic_tracing(gobj)) {\n let prefix = gobj_name(gobj_yuno()) + ' <== ' + url;\n let size = kw.data.length;\n let trace_ievent_callback = gobj_read_attr(gobj_yuno(), \"trace_ievent_callback\");\n if(trace_ievent_callback) {\n trace_ievent_callback(prefix, iev_msg, 2, size);\n } else {\n trace_inter_event(gobj, prefix, iev_msg);\n }\n }\n\n /*----------------------------------------*\n *\n *----------------------------------------*/\n let iev_event = iev_msg.event;\n let iev_kw = iev_msg.kw;\n\n /*-----------------------------------------*\n * If state is not in SESSION, send self.\n * Mainly process EV_IDENTITY_CARD_ACK\n *-----------------------------------------*/\n if(gobj_current_state(gobj) !== \"ST_SESSION\") {\n if(gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {\n /* Handled unless the action says it FAILED. Not `=== 0`: an\n * action that simply returns nothing answers `undefined`, which\n * is not `=== 0`, and the session was then closed on a message\n * that had just been processed fine. */\n let ret = gobj_send_event(gobj, iev_event, iev_kw, gobj);\n if(!(ret < 0)) {\n // iev_kw consumed\n return 0;\n }\n // iev_kw consumed\n } else {\n log_error(`${gobj_short_name(gobj)}: event UNKNOWN in not-session state ${iev_event}`);\n }\n close_websocket(gobj);\n return -1;\n }\n\n iev_msg = null;\n\n /*------------------------------------*\n * Analyze inter_event\n *------------------------------------*/\n let msg_type = msg_iev_get_msg_type(gobj, iev_kw);\n\n /*----------------------------------------*\n * Get inter-event routing information.\n *----------------------------------------*/\n let event_id = msg_iev_get_stack(gobj, iev_kw, IEVENT_STACK_ID);\n\n /*----------------------------------------*\n * Check dst role^name\n *----------------------------------------*/\n let iev_dst_role = kw_get_str(gobj, event_id, \"dst_role\", \"\");\n // Check yuno_name too\n\n if(iev_dst_role.toLowerCase() !== gobj_yuno_role().toLowerCase()) {\n log_error(`\"It's not my role, dst_role: ${iev_dst_role}, my_role: ${gobj_yuno_role()}`);\n return 0;\n }\n\n /*----------------------------------------*\n * Check dst service\n *----------------------------------------*/\n let iev_dst_service = kw_get_str(gobj, event_id, \"dst_service\", \"\");\n\n /*------------------------------------*\n * Is the event a subscription?\n *------------------------------------*/\n if(msg_type === \"__subscribing__\") {\n /*\n * it's a external subscription\n */\n // TODO subscription\n return -1;\n }\n\n /*---------------------------------------*\n * Is the event is a unsubscription?\n *---------------------------------------*/\n if(msg_type === \"__unsubscribing__\") {\n /*\n * it's a external unsubscription\n */\n // TODO unsubscription\n return -1;\n }\n\n /*-------------------------------------------------------*\n * Filter public events of this gobj\n *-------------------------------------------------------*/\n if(gobj_has_event(gobj, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {\n /*\n * It's mine (I manage inter-command and inter-stats)\n */\n gobj_send_event(gobj, iev_event, iev_kw, gobj);\n return 0;\n }\n\n /*-------------------------------------------------------------*\n * Dispatch the event\n *\n * A MESSAGE THAT NAMES A SERVICE IS ADDRESSED TO IT, and when\n * that service is gone the message is not for anybody else.\n * Delivering it to the fallback below is how a view's private\n * stream ends up on every other subscriber of this transport.\n *\n * In an SPA that is not theoretical, and the shape is always the\n * same: a view mounted under a service name subscribes to a\n * backend event, the user navigates away, the view is destroyed,\n * and the frames already in flight keep arriving addressed to a\n * name nobody answers to. They were then published to everyone,\n * which in practice means the application gobj -- subscribed to\n * this transport with a NULL event, deliberately, because naming\n * EV_ON_OPEN in a subscription forwards it upstream and the\n * remote rejects it -- and a null subscription matches\n * everything. Its FSM does not declare a device frame, so it said\n * so, loudly, once per frame: 38 of them in one 26 ms burst on a\n * node with 38 devices.\n *\n * It is the ordinary end of a view's life and not a broken\n * invariant -- an unsubscribe cannot recall what is already on\n * the wire -- so the message is dropped with a WARNING that names\n * what was lost, not with an error and a stack.\n *-------------------------------------------------------------*/\n if(!empty_string(iev_dst_service)) {\n let gobj_service = gobj_find_service(iev_dst_service, false);\n if(!gobj_service) {\n log_warning(`${gobj_short_name(gobj)}: event for a service that is gone, DROPPED: service '${iev_dst_service}', ev '${iev_event}'`);\n return 0;\n }\n if(!gobj_has_event(gobj_service, iev_event, event_flag_t.EVF_PUBLIC_EVENT)) {\n log_error(`${gobj_short_name(gobj)}: Service found but no event or not public, service '${gobj_short_name(gobj_service)}', ev '${iev_event}'`);\n return -1;\n }\n gobj_send_event(gobj_service, iev_event, iev_kw, gobj);\n return 0;\n }\n\n /*\n * SERVICE subscription model: the message names NO destination,\n * so it belongs to whoever subscribed here. This is the path the\n * check above protects, not one it replaces.\n */\n if(gobj_is_pure_child(gobj)) {\n gobj_send_event(gobj_parent(gobj), iev_event, iev_kw, gobj);\n } else {\n gobj_publish_event(gobj, iev_event, iev_kw);\n }\n\n return 0;\n}\n\n/***************************************************************************\n * remote asking for stats\n ***************************************************************************/\nfunction ac_mt_stats(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return 0;\n}\n\n/***************************************************************************\n * remote asking for command\n ***************************************************************************/\nfunction ac_mt_command(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return 0;\n}\n\n/***************************************************************************\n * remote asking for play yuno\n ***************************************************************************/\nfunction ac_play_yuno(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return -1;\n}\n\n/***************************************************************************\n * remote asking for pause yuno\n ***************************************************************************/\nfunction ac_pause_yuno(gobj, event, kw, src)\n{\n /*\n * __RESPONSE__ __MESSAGE__\n */\n // TODO\n return -1;\n}\n\n\n\n\n /***************************\n * FSM\n ***************************/\n\n\n\n\n/*---------------------------------------------*\n * Global methods table\n *---------------------------------------------*/\nconst gmt = {\n mt_create: mt_create,\n mt_writing: mt_writing,\n mt_start: mt_start,\n mt_stop: mt_stop,\n mt_destroy: mt_destroy,\n mt_stats: mt_stats,\n mt_command_parser: mt_command,\n mt_inject_event: mt_inject_event,\n mt_subscription_added: mt_subscription_added,\n mt_subscription_deleted: mt_subscription_deleted,\n};\n\n\n/***************************************************************\n * Create the GClass\n ***************************************************************/\nfunction create_gclass(gclass_name)\n{\n if(__gclass__) {\n log_error(`GClass ALREADY created: ${gclass_name}`);\n return -1;\n }\n\n /*---------------------------------------------*\n * States\n *---------------------------------------------*/\n const st_disconnected = [\n [\"EV_ON_OPEN\", ac_on_open, \"ST_WAIT_IDENTITY_CARD_ACK\"],\n [\"EV_ON_CLOSE\", ac_on_close, null],\n [\"EV_TIMEOUT\", ac_timeout_disconnected,null],\n [null, null, null]\n ];\n const st_wait_identity_card_ack = [\n [\"EV_ON_MESSAGE\", ac_on_message, null],\n [\"EV_IDENTITY_CARD_ACK\", ac_identity_card_ack, null],\n [\"EV_ON_CLOSE\", ac_on_close, \"ST_DISCONNECTED\"],\n [\"EV_TIMEOUT\", ac_timeout_wait_idAck, null],\n [null, null, null]\n ];\n const st_session = [\n [\"EV_ON_MESSAGE\", ac_on_message, null],\n [\"EV_MT_STATS\", ac_mt_stats, null],\n [\"EV_MT_COMMAND\", ac_mt_command, null],\n [\"EV_ON_CLOSE\", ac_on_close, \"ST_DISCONNECTED\"],\n [null, null, null]\n ];\n\n const states = [\n [\"ST_DISCONNECTED\", st_disconnected],\n [\"ST_WAIT_IDENTITY_CARD_ACK\", st_wait_identity_card_ack],\n [\"ST_SESSION\", st_session],\n [null, null]\n ];\n\n /*---------------------------------------------*\n * Events\n *---------------------------------------------*/\n const event_types = [\n [\"EV_ON_MESSAGE\", event_flag_t.EVF_OUTPUT_EVENT],\n [\"EV_IDENTITY_CARD_ACK\", event_flag_t.EVF_PUBLIC_EVENT],\n [\"EV_ON_ID_NAK\", event_flag_t.EVF_PUBLIC_EVENT|event_flag_t.EVF_OUTPUT_EVENT],\n\n [\"EV_MT_STATS\", event_flag_t.EVF_PUBLIC_EVENT],\n [\"EV_MT_COMMAND\", event_flag_t.EVF_PUBLIC_EVENT],\n\n [\"EV_ON_OPEN\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [\"EV_ON_CLOSE\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [\"EV_ON_OPEN_ERROR\", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],\n [\"EV_TIMEOUT\", 0],\n [null, 0]\n ];\n\n /*----------------------------------------*\n * Create the gclass\n *----------------------------------------*/\n __gclass__ = gclass_create(\n gclass_name,\n event_types,\n states,\n gmt,\n 0, // lmt,\n attrs_table,\n PRIVATE_DATA,\n 0, // authz_table,\n 0, // command_table,\n s_user_trace_level,\n gclass_flag_t.gcflag_no_check_output_events // gclass_flag\n );\n if(!__gclass__) {\n // Error already logged\n return -1;\n }\n\n return 0;\n}\n\n/***************************************************************************\n *\n ***************************************************************************/\nfunction register_c_ievent_cli()\n{\n return create_gclass(GCLASS_NAME);\n}\n\nexport { register_c_ievent_cli };\n"],"mappings":"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"}