@lvce-editor/extension-search-view 1.3.0 → 1.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.
@@ -1,86 +1,66 @@
1
- const commands = Object.create(null);
2
- const registerCommand = (key, fn) => {
3
- commands[key] = fn;
4
- };
5
- const register = commandMap => {
6
- for (const [key, value] of Object.entries(commandMap)) {
7
- registerCommand(key, value);
1
+ const normalizeLine = line => {
2
+ if (line.startsWith('Error: ')) {
3
+ return line.slice('Error: '.length);
8
4
  }
9
- };
10
- const getCommand = key => {
11
- return commands[key];
12
- };
13
- const execute = (command, ...args) => {
14
- const fn = getCommand(command);
15
- if (!fn) {
16
- throw new Error(`command not found ${command}`);
5
+ if (line.startsWith('VError: ')) {
6
+ return line.slice('VError: '.length);
17
7
  }
18
- return fn(...args);
19
- };
20
-
21
- const handleError = async (error, notify = true, prefix = '') => {
22
- console.error(error);
8
+ return line;
23
9
  };
24
-
25
- const emptyObject = {};
26
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
27
- const i18nString = (key, placeholders = emptyObject) => {
28
- if (placeholders === emptyObject) {
29
- return key;
10
+ const getCombinedMessage = (error, message) => {
11
+ const stringifiedError = normalizeLine(`${error}`);
12
+ if (message) {
13
+ return `${message}: ${stringifiedError}`;
30
14
  }
31
- const replacer = (match, rest) => {
32
- // @ts-ignore
33
- return placeholders[rest];
34
- };
35
- return key.replaceAll(RE_PLACEHOLDER, replacer);
36
- };
37
-
38
- /**
39
- * @enum {string}
40
- */
41
- const UiStrings = {
42
- NoExtensionsFound: 'No extensions found.',
43
- Filter: 'Filter',
44
- Refresh: 'Refresh',
45
- ClearExtensionSearchResults: 'Clear extension search results',
46
- Enable: 'Enable',
47
- Disable: 'Disable',
48
- Uninstall: 'Uninstall',
49
- InstallAnotherVersion: 'Install Another Version',
50
- SearchExtensionsInMarketplace: 'Search Extensions in Marketplace',
51
- ViewsAndMoreActions: 'Views and more Actions...',
52
- Extensions: 'Extensions',
53
- Installed: 'Installed'
54
- };
55
- const noExtensionsFound = () => {
56
- return i18nString(UiStrings.NoExtensionsFound);
57
- };
58
- const filter = () => {
59
- return i18nString(UiStrings.Filter);
60
- };
61
- const extensions = () => {
62
- return i18nString(UiStrings.Extensions);
63
- };
64
- const clearExtensionSearchResults = () => {
65
- return i18nString(UiStrings.ClearExtensionSearchResults);
15
+ return stringifiedError;
66
16
  };
67
- const searchExtensionsInMarketPlace = () => {
68
- return i18nString(UiStrings.SearchExtensionsInMarketplace);
17
+ const NewLine$2 = '\n';
18
+ const getNewLineIndex$1 = (string, startIndex = undefined) => {
19
+ return string.indexOf(NewLine$2, startIndex);
69
20
  };
70
-
71
- const getFinalDeltaY = (height, itemHeight, itemsLength) => {
72
- const contentHeight = itemsLength * itemHeight;
73
- const finalDeltaY = Math.max(contentHeight - height, 0);
74
- return finalDeltaY;
21
+ const mergeStacks = (parent, child) => {
22
+ if (!child) {
23
+ return parent;
24
+ }
25
+ const parentNewLineIndex = getNewLineIndex$1(parent);
26
+ const childNewLineIndex = getNewLineIndex$1(child);
27
+ if (childNewLineIndex === -1) {
28
+ return parent;
29
+ }
30
+ const parentFirstLine = parent.slice(0, parentNewLineIndex);
31
+ const childRest = child.slice(childNewLineIndex);
32
+ const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
33
+ if (parentFirstLine.includes(childFirstLine)) {
34
+ return parentFirstLine + childRest;
35
+ }
36
+ return child;
75
37
  };
38
+ class VError extends Error {
39
+ constructor(error, message) {
40
+ const combinedMessage = getCombinedMessage(error, message);
41
+ super(combinedMessage);
42
+ this.name = 'VError';
43
+ if (error instanceof Error) {
44
+ this.stack = mergeStacks(this.stack, error.stack);
45
+ }
46
+ if (error.codeFrame) {
47
+ // @ts-ignore
48
+ this.codeFrame = error.codeFrame;
49
+ }
50
+ if (error.code) {
51
+ // @ts-ignore
52
+ this.code = error.code;
53
+ }
54
+ }
55
+ }
76
56
 
77
- let AssertionError$1 = class AssertionError extends Error {
57
+ class AssertionError extends Error {
78
58
  constructor(message) {
79
59
  super(message);
80
60
  this.name = 'AssertionError';
81
61
  }
82
- };
83
- const getType$2 = value => {
62
+ }
63
+ const getType = value => {
84
64
  switch (typeof value) {
85
65
  case 'number':
86
66
  return 'number';
@@ -102,767 +82,535 @@ const getType$2 = value => {
102
82
  return 'unknown';
103
83
  }
104
84
  };
105
- const number$1 = value => {
106
- const type = getType$2(value);
85
+ const number = value => {
86
+ const type = getType(value);
107
87
  if (type !== 'number') {
108
- throw new AssertionError$1('expected value to be of type number');
88
+ throw new AssertionError('expected value to be of type number');
109
89
  }
110
90
  };
111
91
 
112
- const getListHeight$1 = (itemsLength, itemHeight, maxHeight) => {
113
- number$1(itemsLength);
114
- number$1(itemHeight);
115
- number$1(maxHeight);
116
- if (itemsLength === 0) {
117
- return itemHeight;
118
- }
119
- const totalHeight = itemsLength * itemHeight;
120
- return Math.min(totalHeight, maxHeight);
92
+ const isMessagePort = value => {
93
+ return value && value instanceof MessagePort;
121
94
  };
122
-
123
- // TODO optimize this function to return the minimum number
124
- // of visible items needed, e.g. when not scrolled 5 items with
125
- // 20px fill 100px but when scrolled 6 items are needed
126
- const getNumberOfVisibleItems = (listHeight, itemHeight) => {
127
- return Math.ceil(listHeight / itemHeight) + 1;
95
+ const isMessagePortMain = value => {
96
+ return value && value.constructor && value.constructor.name === 'MessagePortMain';
128
97
  };
129
-
130
- /**
131
- *
132
- * @param {number} size
133
- * @param {number} contentSize
134
- * @param {number} minimumSliderSize
135
- * @returns
136
- */
137
- const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
138
- if (size >= contentSize) {
139
- return 0;
140
- }
141
- return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
98
+ const isOffscreenCanvas = value => {
99
+ return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
142
100
  };
143
- const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
144
- const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
145
- return scrollBarOffset;
101
+ const isInstanceOf = (value, constructorName) => {
102
+ return value?.constructor?.name === constructorName;
146
103
  };
147
- const getScrollBarY = getScrollBarOffset;
148
-
149
- const Installed = '@installed';
150
- const Enabled = '@enabled';
151
- const Disabled = '@disabled';
152
- const Builtin = '@builtin';
153
- const Sort = '@sort';
154
- const Id = '@id';
155
- const Outdated = '@outdated';
156
-
157
- const RE_PARAM = /@\w+/g;
158
-
159
- // TODO test sorting and filtering
160
- const parseValue = value => {
161
- const parameters = Object.create(null);
162
- // TODO this is not very functional code (assignment)
163
- const replaced = value.replaceAll(RE_PARAM, (match, by, order) => {
164
- if (match.startsWith(Installed)) {
165
- parameters.installed = true;
166
- }
167
- if (match.startsWith(Enabled)) {
168
- parameters.enabled = true;
169
- }
170
- if (match.startsWith(Disabled)) {
171
- parameters.disabled = true;
172
- }
173
- if (match.startsWith(Builtin)) {
174
- parameters.builtin = true;
175
- }
176
- if (match.startsWith(Sort)) {
177
- // TODO
178
- parameters.sort = 'installs';
179
- }
180
- if (match.startsWith(Id)) {
181
- // TODO
182
- parameters.id = 'abc';
183
- }
184
- if (match.startsWith(Outdated)) {
185
- parameters.outdated = true;
104
+ const isSocket = value => {
105
+ return isInstanceOf(value, 'Socket');
106
+ };
107
+ const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
108
+ const isTransferrable = value => {
109
+ for (const fn of transferrables) {
110
+ if (fn(value)) {
111
+ return true;
186
112
  }
187
- return '';
188
- });
189
- const isLocal = parameters.enabled || parameters.builtin || parameters.disabled || parameters.outdated || parameters.installed;
190
- return {
191
- query: replaced,
192
- ...parameters,
193
- isLocal
194
- };
113
+ }
114
+ return false;
195
115
  };
196
-
197
- const assetDir = '';
198
-
199
- const Web = 1;
200
- const Electron = 2;
201
- const Remote = 3;
202
- const Test = 4;
203
-
204
- // TODO treeshake this function out
205
-
206
- /**
207
- * @returns {number}
208
- */
209
- const getPlatform = () => {
210
- // @ts-ignore
211
- if (typeof PLATFORM !== 'undefined') {
212
- // @ts-ignore
213
- return PLATFORM;
116
+ const walkValue = (value, transferrables, isTransferrable) => {
117
+ if (!value) {
118
+ return;
214
119
  }
215
- if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
216
- return Test;
120
+ if (isTransferrable(value)) {
121
+ transferrables.push(value);
122
+ return;
217
123
  }
218
- // TODO find a better way to pass runtime environment
219
- if (typeof name !== 'undefined' && name.endsWith('(Electron)')) {
220
- return Electron;
124
+ if (Array.isArray(value)) {
125
+ for (const item of value) {
126
+ walkValue(item, transferrables, isTransferrable);
127
+ }
128
+ return;
221
129
  }
222
- if (typeof name !== 'undefined' && name.endsWith('(Web)')) {
223
- return Web;
130
+ if (typeof value === 'object') {
131
+ for (const property of Object.values(value)) {
132
+ walkValue(property, transferrables, isTransferrable);
133
+ }
134
+ return;
224
135
  }
225
- return Remote;
226
136
  };
227
- const platform = getPlatform();
228
-
229
- const getRemoteUrl = extension => {
230
- if (platform === Remote || platform === Electron) {
231
- if (extension.builtin) {
232
- return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
233
- }
234
- return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
235
- }
236
- return '';
237
- };
238
-
239
- const ExtensionDefaultIcon = `${assetDir}/icons/extensionDefaultIcon.png`;
240
- const ExtensionLanguageBasics = `${assetDir}/icons/language-icon.svg`;
241
- const ExtensionTheme = `${assetDir}/icons/theme-icon.png`;
242
-
243
- const isLanguageBasicsExtension = extension => {
244
- return extension.name && extension.name.startsWith('Language Basics');
137
+ const getTransferrables = value => {
138
+ const transferrables = [];
139
+ walkValue(value, transferrables, isTransferrable);
140
+ return transferrables;
245
141
  };
246
- const isThemeExtension = extension => {
247
- return extension.name && extension.name.endsWith(' Theme');
142
+ const attachEvents = that => {
143
+ const handleMessage = (...args) => {
144
+ const data = that.getData(...args);
145
+ that.dispatchEvent(new MessageEvent('message', {
146
+ data
147
+ }));
148
+ };
149
+ that.onMessage(handleMessage);
150
+ const handleClose = event => {
151
+ that.dispatchEvent(new Event('close'));
152
+ };
153
+ that.onClose(handleClose);
248
154
  };
249
- const getIcon = extension => {
250
- if (!extension) {
251
- return ExtensionDefaultIcon;
252
- }
253
- if (!extension.path || !extension.icon) {
254
- if (isLanguageBasicsExtension(extension)) {
255
- return ExtensionLanguageBasics;
256
- }
257
- if (isThemeExtension(extension)) {
258
- return ExtensionTheme;
259
- }
260
- return ExtensionDefaultIcon;
155
+ class Ipc extends EventTarget {
156
+ constructor(rawIpc) {
157
+ super();
158
+ this._rawIpc = rawIpc;
159
+ attachEvents(this);
261
160
  }
262
- return getRemoteUrl(extension);
161
+ }
162
+ const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
163
+ const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
164
+ const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
165
+ const NewLine$1 = '\n';
166
+ const joinLines$1 = lines => {
167
+ return lines.join(NewLine$1);
263
168
  };
264
- const RE_PUBLISHER = /^[a-z\d\-]+/;
265
-
266
- // TODO handle case when extension is of type number|array|null|string
267
- const getPublisher = extension => {
268
- if (!extension || !extension.id) {
269
- return 'n/a';
270
- }
271
- // TODO handle case when id is not of type string -> should not crash application
272
- const match = extension.id.match(RE_PUBLISHER);
273
- if (!match) {
274
- return 'n/a';
275
- }
276
- return match[0];
169
+ const RE_AT = /^\s+at/;
170
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
171
+ const isNormalStackLine = line => {
172
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
277
173
  };
278
- const getName = extension => {
279
- if (extension && extension.name) {
280
- return extension.name;
174
+ const getDetails = lines => {
175
+ const index = lines.findIndex(isNormalStackLine);
176
+ if (index === -1) {
177
+ return {
178
+ actualMessage: joinLines$1(lines),
179
+ rest: []
180
+ };
281
181
  }
282
- if (extension && extension.id) {
283
- return extension.id;
182
+ let lastIndex = index - 1;
183
+ while (++lastIndex < lines.length) {
184
+ if (!isNormalStackLine(lines[lastIndex])) {
185
+ break;
186
+ }
284
187
  }
285
- return 'n/a';
188
+ return {
189
+ actualMessage: lines[index - 1],
190
+ rest: lines.slice(index, lastIndex)
191
+ };
286
192
  };
287
- const getDescription = extension => {
288
- if (!extension || !extension.description) {
289
- return 'n/a';
290
- }
291
- return extension.description;
193
+ const splitLines$1 = lines => {
194
+ return lines.split(NewLine$1);
292
195
  };
293
- const getId = extension => {
294
- if (!extension || !extension.id) {
295
- return 'n/a';
296
- }
297
- return extension.id;
196
+ const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
197
+ const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
198
+ const isMessageCodeBlockStartIndex = line => {
199
+ return RE_MESSAGE_CODE_BLOCK_START.test(line);
298
200
  };
299
-
300
- const matchesParsedValue = (extension, parsedValue) => {
301
- if (extension && typeof extension.name === 'string') {
302
- const extensionNameLower = extension.name.toLowerCase();
303
- return extensionNameLower.includes(parsedValue.query);
304
- }
305
- if (extension && typeof extension.id === 'string') {
306
- const extensionIdLower = extension.id.toLowerCase();
307
- return extensionIdLower.includes(parsedValue.query);
308
- }
309
- return false;
201
+ const isMessageCodeBlockEndIndex = line => {
202
+ return RE_MESSAGE_CODE_BLOCK_END.test(line);
310
203
  };
311
-
312
- const toSorted = (array, compare) => {
313
- return [...array].sort(compare);
204
+ const getMessageCodeBlock = stderr => {
205
+ const lines = splitLines$1(stderr);
206
+ const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
207
+ const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
208
+ const relevantLines = lines.slice(startIndex, endIndex);
209
+ const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
210
+ return relevantMessage;
314
211
  };
315
-
316
- const compareExtension = (extensionA, extensionB) => {
317
- return extensionA.name.localeCompare(extensionB.name) || extensionA.id.localeCompare(extensionB.id);
212
+ const isModuleNotFoundMessage = line => {
213
+ return line.includes('[ERR_MODULE_NOT_FOUND]');
318
214
  };
319
-
320
- const sortExtensions = extensions => {
321
- return toSorted(extensions, compareExtension);
215
+ const getModuleNotFoundError = stderr => {
216
+ const lines = splitLines$1(stderr);
217
+ const messageIndex = lines.findIndex(isModuleNotFoundMessage);
218
+ const message = lines[messageIndex];
219
+ return {
220
+ message,
221
+ code: ERR_MODULE_NOT_FOUND
222
+ };
322
223
  };
323
-
324
- const getExtensions = async (extensions, parsedValue) => {
325
- const filteredExtensions = [];
326
- for (const extension of extensions) {
327
- if (matchesParsedValue(extension, parsedValue)) {
328
- filteredExtensions.push({
329
- name: getName(extension),
330
- id: getId(extension),
331
- publisher: getPublisher(extension),
332
- icon: getIcon(extension),
333
- description: getDescription(extension)
334
- });
335
- }
224
+ const isModuleNotFoundError = stderr => {
225
+ if (!stderr) {
226
+ return false;
336
227
  }
337
- const sortedExtensions = sortExtensions(filteredExtensions);
338
- return sortedExtensions;
228
+ return stderr.includes('ERR_MODULE_NOT_FOUND');
339
229
  };
340
-
341
- const normalizeLine$1 = line => {
342
- if (line.startsWith('Error: ')) {
343
- return line.slice(`Error: `.length);
344
- }
345
- if (line.startsWith('VError: ')) {
346
- return line.slice(`VError: `.length);
230
+ const isModulesSyntaxError = stderr => {
231
+ if (!stderr) {
232
+ return false;
347
233
  }
348
- return line;
234
+ return stderr.includes('SyntaxError: Cannot use import statement outside a module');
349
235
  };
350
- const getCombinedMessage$1 = (error, message) => {
351
- const stringifiedError = normalizeLine$1(`${error}`);
352
- if (message) {
353
- return `${message}: ${stringifiedError}`;
354
- }
355
- return stringifiedError;
236
+ const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
237
+ const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
238
+ const isUnhelpfulNativeModuleError = stderr => {
239
+ return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
356
240
  };
357
- const NewLine$2 = '\n';
358
- const getNewLineIndex$1 = (string, startIndex = undefined) => {
359
- return string.indexOf(NewLine$2, startIndex);
241
+ const getNativeModuleErrorMessage = stderr => {
242
+ const message = getMessageCodeBlock(stderr);
243
+ return {
244
+ message: `Incompatible native node module: ${message}`,
245
+ code: E_INCOMPATIBLE_NATIVE_MODULE
246
+ };
360
247
  };
361
- const mergeStacks$1 = (parent, child) => {
362
- if (!child) {
363
- return parent;
248
+ const getModuleSyntaxError = () => {
249
+ return {
250
+ message: `ES Modules are not supported in electron`,
251
+ code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
252
+ };
253
+ };
254
+ const getHelpfulChildProcessError = (stdout, stderr) => {
255
+ if (isUnhelpfulNativeModuleError(stderr)) {
256
+ return getNativeModuleErrorMessage(stderr);
364
257
  }
365
- const parentNewLineIndex = getNewLineIndex$1(parent);
366
- const childNewLineIndex = getNewLineIndex$1(child);
367
- if (childNewLineIndex === -1) {
368
- return parent;
258
+ if (isModulesSyntaxError(stderr)) {
259
+ return getModuleSyntaxError();
369
260
  }
370
- const parentFirstLine = parent.slice(0, parentNewLineIndex);
371
- const childRest = child.slice(childNewLineIndex);
372
- const childFirstLine = normalizeLine$1(child.slice(0, childNewLineIndex));
373
- if (parentFirstLine.includes(childFirstLine)) {
374
- return parentFirstLine + childRest;
261
+ if (isModuleNotFoundError(stderr)) {
262
+ return getModuleNotFoundError(stderr);
375
263
  }
376
- return child;
264
+ const lines = splitLines$1(stderr);
265
+ const {
266
+ actualMessage,
267
+ rest
268
+ } = getDetails(lines);
269
+ return {
270
+ message: actualMessage,
271
+ code: '',
272
+ stack: rest
273
+ };
377
274
  };
378
- let VError$1 = class VError extends Error {
379
- constructor(error, message) {
380
- const combinedMessage = getCombinedMessage$1(error, message);
381
- super(combinedMessage);
382
- this.name = 'VError';
383
- if (error instanceof Error) {
384
- this.stack = mergeStacks$1(this.stack, error.stack);
385
- }
386
- if (error.codeFrame) {
275
+ class IpcError extends VError {
276
+ // @ts-ignore
277
+ constructor(betterMessage, stdout = '', stderr = '') {
278
+ if (stdout || stderr) {
387
279
  // @ts-ignore
388
- this.codeFrame = error.codeFrame;
389
- }
390
- if (error.code) {
280
+ const {
281
+ message,
282
+ code,
283
+ stack
284
+ } = getHelpfulChildProcessError(stdout, stderr);
285
+ const cause = new Error(message);
391
286
  // @ts-ignore
392
- this.code = error.code;
287
+ cause.code = code;
288
+ cause.stack = stack;
289
+ super(cause, betterMessage);
290
+ } else {
291
+ super(betterMessage);
393
292
  }
293
+ // @ts-ignore
294
+ this.name = 'IpcError';
295
+ // @ts-ignore
296
+ this.stdout = stdout;
297
+ // @ts-ignore
298
+ this.stderr = stderr;
394
299
  }
300
+ }
301
+ const readyMessage = 'ready';
302
+ const getData$2 = event => {
303
+ return event.data;
395
304
  };
396
-
397
- const searchExtensions = async (extensions, value) => {
398
- try {
399
- const parsedValue = parseValue(value);
400
- const filteredExtensions = await getExtensions(extensions, parsedValue);
401
- return filteredExtensions;
402
- } catch (error) {
403
- throw new VError$1(error, 'Failed to search for extensions');
305
+ const listen$7 = () => {
306
+ // @ts-ignore
307
+ if (typeof WorkerGlobalScope === 'undefined') {
308
+ throw new TypeError('module is not in web worker scope');
404
309
  }
310
+ return globalThis;
405
311
  };
406
-
407
- // TODO debounce
408
- const handleInput = async (state, value) => {
409
- try {
410
- const {
411
- allExtensions,
412
- itemHeight,
413
- minimumSliderSize,
414
- height
415
- } = state;
416
- // TODO cancel ongoing requests
417
- // TODO handle errors
418
- const items = await searchExtensions(allExtensions, value);
419
- if (items.length === 0) {
420
- return {
421
- ...state,
422
- items,
423
- minLineY: 0,
424
- deltaY: 0,
425
- allExtensions,
426
- maxLineY: 0,
427
- scrollBarHeight: 0,
428
- finalDeltaY: 0,
429
- message: noExtensionsFound(),
430
- searchValue: value,
431
- placeholder: searchExtensionsInMarketPlace()
432
- };
433
- }
312
+ const signal$8 = global => {
313
+ global.postMessage(readyMessage);
314
+ };
315
+ class IpcChildWithModuleWorker extends Ipc {
316
+ getData(event) {
317
+ return getData$2(event);
318
+ }
319
+ send(message) {
434
320
  // @ts-ignore
435
- const listHeight = getListHeight$1(state);
436
- const total = items.length;
437
- const contentHeight = total * itemHeight;
438
- const scrollBarHeight = getScrollBarSize(height, contentHeight, minimumSliderSize);
439
- const numberOfVisible = getNumberOfVisibleItems(listHeight, itemHeight);
440
- const maxLineY = Math.min(numberOfVisible, total);
441
- const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
442
- return {
443
- ...state,
444
- items,
445
- minLineY: 0,
446
- deltaY: 0,
447
- allExtensions,
448
- maxLineY,
449
- scrollBarHeight,
450
- finalDeltaY,
451
- message: '',
452
- searchValue: value,
453
- placeholder: searchExtensionsInMarketPlace()
454
- };
455
-
456
- // TODO handle out of order responses (a bit complicated)
457
- // for now just assume everything comes back in order
458
- } catch (error) {
459
- await handleError(error);
460
- return {
461
- ...state,
462
- searchValue: value,
463
- message: `${error}`
464
- };
321
+ this._rawIpc.postMessage(message);
322
+ }
323
+ sendAndTransfer(message) {
324
+ const transfer = getTransferrables(message);
325
+ // @ts-ignore
326
+ this._rawIpc.postMessage(message, transfer);
465
327
  }
328
+ dispose() {
329
+ // ignore
330
+ }
331
+ onClose(callback) {
332
+ // ignore
333
+ }
334
+ onMessage(callback) {
335
+ this._rawIpc.addEventListener('message', callback);
336
+ }
337
+ }
338
+ const wrap$f = global => {
339
+ return new IpcChildWithModuleWorker(global);
466
340
  };
467
-
468
- const clearSearchResults = state => {
469
- return handleInput(state, '');
341
+ const withResolvers = () => {
342
+ let _resolve;
343
+ const promise = new Promise(resolve => {
344
+ _resolve = resolve;
345
+ });
346
+ return {
347
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
348
+ resolve: _resolve,
349
+ promise
350
+ };
470
351
  };
471
-
472
- const Button = 1;
473
-
474
- const ExtensionActions = 'ExtensionActions';
475
- const ExtensionActive = 'ExtensionActive';
476
- const ExtensionHeader = 'ExtensionHeader';
477
- const ExtensionListItem = 'ExtensionListItem';
478
- const ExtensionListItemAuthorName = 'ExtensionListItemAuthorName';
479
- const ExtensionListItemDescription = 'ExtensionListItemDescription';
480
- const ExtensionListItemDetail = 'ExtensionListItemDetail';
481
- const ExtensionListItemFooter = 'ExtensionListItemFooter';
482
- const ExtensionListItemIcon = 'ExtensionListItemIcon';
483
- const ExtensionListItemName = 'ExtensionListItemName';
484
- const ListItems = 'ListItems';
485
- const MultilineInputBox = 'MultilineInputBox';
486
- const ScrollBarThumb = 'ScrollBarThumb';
487
- const ScrollBarThumbActive = 'ScrollBarThumbActive';
488
- const SearchField = 'SearchField';
489
- const SearchFieldButtons = 'SearchFieldButtons';
490
- const SearchFieldContainer = 'SearchFieldContainer';
491
-
492
- const CheckBox = 'checkbox';
493
- const List = 'list';
494
- const ListItem = 'listitem';
495
- const None = 'none';
496
-
497
- const Div = 4;
498
- const Text = 12;
499
- const Img = 17;
500
- const TextArea = 62;
501
-
502
- const getSearchFieldButtonVirtualDom = button => {
352
+ const waitForFirstMessage = async port => {
503
353
  const {
504
- icon,
505
- checked,
506
- title
507
- } = button;
508
- return [{
509
- type: Div,
510
- className: `SearchFieldButton ${checked ? 'SearchFieldButtonChecked' : ''}`,
511
- title,
512
- role: CheckBox,
513
- ariaChecked: checked,
514
- tabIndex: 0,
515
- childCount: 1
516
- }, {
517
- type: Div,
518
- className: `MaskIcon ${icon}`,
519
- childCount: 0
520
- }];
354
+ resolve,
355
+ promise
356
+ } = withResolvers();
357
+ port.addEventListener('message', resolve, {
358
+ once: true
359
+ });
360
+ const event = await promise;
361
+ // @ts-ignore
362
+ return event.data;
521
363
  };
522
-
523
- const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, outsideButtons, onFocus = '') => {
524
- const dom = [{
525
- type: Div,
526
- className: SearchField,
527
- role: None,
528
- childCount: 2
529
- }, {
530
- type: TextArea,
531
- className: MultilineInputBox,
532
- spellcheck: false,
533
- autocapitalize: 'off',
534
- autocorrect: 'off',
535
- placeholder,
536
- name,
537
- onInput,
538
- onFocus,
539
- childCount: 0
540
- }, {
541
- type: Div,
542
- className: SearchFieldButtons,
543
- childCount: insideButtons.length
544
- }, ...insideButtons.flatMap(getSearchFieldButtonVirtualDom)];
545
- if (outsideButtons.length > 0) {
546
- dom.unshift({
547
- type: Div,
548
- className: SearchFieldContainer,
549
- role: None,
550
- childCount: 1 + outsideButtons.length
364
+ const listen$6 = async () => {
365
+ const parentIpcRaw = listen$7();
366
+ signal$8(parentIpcRaw);
367
+ const parentIpc = wrap$f(parentIpcRaw);
368
+ const firstMessage = await waitForFirstMessage(parentIpc);
369
+ if (firstMessage.method !== 'initialize') {
370
+ throw new IpcError('unexpected first message');
371
+ }
372
+ const type = firstMessage.params[0];
373
+ if (type === 'message-port') {
374
+ parentIpc.send({
375
+ jsonrpc: '2.0',
376
+ id: firstMessage.id,
377
+ result: null
551
378
  });
552
- dom.push(...outsideButtons.flatMap(getSearchFieldButtonVirtualDom));
379
+ parentIpc.dispose();
380
+ const port = firstMessage.params[1];
381
+ return port;
553
382
  }
554
- return dom;
383
+ return globalThis;
555
384
  };
556
-
557
- const getExtensionHeaderVirtualDom = (placeholder, actions) => {
558
- return [{
559
- type: Div,
560
- className: ExtensionHeader,
561
- childCount: 1
562
- }, ...getSearchFieldVirtualDom('extensions', placeholder, 'handleExtensionsInput', actions, [])];
385
+ class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
386
+ getData(event) {
387
+ return getData$2(event);
388
+ }
389
+ send(message) {
390
+ this._rawIpc.postMessage(message);
391
+ }
392
+ sendAndTransfer(message) {
393
+ const transfer = getTransferrables(message);
394
+ this._rawIpc.postMessage(message, transfer);
395
+ }
396
+ dispose() {
397
+ if (this._rawIpc.close) {
398
+ this._rawIpc.close();
399
+ }
400
+ }
401
+ onClose(callback) {
402
+ // ignore
403
+ }
404
+ onMessage(callback) {
405
+ this._rawIpc.addEventListener('message', callback);
406
+ this._rawIpc.start();
407
+ }
408
+ }
409
+ const wrap$e = port => {
410
+ return new IpcChildWithModuleWorkerAndMessagePort(port);
411
+ };
412
+ const IpcChildWithModuleWorkerAndMessagePort$1 = {
413
+ __proto__: null,
414
+ listen: listen$6,
415
+ wrap: wrap$e
563
416
  };
564
417
 
565
- const HandleContextMenu = 'handleContextMenu';
566
- const HandlePointerDown = 'handlePointerDown';
567
- const HandleTouchStart = 'handleTouchStart';
568
- const HandleWheel = 'handleWheel';
569
-
570
- const Extension = 'Extension';
571
-
572
- const text = data => {
418
+ const Two = '2.0';
419
+ const create$4 = (method, params) => {
573
420
  return {
574
- type: Text,
575
- text: data,
576
- childCount: 0
421
+ jsonrpc: Two,
422
+ method,
423
+ params
577
424
  };
578
425
  };
579
-
580
- const listItemDetail = {
581
- type: Div,
582
- className: ExtensionListItemDetail,
583
- childCount: 3
584
- };
585
- const listItemName = {
586
- type: Div,
587
- className: ExtensionListItemName,
588
- childCount: 1
426
+ const callbacks = Object.create(null);
427
+ const set$1 = (id, fn) => {
428
+ callbacks[id] = fn;
589
429
  };
590
- const listItemDescription = {
591
- type: Div,
592
- className: ExtensionListItemDescription,
593
- childCount: 1
430
+ const get = id => {
431
+ return callbacks[id];
594
432
  };
595
- const listItemFooter = {
596
- type: Div,
597
- className: ExtensionListItemFooter,
598
- childCount: 2
433
+ const remove = id => {
434
+ delete callbacks[id];
599
435
  };
600
- const listItemAuthorName = {
601
- type: Div,
602
- className: ExtensionListItemAuthorName,
603
- childCount: 1
436
+ let id = 0;
437
+ const create$3 = () => {
438
+ return ++id;
604
439
  };
605
- const getExtensionListItemVirtualDom = extension => {
440
+ const registerPromise = () => {
441
+ const id = create$3();
606
442
  const {
607
- posInSet,
608
- setSize,
609
- top,
610
- icon,
611
- name,
612
- description,
613
- publisher,
614
- focused
615
- } = extension;
616
- const dom = [{
617
- type: Div,
618
- role: ListItem,
619
- ariaRoleDescription: Extension,
620
- className: ExtensionListItem,
621
- ariaPosInSet: posInSet,
622
- ariaSetSize: setSize,
623
- top,
624
- childCount: 2
625
- }, {
626
- type: Img,
627
- src: icon,
628
- className: ExtensionListItemIcon,
629
- role: None,
630
- childCount: 0
631
- }, listItemDetail, listItemName, text(name), listItemDescription, text(description), listItemFooter, listItemAuthorName, text(publisher), {
632
- type: Div,
633
- className: ExtensionActions,
634
- childCount: 0
635
- }];
636
- if (focused) {
637
- dom[0].id = 'ExtensionActive';
638
- dom[0].className += ' ' + ExtensionActive;
639
- }
640
- return dom;
641
- };
642
-
643
- const getExtensionsListVirtualDom = visibleExtensions => {
644
- const dom = [{
645
- type: Div,
646
- className: ListItems,
647
- tabIndex: 0,
648
- ariaLabel: extensions(),
649
- role: List,
650
- oncontextmenu: HandleContextMenu,
651
- onpointerdown: HandlePointerDown,
652
- ontouchstart: HandleTouchStart,
653
- onwheelpassive: HandleWheel,
654
- childCount: visibleExtensions.length
655
- }, ...visibleExtensions.flatMap(getExtensionListItemVirtualDom)];
656
- return dom;
657
- };
658
-
659
- const getExtensionsVirtualDom = visibleExtensions => {
660
- const dom = getExtensionsListVirtualDom(visibleExtensions);
661
- // TODO
662
- return dom;
663
- };
664
-
665
- const getVisibleItem = (item, setSize, itemHeight, minLineY, relative, i, focusedIndex) => {
443
+ resolve,
444
+ promise
445
+ } = Promise.withResolvers();
446
+ set$1(id, resolve);
666
447
  return {
667
- ...item,
668
- setSize,
669
- posInSet: i + 1,
670
- top: (i - minLineY) * itemHeight - relative,
671
- focused: i === focusedIndex
448
+ id,
449
+ promise
672
450
  };
673
451
  };
674
- const getVisible = state => {
675
- const {
676
- minLineY,
677
- maxLineY,
678
- items,
679
- itemHeight,
680
- deltaY,
681
- focusedIndex
682
- } = state;
683
- const setSize = items.length;
684
- const visible = [];
685
- const relative = deltaY % itemHeight;
686
- for (let i = minLineY; i < maxLineY; i++) {
687
- const item = items[i];
688
- visible.push(getVisibleItem(item, setSize, itemHeight, minLineY, relative, i, focusedIndex));
689
- }
690
- return visible;
691
- };
692
-
693
- const ClearAll = 'ClearAll';
694
- const Filter = 'Filter';
695
-
696
- const px = value => {
697
- return `${value}px`;
698
- };
699
- const position = (x, y) => {
700
- return `${x}px ${y}px`;
701
- };
702
-
703
- const SetMessage = 'setMessage';
704
- const SetScrollBar = 'setScrollBar';
705
- const SetSearchValue = 'setSearchValue';
706
-
707
- const getListHeight = state => {
452
+ const create$2 = (method, params) => {
708
453
  const {
709
- height,
710
- headerHeight
711
- } = state;
712
- return height - headerHeight;
454
+ id,
455
+ promise
456
+ } = registerPromise();
457
+ const message = {
458
+ jsonrpc: Two,
459
+ method,
460
+ params,
461
+ id
462
+ };
463
+ return {
464
+ message,
465
+ promise
466
+ };
713
467
  };
714
- const renderExtensions = {
715
- isEqual(oldState, newState) {
716
- return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.deltaY === newState.deltaY && oldState.focusedIndex === newState.focusedIndex;
717
- },
718
- apply(oldState, newState) {
719
- // TODO render extensions incrementally when scrolling
720
- const visibleExtensions = getVisible(newState);
721
- const dom = getExtensionsVirtualDom(visibleExtensions);
722
- return ['setExtensionsDom', dom];
468
+ class JsonRpcError extends Error {
469
+ constructor(message) {
470
+ super(message);
471
+ this.name = 'JsonRpcError';
723
472
  }
724
- };
725
- const renderScrollBar = {
726
- isEqual(oldState, newState) {
727
- return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length && oldState.scrollBarActive === newState.scrollBarActive;
728
- },
729
- apply(oldState, newState) {
730
- // @ts-ignore
731
- const listHeight = getListHeight(newState);
732
- const total = newState.items.length;
733
- const contentHeight = total * newState.itemHeight;
734
- const scrollBarHeight = getScrollBarSize(listHeight, contentHeight, newState.minimumSliderSize);
735
- const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
736
- const roundedScrollBarY = Math.round(scrollBarY);
737
- const heightString = px(scrollBarHeight);
738
- const translateString = position(0, roundedScrollBarY);
739
- let className = ScrollBarThumb;
740
- if (newState.scrollBarActive) {
741
- className += ' ' + ScrollBarThumbActive;
473
+ }
474
+ const NewLine = '\n';
475
+ const DomException = 'DOMException';
476
+ const ReferenceError$1 = 'ReferenceError';
477
+ const SyntaxError$1 = 'SyntaxError';
478
+ const TypeError$1 = 'TypeError';
479
+ const getErrorConstructor = (message, type) => {
480
+ if (type) {
481
+ switch (type) {
482
+ case DomException:
483
+ return DOMException;
484
+ case TypeError$1:
485
+ return TypeError;
486
+ case SyntaxError$1:
487
+ return SyntaxError;
488
+ case ReferenceError$1:
489
+ return ReferenceError;
490
+ default:
491
+ return Error;
742
492
  }
743
- return [/* method */SetScrollBar, translateString, heightString, className];
744
493
  }
745
- };
746
- const renderMessage = {
747
- isEqual(oldState, newState) {
748
- return oldState.message === newState.message;
749
- },
750
- apply(oldState, newState) {
751
- return [/* method */SetMessage, /* message */newState.message];
494
+ if (message.startsWith('TypeError: ')) {
495
+ return TypeError;
752
496
  }
753
- };
754
- const renderSearchValue = {
755
- isEqual(oldState, newState) {
756
- return oldState.searchValue === newState.searchValue;
757
- },
758
- apply(oldState, newState) {
759
- return [/* method */SetSearchValue, oldState.searchValue, newState.searchValue];
497
+ if (message.startsWith('SyntaxError: ')) {
498
+ return SyntaxError;
760
499
  }
761
- };
762
- const renderHeader = {
763
- isEqual(oldState, newState) {
764
- return oldState.placeholder === newState.placeholder;
765
- },
766
- apply(oldState, newState) {
767
- const actions = [{
768
- type: Button,
769
- title: clearExtensionSearchResults(),
770
- icon: `MaskIcon${ClearAll}`,
771
- command: 'Extensions.clearSearchResults'
772
- }, {
773
- type: Button,
774
- title: filter(),
775
- icon: `MaskIcon${Filter}`
776
- }];
777
- const dom = getExtensionHeaderVirtualDom(newState.placeholder, actions);
778
- return ['setHeaderDom', dom];
500
+ if (message.startsWith('ReferenceError: ')) {
501
+ return ReferenceError;
779
502
  }
503
+ return Error;
780
504
  };
781
- const render = [renderScrollBar, renderMessage, renderExtensions, renderSearchValue, renderHeader];
782
- const doRender = (oldState, newState) => {
783
- const commands = [];
784
- for (const item of render) {
785
- if (!item.isEqual(oldState, newState)) {
786
- commands.push(item.apply(oldState, newState));
505
+ const constructError = (message, type, name) => {
506
+ const ErrorConstructor = getErrorConstructor(message, type);
507
+ if (ErrorConstructor === DOMException && name) {
508
+ return new ErrorConstructor(message, name);
509
+ }
510
+ if (ErrorConstructor === Error) {
511
+ const error = new Error(message);
512
+ if (name && name !== 'VError') {
513
+ error.name = name;
787
514
  }
515
+ return error;
788
516
  }
789
- return commands;
517
+ return new ErrorConstructor(message);
790
518
  };
791
-
792
- const commandMap = {
793
- 'SearchExtensions.searchExtensions': searchExtensions,
794
- 'SearchExtensions.render': doRender,
795
- 'SearchExtensions.clearSearchResults': clearSearchResults
519
+ const getNewLineIndex = (string, startIndex = undefined) => {
520
+ return string.indexOf(NewLine, startIndex);
796
521
  };
797
-
798
- const Two = '2.0';
799
- class AssertionError extends Error {
800
- constructor(message) {
801
- super(message);
802
- this.name = 'AssertionError';
522
+ const getParentStack = error => {
523
+ let parentStack = error.stack || error.data || error.message || '';
524
+ if (parentStack.startsWith(' at')) {
525
+ parentStack = error.message + NewLine + parentStack;
803
526
  }
804
- }
805
- const getType$1 = value => {
806
- switch (typeof value) {
807
- case 'number':
808
- return 'number';
809
- case 'function':
810
- return 'function';
811
- case 'string':
812
- return 'string';
813
- case 'object':
814
- if (value === null) {
815
- return 'null';
527
+ return parentStack;
528
+ };
529
+ const joinLines = lines => {
530
+ return lines.join(NewLine);
531
+ };
532
+ const MethodNotFound = -32601;
533
+ const Custom = -32001;
534
+ const splitLines = lines => {
535
+ return lines.split(NewLine);
536
+ };
537
+ const restoreJsonRpcError = error => {
538
+ if (error && error instanceof Error) {
539
+ return error;
540
+ }
541
+ const currentStack = joinLines(splitLines(new Error().stack || '').slice(1));
542
+ if (error && error.code && error.code === MethodNotFound) {
543
+ const restoredError = new JsonRpcError(error.message);
544
+ const parentStack = getParentStack(error);
545
+ restoredError.stack = parentStack + NewLine + currentStack;
546
+ return restoredError;
547
+ }
548
+ if (error && error.message) {
549
+ const restoredError = constructError(error.message, error.type, error.name);
550
+ if (error.data) {
551
+ if (error.data.stack && error.data.type && error.message) {
552
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
553
+ } else if (error.data.stack) {
554
+ restoredError.stack = error.data.stack;
816
555
  }
817
- if (Array.isArray(value)) {
818
- return 'array';
556
+ if (error.data.codeFrame) {
557
+ // @ts-ignore
558
+ restoredError.codeFrame = error.data.codeFrame;
819
559
  }
820
- return 'object';
821
- case 'boolean':
822
- return 'boolean';
823
- default:
824
- return 'unknown';
560
+ if (error.data.code) {
561
+ // @ts-ignore
562
+ restoredError.code = error.data.code;
563
+ }
564
+ if (error.data.type) {
565
+ // @ts-ignore
566
+ restoredError.name = error.data.type;
567
+ }
568
+ } else {
569
+ if (error.stack) {
570
+ const lowerStack = restoredError.stack || '';
571
+ // @ts-ignore
572
+ const indexNewLine = getNewLineIndex(lowerStack);
573
+ const parentStack = getParentStack(error);
574
+ // @ts-ignore
575
+ restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
576
+ }
577
+ if (error.codeFrame) {
578
+ // @ts-ignore
579
+ restoredError.codeFrame = error.codeFrame;
580
+ }
581
+ }
582
+ return restoredError;
825
583
  }
826
- };
827
- const number = value => {
828
- const type = getType$1(value);
829
- if (type !== 'number') {
830
- throw new AssertionError('expected value to be of type number');
584
+ if (typeof error === 'string') {
585
+ return new Error(`JsonRpc Error: ${error}`);
831
586
  }
587
+ return new Error(`JsonRpc Error: ${error}`);
832
588
  };
833
- const state$1 = {
834
- callbacks: Object.create(null)
835
- };
836
- const get = id => {
837
- return state$1.callbacks[id];
838
- };
839
- const remove = id => {
840
- delete state$1.callbacks[id];
589
+ const unwrapJsonRpcResult = responseMessage => {
590
+ if ('error' in responseMessage) {
591
+ const restoredError = restoreJsonRpcError(responseMessage.error);
592
+ throw restoredError;
593
+ }
594
+ if ('result' in responseMessage) {
595
+ return responseMessage.result;
596
+ }
597
+ throw new JsonRpcError('unexpected response message');
841
598
  };
842
599
  const warn = (...args) => {
843
600
  console.warn(...args);
844
601
  };
845
- const resolve = (id, args) => {
846
- number(id);
602
+ const resolve = (id, response) => {
847
603
  const fn = get(id);
848
604
  if (!fn) {
849
- console.log(args);
605
+ console.log(response);
850
606
  warn(`callback ${id} may already be disposed`);
851
607
  return;
852
608
  }
853
- fn(args);
609
+ fn(response);
854
610
  remove(id);
855
611
  };
856
- class JsonRpcError extends Error {
857
- constructor(message) {
858
- super(message);
859
- this.name = 'JsonRpcError';
860
- }
861
- }
862
- const MethodNotFound = -32601;
863
- const Custom = -32001;
864
612
  const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
865
- const getType = prettyError => {
613
+ const getErrorType = prettyError => {
866
614
  if (prettyError && prettyError.type) {
867
615
  return prettyError.type;
868
616
  }
@@ -885,7 +633,7 @@ const getErrorProperty = (error, prettyError) => {
885
633
  data: {
886
634
  stack: prettyError.stack,
887
635
  codeFrame: prettyError.codeFrame,
888
- type: getType(prettyError),
636
+ type: getErrorType(prettyError),
889
637
  code: prettyError.code,
890
638
  name: prettyError.name
891
639
  }
@@ -904,7 +652,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
904
652
  const errorProperty = getErrorProperty(error, prettyError);
905
653
  return create$1(message, errorProperty);
906
654
  };
907
- const create = (message, result) => {
655
+ const create$5 = (message, result) => {
908
656
  return {
909
657
  jsonrpc: Two,
910
658
  id: message.id,
@@ -913,7 +661,7 @@ const create = (message, result) => {
913
661
  };
914
662
  const getSuccessResponse = (message, result) => {
915
663
  const resultProperty = result ?? null;
916
- return create(message, resultProperty);
664
+ return create$5(message, resultProperty);
917
665
  };
918
666
  const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
919
667
  try {
@@ -933,32 +681,42 @@ const defaultRequiresSocket = () => {
933
681
  return false;
934
682
  };
935
683
  const defaultResolve = resolve;
936
- const handleJsonRpcMessage = async (...args) => {
937
- let message;
938
- let ipc;
939
- let execute;
940
- let preparePrettyError;
941
- let logError;
942
- let resolve;
943
- let requiresSocket;
684
+
685
+ // TODO maybe remove this in v6 or v7, only accept options object to simplify the code
686
+ const normalizeParams = args => {
944
687
  if (args.length === 1) {
945
- const arg = args[0];
946
- message = arg.message;
947
- ipc = arg.ipc;
948
- execute = arg.execute;
949
- preparePrettyError = arg.preparePrettyError || defaultPreparePrettyError;
950
- logError = arg.logError || defaultLogError;
951
- requiresSocket = arg.requiresSocket || defaultRequiresSocket;
952
- resolve = arg.resolve || defaultResolve;
953
- } else {
954
- ipc = args[0];
955
- message = args[1];
956
- execute = args[2];
957
- resolve = args[3];
958
- preparePrettyError = args[4];
959
- logError = args[5];
960
- requiresSocket = args[6];
688
+ const options = args[0];
689
+ return {
690
+ ipc: options.ipc,
691
+ message: options.message,
692
+ execute: options.execute,
693
+ resolve: options.resolve || defaultResolve,
694
+ preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
695
+ logError: options.logError || defaultLogError,
696
+ requiresSocket: options.requiresSocket || defaultRequiresSocket
697
+ };
961
698
  }
699
+ return {
700
+ ipc: args[0],
701
+ message: args[1],
702
+ execute: args[2],
703
+ resolve: args[3],
704
+ preparePrettyError: args[4],
705
+ logError: args[5],
706
+ requiresSocket: args[6]
707
+ };
708
+ };
709
+ const handleJsonRpcMessage = async (...args) => {
710
+ const options = normalizeParams(args);
711
+ const {
712
+ message,
713
+ ipc,
714
+ execute,
715
+ resolve,
716
+ preparePrettyError,
717
+ logError,
718
+ requiresSocket
719
+ } = options;
962
720
  if ('id' in message) {
963
721
  if ('method' in message) {
964
722
  const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
@@ -979,458 +737,864 @@ const handleJsonRpcMessage = async (...args) => {
979
737
  }
980
738
  throw new JsonRpcError('unexpected message');
981
739
  };
982
-
983
- const requiresSocket = () => {
984
- return false;
740
+ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
741
+ const {
742
+ message,
743
+ promise
744
+ } = create$2(method, params);
745
+ if (useSendAndTransfer && ipc.sendAndTransfer) {
746
+ ipc.sendAndTransfer(message);
747
+ } else {
748
+ ipc.send(message);
749
+ }
750
+ const responseMessage = await promise;
751
+ return unwrapJsonRpcResult(responseMessage);
985
752
  };
986
- const preparePrettyError = error => {
987
- return error;
753
+ const send = (transport, method, ...params) => {
754
+ const message = create$4(method, params);
755
+ transport.send(message);
988
756
  };
989
- const logError = error => {
990
- // handled by renderer worker
757
+ const invoke = (ipc, method, ...params) => {
758
+ return invokeHelper(ipc, method, params, false);
991
759
  };
992
- const handleMessage = event => {
993
- return handleJsonRpcMessage(event.target, event.data, execute, resolve, preparePrettyError, logError, requiresSocket);
760
+ const invokeAndTransfer = (ipc, method, ...params) => {
761
+ return invokeHelper(ipc, method, params, true);
994
762
  };
995
763
 
996
- const handleIpc = ipc => {
997
- ipc.addEventListener('message', handleMessage);
764
+ const commands = Object.create(null);
765
+ const register = commandMap => {
766
+ Object.assign(commands, commandMap);
998
767
  };
999
-
1000
- const MessagePort$1 = 1;
1001
- const ModuleWorker = 2;
1002
- const ReferencePort = 3;
1003
- const ModuleWorkerAndMessagePort = 8;
1004
- const Auto = () => {
1005
- // @ts-ignore
1006
- if (globalThis.acceptPort) {
1007
- return MessagePort$1;
1008
- }
1009
- // @ts-ignore
1010
- if (globalThis.acceptReferencePort) {
1011
- return ReferencePort;
768
+ const getCommand = key => {
769
+ return commands[key];
770
+ };
771
+ const execute = (command, ...args) => {
772
+ const fn = getCommand(command);
773
+ if (!fn) {
774
+ throw new Error(`command not found ${command}`);
1012
775
  }
1013
- return ModuleWorkerAndMessagePort;
776
+ return fn(...args);
1014
777
  };
1015
778
 
1016
- const getData$1 = event => {
1017
- return event.data;
1018
- };
1019
- const walkValue = (value, transferrables, isTransferrable) => {
1020
- if (!value) {
1021
- return;
1022
- }
1023
- if (isTransferrable(value)) {
1024
- transferrables.push(value);
1025
- return;
1026
- }
1027
- if (Array.isArray(value)) {
1028
- for (const item of value) {
1029
- walkValue(item, transferrables, isTransferrable);
1030
- }
1031
- return;
1032
- }
1033
- if (typeof value === 'object') {
1034
- for (const property of Object.values(value)) {
1035
- walkValue(property, transferrables, isTransferrable);
779
+ const createRpc = ipc => {
780
+ const rpc = {
781
+ // @ts-ignore
782
+ ipc,
783
+ /**
784
+ * @deprecated
785
+ */
786
+ send(method, ...params) {
787
+ send(ipc, method, ...params);
788
+ },
789
+ invoke(method, ...params) {
790
+ return invoke(ipc, method, ...params);
791
+ },
792
+ invokeAndTransfer(method, ...params) {
793
+ return invokeAndTransfer(ipc, method, ...params);
1036
794
  }
1037
- return;
1038
- }
1039
- };
1040
- const isMessagePort = value => {
1041
- return value && value instanceof MessagePort;
795
+ };
796
+ return rpc;
1042
797
  };
1043
- const isMessagePortMain = value => {
1044
- return value && value.constructor && value.constructor.name === 'MessagePortMain';
798
+ const requiresSocket = () => {
799
+ return false;
1045
800
  };
1046
- const isOffscreenCanvas = value => {
1047
- return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
801
+ const preparePrettyError = error => {
802
+ return error;
1048
803
  };
1049
- const isInstanceOf = (value, constructorName) => {
1050
- return value?.constructor?.name === constructorName;
804
+ const logError = () => {
805
+ // handled by renderer worker
1051
806
  };
1052
- const isSocket = value => {
1053
- return isInstanceOf(value, 'Socket');
807
+ const handleMessage = event => {
808
+ const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
809
+ const actualExecute = event?.target?.execute || execute;
810
+ return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
1054
811
  };
1055
- const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
1056
- const isTransferrable = value => {
1057
- for (const fn of transferrables) {
1058
- if (fn(value)) {
1059
- return true;
1060
- }
812
+ const handleIpc = ipc => {
813
+ if ('addEventListener' in ipc) {
814
+ ipc.addEventListener('message', handleMessage);
815
+ } else if ('on' in ipc) {
816
+ // deprecated
817
+ ipc.on('message', handleMessage);
1061
818
  }
1062
- return false;
1063
- };
1064
- const getTransferrables = value => {
1065
- const transferrables = [];
1066
- walkValue(value, transferrables, isTransferrable);
1067
- return transferrables;
1068
- };
1069
- const attachEvents = that => {
1070
- const handleMessage = (...args) => {
1071
- const data = that.getData(...args);
1072
- that.dispatchEvent(new MessageEvent('message', {
1073
- data
1074
- }));
1075
- };
1076
- that.onMessage(handleMessage);
1077
- const handleClose = event => {
1078
- that.dispatchEvent(new Event('close'));
1079
- };
1080
- that.onClose(handleClose);
1081
819
  };
1082
- class Ipc extends EventTarget {
1083
- constructor(rawIpc) {
1084
- super();
1085
- this._rawIpc = rawIpc;
1086
- attachEvents(this);
1087
- }
1088
- }
1089
- const readyMessage = 'ready';
1090
- const listen$4 = () => {
1091
- // @ts-ignore
1092
- if (typeof WorkerGlobalScope === 'undefined') {
1093
- throw new TypeError('module is not in web worker scope');
820
+ const listen$1 = async (module, options) => {
821
+ const rawIpc = await module.listen(options);
822
+ if (module.signal) {
823
+ module.signal(rawIpc);
1094
824
  }
1095
- return globalThis;
1096
- };
1097
- const signal$3 = global => {
1098
- global.postMessage(readyMessage);
825
+ const ipc = module.wrap(rawIpc);
826
+ return ipc;
1099
827
  };
1100
- class IpcChildWithModuleWorker extends Ipc {
1101
- getData(event) {
1102
- return getData$1(event);
1103
- }
1104
- send(message) {
1105
- // @ts-ignore
1106
- this._rawIpc.postMessage(message);
1107
- }
1108
- sendAndTransfer(message) {
1109
- const transfer = getTransferrables(message);
1110
- // @ts-ignore
1111
- this._rawIpc.postMessage(message, transfer);
1112
- }
1113
- dispose() {
1114
- // ignore
1115
- }
1116
- onClose(callback) {
1117
- // ignore
1118
- }
1119
- onMessage(callback) {
1120
- this._rawIpc.addEventListener('message', callback);
1121
- }
1122
- }
1123
- const wrap$6 = global => {
1124
- return new IpcChildWithModuleWorker(global);
828
+ const create = async ({
829
+ commandMap
830
+ }) => {
831
+ // TODO create a commandMap per rpc instance
832
+ register(commandMap);
833
+ const ipc = await listen$1(IpcChildWithModuleWorkerAndMessagePort$1);
834
+ handleIpc(ipc);
835
+ const rpc = createRpc(ipc);
836
+ return rpc;
1125
837
  };
1126
- const IpcChildWithModuleWorker$1 = {
838
+ const WebWorkerRpcClient = {
1127
839
  __proto__: null,
1128
- listen: listen$4,
1129
- signal: signal$3,
1130
- wrap: wrap$6
840
+ create
1131
841
  };
1132
- const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
1133
- const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
1134
- const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
1135
- const NewLine$1 = '\n';
1136
- const joinLines = lines => {
1137
- return lines.join(NewLine$1);
842
+
843
+ const handleError = async (error, notify = true, prefix = '') => {
844
+ console.error(error);
1138
845
  };
1139
- const splitLines = lines => {
1140
- return lines.split(NewLine$1);
846
+
847
+ const emptyObject = {};
848
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
849
+ const i18nString = (key, placeholders = emptyObject) => {
850
+ if (placeholders === emptyObject) {
851
+ return key;
852
+ }
853
+ const replacer = (match, rest) => {
854
+ return placeholders[rest];
855
+ };
856
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
1141
857
  };
1142
- const isModuleNotFoundMessage = line => {
1143
- return line.includes('[ERR_MODULE_NOT_FOUND]');
858
+
859
+ /**
860
+ * @enum {string}
861
+ */
862
+ const UiStrings = {
863
+ NoExtensionsFound: 'No extensions found.',
864
+ Filter: 'Filter',
865
+ Refresh: 'Refresh',
866
+ ClearExtensionSearchResults: 'Clear extension search results',
867
+ Enable: 'Enable',
868
+ Disable: 'Disable',
869
+ Uninstall: 'Uninstall',
870
+ InstallAnotherVersion: 'Install Another Version',
871
+ SearchExtensionsInMarketplace: 'Search Extensions in Marketplace',
872
+ ViewsAndMoreActions: 'Views and more Actions...',
873
+ Extensions: 'Extensions',
874
+ Installed: 'Installed'
1144
875
  };
1145
- const getModuleNotFoundError = stderr => {
1146
- const lines = splitLines(stderr);
1147
- const messageIndex = lines.findIndex(isModuleNotFoundMessage);
1148
- const message = lines[messageIndex];
1149
- return {
1150
- message,
1151
- code: ERR_MODULE_NOT_FOUND
1152
- };
876
+ const noExtensionsFound = () => {
877
+ return i18nString(UiStrings.NoExtensionsFound);
1153
878
  };
1154
- const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
1155
- const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
1156
- const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
1157
- const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
1158
- const RE_AT = /^\s+at/;
1159
- const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
1160
- const isUnhelpfulNativeModuleError = stderr => {
1161
- return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
879
+ const filter = () => {
880
+ return i18nString(UiStrings.Filter);
1162
881
  };
1163
- const isMessageCodeBlockStartIndex = line => {
1164
- return RE_MESSAGE_CODE_BLOCK_START.test(line);
882
+ const extensions = () => {
883
+ return i18nString(UiStrings.Extensions);
1165
884
  };
1166
- const isMessageCodeBlockEndIndex = line => {
1167
- return RE_MESSAGE_CODE_BLOCK_END.test(line);
885
+ const clearExtensionSearchResults = () => {
886
+ return i18nString(UiStrings.ClearExtensionSearchResults);
1168
887
  };
1169
- const getMessageCodeBlock = stderr => {
1170
- const lines = splitLines(stderr);
1171
- const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
1172
- const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
1173
- const relevantLines = lines.slice(startIndex, endIndex);
1174
- const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
1175
- return relevantMessage;
888
+ const searchExtensionsInMarketPlace = () => {
889
+ return i18nString(UiStrings.SearchExtensionsInMarketplace);
1176
890
  };
1177
- const getNativeModuleErrorMessage = stderr => {
1178
- const message = getMessageCodeBlock(stderr);
1179
- return {
1180
- message: `Incompatible native node module: ${message}`,
1181
- code: E_INCOMPATIBLE_NATIVE_MODULE
1182
- };
891
+
892
+ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
893
+ const contentHeight = itemsLength * itemHeight;
894
+ const finalDeltaY = Math.max(contentHeight - height, 0);
895
+ return finalDeltaY;
1183
896
  };
1184
- const isModulesSyntaxError = stderr => {
1185
- if (!stderr) {
1186
- return false;
897
+
898
+ const getListHeight$1 = (itemsLength, itemHeight, maxHeight) => {
899
+ number(itemsLength);
900
+ number(itemHeight);
901
+ number(maxHeight);
902
+ if (itemsLength === 0) {
903
+ return itemHeight;
1187
904
  }
1188
- return stderr.includes('SyntaxError: Cannot use import statement outside a module');
905
+ const totalHeight = itemsLength * itemHeight;
906
+ return Math.min(totalHeight, maxHeight);
1189
907
  };
1190
- const getModuleSyntaxError = () => {
908
+
909
+ // TODO optimize this function to return the minimum number
910
+ // of visible items needed, e.g. when not scrolled 5 items with
911
+ // 20px fill 100px but when scrolled 6 items are needed
912
+ const getNumberOfVisibleItems = (listHeight, itemHeight) => {
913
+ return Math.ceil(listHeight / itemHeight) + 1;
914
+ };
915
+
916
+ /**
917
+ *
918
+ * @param {number} size
919
+ * @param {number} contentSize
920
+ * @param {number} minimumSliderSize
921
+ * @returns
922
+ */
923
+ const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
924
+ if (size >= contentSize) {
925
+ return 0;
926
+ }
927
+ return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
928
+ };
929
+ const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
930
+ const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
931
+ return scrollBarOffset;
932
+ };
933
+ const getScrollBarY = getScrollBarOffset;
934
+
935
+ const Installed = '@installed';
936
+ const Enabled = '@enabled';
937
+ const Disabled = '@disabled';
938
+ const Builtin = '@builtin';
939
+ const Sort = '@sort';
940
+ const Id = '@id';
941
+ const Outdated = '@outdated';
942
+
943
+ const RE_PARAM = /@\w+/g;
944
+
945
+ // TODO test sorting and filtering
946
+ const parseValue = value => {
947
+ const parameters = Object.create(null);
948
+ // TODO this is not very functional code (assignment)
949
+ const replaced = value.replaceAll(RE_PARAM, (match, by, order) => {
950
+ if (match.startsWith(Installed)) {
951
+ parameters.installed = true;
952
+ }
953
+ if (match.startsWith(Enabled)) {
954
+ parameters.enabled = true;
955
+ }
956
+ if (match.startsWith(Disabled)) {
957
+ parameters.disabled = true;
958
+ }
959
+ if (match.startsWith(Builtin)) {
960
+ parameters.builtin = true;
961
+ }
962
+ if (match.startsWith(Sort)) {
963
+ // TODO
964
+ parameters.sort = 'installs';
965
+ }
966
+ if (match.startsWith(Id)) {
967
+ // TODO
968
+ parameters.id = 'abc';
969
+ }
970
+ if (match.startsWith(Outdated)) {
971
+ parameters.outdated = true;
972
+ }
973
+ return '';
974
+ });
975
+ const isLocal = parameters.enabled || parameters.builtin || parameters.disabled || parameters.outdated || parameters.installed;
1191
976
  return {
1192
- message: `ES Modules are not supported in electron`,
1193
- code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
977
+ query: replaced,
978
+ ...parameters,
979
+ isLocal
1194
980
  };
1195
981
  };
1196
- const isModuleNotFoundError = stderr => {
1197
- if (!stderr) {
1198
- return false;
982
+
983
+ const assetDir = '';
984
+
985
+ const Web = 1;
986
+ const Electron = 2;
987
+ const Remote = 3;
988
+ const Test = 4;
989
+
990
+ // TODO treeshake this function out
991
+
992
+ /**
993
+ * @returns {number}
994
+ */
995
+ const getPlatform = () => {
996
+ // @ts-ignore
997
+ if (typeof PLATFORM !== 'undefined') {
998
+ // @ts-ignore
999
+ return PLATFORM;
1199
1000
  }
1200
- return stderr.includes('ERR_MODULE_NOT_FOUND');
1001
+ if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
1002
+ return Test;
1003
+ }
1004
+ // TODO find a better way to pass runtime environment
1005
+ if (typeof name !== 'undefined' && name.endsWith('(Electron)')) {
1006
+ return Electron;
1007
+ }
1008
+ if (typeof name !== 'undefined' && name.endsWith('(Web)')) {
1009
+ return Web;
1010
+ }
1011
+ return Remote;
1201
1012
  };
1202
- const isNormalStackLine = line => {
1203
- return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
1013
+ const platform = getPlatform();
1014
+
1015
+ const getRemoteUrl = extension => {
1016
+ if (platform === Remote || platform === Electron) {
1017
+ if (extension.builtin) {
1018
+ return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
1019
+ }
1020
+ return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
1021
+ }
1022
+ return '';
1204
1023
  };
1205
- const getDetails = lines => {
1206
- const index = lines.findIndex(isNormalStackLine);
1207
- if (index === -1) {
1208
- return {
1209
- actualMessage: joinLines(lines),
1210
- rest: []
1211
- };
1024
+
1025
+ const ExtensionDefaultIcon = `${assetDir}/icons/extensionDefaultIcon.png`;
1026
+ const ExtensionLanguageBasics = `${assetDir}/icons/language-icon.svg`;
1027
+ const ExtensionTheme = `${assetDir}/icons/theme-icon.png`;
1028
+
1029
+ const isLanguageBasicsExtension = extension => {
1030
+ return extension.name && extension.name.startsWith('Language Basics');
1031
+ };
1032
+ const isThemeExtension = extension => {
1033
+ return extension.name && extension.name.endsWith(' Theme');
1034
+ };
1035
+ const getIcon = extension => {
1036
+ if (!extension) {
1037
+ return ExtensionDefaultIcon;
1212
1038
  }
1213
- let lastIndex = index - 1;
1214
- while (++lastIndex < lines.length) {
1215
- if (!isNormalStackLine(lines[lastIndex])) {
1216
- break;
1039
+ if (!extension.path || !extension.icon) {
1040
+ if (isLanguageBasicsExtension(extension)) {
1041
+ return ExtensionLanguageBasics;
1217
1042
  }
1043
+ if (isThemeExtension(extension)) {
1044
+ return ExtensionTheme;
1045
+ }
1046
+ return ExtensionDefaultIcon;
1218
1047
  }
1219
- return {
1220
- actualMessage: lines[index - 1],
1221
- rest: lines.slice(index, lastIndex)
1222
- };
1048
+ return getRemoteUrl(extension);
1223
1049
  };
1224
- const getHelpfulChildProcessError = (stdout, stderr) => {
1225
- if (isUnhelpfulNativeModuleError(stderr)) {
1226
- return getNativeModuleErrorMessage(stderr);
1050
+ const RE_PUBLISHER = /^[a-z\d\-]+/;
1051
+
1052
+ // TODO handle case when extension is of type number|array|null|string
1053
+ const getPublisher = extension => {
1054
+ if (!extension || !extension.id) {
1055
+ return 'n/a';
1227
1056
  }
1228
- if (isModulesSyntaxError(stderr)) {
1229
- return getModuleSyntaxError();
1057
+ // TODO handle case when id is not of type string -> should not crash application
1058
+ const match = extension.id.match(RE_PUBLISHER);
1059
+ if (!match) {
1060
+ return 'n/a';
1230
1061
  }
1231
- if (isModuleNotFoundError(stderr)) {
1232
- return getModuleNotFoundError(stderr);
1062
+ return match[0];
1063
+ };
1064
+ const getName = extension => {
1065
+ if (extension && extension.name) {
1066
+ return extension.name;
1233
1067
  }
1234
- const lines = splitLines(stderr);
1235
- const {
1236
- actualMessage,
1237
- rest
1238
- } = getDetails(lines);
1068
+ if (extension && extension.id) {
1069
+ return extension.id;
1070
+ }
1071
+ return 'n/a';
1072
+ };
1073
+ const getDescription = extension => {
1074
+ if (!extension || !extension.description) {
1075
+ return 'n/a';
1076
+ }
1077
+ return extension.description;
1078
+ };
1079
+ const getId = extension => {
1080
+ if (!extension || !extension.id) {
1081
+ return 'n/a';
1082
+ }
1083
+ return extension.id;
1084
+ };
1085
+
1086
+ const matchesParsedValue = (extension, parsedValue) => {
1087
+ if (extension && typeof extension.name === 'string') {
1088
+ const extensionNameLower = extension.name.toLowerCase();
1089
+ return extensionNameLower.includes(parsedValue.query);
1090
+ }
1091
+ if (extension && typeof extension.id === 'string') {
1092
+ const extensionIdLower = extension.id.toLowerCase();
1093
+ return extensionIdLower.includes(parsedValue.query);
1094
+ }
1095
+ return false;
1096
+ };
1097
+
1098
+ const toSorted = (array, compare) => {
1099
+ return [...array].sort(compare);
1100
+ };
1101
+
1102
+ const compareExtension = (extensionA, extensionB) => {
1103
+ return extensionA.name.localeCompare(extensionB.name) || extensionA.id.localeCompare(extensionB.id);
1104
+ };
1105
+
1106
+ const sortExtensions = extensions => {
1107
+ return toSorted(extensions, compareExtension);
1108
+ };
1109
+
1110
+ const getExtensions = async (extensions, parsedValue) => {
1111
+ const filteredExtensions = [];
1112
+ for (const extension of extensions) {
1113
+ if (matchesParsedValue(extension, parsedValue)) {
1114
+ filteredExtensions.push({
1115
+ name: getName(extension),
1116
+ id: getId(extension),
1117
+ publisher: getPublisher(extension),
1118
+ icon: getIcon(extension),
1119
+ description: getDescription(extension)
1120
+ });
1121
+ }
1122
+ }
1123
+ const sortedExtensions = sortExtensions(filteredExtensions);
1124
+ return sortedExtensions;
1125
+ };
1126
+
1127
+ const searchExtensions = async (extensions, value) => {
1128
+ try {
1129
+ const parsedValue = parseValue(value);
1130
+ const filteredExtensions = await getExtensions(extensions, parsedValue);
1131
+ return filteredExtensions;
1132
+ } catch (error) {
1133
+ throw new VError(error, 'Failed to search for extensions');
1134
+ }
1135
+ };
1136
+
1137
+ // TODO debounce
1138
+ const handleInput = async (state, value) => {
1139
+ try {
1140
+ const {
1141
+ allExtensions,
1142
+ itemHeight,
1143
+ minimumSliderSize,
1144
+ height
1145
+ } = state;
1146
+ // TODO cancel ongoing requests
1147
+ // TODO handle errors
1148
+ const items = await searchExtensions(allExtensions, value);
1149
+ if (items.length === 0) {
1150
+ return {
1151
+ ...state,
1152
+ items,
1153
+ minLineY: 0,
1154
+ deltaY: 0,
1155
+ allExtensions,
1156
+ maxLineY: 0,
1157
+ scrollBarHeight: 0,
1158
+ finalDeltaY: 0,
1159
+ message: noExtensionsFound(),
1160
+ searchValue: value,
1161
+ placeholder: searchExtensionsInMarketPlace()
1162
+ };
1163
+ }
1164
+ // @ts-ignore
1165
+ const listHeight = getListHeight$1(state);
1166
+ const total = items.length;
1167
+ const contentHeight = total * itemHeight;
1168
+ const scrollBarHeight = getScrollBarSize(height, contentHeight, minimumSliderSize);
1169
+ const numberOfVisible = getNumberOfVisibleItems(listHeight, itemHeight);
1170
+ const maxLineY = Math.min(numberOfVisible, total);
1171
+ const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
1172
+ return {
1173
+ ...state,
1174
+ items,
1175
+ minLineY: 0,
1176
+ deltaY: 0,
1177
+ allExtensions,
1178
+ maxLineY,
1179
+ scrollBarHeight,
1180
+ finalDeltaY,
1181
+ message: '',
1182
+ searchValue: value,
1183
+ placeholder: searchExtensionsInMarketPlace()
1184
+ };
1185
+
1186
+ // TODO handle out of order responses (a bit complicated)
1187
+ // for now just assume everything comes back in order
1188
+ } catch (error) {
1189
+ await handleError(error);
1190
+ return {
1191
+ ...state,
1192
+ searchValue: value,
1193
+ message: `${error}`
1194
+ };
1195
+ }
1196
+ };
1197
+
1198
+ const clearSearchResults = state => {
1199
+ return handleInput(state, '');
1200
+ };
1201
+
1202
+ const Enter = 3;
1203
+ const Space = 9;
1204
+ const PageUp = 10;
1205
+ const PageDown = 11;
1206
+ const End = 255;
1207
+ const Home = 12;
1208
+ const UpArrow = 14;
1209
+ const DownArrow = 16;
1210
+
1211
+ const CtrlCmd = 1 << 11 >>> 0;
1212
+
1213
+ const FocusExtensions = 15;
1214
+
1215
+ const getKeyBindings = () => {
1216
+ return [{
1217
+ key: Home,
1218
+ command: 'Extensions.focusFirst',
1219
+ when: FocusExtensions
1220
+ }, {
1221
+ key: End,
1222
+ command: 'Extensions.focusLast',
1223
+ when: FocusExtensions
1224
+ }, {
1225
+ key: PageUp,
1226
+ command: 'Extensions.focusPreviousPage',
1227
+ when: FocusExtensions
1228
+ }, {
1229
+ key: PageDown,
1230
+ command: 'Extensions.focusNextPage',
1231
+ when: FocusExtensions
1232
+ }, {
1233
+ key: UpArrow,
1234
+ command: 'Extensions.focusPrevious',
1235
+ when: FocusExtensions
1236
+ }, {
1237
+ key: DownArrow,
1238
+ command: 'Extensions.focusNext',
1239
+ when: FocusExtensions
1240
+ }, {
1241
+ key: Space,
1242
+ command: 'Extensions.handleClickCurrentButKeepFocus',
1243
+ when: FocusExtensions
1244
+ }, {
1245
+ key: Enter,
1246
+ command: 'Extensions.handleClickCurrent',
1247
+ when: FocusExtensions
1248
+ }, {
1249
+ key: CtrlCmd | Space,
1250
+ command: 'Extensions.toggleSuggest',
1251
+ when: FocusExtensions
1252
+ }, {
1253
+ key: CtrlCmd | DownArrow,
1254
+ command: 'Extensions.scrollDown',
1255
+ when: FocusExtensions
1256
+ }];
1257
+ };
1258
+
1259
+ const Button = 1;
1260
+
1261
+ const ExtensionActions = 'ExtensionActions';
1262
+ const ExtensionActive = 'ExtensionActive';
1263
+ const ExtensionHeader = 'ExtensionHeader';
1264
+ const ExtensionListItem = 'ExtensionListItem';
1265
+ const ExtensionListItemAuthorName = 'ExtensionListItemAuthorName';
1266
+ const ExtensionListItemDescription = 'ExtensionListItemDescription';
1267
+ const ExtensionListItemDetail = 'ExtensionListItemDetail';
1268
+ const ExtensionListItemFooter = 'ExtensionListItemFooter';
1269
+ const ExtensionListItemIcon = 'ExtensionListItemIcon';
1270
+ const ExtensionListItemName = 'ExtensionListItemName';
1271
+ const ListItems = 'ListItems';
1272
+ const MultilineInputBox = 'MultilineInputBox';
1273
+ const ScrollBarThumb = 'ScrollBarThumb';
1274
+ const ScrollBarThumbActive = 'ScrollBarThumbActive';
1275
+ const SearchField = 'SearchField';
1276
+ const SearchFieldButtons = 'SearchFieldButtons';
1277
+ const SearchFieldContainer = 'SearchFieldContainer';
1278
+
1279
+ const CheckBox = 'checkbox';
1280
+ const List = 'list';
1281
+ const ListItem = 'listitem';
1282
+ const None = 'none';
1283
+
1284
+ const Div = 4;
1285
+ const Text = 12;
1286
+ const Img = 17;
1287
+ const TextArea = 62;
1288
+
1289
+ const getSearchFieldButtonVirtualDom = button => {
1290
+ const {
1291
+ icon,
1292
+ checked,
1293
+ title
1294
+ } = button;
1295
+ return [{
1296
+ type: Div,
1297
+ className: `SearchFieldButton ${checked ? 'SearchFieldButtonChecked' : ''}`,
1298
+ title,
1299
+ role: CheckBox,
1300
+ ariaChecked: checked,
1301
+ tabIndex: 0,
1302
+ childCount: 1
1303
+ }, {
1304
+ type: Div,
1305
+ className: `MaskIcon ${icon}`,
1306
+ childCount: 0
1307
+ }];
1308
+ };
1309
+
1310
+ const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, outsideButtons, onFocus = '') => {
1311
+ const dom = [{
1312
+ type: Div,
1313
+ className: SearchField,
1314
+ role: None,
1315
+ childCount: 2
1316
+ }, {
1317
+ type: TextArea,
1318
+ className: MultilineInputBox,
1319
+ spellcheck: false,
1320
+ autocapitalize: 'off',
1321
+ autocorrect: 'off',
1322
+ placeholder,
1323
+ name,
1324
+ onInput,
1325
+ onFocus,
1326
+ childCount: 0
1327
+ }, {
1328
+ type: Div,
1329
+ className: SearchFieldButtons,
1330
+ childCount: insideButtons.length
1331
+ }, ...insideButtons.flatMap(getSearchFieldButtonVirtualDom)];
1332
+ if (outsideButtons.length > 0) {
1333
+ dom.unshift({
1334
+ type: Div,
1335
+ className: SearchFieldContainer,
1336
+ role: None,
1337
+ childCount: 1 + outsideButtons.length
1338
+ });
1339
+ dom.push(...outsideButtons.flatMap(getSearchFieldButtonVirtualDom));
1340
+ }
1341
+ return dom;
1342
+ };
1343
+
1344
+ const getExtensionHeaderVirtualDom = (placeholder, actions) => {
1345
+ return [{
1346
+ type: Div,
1347
+ className: ExtensionHeader,
1348
+ childCount: 1
1349
+ }, ...getSearchFieldVirtualDom('extensions', placeholder, 'handleExtensionsInput', actions, [])];
1350
+ };
1351
+
1352
+ const HandleContextMenu = 'handleContextMenu';
1353
+ const HandlePointerDown = 'handlePointerDown';
1354
+ const HandleTouchStart = 'handleTouchStart';
1355
+ const HandleWheel = 'handleWheel';
1356
+
1357
+ const Extension = 'Extension';
1358
+
1359
+ const text = data => {
1360
+ return {
1361
+ type: Text,
1362
+ text: data,
1363
+ childCount: 0
1364
+ };
1365
+ };
1366
+
1367
+ const listItemDetail = {
1368
+ type: Div,
1369
+ className: ExtensionListItemDetail,
1370
+ childCount: 3
1371
+ };
1372
+ const listItemName = {
1373
+ type: Div,
1374
+ className: ExtensionListItemName,
1375
+ childCount: 1
1376
+ };
1377
+ const listItemDescription = {
1378
+ type: Div,
1379
+ className: ExtensionListItemDescription,
1380
+ childCount: 1
1381
+ };
1382
+ const listItemFooter = {
1383
+ type: Div,
1384
+ className: ExtensionListItemFooter,
1385
+ childCount: 2
1386
+ };
1387
+ const listItemAuthorName = {
1388
+ type: Div,
1389
+ className: ExtensionListItemAuthorName,
1390
+ childCount: 1
1391
+ };
1392
+ const getExtensionListItemVirtualDom = extension => {
1393
+ const {
1394
+ posInSet,
1395
+ setSize,
1396
+ top,
1397
+ icon,
1398
+ name,
1399
+ description,
1400
+ publisher,
1401
+ focused
1402
+ } = extension;
1403
+ const dom = [{
1404
+ type: Div,
1405
+ role: ListItem,
1406
+ ariaRoleDescription: Extension,
1407
+ className: ExtensionListItem,
1408
+ ariaPosInSet: posInSet,
1409
+ ariaSetSize: setSize,
1410
+ top,
1411
+ childCount: 2
1412
+ }, {
1413
+ type: Img,
1414
+ src: icon,
1415
+ className: ExtensionListItemIcon,
1416
+ role: None,
1417
+ childCount: 0
1418
+ }, listItemDetail, listItemName, text(name), listItemDescription, text(description), listItemFooter, listItemAuthorName, text(publisher), {
1419
+ type: Div,
1420
+ className: ExtensionActions,
1421
+ childCount: 0
1422
+ }];
1423
+ if (focused) {
1424
+ dom[0].id = 'ExtensionActive';
1425
+ dom[0].className += ' ' + ExtensionActive;
1426
+ }
1427
+ return dom;
1428
+ };
1429
+
1430
+ const getExtensionsListVirtualDom = visibleExtensions => {
1431
+ const dom = [{
1432
+ type: Div,
1433
+ className: ListItems,
1434
+ tabIndex: 0,
1435
+ ariaLabel: extensions(),
1436
+ role: List,
1437
+ oncontextmenu: HandleContextMenu,
1438
+ onpointerdown: HandlePointerDown,
1439
+ ontouchstart: HandleTouchStart,
1440
+ onwheelpassive: HandleWheel,
1441
+ childCount: visibleExtensions.length
1442
+ }, ...visibleExtensions.flatMap(getExtensionListItemVirtualDom)];
1443
+ return dom;
1444
+ };
1445
+
1446
+ const getExtensionsVirtualDom = visibleExtensions => {
1447
+ const dom = getExtensionsListVirtualDom(visibleExtensions);
1448
+ // TODO
1449
+ return dom;
1450
+ };
1451
+
1452
+ const getVisibleItem = (item, setSize, itemHeight, minLineY, relative, i, focusedIndex) => {
1239
1453
  return {
1240
- message: `${actualMessage}`,
1241
- code: '',
1242
- stack: rest
1454
+ ...item,
1455
+ setSize,
1456
+ posInSet: i + 1,
1457
+ top: (i - minLineY) * itemHeight - relative,
1458
+ focused: i === focusedIndex
1243
1459
  };
1244
1460
  };
1245
- const normalizeLine = line => {
1246
- if (line.startsWith('Error: ')) {
1247
- return line.slice(`Error: `.length);
1248
- }
1249
- if (line.startsWith('VError: ')) {
1250
- return line.slice(`VError: `.length);
1461
+ const getVisible = state => {
1462
+ const {
1463
+ minLineY,
1464
+ maxLineY,
1465
+ items,
1466
+ itemHeight,
1467
+ deltaY,
1468
+ focusedIndex
1469
+ } = state;
1470
+ const setSize = items.length;
1471
+ const visible = [];
1472
+ const relative = deltaY % itemHeight;
1473
+ for (let i = minLineY; i < maxLineY; i++) {
1474
+ const item = items[i];
1475
+ visible.push(getVisibleItem(item, setSize, itemHeight, minLineY, relative, i, focusedIndex));
1251
1476
  }
1252
- return line;
1477
+ return visible;
1253
1478
  };
1254
- const getCombinedMessage = (error, message) => {
1255
- const stringifiedError = normalizeLine(`${error}`);
1256
- if (message) {
1257
- return `${message}: ${stringifiedError}`;
1258
- }
1259
- return stringifiedError;
1479
+
1480
+ const ClearAll = 'ClearAll';
1481
+ const Filter = 'Filter';
1482
+
1483
+ const px = value => {
1484
+ return `${value}px`;
1260
1485
  };
1261
- const NewLine = '\n';
1262
- const getNewLineIndex = (string, startIndex = undefined) => {
1263
- return string.indexOf(NewLine, startIndex);
1486
+ const position = (x, y) => {
1487
+ return `${x}px ${y}px`;
1264
1488
  };
1265
- const mergeStacks = (parent, child) => {
1266
- if (!child) {
1267
- return parent;
1268
- }
1269
- const parentNewLineIndex = getNewLineIndex(parent);
1270
- const childNewLineIndex = getNewLineIndex(child);
1271
- if (childNewLineIndex === -1) {
1272
- return parent;
1273
- }
1274
- const parentFirstLine = parent.slice(0, parentNewLineIndex);
1275
- const childRest = child.slice(childNewLineIndex);
1276
- const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
1277
- if (parentFirstLine.includes(childFirstLine)) {
1278
- return parentFirstLine + childRest;
1279
- }
1280
- return child;
1489
+
1490
+ const SetMessage = 'setMessage';
1491
+ const SetScrollBar = 'setScrollBar';
1492
+ const SetSearchValue = 'setSearchValue';
1493
+
1494
+ const getListHeight = state => {
1495
+ const {
1496
+ height,
1497
+ headerHeight
1498
+ } = state;
1499
+ return height - headerHeight;
1281
1500
  };
1282
- class VError extends Error {
1283
- constructor(error, message) {
1284
- const combinedMessage = getCombinedMessage(error, message);
1285
- super(combinedMessage);
1286
- this.name = 'VError';
1287
- if (error instanceof Error) {
1288
- this.stack = mergeStacks(this.stack, error.stack);
1289
- }
1290
- if (error.codeFrame) {
1291
- // @ts-ignore
1292
- this.codeFrame = error.codeFrame;
1293
- }
1294
- if (error.code) {
1295
- // @ts-ignore
1296
- this.code = error.code;
1297
- }
1501
+ const renderExtensions = {
1502
+ isEqual(oldState, newState) {
1503
+ return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.deltaY === newState.deltaY && oldState.focusedIndex === newState.focusedIndex;
1504
+ },
1505
+ apply(oldState, newState) {
1506
+ // TODO render extensions incrementally when scrolling
1507
+ const visibleExtensions = getVisible(newState);
1508
+ const dom = getExtensionsVirtualDom(visibleExtensions);
1509
+ return ['setExtensionsDom', dom];
1298
1510
  }
1299
- }
1300
- class IpcError extends VError {
1301
- // @ts-ignore
1302
- constructor(betterMessage, stdout = '', stderr = '') {
1303
- if (stdout || stderr) {
1304
- // @ts-ignore
1305
- const {
1306
- message,
1307
- code,
1308
- stack
1309
- } = getHelpfulChildProcessError(stdout, stderr);
1310
- const cause = new Error(message);
1311
- // @ts-ignore
1312
- cause.code = code;
1313
- cause.stack = stack;
1314
- super(cause, betterMessage);
1315
- } else {
1316
- super(betterMessage);
1317
- }
1318
- // @ts-ignore
1319
- this.name = 'IpcError';
1320
- // @ts-ignore
1321
- this.stdout = stdout;
1511
+ };
1512
+ const renderScrollBar = {
1513
+ isEqual(oldState, newState) {
1514
+ return oldState.negativeMargin === newState.negativeMargin && oldState.deltaY === newState.deltaY && oldState.height === newState.height && oldState.finalDeltaY === newState.finalDeltaY && oldState.items.length === newState.items.length && oldState.scrollBarActive === newState.scrollBarActive;
1515
+ },
1516
+ apply(oldState, newState) {
1322
1517
  // @ts-ignore
1323
- this.stderr = stderr;
1518
+ const listHeight = getListHeight(newState);
1519
+ const total = newState.items.length;
1520
+ const contentHeight = total * newState.itemHeight;
1521
+ const scrollBarHeight = getScrollBarSize(listHeight, contentHeight, newState.minimumSliderSize);
1522
+ const scrollBarY = getScrollBarY(newState.deltaY, newState.finalDeltaY, newState.height - newState.headerHeight, scrollBarHeight);
1523
+ const roundedScrollBarY = Math.round(scrollBarY);
1524
+ const heightString = px(scrollBarHeight);
1525
+ const translateString = position(0, roundedScrollBarY);
1526
+ let className = ScrollBarThumb;
1527
+ if (newState.scrollBarActive) {
1528
+ className += ' ' + ScrollBarThumbActive;
1529
+ }
1530
+ return [/* method */SetScrollBar, translateString, heightString, className];
1324
1531
  }
1325
- }
1326
- const withResolvers = () => {
1327
- let _resolve;
1328
- const promise = new Promise(resolve => {
1329
- _resolve = resolve;
1330
- });
1331
- return {
1332
- resolve: _resolve,
1333
- promise
1334
- };
1335
- };
1336
- const waitForFirstMessage = async port => {
1337
- const {
1338
- resolve,
1339
- promise
1340
- } = withResolvers();
1341
- port.addEventListener('message', resolve, {
1342
- once: true
1343
- });
1344
- const event = await promise;
1345
- // @ts-ignore
1346
- return event.data;
1347
1532
  };
1348
- const listen$3 = async () => {
1349
- const parentIpcRaw = listen$4();
1350
- signal$3(parentIpcRaw);
1351
- const parentIpc = wrap$6(parentIpcRaw);
1352
- const firstMessage = await waitForFirstMessage(parentIpc);
1353
- if (firstMessage.method !== 'initialize') {
1354
- throw new IpcError('unexpected first message');
1355
- }
1356
- const type = firstMessage.params[0];
1357
- if (type === 'message-port') {
1358
- parentIpc.send({
1359
- jsonrpc: '2.0',
1360
- id: firstMessage.id,
1361
- result: null
1362
- });
1363
- parentIpc.dispose();
1364
- const port = firstMessage.params[1];
1365
- return port;
1533
+ const renderMessage = {
1534
+ isEqual(oldState, newState) {
1535
+ return oldState.message === newState.message;
1536
+ },
1537
+ apply(oldState, newState) {
1538
+ return [/* method */SetMessage, /* message */newState.message];
1366
1539
  }
1367
- return globalThis;
1368
1540
  };
1369
- class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
1370
- constructor(port) {
1371
- super(port);
1372
- }
1373
- getData(event) {
1374
- return getData$1(event);
1375
- }
1376
- send(message) {
1377
- this._rawIpc.postMessage(message);
1541
+ const renderSearchValue = {
1542
+ isEqual(oldState, newState) {
1543
+ return oldState.searchValue === newState.searchValue;
1544
+ },
1545
+ apply(oldState, newState) {
1546
+ return [/* method */SetSearchValue, oldState.searchValue, newState.searchValue];
1378
1547
  }
1379
- sendAndTransfer(message) {
1380
- const transfer = getTransferrables(message);
1381
- this._rawIpc.postMessage(message, transfer);
1548
+ };
1549
+ const renderHeader = {
1550
+ isEqual(oldState, newState) {
1551
+ return oldState.placeholder === newState.placeholder;
1552
+ },
1553
+ apply(oldState, newState) {
1554
+ const actions = [{
1555
+ type: Button,
1556
+ title: clearExtensionSearchResults(),
1557
+ icon: `MaskIcon${ClearAll}`,
1558
+ command: 'Extensions.clearSearchResults'
1559
+ }, {
1560
+ type: Button,
1561
+ title: filter(),
1562
+ icon: `MaskIcon${Filter}`
1563
+ }];
1564
+ const dom = getExtensionHeaderVirtualDom(newState.placeholder, actions);
1565
+ return ['setHeaderDom', dom];
1382
1566
  }
1383
- dispose() {
1384
- if (this._rawIpc.close) {
1385
- this._rawIpc.close();
1567
+ };
1568
+ const render = [renderScrollBar, renderMessage, renderExtensions, renderSearchValue, renderHeader];
1569
+ const doRender = (oldState, newState) => {
1570
+ const commands = [];
1571
+ for (const item of render) {
1572
+ if (!item.isEqual(oldState, newState)) {
1573
+ commands.push(item.apply(oldState, newState));
1386
1574
  }
1387
1575
  }
1388
- onClose(callback) {
1389
- // ignore
1390
- }
1391
- onMessage(callback) {
1392
- this._rawIpc.addEventListener('message', callback);
1393
- this._rawIpc.start();
1394
- }
1395
- }
1396
- const wrap$5 = port => {
1397
- return new IpcChildWithModuleWorkerAndMessagePort(port);
1398
- };
1399
- const IpcChildWithModuleWorkerAndMessagePort$1 = {
1400
- __proto__: null,
1401
- listen: listen$3,
1402
- wrap: wrap$5
1576
+ return commands;
1403
1577
  };
1404
1578
 
1405
- const getModule = method => {
1406
- switch (method) {
1407
- case ModuleWorker:
1408
- return IpcChildWithModuleWorker$1;
1409
- case ModuleWorkerAndMessagePort:
1410
- return IpcChildWithModuleWorkerAndMessagePort$1;
1411
- default:
1412
- throw new Error('unexpected ipc type');
1413
- }
1579
+ const commandMap = {
1580
+ 'SearchExtensions.clearSearchResults': clearSearchResults,
1581
+ 'SearchExtensions.getKeyBindings': getKeyBindings,
1582
+ 'SearchExtensions.render': doRender,
1583
+ 'SearchExtensions.searchExtensions': searchExtensions
1414
1584
  };
1415
1585
 
1416
- const listen$1 = async ({
1417
- method
1418
- }) => {
1419
- const module = await getModule(method);
1420
- const rawIpc = await module.listen();
1421
- if (module.signal) {
1422
- module.signal(rawIpc);
1423
- }
1424
- const ipc = module.wrap(rawIpc);
1425
- return ipc;
1586
+ const RendererWorker = 1;
1587
+
1588
+ const rpcs = Object.create(null);
1589
+ const set = (id, rpc) => {
1590
+ rpcs[id] = rpc;
1426
1591
  };
1427
1592
 
1428
1593
  const listen = async () => {
1429
- register(commandMap);
1430
- const ipc = await listen$1({
1431
- method: Auto()
1594
+ const rpc = await WebWorkerRpcClient.create({
1595
+ commandMap: commandMap
1432
1596
  });
1433
- handleIpc(ipc);
1597
+ set(RendererWorker, rpc);
1434
1598
  };
1435
1599
 
1436
1600
  const main = async () => {