@vernikr/size-report 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/page/state.js CHANGED
@@ -1,27 +1,22 @@
1
- /* Программа страницы отчёта: панель выбора с легендой и таблица.
1
+ /* The page's choice state: what is switched on, how it survives a closing and how it travels as a link.
2
2
  *
3
- * Это обычный исходник, а не строка в движке: его видит линтер, и он же
4
- * вклеивается в собранную страницу (`pageScript` снимает модульный синтаксис
5
- * импорт ниже и объявления с `export` из соседнего файла). Расчёт берётся из
6
- * производных величин, поэтому включение метрики, категории или файла зовёт тот
7
- * же расчёт, что считает статическую таблицу, и не может дать других чисел.
3
+ * An ordinary source file rather than a string inside the engine: a linter sees it, and it is pasted into the assembled
4
+ * page (`pageScript` strips module syntax — the `import` lines and the `export` keywords of the chapters). The numbers
5
+ * come from the derived quantities, so switching a metric, a category or a file calls the same calculation the report's
6
+ * numbers come from and cannot yield different ones.
8
7
  *
9
- * Страница один файл без внешних ссылок, поэтому здесь нет ни динамического
10
- * импорта, ни загрузки чего-либо по сети: оформление приходит тем же файлом,
11
- * а разметка клеток повторяет статическую таблицу (`clip` и подпись коммита —
12
- * правила общей части оформления).
8
+ * The page is one file without external references, so there is no dynamic import here and nothing is loaded over the
9
+ * network: the styling arrives in the same file, and the cell markup follows the rules of the shared part of the styling
10
+ * (`clip`, a commit's caption).
13
11
  *
14
- * Панель помнит выбор читателя между открытиями и умеет передать его ссылкой
15
- * («Память выбора» ниже): запись привязана к паспорту отчёта и хранит только
16
- * выключенное по именам, поэтому чужая запись не применяется, а исчезнувшее имя
17
- * просто ничего не значит. Та же запись ложится в адрес — его и отправляют коллеге.
12
+ * The panel remembers the reader's choice between visits and can hand it over as a link ("the choice's memory" below):
13
+ * the record is tied to the report's passport and keeps only what is switched off, by name, so someone else's record is
14
+ * not applied while a vanished name simply means nothing. The same record goes into the address — which is what one
15
+ * sends to a colleague.
18
16
  *
19
- * Точность числа страница не выводит сама: пометки приближённых клеток приходят в
20
- * данных, от того же правила, по которому названа точность метрики. Из путей и
21
- * форматов страница такого вывода не делает — второго правила точности не будет. */
22
-
23
- /* Импорт — одной строкой: модульный синтаксис снимается при вклейке построчно,
24
- * и оставшаяся строка `import` попала бы в страницу (её ловит проверка). */
17
+ * The page does not derive a number's accuracy itself: the marks of approximate cells arrive in the data, from the same
18
+ * rule that names a metric's accuracy. The page draws no such conclusion from paths and formats — there will be no
19
+ * second rule of accuracy. */
25
20
 
26
21
  export const appData = JSON.parse(document.getElementById('data').textContent);
27
22
  export const appUi = JSON.parse(document.getElementById('ui').textContent);
@@ -29,42 +24,39 @@ export const appView = { metrics: {}, files: [], folded: {} };
29
24
  appData.metrics.forEach((m) => { appView.metrics[m.key] = true; });
30
25
  appData.files.forEach(() => { appView.files.push(true); });
31
26
 
32
- /* Описание метрики по ключу: подсказка приближённой клетки называет способ её
33
- * числа тот же, что стоит в подписи метрики, поэтому двух ответов про «чем
34
- * посчитано» у страницы нет. */
27
+ /* A metric's description by key: the tooltip of an approximate cell names the way its number was obtained — the same one
28
+ * that stands in the metric's caption, so the page holds no two answers about "counted with what". */
35
29
  export const appMetric = {};
