@yuneta/gobj-ui 7.23.31 → 7.23.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gobj-ui.cjs.js +90 -5
- package/dist/gobj-ui.es.js +90 -5
- package/package.json +1 -1
- package/src/dev_machine_trace.js +116 -0
- package/src/dev_machine_trace.test.js +98 -0
- package/src/yui_dev.js +39 -5
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -64092,6 +64092,86 @@ function register_c_yui_period() {
|
|
|
64092
64092
|
return create_gclass(GCLASS_NAME);
|
|
64093
64093
|
}
|
|
64094
64094
|
//#endregion
|
|
64095
|
+
//#region src/dev_machine_trace.js
|
|
64096
|
+
/***********************************************************************
|
|
64097
|
+
* dev_machine_trace.js
|
|
64098
|
+
*
|
|
64099
|
+
* Reading a MACHINE trace line back.
|
|
64100
|
+
*
|
|
64101
|
+
* The developer window mirrors the runtime's log, and the
|
|
64102
|
+
* `machine` trace is most of what lands there once it is on.
|
|
64103
|
+
* Those lines arrive as text, so to the window they were just
|
|
64104
|
+
* "a debug log" -- which is why its `Periodic` filter could
|
|
64105
|
+
* not touch them: the filter works on a signature, and every
|
|
64106
|
+
* mirrored log carried the same one (`log:debug`).
|
|
64107
|
+
*
|
|
64108
|
+
* This gives a machine line back its EVENT, which is the only
|
|
64109
|
+
* thing that says whether it is noise. Both formats gobj-js
|
|
64110
|
+
* emits (`gobj_set_trace_machine_format`):
|
|
64111
|
+
*
|
|
64112
|
+
* 0 verbose "🔄 mach(C_TIMER^t), st: ST_IDLE, ev: EV_TIMEOUT, ac: …"
|
|
64113
|
+
* "<- mach(C_TIMER^t), st: ST_IDLE, ev: EV_TIMEOUT, ret: 0"
|
|
64114
|
+
* 1 compact "🔄 EV_TIMEOUT C_TIMER^t ST_IDLE from C_TIMER^t"
|
|
64115
|
+
*
|
|
64116
|
+
* Copyright (c) 2026, ArtGins.
|
|
64117
|
+
* All Rights Reserved.
|
|
64118
|
+
***********************************************************************/
|
|
64119
|
+
var MACHINE_MARK_RE = /\bmach\(/;
|
|
64120
|
+
var EVENT_FIELD_RE = /\bev:\s*([A-Za-z0-9_]+)/;
|
|
64121
|
+
var EVENT_HEAD_RE = /^\s*\S{0,4}\s*(EV_[A-Za-z0-9_]+)(?=\s|$)/;
|
|
64122
|
+
var PERIODIC_EVENT_RE = /PERIODIC|TIMEOUT|HEARTBEAT|PING|POLL/i;
|
|
64123
|
+
/************************************************************
|
|
64124
|
+
* The event of a machine trace line, or "" when the line is
|
|
64125
|
+
* not one.
|
|
64126
|
+
*
|
|
64127
|
+
* "" is also the answer for a machine line that carries no
|
|
64128
|
+
* event -- a state change ("new st(…), prev st(…)") -- and
|
|
64129
|
+
* that is right: what it reports is not repetitive.
|
|
64130
|
+
************************************************************/
|
|
64131
|
+
function machine_event_of(text) {
|
|
64132
|
+
if (typeof text !== "string" || text.length === 0) return "";
|
|
64133
|
+
if (MACHINE_MARK_RE.test(text)) {
|
|
64134
|
+
let m = EVENT_FIELD_RE.exec(text);
|
|
64135
|
+
return m ? m[1] : "";
|
|
64136
|
+
}
|
|
64137
|
+
let m = EVENT_HEAD_RE.exec(text);
|
|
64138
|
+
return m ? m[1] : "";
|
|
64139
|
+
}
|
|
64140
|
+
/************************************************************
|
|
64141
|
+
* Is this event one of the ones that arrive by themselves,
|
|
64142
|
+
* for ever, and say nothing about what the app is doing?
|
|
64143
|
+
************************************************************/
|
|
64144
|
+
function is_periodic_event(event_name) {
|
|
64145
|
+
if (!event_name) return false;
|
|
64146
|
+
return PERIODIC_EVENT_RE.test(event_name);
|
|
64147
|
+
}
|
|
64148
|
+
/************************************************************
|
|
64149
|
+
* The signature of a mirrored log line: what the window
|
|
64150
|
+
* counts it under and what its filters match on.
|
|
64151
|
+
*
|
|
64152
|
+
* A machine line is signed by its EVENT, so a hundred
|
|
64153
|
+
* EV_TIMEOUTs are one recurring thing rather than a hundred
|
|
64154
|
+
* anonymous debug lines. Everything else is signed by its
|
|
64155
|
+
* level, as before.
|
|
64156
|
+
************************************************************/
|
|
64157
|
+
function log_signature(level, text) {
|
|
64158
|
+
let event = machine_event_of(text);
|
|
64159
|
+
if (event) return "mach:" + event;
|
|
64160
|
+
return "log:" + (level || "debug");
|
|
64161
|
+
}
|
|
64162
|
+
/************************************************************
|
|
64163
|
+
* May the periodic filter hide this log line?
|
|
64164
|
+
*
|
|
64165
|
+
* Only a machine transition, and only below warning level.
|
|
64166
|
+
* An ERROR that names EV_TIMEOUT -- "Event NOT DEFINED in
|
|
64167
|
+
* state", which is exactly the loud one the framework wants
|
|
64168
|
+
* seen -- must never disappear because of the word in it.
|
|
64169
|
+
************************************************************/
|
|
64170
|
+
function log_is_periodic(level, text) {
|
|
64171
|
+
if (level === "error" || level === "warning") return false;
|
|
64172
|
+
return is_periodic_event(machine_event_of(text));
|
|
64173
|
+
}
|
|
64174
|
+
//#endregion
|
|
64095
64175
|
//#region src/yui_dev.js
|
|
64096
64176
|
/***********************************************************************
|
|
64097
64177
|
* ui_dev.js
|
|
@@ -64228,8 +64308,9 @@ function dev_view() {
|
|
|
64228
64308
|
let v = (0, _yuneta_gobj_js.kw_get_local_storage_value)("dev_view_mode", "detailed", false);
|
|
64229
64309
|
return v === "compact" || v === "name" || v === "full" ? v : "detailed";
|
|
64230
64310
|
}
|
|
64311
|
+
var HIDE_PERIODIC_DEFAULT = 1;
|
|
64231
64312
|
function dev_hide_periodic() {
|
|
64232
|
-
return dev_num("dev_hide_periodic",
|
|
64313
|
+
return dev_num("dev_hide_periodic", HIDE_PERIODIC_DEFAULT) ? true : false;
|
|
64233
64314
|
}
|
|
64234
64315
|
function dev_route() {
|
|
64235
64316
|
let v = (0, _yuneta_gobj_js.kw_get_local_storage_value)("dev_output_route", "both", false);
|
|
@@ -64305,7 +64386,10 @@ function build_filter_ctx() {
|
|
|
64305
64386
|
};
|
|
64306
64387
|
}
|
|
64307
64388
|
function entry_hidden(e, ctx) {
|
|
64308
|
-
if (e.kind === "log")
|
|
64389
|
+
if (e.kind === "log") {
|
|
64390
|
+
if (ctx.hide_periodic && e.periodic) return true;
|
|
64391
|
+
return !!(ctx.search && e.hay.indexOf(ctx.search) < 0);
|
|
64392
|
+
}
|
|
64309
64393
|
if (e.dir === 1 && !ctx.out) return true;
|
|
64310
64394
|
if (e.dir === 2 && !ctx.inc) return true;
|
|
64311
64395
|
if (e.dir === 3 && !ctx.err) return true;
|
|
@@ -65006,7 +65090,8 @@ function info_log(level, msg, hora) {
|
|
|
65006
65090
|
dir: 0,
|
|
65007
65091
|
size: 0,
|
|
65008
65092
|
ts: traffic_now(),
|
|
65009
|
-
sig:
|
|
65093
|
+
sig: log_signature(lvl, text),
|
|
65094
|
+
periodic: log_is_periodic(lvl, text),
|
|
65010
65095
|
hay: (lvl + " " + text).toLowerCase(),
|
|
65011
65096
|
$node: null
|
|
65012
65097
|
};
|
|
@@ -65339,12 +65424,12 @@ function build_control_bar() {
|
|
|
65339
65424
|
class: "YDEV_CHIP",
|
|
65340
65425
|
"data-toggle": "periodic",
|
|
65341
65426
|
type: "button",
|
|
65342
|
-
title: "Hide
|
|
65427
|
+
title: "Hide the timers: EV_TIMEOUT / PERIODIC / HEARTBEAT / PING transitions, and recurring traffic. On by default"
|
|
65343
65428
|
},
|
|
65344
65429
|
"⊘ Periodic",
|
|
65345
65430
|
{ click: (ev) => {
|
|
65346
65431
|
ev.stopPropagation();
|
|
65347
|
-
toggle_pref("dev_hide_periodic",
|
|
65432
|
+
toggle_pref("dev_hide_periodic", HIDE_PERIODIC_DEFAULT);
|
|
65348
65433
|
} }
|
|
65349
65434
|
];
|
|
65350
65435
|
let search = [
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -64087,6 +64087,86 @@ function register_c_yui_period() {
|
|
|
64087
64087
|
return create_gclass(GCLASS_NAME);
|
|
64088
64088
|
}
|
|
64089
64089
|
//#endregion
|
|
64090
|
+
//#region src/dev_machine_trace.js
|
|
64091
|
+
/***********************************************************************
|
|
64092
|
+
* dev_machine_trace.js
|
|
64093
|
+
*
|
|
64094
|
+
* Reading a MACHINE trace line back.
|
|
64095
|
+
*
|
|
64096
|
+
* The developer window mirrors the runtime's log, and the
|
|
64097
|
+
* `machine` trace is most of what lands there once it is on.
|
|
64098
|
+
* Those lines arrive as text, so to the window they were just
|
|
64099
|
+
* "a debug log" -- which is why its `Periodic` filter could
|
|
64100
|
+
* not touch them: the filter works on a signature, and every
|
|
64101
|
+
* mirrored log carried the same one (`log:debug`).
|
|
64102
|
+
*
|
|
64103
|
+
* This gives a machine line back its EVENT, which is the only
|
|
64104
|
+
* thing that says whether it is noise. Both formats gobj-js
|
|
64105
|
+
* emits (`gobj_set_trace_machine_format`):
|
|
64106
|
+
*
|
|
64107
|
+
* 0 verbose "🔄 mach(C_TIMER^t), st: ST_IDLE, ev: EV_TIMEOUT, ac: …"
|
|
64108
|
+
* "<- mach(C_TIMER^t), st: ST_IDLE, ev: EV_TIMEOUT, ret: 0"
|
|
64109
|
+
* 1 compact "🔄 EV_TIMEOUT C_TIMER^t ST_IDLE from C_TIMER^t"
|
|
64110
|
+
*
|
|
64111
|
+
* Copyright (c) 2026, ArtGins.
|
|
64112
|
+
* All Rights Reserved.
|
|
64113
|
+
***********************************************************************/
|
|
64114
|
+
var MACHINE_MARK_RE = /\bmach\(/;
|
|
64115
|
+
var EVENT_FIELD_RE = /\bev:\s*([A-Za-z0-9_]+)/;
|
|
64116
|
+
var EVENT_HEAD_RE = /^\s*\S{0,4}\s*(EV_[A-Za-z0-9_]+)(?=\s|$)/;
|
|
64117
|
+
var PERIODIC_EVENT_RE = /PERIODIC|TIMEOUT|HEARTBEAT|PING|POLL/i;
|
|
64118
|
+
/************************************************************
|
|
64119
|
+
* The event of a machine trace line, or "" when the line is
|
|
64120
|
+
* not one.
|
|
64121
|
+
*
|
|
64122
|
+
* "" is also the answer for a machine line that carries no
|
|
64123
|
+
* event -- a state change ("new st(…), prev st(…)") -- and
|
|
64124
|
+
* that is right: what it reports is not repetitive.
|
|
64125
|
+
************************************************************/
|
|
64126
|
+
function machine_event_of(text) {
|
|
64127
|
+
if (typeof text !== "string" || text.length === 0) return "";
|
|
64128
|
+
if (MACHINE_MARK_RE.test(text)) {
|
|
64129
|
+
let m = EVENT_FIELD_RE.exec(text);
|
|
64130
|
+
return m ? m[1] : "";
|
|
64131
|
+
}
|
|
64132
|
+
let m = EVENT_HEAD_RE.exec(text);
|
|
64133
|
+
return m ? m[1] : "";
|
|
64134
|
+
}
|
|
64135
|
+
/************************************************************
|
|
64136
|
+
* Is this event one of the ones that arrive by themselves,
|
|
64137
|
+
* for ever, and say nothing about what the app is doing?
|
|
64138
|
+
************************************************************/
|
|
64139
|
+
function is_periodic_event(event_name) {
|
|
64140
|
+
if (!event_name) return false;
|
|
64141
|
+
return PERIODIC_EVENT_RE.test(event_name);
|
|
64142
|
+
}
|
|
64143
|
+
/************************************************************
|
|
64144
|
+
* The signature of a mirrored log line: what the window
|
|
64145
|
+
* counts it under and what its filters match on.
|
|
64146
|
+
*
|
|
64147
|
+
* A machine line is signed by its EVENT, so a hundred
|
|
64148
|
+
* EV_TIMEOUTs are one recurring thing rather than a hundred
|
|
64149
|
+
* anonymous debug lines. Everything else is signed by its
|
|
64150
|
+
* level, as before.
|
|
64151
|
+
************************************************************/
|
|
64152
|
+
function log_signature(level, text) {
|
|
64153
|
+
let event = machine_event_of(text);
|
|
64154
|
+
if (event) return "mach:" + event;
|
|
64155
|
+
return "log:" + (level || "debug");
|
|
64156
|
+
}
|
|
64157
|
+
/************************************************************
|
|
64158
|
+
* May the periodic filter hide this log line?
|
|
64159
|
+
*
|
|
64160
|
+
* Only a machine transition, and only below warning level.
|
|
64161
|
+
* An ERROR that names EV_TIMEOUT -- "Event NOT DEFINED in
|
|
64162
|
+
* state", which is exactly the loud one the framework wants
|
|
64163
|
+
* seen -- must never disappear because of the word in it.
|
|
64164
|
+
************************************************************/
|
|
64165
|
+
function log_is_periodic(level, text) {
|
|
64166
|
+
if (level === "error" || level === "warning") return false;
|
|
64167
|
+
return is_periodic_event(machine_event_of(text));
|
|
64168
|
+
}
|
|
64169
|
+
//#endregion
|
|
64090
64170
|
//#region src/yui_dev.js
|
|
64091
64171
|
/***********************************************************************
|
|
64092
64172
|
* ui_dev.js
|
|
@@ -64223,8 +64303,9 @@ function dev_view() {
|
|
|
64223
64303
|
let v = kw_get_local_storage_value("dev_view_mode", "detailed", false);
|
|
64224
64304
|
return v === "compact" || v === "name" || v === "full" ? v : "detailed";
|
|
64225
64305
|
}
|
|
64306
|
+
var HIDE_PERIODIC_DEFAULT = 1;
|
|
64226
64307
|
function dev_hide_periodic() {
|
|
64227
|
-
return dev_num("dev_hide_periodic",
|
|
64308
|
+
return dev_num("dev_hide_periodic", HIDE_PERIODIC_DEFAULT) ? true : false;
|
|
64228
64309
|
}
|
|
64229
64310
|
function dev_route() {
|
|
64230
64311
|
let v = kw_get_local_storage_value("dev_output_route", "both", false);
|
|
@@ -64300,7 +64381,10 @@ function build_filter_ctx() {
|
|
|
64300
64381
|
};
|
|
64301
64382
|
}
|
|
64302
64383
|
function entry_hidden(e, ctx) {
|
|
64303
|
-
if (e.kind === "log")
|
|
64384
|
+
if (e.kind === "log") {
|
|
64385
|
+
if (ctx.hide_periodic && e.periodic) return true;
|
|
64386
|
+
return !!(ctx.search && e.hay.indexOf(ctx.search) < 0);
|
|
64387
|
+
}
|
|
64304
64388
|
if (e.dir === 1 && !ctx.out) return true;
|
|
64305
64389
|
if (e.dir === 2 && !ctx.inc) return true;
|
|
64306
64390
|
if (e.dir === 3 && !ctx.err) return true;
|
|
@@ -65001,7 +65085,8 @@ function info_log(level, msg, hora) {
|
|
|
65001
65085
|
dir: 0,
|
|
65002
65086
|
size: 0,
|
|
65003
65087
|
ts: traffic_now(),
|
|
65004
|
-
sig:
|
|
65088
|
+
sig: log_signature(lvl, text),
|
|
65089
|
+
periodic: log_is_periodic(lvl, text),
|
|
65005
65090
|
hay: (lvl + " " + text).toLowerCase(),
|
|
65006
65091
|
$node: null
|
|
65007
65092
|
};
|
|
@@ -65334,12 +65419,12 @@ function build_control_bar() {
|
|
|
65334
65419
|
class: "YDEV_CHIP",
|
|
65335
65420
|
"data-toggle": "periodic",
|
|
65336
65421
|
type: "button",
|
|
65337
|
-
title: "Hide
|
|
65422
|
+
title: "Hide the timers: EV_TIMEOUT / PERIODIC / HEARTBEAT / PING transitions, and recurring traffic. On by default"
|
|
65338
65423
|
},
|
|
65339
65424
|
"⊘ Periodic",
|
|
65340
65425
|
{ click: (ev) => {
|
|
65341
65426
|
ev.stopPropagation();
|
|
65342
|
-
toggle_pref("dev_hide_periodic",
|
|
65427
|
+
toggle_pref("dev_hide_periodic", HIDE_PERIODIC_DEFAULT);
|
|
65343
65428
|
} }
|
|
65344
65429
|
];
|
|
65345
65430
|
let search = [
|
package/package.json
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* dev_machine_trace.js
|
|
3
|
+
*
|
|
4
|
+
* Reading a MACHINE trace line back.
|
|
5
|
+
*
|
|
6
|
+
* The developer window mirrors the runtime's log, and the
|
|
7
|
+
* `machine` trace is most of what lands there once it is on.
|
|
8
|
+
* Those lines arrive as text, so to the window they were just
|
|
9
|
+
* "a debug log" -- which is why its `Periodic` filter could
|
|
10
|
+
* not touch them: the filter works on a signature, and every
|
|
11
|
+
* mirrored log carried the same one (`log:debug`).
|
|
12
|
+
*
|
|
13
|
+
* This gives a machine line back its EVENT, which is the only
|
|
14
|
+
* thing that says whether it is noise. Both formats gobj-js
|
|
15
|
+
* emits (`gobj_set_trace_machine_format`):
|
|
16
|
+
*
|
|
17
|
+
* 0 verbose "🔄 mach(C_TIMER^t), st: ST_IDLE, ev: EV_TIMEOUT, ac: …"
|
|
18
|
+
* "<- mach(C_TIMER^t), st: ST_IDLE, ev: EV_TIMEOUT, ret: 0"
|
|
19
|
+
* 1 compact "🔄 EV_TIMEOUT C_TIMER^t ST_IDLE from C_TIMER^t"
|
|
20
|
+
*
|
|
21
|
+
* Copyright (c) 2026, ArtGins.
|
|
22
|
+
* All Rights Reserved.
|
|
23
|
+
***********************************************************************/
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/* The verbose format names itself; the compact one does not. */
|
|
27
|
+
const MACHINE_MARK_RE = /\bmach\(/;
|
|
28
|
+
|
|
29
|
+
/* Verbose: the event is the `ev:` field. */
|
|
30
|
+
const EVENT_FIELD_RE = /\bev:\s*([A-Za-z0-9_]+)/;
|
|
31
|
+
|
|
32
|
+
/* Compact: the event is the first token, behind the emoji. Anchored,
|
|
33
|
+
* so a line that merely MENTIONS an event ("subscribed to EV_X") is
|
|
34
|
+
* not mistaken for a transition. */
|
|
35
|
+
const EVENT_HEAD_RE = /^\s*\S{0,4}\s*(EV_[A-Za-z0-9_]+)(?=\s|$)/;
|
|
36
|
+
|
|
37
|
+
/* What "recurring" means by name. The count-based half of the filter
|
|
38
|
+
* lives in the window, which is the only thing that can count. */
|
|
39
|
+
const PERIODIC_EVENT_RE = /PERIODIC|TIMEOUT|HEARTBEAT|PING|POLL/i;
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
/************************************************************
|
|
43
|
+
* The event of a machine trace line, or "" when the line is
|
|
44
|
+
* not one.
|
|
45
|
+
*
|
|
46
|
+
* "" is also the answer for a machine line that carries no
|
|
47
|
+
* event -- a state change ("new st(…), prev st(…)") -- and
|
|
48
|
+
* that is right: what it reports is not repetitive.
|
|
49
|
+
************************************************************/
|
|
50
|
+
function machine_event_of(text)
|
|
51
|
+
{
|
|
52
|
+
if(typeof text !== "string" || text.length === 0) {
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if(MACHINE_MARK_RE.test(text)) {
|
|
57
|
+
let m = EVENT_FIELD_RE.exec(text);
|
|
58
|
+
return m? m[1]: "";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let m = EVENT_HEAD_RE.exec(text);
|
|
62
|
+
return m? m[1]: "";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/************************************************************
|
|
66
|
+
* Is this event one of the ones that arrive by themselves,
|
|
67
|
+
* for ever, and say nothing about what the app is doing?
|
|
68
|
+
************************************************************/
|
|
69
|
+
function is_periodic_event(event_name)
|
|
70
|
+
{
|
|
71
|
+
if(!event_name) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return PERIODIC_EVENT_RE.test(event_name);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/************************************************************
|
|
78
|
+
* The signature of a mirrored log line: what the window
|
|
79
|
+
* counts it under and what its filters match on.
|
|
80
|
+
*
|
|
81
|
+
* A machine line is signed by its EVENT, so a hundred
|
|
82
|
+
* EV_TIMEOUTs are one recurring thing rather than a hundred
|
|
83
|
+
* anonymous debug lines. Everything else is signed by its
|
|
84
|
+
* level, as before.
|
|
85
|
+
************************************************************/
|
|
86
|
+
function log_signature(level, text)
|
|
87
|
+
{
|
|
88
|
+
let event = machine_event_of(text);
|
|
89
|
+
if(event) {
|
|
90
|
+
return "mach:" + event;
|
|
91
|
+
}
|
|
92
|
+
return "log:" + (level || "debug");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/************************************************************
|
|
96
|
+
* May the periodic filter hide this log line?
|
|
97
|
+
*
|
|
98
|
+
* Only a machine transition, and only below warning level.
|
|
99
|
+
* An ERROR that names EV_TIMEOUT -- "Event NOT DEFINED in
|
|
100
|
+
* state", which is exactly the loud one the framework wants
|
|
101
|
+
* seen -- must never disappear because of the word in it.
|
|
102
|
+
************************************************************/
|
|
103
|
+
function log_is_periodic(level, text)
|
|
104
|
+
{
|
|
105
|
+
if(level === "error" || level === "warning") {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return is_periodic_event(machine_event_of(text));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
machine_event_of,
|
|
113
|
+
is_periodic_event,
|
|
114
|
+
log_signature,
|
|
115
|
+
log_is_periodic,
|
|
116
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import {describe, it, expect} from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
machine_event_of,
|
|
4
|
+
is_periodic_event,
|
|
5
|
+
log_signature,
|
|
6
|
+
log_is_periodic,
|
|
7
|
+
} from "./dev_machine_trace.js";
|
|
8
|
+
|
|
9
|
+
/* Real lines, copied from the developer window. */
|
|
10
|
+
const VERBOSE_IN =
|
|
11
|
+
"🔄 mach(C_TIMER^demo_yuno), st: ST_IDLE, ev: EV_TIMEOUT, ac: fi(), from(C_TIMER^demo_yuno)";
|
|
12
|
+
const VERBOSE_RET =
|
|
13
|
+
"<- mach(C_YUNO^demo_yuno), st: ST_IDLE, ev: EV_TIMEOUT_PERIODIC, ret: 0";
|
|
14
|
+
const VERBOSE_WORK =
|
|
15
|
+
"🔄 mach(C_YUI_SHELL^shell), st: ST_IDLE, ev: EV_ROUTE_CHANGED, ac: ac_route(), from(C_YUI_NAV^nav)";
|
|
16
|
+
const COMPACT =
|
|
17
|
+
"🔄 EV_TIMEOUT C_TIMER^demo_yuno ST_IDLE from C_TIMER^demo_yuno";
|
|
18
|
+
const STATE_CHANGE =
|
|
19
|
+
"🔀🔀 mach(C_TCP^conn), new st(ST_CONNECTED), prev st(ST_WAIT_CONNECTED)";
|
|
20
|
+
const NOT_DEFINED =
|
|
21
|
+
"📛 mach(C_X^x), st: ST_IDLE, ev: EV_TIMEOUT, 📛📛ERROR Event NOT DEFINED in state📛📛, from(C_TIMER^t)";
|
|
22
|
+
|
|
23
|
+
describe("machine_event_of", () => {
|
|
24
|
+
it("reads the event out of the verbose format, both lines of it", () => {
|
|
25
|
+
expect(machine_event_of(VERBOSE_IN)).toBe("EV_TIMEOUT");
|
|
26
|
+
expect(machine_event_of(VERBOSE_RET)).toBe("EV_TIMEOUT_PERIODIC");
|
|
27
|
+
expect(machine_event_of(VERBOSE_WORK)).toBe("EV_ROUTE_CHANGED");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("reads it out of the compact format, where it leads the line", () => {
|
|
31
|
+
expect(machine_event_of(COMPACT)).toBe("EV_TIMEOUT");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("a state change carries no event, and says so", () => {
|
|
35
|
+
expect(machine_event_of(STATE_CHANGE)).toBe("");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("a line that merely MENTIONS an event is not a transition", () => {
|
|
39
|
+
expect(machine_event_of("subscribed to EV_TIMEOUT of C_TIMER^t")).toBe("");
|
|
40
|
+
expect(machine_event_of("cannot send EV_ON_OPEN")).toBe("");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("is safe on anything that is not a line", () => {
|
|
44
|
+
expect(machine_event_of("")).toBe("");
|
|
45
|
+
expect(machine_event_of(null)).toBe("");
|
|
46
|
+
expect(machine_event_of(undefined)).toBe("");
|
|
47
|
+
expect(machine_event_of(42)).toBe("");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe("is_periodic_event", () => {
|
|
52
|
+
it("names the events that arrive by themselves for ever", () => {
|
|
53
|
+
expect(is_periodic_event("EV_TIMEOUT")).toBe(true);
|
|
54
|
+
expect(is_periodic_event("EV_TIMEOUT_PERIODIC")).toBe(true);
|
|
55
|
+
expect(is_periodic_event("EV_HEARTBEAT")).toBe(true);
|
|
56
|
+
expect(is_periodic_event("EV_PING")).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("leaves the ones a user caused alone", () => {
|
|
60
|
+
expect(is_periodic_event("EV_ROUTE_CHANGED")).toBe(false);
|
|
61
|
+
expect(is_periodic_event("EV_ON_MESSAGE")).toBe(false);
|
|
62
|
+
expect(is_periodic_event("")).toBe(false);
|
|
63
|
+
expect(is_periodic_event(null)).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe("log_signature", () => {
|
|
68
|
+
it("signs a machine line by its EVENT, so a hundred of them are one thing", () => {
|
|
69
|
+
expect(log_signature("debug", VERBOSE_IN)).toBe("mach:EV_TIMEOUT");
|
|
70
|
+
expect(log_signature("debug", VERBOSE_RET)).toBe("mach:EV_TIMEOUT_PERIODIC");
|
|
71
|
+
expect(log_signature("debug", COMPACT)).toBe("mach:EV_TIMEOUT");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("signs everything else by its level, as before", () => {
|
|
75
|
+
expect(log_signature("error", "connect failed")).toBe("log:error");
|
|
76
|
+
expect(log_signature("debug", "hello")).toBe("log:debug");
|
|
77
|
+
expect(log_signature("", "hello")).toBe("log:debug");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe("log_is_periodic", () => {
|
|
82
|
+
it("hides the timer traffic the filter is for", () => {
|
|
83
|
+
expect(log_is_periodic("debug", VERBOSE_IN)).toBe(true);
|
|
84
|
+
expect(log_is_periodic("debug", VERBOSE_RET)).toBe(true);
|
|
85
|
+
expect(log_is_periodic("debug", COMPACT)).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("NEVER hides an error or a warning that names a timeout", () => {
|
|
89
|
+
expect(log_is_periodic("error", NOT_DEFINED)).toBe(false);
|
|
90
|
+
expect(log_is_periodic("warning", VERBOSE_RET)).toBe(false);
|
|
91
|
+
expect(log_is_periodic("error", "connection timeout")).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("leaves a transition somebody caused alone", () => {
|
|
95
|
+
expect(log_is_periodic("debug", VERBOSE_WORK)).toBe(false);
|
|
96
|
+
expect(log_is_periodic("debug", "just a log line")).toBe(false);
|
|
97
|
+
});
|
|
98
|
+
});
|
package/src/yui_dev.js
CHANGED
|
@@ -21,6 +21,8 @@ import {
|
|
|
21
21
|
gobj_set_trace_machine_format,
|
|
22
22
|
} from "@yuneta/gobj-js";
|
|
23
23
|
|
|
24
|
+
import {log_signature, log_is_periodic} from "./dev_machine_trace.js";
|
|
25
|
+
|
|
24
26
|
import i18next from 'i18next';
|
|
25
27
|
|
|
26
28
|
/***********************************************************************
|
|
@@ -164,9 +166,20 @@ function dev_view()
|
|
|
164
166
|
return (v === "compact" || v === "name" || v === "full") ? v : "detailed";
|
|
165
167
|
}
|
|
166
168
|
|
|
169
|
+
/* ON by default. The machine trace is the reason this window
|
|
170
|
+
* exists, and a yuno with one timer emits two lines a second for
|
|
171
|
+
* ever: leaving the filter off meant the first thing anybody saw
|
|
172
|
+
* after enabling Automata was a wall of EV_TIMEOUT with their own
|
|
173
|
+
* transitions somewhere inside it. The chip turns it back off.
|
|
174
|
+
*
|
|
175
|
+
* A CONSTANT, and not the literal in two places: the reader and the
|
|
176
|
+
* toggle must agree on what "unset" means, or the first click on the
|
|
177
|
+
* chip writes the value it already had and appears to do nothing. */
|
|
178
|
+
const HIDE_PERIODIC_DEFAULT = 1;
|
|
179
|
+
|
|
167
180
|
function dev_hide_periodic()
|
|
168
181
|
{
|
|
169
|
-
return dev_num("dev_hide_periodic",
|
|
182
|
+
return dev_num("dev_hide_periodic", HIDE_PERIODIC_DEFAULT) ? true : false;
|
|
170
183
|
}
|
|
171
184
|
|
|
172
185
|
/* Where dev output (traffic + all logs + automata) is routed:
|
|
@@ -300,7 +313,21 @@ function entry_hidden(e, ctx)
|
|
|
300
313
|
{
|
|
301
314
|
if(e.kind === "log") {
|
|
302
315
|
/* Mirrored console logs respect the search box only — not the
|
|
303
|
-
* in/out/err
|
|
316
|
+
* in/out/err traffic filters, which are about DIRECTION and a
|
|
317
|
+
* log has none.
|
|
318
|
+
*
|
|
319
|
+
* The PERIODIC filter does reach them, and it has to: once
|
|
320
|
+
* Automata is on, the machine trace is what floods this
|
|
321
|
+
* window, and every one of those lines arrives here as a log.
|
|
322
|
+
* It applies to a machine TRANSITION only, and never above
|
|
323
|
+
* debug level — see log_is_periodic(). By NAME and not by
|
|
324
|
+
* count, unlike the traffic half below: a busy FSM crosses
|
|
325
|
+
* the recurrence threshold on almost every event within
|
|
326
|
+
* seconds, so counting here would empty the window of the
|
|
327
|
+
* very transitions somebody turned Automata on to read. */
|
|
328
|
+
if(ctx.hide_periodic && e.periodic) {
|
|
329
|
+
return true;
|
|
330
|
+
}
|
|
304
331
|
return !!(ctx.search && e.hay.indexOf(ctx.search) < 0);
|
|
305
332
|
}
|
|
306
333
|
if(e.dir === 1 && !ctx.out) {
|
|
@@ -1031,10 +1058,16 @@ function info_log(level, msg, hora)
|
|
|
1031
1058
|
} else {
|
|
1032
1059
|
text = is_string(msg) ? msg : String(msg);
|
|
1033
1060
|
}
|
|
1061
|
+
/* A machine line is signed by its EVENT, not by "log:debug":
|
|
1062
|
+
* that is what makes a hundred EV_TIMEOUTs ONE recurring
|
|
1063
|
+
* thing the filter and the counter can see, instead of a
|
|
1064
|
+
* hundred anonymous debug lines they cannot tell apart. */
|
|
1034
1065
|
let entry = {
|
|
1035
1066
|
kind: "log", level: lvl, text: text,
|
|
1036
1067
|
dir: 0, size: 0, ts: traffic_now(),
|
|
1037
|
-
sig:
|
|
1068
|
+
sig: log_signature(lvl, text),
|
|
1069
|
+
periodic: log_is_periodic(lvl, text),
|
|
1070
|
+
hay: (lvl + " " + text).toLowerCase(), $node: null,
|
|
1038
1071
|
};
|
|
1039
1072
|
TRAFFIC_LOG.push(entry);
|
|
1040
1073
|
if(TRAFFIC_LOG.length > TRAFFIC_MAX) {
|
|
@@ -1384,11 +1417,12 @@ function build_control_bar()
|
|
|
1384
1417
|
|
|
1385
1418
|
let periodic_chip = ['button', {
|
|
1386
1419
|
class: 'YDEV_CHIP', 'data-toggle': 'periodic', type: 'button',
|
|
1387
|
-
title: 'Hide
|
|
1420
|
+
title: 'Hide the timers: EV_TIMEOUT / PERIODIC / HEARTBEAT / PING ' +
|
|
1421
|
+
'transitions, and recurring traffic. On by default',
|
|
1388
1422
|
}, '⊘ Periodic', {
|
|
1389
1423
|
click: (ev) => {
|
|
1390
1424
|
ev.stopPropagation();
|
|
1391
|
-
toggle_pref('dev_hide_periodic',
|
|
1425
|
+
toggle_pref('dev_hide_periodic', HIDE_PERIODIC_DEFAULT);
|
|
1392
1426
|
}
|
|
1393
1427
|
}];
|
|
1394
1428
|
|