36
30
  appData.metrics.forEach((m) => { appMetric[m.key] = m; });
37
31
 
38
- /* Колонка по пути файла: дерево страницы дерево проекта (все пути каталога), а
39
- * числа есть только у колонок, поэтому лист дерева по этому указателю и решает,
40
- * галочка он или подпись. Имя берётся тем же правилом, что у записи выбора
41
- * (`appFileAt`), — дерево и память читателя разойтись не могут. */
32
+ /* A column by a file's path: the page's tree is the project's tree (every path of the catalogue) while the numbers
33
+ * belong to columns only, so this pointer is what decides whether a leaf is a checkbox or a caption. The name follows the
34
+ * same rule as the choice's record (`appFileAt`), so the tree and the reader's memory cannot drift apart. */
42
35
  export const appMeasured = {};
43
36
  appData.files.forEach((_f, i) => { appMeasured[appFileAt(i)] = i; });
44
37
 
45
- /* Ссылка это тот же выбор в адресе, под своим именем: чужой якорь страницы
46
- * ссылкой не считается, и спорить с ним нечем. */
38
+ /* A link is that same choice in the address, under a name of its own: someone else's anchor on the page does not count
39
+ * as a link, and there is nothing to argue with it about. */
47
40
  const APP_LINK = '#size-report=';
48
41
 
49
- /* Три обстоятельства первой отрисовки, которые действуют только на ней:
50
- * адрес в ней не переписывается (его прислали читателю, а не наоборот), память
51
- * не трогается (присланная ссылка не выбор читателя), а сообщение о ссылке
52
- * ещё не гаснет. */
42
+ /* Three circumstances of the first drawing, which act on it alone: the address is not rewritten during it (it was sent to
43
+ * the reader rather than the other way), the memory is not touched (a link that came in is not the reader's choice), and
44
+ * the message about the link has not faded yet. */
53
45
  let appStartup = true;
54
46
  let appForeign = false;
55
47
  let appTransient = false;
56
48
 
57
- /* -------- память выбора читателя -------- */
49
+ /* -------- the reader's memory of his choice -------- */
58
50
 
59
- /* Имя файла для записи путь на HEAD, а если файла там уже нет, последний из
60
- * настроек: по нему файл и опознаётся в отчёте. */
51
+ /* The name of a file for the record is its path at HEAD, or the last of the settings when the file is already gone from
52
+ * there: that is the name it is recognised by in the report. */
61
53
  export function appFileAt(i) {
62
54
  const f = appData.files[i];
63
55
  return f.path === null ? f.paths[0] : f.path;
64
56
  }
65
57
 
66
- /* Отпечаток паспорта: опознавательный знак записи, а не защита от подделки,
67
- * поэтому 32 бит достаточно (FNV-1a). */
58
+ /* The passport's fingerprint: an identifying mark of a record rather than protection against forgery, so 32 bits are
59
+ * enough (FNV-1a). */
68
60
  function appHash(text) {
69
61
  let h = 2166136261;
70
62
  for (let i = 0; i < text.length; i++) {
@@ -74,22 +66,20 @@ function appHash(text) {
74
66
  return (h >>> 0).toString(16);
75
67
  }
76
68
 
77
- /* Паспорт отчёта: имя инструмента, схема данных, путь артефакта, заголовок и метки
78
- * колонок в порядке отчёта. Он и отделяет один отчёт от другого по нему выбирается
79
- * ключ записи, поэтому выбор с чужого отчёта не подхватывается. Версии пакета и
80
- * верхушки истории в паспорте нет намеренно: это тот же отчёт обновление
81
- * инструмента не меняет того, что значит колонка, а подросшая история это та же
82
- * история, к которой читатель и возвращается. */
69
+ /* The report's passport: the tool's name, the data schema, the artifact's path, the title and the column labels in the
70
+ * report's order. It is what tells one report from anotherthe record's key is chosen by it, so a choice made in
71
+ * someone else's report is not picked up. The package version and the top of the history are absent on purpose: this is
72
+ * the same report updating the tool does not change what a column means, while a grown history is the very history the
73
+ * reader comes back to. */
83
74
  function appPassport() {
84
75
  return appHash([appData.tool.name, appData.schema, appData.report.artifact,
85
76
  appData.report.title, appData.files.map((f) => f.label).join('|')].join('\n'));
86
77
  }
87
78
  const appKey = 'size-report:' + appPassport();
88
79
 
89
- /* Запись выбора одна на всё: её кладут и в память, и в адрес, поэтому двух
90
- * форматов одного состояния не бывает. Хранится только выключенное, по именам:
91
- * «включено» и «записи нет» одно и то же состояние, поэтому возврат всех галочек
92
- * убирает запись, а не оставляет след, неотличимый от выбора. */
80
+ /* One record of the choice for everything: it goes both into the memory and into the address, so there are no two formats
81
+ * of one state. Only what is switched off is kept, by name: "switched on" and "no record" are the same state, which is
82
+ * why turning every checkbox back on removes the record instead of leaving a trace indistinguishable from a choice. */
93
83
  function appRecord() {
94
84
  const metrics = {};
95
85
  const files = {};
@@ -98,7 +88,7 @@ function appRecord() {
98
88
  return { v: 1, passport: appPassport(), metrics: metrics, files: files };
99
89
  }
100
90
 
101
- // Своя ли запись и того ли форматаодно правило и для памяти, и для адреса.
91
+ // Whether a record is ours and of the right format one rule for the memory and the address alike.
102
92
  function appRecordOk(rec) {
103
93
  return rec !== null && typeof rec === 'object' && rec.v === 1 && rec.passport === appPassport();
104
94
  }
@@ -111,34 +101,33 @@ export function appWrite() {
111
101
  if (empty) window.localStorage.removeItem(appKey);
112
102
  else window.localStorage.setItem(appKey, JSON.stringify(rec));
113
103
  } catch (_e) {
114
- /* Памяти нет (браузер её не даёт этой странице): выбор не переживёт закрытия,
115
- * а числа и разметка от этого не зависят. */
104
+ /* There is no memory (the browser grants this page none): the choice will not survive a closing, while the numbers
105
+ * and the markup do not depend on it. */
116
106
  }
117
107
  }
118
- /* Адрес и есть ссылка для коллеги, поэтому он повторяет выбор. Но не на первой
119
- * отрисовке и не тогда, когда ссылка оказалась чужой: присланный адрес не наш,
120
- * его читателю ещё читать. */
108
+ /* The address is the link for a colleague, which is why it repeats the choice. But not during the first drawing and not
109
+ * when the link turned out to be someone else's: an address that came in is not ours, and the reader has yet to read
110
+ * it. */
121
111
  if (appStartup || appForeign) return;
122
112
  try {
123
113
  window.history.replaceState(null, '', APP_LINK + encodeURIComponent(JSON.stringify(rec)));
124
114
  } catch (_e) {
125
- /* Браузер не даёт менять адрес: ссылку тогда берут из памяти браузера. */
115
+ /* The browser grants no change of the address: the link is then taken from the browser's memory. */
126
116
  }
127
117
  }
128
118
 
129
- /* Сброс к «включено всё»: граница между «в отчёте этого больше нет» и
130
- * «выключено» это запись, а не отсутствие значения. Ссылка несёт весь выбор
131
- * отправителя, поэтому применяется на чистом виде, а не поверх чужого. */
119
+ /* A reset to "everything on": the border between "this is no longer in the report" and "switched off" is the record
120
+ * rather than a missing value. A link carries the sender's whole choice, which is why it is applied to a clean view rather
121
+ * than on top of someone else's. */
132
122
  function appAll() {
133
123
  appData.metrics.forEach((m) => { appView.metrics[m.key] = true; });
134
124
  appData.files.forEach((_f, i) => { appView.files[i] = true; });
135
125
  }
136
126
 
137
- /* Что говорит адрес. Отвечает либо своей записью, либо отказом (`linkForeign` —
138
- * ссылка другого отчёта, `linkBroken` — прочитать нечего): чужой или испорченный
139
- * выбор не применяется, но и не молчит иначе читатель не поймёт, почему он видит
140
- * не то, что ему прислали. Адрес без имени ссылки не ссылка вовсе: молчание, чтобы
141
- * не спорить с обычными якорями страницы. */
127
+ /* What the address says. It answers either with a record of ours or with a refusal (`linkForeign` — a link of another
128
+ * report, `linkBroken` — nothing to read): someone else's or a broken choice is not applied, but it does not stay silent
129
+ * either otherwise the reader would not understand why he sees something other than what was sent to him. An address
130
+ * without the link's name is no link at all: silence, so as not to argue with the page's ordinary anchors. */
142
131
  function appLinkRead() {
143
132
  const hash = window.location.hash || '';
144
133
  if (hash.indexOf(APP_LINK) !== 0) return { rec: null, refused: null };
@@ -160,8 +149,8 @@ function appLinkRead() {
160
149
  return { rec: rec, refused: null, extra: appUnknown(rec) };
161
150
  }
162
151
 
163
- /* Сколько имён в ссылке этому отчёту неизвестны: о них читателю надо сказать
164
- * иначе он будет искать в таблице то, чего в ней и не было. */
152
+ /* How many names in the link are unknown to this report: the reader has to be told about them otherwise he would look
153
+ * in the table for something that was never there. */
165
154
  function appUnknown(rec) {
166
155
  const known = {};
167
156
  const metricKeys = {};
@@ -173,19 +162,18 @@ function appUnknown(rec) {
173
162
  return n;
174
163
  }
175
164
 
176
- /* Сообщение о ссылке гаснет после первого же действия читателя: он его прочитал, а
177
- * постоянное предупреждение это шум поверх чисел. */
165
+ /* The message about the link fades after the reader's very first action: he has read it, and a permanent warning is noise
166
+ * on top of the numbers. */
178
167
  export function appNotice(text) {
179
168
  const el = document.getElementById('notice');
180
169
  el.textContent = text;
181
170
  el.hidden = text === '';
182
171
  }
183
172
 
184
- /* Что делает с адресом его событиеоткрытие страницы и перемена якоря на уже
185
- * открытой (браузер в этом случае документ не перезагружает, а лишь переставляет
186
- * якорь, поэтому без этого разбора ссылка работала бы только в новой вкладке).
187
- * Своя ссылка заменяет вид целиком: в ней весь выбор отправителя, а не разница с
188
- * чужим. Отказ объясняется словами — и не трогает ни вид, ни адрес. */
173
+ /* What its event does with the address opening the page and an anchor change on an already open one (the browser does
174
+ * not reload the document then, it only moves the anchor, so without this reading a link would work in a new tab alone).
175
+ * A link of ours replaces the view whole: it holds the sender's entire choice rather than a difference from someone
176
+ * else's. A refusal is explained in words and touches neither the view nor the address. */
189
177
  export function appLinkUse() {
190
178
  const link = appLinkRead();
191
179
  if (link.rec !== null) {
@@ -201,9 +189,8 @@ export function appLinkUse() {
201
189
  return 'none';
202
190
  }
203
191
 
204
- /* Чтение: только своя записьсвоей версии формата и своего паспорта. Запись
205
- * чужого отчёта лежит под другим ключом, а чужая, устаревшая или испорченная
206
- * равносильна её отсутствию. */
192
+ /* Reading: only a record of ours of our format version and our passport. Another report's record lies under another key,
193
+ * while a foreign, outdated or broken one amounts to its absence. */
207
194
  export function appRead() {
208
195
  let text = null;
209
196
  try {
@@ -221,10 +208,9 @@ export function appRead() {
221
208
  return appRecordOk(rec) ? rec : null;
222
209
  }
223
210
 
224
- /* Применение по именам: файл опознаётся путём, метрика ключом. Имени, которого в
225
- * отчёте нет, ничего не соответствует (колонку перенаправили на другой путь,
226
- * метрику убрали из настроек), а появившиеся файлы и метрики остаются включёнными
227
- * как их видит тот, кто открыл страницу впервые. */
211
+ /* Applying goes by name: a file is recognised by its path, a metric by its key. A name the report does not hold matches
212
+ * nothing (a column was pointed at another path, a metric was dropped from the settings), while files and metrics that
213
+ * appeared stay switched on the way someone opening the page for the first time sees them. */
228
214
  export function appApply(rec) {
229
215
  const metrics = rec.metrics || {};
230
216
  const files = rec.files || {};
@@ -232,13 +218,12 @@ export function appApply(rec) {
232
218
  appData.files.forEach((_f, i) => { if (files[appFileAt(i)] === false) appView.files[i] = false; });
233
219
  }
234
220
 
235
- /* -------- сложенное дерево -------- */
221
+ /* -------- the folded tree -------- */
236
222
 
237
- /* Сложенные папки память того же рода, что выбор, но своей записи: она про то,
238
- * сколько дерева видно, а не про то, какие числа читают. Поэтому в адрес она не
239
- * идёт: ссылку отправляют ради чисел, а разложенное дерево дело смотрящего. Как и
240
- * у выбора, здесь помнится только сложенное (`true`), а имя папки это путь
241
- * («src/page»), поэтому исчезнувшее имя просто ничего не значит. */
223
+ /* Folded folders are a memory of the same kind as the choice, but of a record of their own: it is about how much of the
224
+ * tree is visible rather than about which numbers are read. Hence it does not go into the address: a link is sent for the
225
+ * sake of the numbers, while an unfolded tree is the onlooker's business. As with the choice, only what is folded is kept
226
+ * (`true`), and a folder's name is its path ("src/page"), so a vanished name simply means nothing. */
242
227
  const appFoldKey = appKey + ':tree';
243
228
 
244
229
  export function appFoldRead() {
@@ -268,7 +253,7 @@ export function appFoldSet(path, folded) {
268
253
  if (Object.keys(rec.folded).length === 0) window.localStorage.removeItem(appFoldKey);
269
254
  else window.localStorage.setItem(appFoldKey, JSON.stringify(rec));
270
255
  } catch (_e) {
271
- /* Памяти нет: сложенное не переживёт закрытия страницы, а вид от этого не
272
- * зависит дерево сложено ровно так, как его сложил читатель сейчас. */
256
+ /* There is no memory: what is folded will not survive a closing, while the view does not depend on it — the tree is
257
+ * folded exactly the way the reader folded it just now. */
273
258
  }
274
259
  }
package/src/page/table.js CHANGED
@@ -2,11 +2,10 @@ import { cellParts, commitParts, nowModel, rowModel, valueParts } from '../deriv
2
2
  import { appEl } from './dom.js';
3
3
  import { appData, appUi, appView, appMetric } from './state.js';
4
4
 
5
- /* Приближённая клетка: пометка берётся из данных движка, а не выводится здесь из
6
- * пути файла, правило точности живёт там же, где считаются числа. У клетки
7
- * файла это её собственное число, у итога худшее из вошедших в него, иначе
8
- * сумма обещала бы точность, которой нет у слагаемых. Возвращается описание
9
- * метрики (её способ и идёт в подсказку клетки) либо ничего. */
5
+ /* An approximate cell: the mark comes from the engine's data rather than being derived here from a file's path — the rule
6
+ * of accuracy lives where the numbers are counted. For a file's cell it is that number itself, for a total the worst of
7
+ * what went into it, or the sum would promise an accuracy its terms do not have. Returns the metric's description (its way
8
+ * of counting is what goes into the cell's tooltip) or nothing. */
10
9
  export function appApprox(where, files, key) {
11
10
  const marks = appData.approx[key];
12
11
  if (marks === undefined) return null;
@@ -18,13 +17,13 @@ export function appApprox(where, files, key) {
18
17
  return null;
19
18
  }
20
19
 
21
- /* Класс клетки собирается в одном месте: и пометка приближения, и пропуск
22
- * («файла нет») свойства самой клетки, а не её содержимого. */
20
+ /* The cell's class is assembled in one place: both the mark of approximation and the gap ("no such file") are properties
21
+ * of the cell itself rather than of its content. */
23
22
  function appCellClass(first, miss, approx) {
24
23
  return 'num' + (first ? ' g' : '') + (miss ? ' miss' : '') + (approx === null ? '' : ' approx');
25
24
  }
26
25
 
27
- // Разметка клетки строки-коммита: правила в cellParts, здесь только узел.
26
+ // The markup of a commit row's cell: the rules live in cellParts, only the node is here.
28
27
  export function appCell(cell, first, approx) {
29
28
  const parts = cellParts(cell.value, cell.delta, '−');
30
29
  const td = appEl('td', appCellClass(first, parts.miss, approx));
@@ -34,7 +33,7 @@ export function appCell(cell, first, approx) {
34
33
  return td;
35
34
  }
36
35
 
37
- // Разметка клетки верхней строки: правила в valueParts.
36
+ // The markup of the top row's cell: the rules live in valueParts.
38
37
  export function appValueCell(value, first, approx) {
39
38
  const parts = valueParts(value);
40
39
  const td = appEl('td', appCellClass(first, parts.miss, approx));
@@ -43,9 +42,8 @@ export function appValueCell(value, first, approx) {
43
42
  return td;
44
43
  }
45
44
 
46
- /* Подпись коммита той же разметкой, что в статической таблице: дата, тема,
47
- * метка раздела журнала. Ширину колонки и обрезку длинной темы задаёт общая часть
48
- * оформления, поэтому колонка не прыгает при переключении файлов. */
45
+ /* A commit's caption: the date, the subject, the journal section's mark. The column's width and the clipping of a long
46
+ * subject come from the shared part of the styling, which is why the column does not jump when files are switched. */
49
47
  export function appCommit(row) {
50
48
  const parts = commitParts(row, appData.report.showSha, row.href);
51
49
  const name = parts.href ? appEl('a', 'subj', parts.subject) : appEl('span', 'subj', parts.subject);
@@ -69,9 +67,9 @@ export function appSubHead(metrics) {
69
67
  return tr;
70
68
  }
71
69
 
72
- /* Состояния пустоты: когда чисел не будет вовсе, страница говорит об этом словами,
73
- * а не сеткой без колонок. Файлы можно выключить все тогда остаётся общий объём,
74
- * и подсказка объясняет, почему колонок нет. */
70
+ /* The empty states: when there will be no numbers at all, the page says so in words rather than showing a grid without
71
+ * columns. Every file can be switched off then the total volume remains, and the note explains why there are no
72
+ * columns. */
75
73
  export function appState(metricsCount, filesCount) {
76
74
  const state = document.getElementById('state');
77
75
  const text = metricsCount === 0 ? appUi.empty : (filesCount === 0 ? appUi.noFiles : '');
@@ -80,9 +78,9 @@ export function appState(metricsCount, filesCount) {
80
78
  document.getElementById('shell').hidden = metricsCount === 0;
81
79
  }
82
80
 
83
- /* Шапка: строка групп (итог и файлы) и строка метрик под ней. Метрики повторяются
84
- * на каждый файл, поэтому подшапка собирается один раз, а дальше её узлы
85
- * переезжают в следующие — копий разметки не заводится. */
81
+ /* The header: a row of groups (the total and the files) and a row of metrics under it. The metrics repeat for every file,
82
+ * so the sub-header is assembled once and its nodes then move on into the following ones — no copies of the markup are
83
+ * made. */
86
84
  export function appHead(shown, files, metrics) {
87
85
  const head = appEl('tr');
88
86
  const commit = appEl('th', 'c-commit', appUi.commit);
@@ -107,9 +105,9 @@ export function appHead(shown, files, metrics) {
107
105
  return thead;
108
106
  }
109
107
 
110
- /* Строка-коммит: подпись и числа. Дельты считает общий расчёт (`rowModel`) тот
111
- * же, что считает статическую таблицу; здесь только узлы. Пометка приближения
112
- * своя у каждой клетки: у итога по всем вошедшим файлам, у файла по нему самому. */
108
+ /* A commit row: the caption and the numbers. The deltas come from the shared calculation (`rowModel`) rather than from
109
+ * here two ways to count one row would be two answers. The mark of approximation is each cell's own: for a total it
110
+ * covers every file that went into it, for a file that file alone. */
113
111
  export function appRow(r, metrics, files) {
114
112
  const row = appData.rows[r];
115
113
  const prev = r === 0 ? null : appData.rows[r - 1];
@@ -125,9 +123,8 @@ export function appRow(r, metrics, files) {
125
123
  return tr;
126
124
  }
127
125
 
128
- /* Тело: строки коммитов снизу вверх (свежие первыми) плюс верхняя строка «сейчас»
129
- * с абсолютными размерами на HEAD. Дельты под ней сходятся с ней, поэтому она и
130
- * стоит первой. */
126
+ /* The body: the commit rows built from the newest down, plus the "now" row with the absolute sizes at HEAD. The deltas
127
+ * under it add up to it, which is why it stands first. */
131
128
  export function appBody(metrics, files) {
132
129
  const body = appEl('tbody');
133
130
  for (let r = appData.rows.length - 1; r >= 0; r--) body.appendChild(appRow(r, metrics, files));
@@ -1,18 +1,18 @@
1
1
  import vm from 'vm';
2
2
  import { workerData } from 'worker_threads';
3
3
 
4
- /* Рабочий поток разбора: компилирует текст и отвечает причиной (или её
5
- * отсутствием). Исполнения нет — `SourceTextModule` только разбирает текст,
6
- * поэтому ни `import`, ни код модуля не выполняются: файл проекта остаётся
7
- * чужим кодом, который никто не запускает.
4
+ /* The parsing worker: it compiles the text and answers with a reason (or with the absence of
5
+ * one). Nothing is executed — `SourceTextModule` only parses the text, so neither `import`
6
+ * nor the code of the module runs: the file of the project stays foreign code that nobody
7
+ * launches.
8
8
  *
9
- * Флаги приходят от главного потока (`--experimental-vm-modules` без него
10
- * `vm.SourceTextModule` не существует, `--no-warnings` иначе предупреждение об
11
- * эксперименте ушло бы в вывод команды). Модуля может не быть: тогда ответ несёт
12
- * `available: false`, и главный поток возвращается к запуску `node --check`.
9
+ * The flags arrive from the main thread (`--experimental-vm-modules`, without which
10
+ * `vm.SourceTextModule` does not exist, and `--no-warnings` lest the experimental warning end
11
+ * up in the command's output). The module may be absent: then the answer carries
12
+ * `available: false`, and the main thread falls back to launching `node --check`.
13
13
  *
14
- * Готовность ответа отмечается в общей памяти: главный поток ждёт её синхронно
15
- * (`Atomics.wait`), потому что измерение истории синхронное.
14
+ * Readiness is marked in shared memory: the main thread waits for it synchronously
15
+ * (`Atomics.wait`), because measuring the history is synchronous.
16
16
  */
17
17
  const { port, sig } = workerData;
18
18
  const available = typeof vm.SourceTextModule === 'function';