@lvce-editor/iframe-worker 1.5.0 → 2.1.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,438 +1,194 @@
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);
8
- }
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}`);
17
- }
18
- return fn(...args);
19
- };
20
-
21
- const createUrl = (protocol, host) => {
22
- return protocol + '//' + host;
1
+ const Two = '2.0';
2
+ const state = {
3
+ callbacks: Object.create(null)
23
4
  };
24
-
25
- const createLocalHostUrl = (locationProtocol, locationHost, isGitpod, webViewPort) => {
26
- if (isGitpod) {
27
- return createUrl(locationProtocol, locationHost.replace('3000', `${webViewPort}`));
28
- }
29
- return `http://localhost:${webViewPort}`;
5
+ const set = (id, fn) => {
6
+ state.callbacks[id] = fn;
30
7
  };
31
-
32
- const Web = 1;
33
- const Electron = 2;
34
- const Remote = 3;
35
- const Test = 4;
36
-
37
- /* istanbul ignore file */
38
-
39
- // TODO this should always be completely tree shaken out during build, maybe need to be marked as @__Pure for terser to work
40
-
41
- // TODO treeshake this function out when targeting electron
42
-
43
- /**
44
- * @returns {number}
45
- */
46
- const getPlatform = () => {
47
- // @ts-ignore
48
- if (typeof PLATFORM !== 'undefined') {
49
- // @ts-ignore
50
- return PLATFORM;
51
- }
52
- // @ts-ignore
53
- if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
54
- return Test;
55
- }
56
- // TODO find a better way to pass runtime environment
57
- if (typeof name !== 'undefined' && name.endsWith('(Electron)')) {
58
- return Electron;
59
- }
60
- if (typeof name !== 'undefined' && name.endsWith('(Web)')) {
61
- return Web;
62
- }
63
- return Remote;
64
- };
65
- const platform = getPlatform();
66
-
67
- const getAssetDir = () => {
68
- // @ts-ignore
69
- if (typeof ASSET_DIR !== 'undefined') {
70
- // @ts-ignore
71
- return ASSET_DIR;
72
- }
73
- if (platform === Electron) {
74
- return '';
75
- }
76
- return '';
8
+ const get = id => {
9
+ return state.callbacks[id];
77
10
  };
78
- const assetDir = getAssetDir();
79
-
80
- const getWebViewHtml = (baseUrl, locationOrigin, elements) => {
81
- if (!elements) {
82
- return '';
83
- }
84
- const middle = [];
85
- middle.push('<meta charset="utf-8">');
86
- for (const element of elements) {
87
- if (element.type === 'title') {
88
- middle.push(`<title>${element.value}</title>`);
89
- } else if (element.type === 'script') {
90
- middle.push(`<script type="module" src="${locationOrigin}${assetDir}/js/preview-injected.js"></script>`);
91
- middle.push(`<script type="module" src="${locationOrigin}${baseUrl}/${element.path}"></script>`);
92
- } else if (element.type === 'css') {
93
- middle.push(`<link rel="stylesheet" href="${locationOrigin}${baseUrl}/${element.path}" />`);
94
- }
95
- }
96
- const middleHtml = middle.join('\n ');
97
- let html = `<!DOCTYPE html>
98
- <html>
99
- <head>
100
- ${middleHtml}
101
- </head>
102
- </html>
103
- `;
104
- return html;
11
+ const remove = id => {
12
+ delete state.callbacks[id];
105
13
  };
106
-
107
- const WebView = 'lvce-oss-webview';
108
-
109
- const getWebView$1 = (webViews, webViewId) => {
110
- for (const webView of webViews) {
111
- if (webView.id === webViewId) {
112
- return webView;
113
- }
114
- }
115
- return undefined;
14
+ let id = 0;
15
+ const create$3 = () => {
16
+ return ++id;
116
17
  };
117
- const getWebViewPath = (webViews, webViewId) => {
118
- const webView = getWebView$1(webViews, webViewId);
119
- if (!webView) {
120
- return '';
121
- }
122
- return webView.path;
123
- };
124
- const getWebViewUri = (webViews, webViewId) => {
125
- const webViewPath = getWebViewPath(webViews, webViewId);
126
- if (!webViewPath) {
127
- return '';
128
- }
129
- if (webViewPath.startsWith('/')) {
130
- // TODO make it work on windows also
131
- return `file://${webViewPath}`;
132
- }
133
- return webViewPath;
18
+ const warn = (...args) => {
19
+ console.warn(...args);
134
20
  };
135
- const getIframeSrcRemote = (webViews, webViewPort, webViewId, locationProtocol, locationHost, isGitpod, root) => {
136
- const webView = getWebView$1(webViews, webViewId);
137
- const webViewUri = getWebViewUri(webViews, webViewId);
138
- if (!webViewUri) {
139
- return undefined;
140
- }
141
- let iframeSrc = webViewUri;
142
- let webViewRoot = webViewUri;
143
- if (platform === Electron) {
144
- const relativePath = new URL(webViewUri).pathname.replace('/index.html', '');
145
- iframeSrc = `${WebView}://-${relativePath}/`;
146
- // TODO
147
- } else if (platform === Remote) {
148
- const relativePath = new URL(webViewUri).pathname.replace('/index.html', '');
149
- if (webViewUri.startsWith('file://')) {
150
- // ignore
151
- webViewRoot = webViewUri.slice('file://'.length).replace('/index.html', '');
152
- } else {
153
- webViewRoot = root + relativePath;
154
- }
155
- iframeSrc = createLocalHostUrl(locationProtocol, locationHost, isGitpod, webViewPort);
156
- }
157
- let iframeContent = getWebViewHtml('', '', webView.elements);
158
- // TODO either
159
- // - load webviews the same as in web using blob urls
160
- // - load webviews from a pattern like /webviews/:id/:fileName
161
- iframeContent = iframeContent.replaceAll('/media/', '/').replaceAll('//', '/');
21
+ const registerPromise = () => {
22
+ const id = create$3();
23
+ const {
24
+ resolve,
25
+ promise
26
+ } = Promise.withResolvers();
27
+ set(id, resolve);
162
28
  return {
163
- srcDoc: '',
164
- iframeSrc,
165
- webViewRoot,
166
- iframeContent
29
+ id,
30
+ promise
167
31
  };
168
32
  };
169
-
170
- const getBlobUrl = (content, contentType) => {
171
- const blob = new Blob([content], {
172
- type: contentType
173
- });
174
- const url = URL.createObjectURL(blob); // TODO dispose
175
- return url;
176
- };
177
-
178
- const getDefaultBaseUrl = webView => {
179
- const {
180
- remotePath,
181
- path
182
- } = webView;
183
- if (remotePath) {
184
- if (remotePath.endsWith('/index.html')) {
185
- return remotePath.slice(0, -'/index.html'.length);
186
- }
187
- return remotePath;
188
- }
189
- if (path) {
190
- if (path.endsWith('/index.html')) {
191
- return path.slice(0, -'/index.html'.length);
192
- }
193
- return path;
33
+ const resolve = (id, response) => {
34
+ const fn = get(id);
35
+ if (!fn) {
36
+ console.log(response);
37
+ warn(`callback ${id} may already be disposed`);
38
+ return;
194
39
  }
195
- return '';
40
+ fn(response);
41
+ remove(id);
196
42
  };
197
- const getWebViewBaseUrl = webView => {
198
- const defaultBaseUrl = getDefaultBaseUrl(webView);
199
- return defaultBaseUrl;
43
+ const create$2 = (method, params) => {
44
+ const {
45
+ id,
46
+ promise
47
+ } = registerPromise();
48
+ const message = {
49
+ jsonrpc: Two,
50
+ method,
51
+ params,
52
+ id
53
+ };
54
+ return {
55
+ message,
56
+ promise
57
+ };
200
58
  };
201
-
202
- const getIframeSrc$1 = (webView, locationOrigin) => {
203
- const baseUrl = getWebViewBaseUrl(webView);
204
- const srcHtml = getWebViewHtml(baseUrl, locationOrigin, webView.elements);
205
- if (srcHtml) {
206
- const blobUrl = getBlobUrl(srcHtml, 'text/html');
207
- return {
208
- srcDoc: '',
209
- iframeSrc: blobUrl,
210
- webViewRoot: '',
211
- iframeContent: ''
212
- };
59
+ class JsonRpcError extends Error {
60
+ constructor(message) {
61
+ super(message);
62
+ this.name = 'JsonRpcError';
213
63
  }
214
- return undefined;
215
- };
216
-
217
- const getWebView = (webViews, webViewId) => {
218
- for (const webView of webViews) {
219
- if (webView.id === webViewId) {
220
- return webView;
64
+ }
65
+ const NewLine$3 = '\n';
66
+ const DomException = 'DOMException';
67
+ const ReferenceError$1 = 'ReferenceError';
68
+ const SyntaxError$1 = 'SyntaxError';
69
+ const TypeError$1 = 'TypeError';
70
+ const getErrorConstructor = (message, type) => {
71
+ if (type) {
72
+ switch (type) {
73
+ case DomException:
74
+ return DOMException;
75
+ case TypeError$1:
76
+ return TypeError;
77
+ case SyntaxError$1:
78
+ return SyntaxError;
79
+ case ReferenceError$1:
80
+ return ReferenceError;
81
+ default:
82
+ return Error;
221
83
  }
222
84
  }
223
- return undefined;
224
- };
225
-
226
- const normalizeLine$1 = line => {
227
- if (line.startsWith('Error: ')) {
228
- return line.slice(`Error: `.length);
229
- }
230
- if (line.startsWith('VError: ')) {
231
- return line.slice(`VError: `.length);
232
- }
233
- return line;
234
- };
235
- const getCombinedMessage$1 = (error, message) => {
236
- const stringifiedError = normalizeLine$1(`${error}`);
237
- if (message) {
238
- return `${message}: ${stringifiedError}`;
239
- }
240
- return stringifiedError;
241
- };
242
- const NewLine$2 = '\n';
243
- const getNewLineIndex$1 = (string, startIndex = undefined) => {
244
- return string.indexOf(NewLine$2, startIndex);
245
- };
246
- const mergeStacks$1 = (parent, child) => {
247
- if (!child) {
248
- return parent;
85
+ if (message.startsWith('TypeError: ')) {
86
+ return TypeError;
249
87
  }
250
- const parentNewLineIndex = getNewLineIndex$1(parent);
251
- const childNewLineIndex = getNewLineIndex$1(child);
252
- if (childNewLineIndex === -1) {
253
- return parent;
88
+ if (message.startsWith('SyntaxError: ')) {
89
+ return SyntaxError;
254
90
  }
255
- const parentFirstLine = parent.slice(0, parentNewLineIndex);
256
- const childRest = child.slice(childNewLineIndex);
257
- const childFirstLine = normalizeLine$1(child.slice(0, childNewLineIndex));
258
- if (parentFirstLine.includes(childFirstLine)) {
259
- return parentFirstLine + childRest;
91
+ if (message.startsWith('ReferenceError: ')) {
92
+ return ReferenceError;
260
93
  }
261
- return child;
94
+ return Error;
262
95
  };
263
- let VError$1 = class VError extends Error {
264
- constructor(error, message) {
265
- const combinedMessage = getCombinedMessage$1(error, message);
266
- super(combinedMessage);
267
- this.name = 'VError';
268
- if (error instanceof Error) {
269
- this.stack = mergeStacks$1(this.stack, error.stack);
270
- }
271
- if (error.codeFrame) {
272
- // @ts-ignore
273
- this.codeFrame = error.codeFrame;
274
- }
275
- if (error.code) {
276
- // @ts-ignore
277
- this.code = error.code;
278
- }
96
+ const constructError = (message, type, name) => {
97
+ const ErrorConstructor = getErrorConstructor(message, type);
98
+ if (ErrorConstructor === DOMException && name) {
99
+ return new ErrorConstructor(message, name);
279
100
  }
280
- };
281
-
282
- const getIframeSrc = (webViews, webViewId, webViewPort, root, isGitpod, locationProtocol, locationHost, locationOrigin) => {
283
- try {
284
- const webView = getWebView(webViews, webViewId);
285
- if (platform === Web) {
286
- return getIframeSrc$1(webView, locationOrigin);
101
+ if (ErrorConstructor === Error) {
102
+ const error = new Error(message);
103
+ if (name && name !== 'VError') {
104
+ error.name = name;
287
105
  }
288
- return getIframeSrcRemote(webViews, webViewPort, webViewId, locationProtocol, locationHost, isGitpod, root);
289
- } catch (error) {
290
- throw new VError$1(error, `Failed to construct webview iframe src`);
291
- }
292
- };
293
-
294
- const SemiColon = ';';
295
- const Space = ' ';
296
-
297
- const addSemicolon = line => {
298
- return line + SemiColon;
299
- };
300
-
301
- const getContentSecurityPolicy = items => {
302
- return items.map(addSemicolon).join(Space);
303
- };
304
-
305
- const getWebViewCsp = webView => {
306
- if (webView && webView.contentSecurityPolicy) {
307
- return getContentSecurityPolicy(webView.contentSecurityPolicy);
106
+ return error;
308
107
  }
309
- const csp = getContentSecurityPolicy([`default-src 'none'`, `script-src 'self'`, `style-src 'self'`, `img-src 'self'`, `media-src 'self'`]);
310
- return csp;
311
- };
312
-
313
- const getWebViewFrameAncestors = (locationProtocol, locationHost) => {
314
- const frameAncestors = createUrl(locationProtocol, locationHost);
315
- return frameAncestors;
108
+ return new ErrorConstructor(message);
316
109
  };
317
-
318
- const getWebViewOrigin = webViewPort => {
319
- // TODO don't hardcode protocol
320
- let origin = '';
321
- if (platform === Electron) {
322
- origin = `${WebView}://-/`;
323
- } else if (platform === Remote) {
324
- origin = `http://localhost:${webViewPort}`;
325
- } else {
326
- origin = '*'; // TODO
327
- }
328
- return origin;
110
+ const getNewLineIndex$2 = (string, startIndex = undefined) => {
111
+ return string.indexOf(NewLine$3, startIndex);
329
112
  };
330
-
331
- const AllowScripts = 'allow-scripts';
332
- const AllowSameOrigin = 'allow-same-origin';
333
-
334
- const getIframeSandbox = (webView, platform) => {
335
- const extensionSandbox = webView.sandbox || [];
336
- if (platform === Remote) {
337
- return [AllowScripts, AllowSameOrigin, ...extensionSandbox]; // TODO maybe disallow same origin
113
+ const getParentStack = error => {
114
+ let parentStack = error.stack || error.data || error.message || '';
115
+ if (parentStack.startsWith(' at')) {
116
+ parentStack = error.message + NewLine$3 + parentStack;
338
117
  }
339
- if (platform === Web) {
340
- return [AllowScripts, ...extensionSandbox];
341
- }
342
- return [AllowScripts, AllowSameOrigin, ...extensionSandbox];
118
+ return parentStack;
343
119
  };
344
-
345
- const getOrigin = () => {
346
- return location.origin;
347
- };
348
- const getHost = () => {
349
- return location.host;
350
- };
351
- const getProtocol = () => {
352
- return location.protocol;
353
- };
354
-
355
- const commandMap = {
356
- 'Location.getHost': getHost,
357
- 'Location.getOrigin': getOrigin,
358
- 'Location.getProtocol': getProtocol,
359
- 'WebView.getBaseUrl': getWebViewBaseUrl,
360
- 'WebView.getFrameAncestors': getWebViewFrameAncestors,
361
- 'WebView.getHtml': getWebViewHtml,
362
- 'WebView.getIframeSrc': getIframeSrc,
363
- 'WebView.getOrigin': getWebViewOrigin,
364
- 'WebView.getSandbox': getIframeSandbox,
365
- 'WebView.getWebViewCsp': getWebViewCsp
120
+ const joinLines$1 = lines => {
121
+ return lines.join(NewLine$3);
366
122
  };
367
-
368
- const Two = '2.0';
369
- class AssertionError extends Error {
370
- constructor(message) {
371
- super(message);
372
- this.name = 'AssertionError';
373
- }
374
- }
375
- const getType$1 = value => {
376
- switch (typeof value) {
377
- case 'number':
378
- return 'number';
379
- case 'function':
380
- return 'function';
381
- case 'string':
382
- return 'string';
383
- case 'object':
384
- if (value === null) {
385
- return 'null';
123
+ const MethodNotFound = -32601;
124
+ const Custom = -32001;
125
+ const splitLines$1 = lines => {
126
+ return lines.split(NewLine$3);
127
+ };
128
+ const restoreJsonRpcError = error => {
129
+ if (error && error instanceof Error) {
130
+ return error;
131
+ }
132
+ const currentStack = joinLines$1(splitLines$1(new Error().stack || '').slice(1));
133
+ if (error && error.code && error.code === MethodNotFound) {
134
+ const restoredError = new JsonRpcError(error.message);
135
+ const parentStack = getParentStack(error);
136
+ restoredError.stack = parentStack + NewLine$3 + currentStack;
137
+ return restoredError;
138
+ }
139
+ if (error && error.message) {
140
+ const restoredError = constructError(error.message, error.type, error.name);
141
+ if (error.data) {
142
+ if (error.data.stack && error.data.type && error.message) {
143
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine$3 + error.data.stack + NewLine$3 + currentStack;
144
+ } else if (error.data.stack) {
145
+ restoredError.stack = error.data.stack;
146
+ }
147
+ if (error.data.codeFrame) {
148
+ // @ts-ignore
149
+ restoredError.codeFrame = error.data.codeFrame;
150
+ }
151
+ if (error.data.code) {
152
+ // @ts-ignore
153
+ restoredError.code = error.data.code;
154
+ }
155
+ if (error.data.type) {
156
+ // @ts-ignore
157
+ restoredError.name = error.data.type;
158
+ }
159
+ } else {
160
+ if (error.stack) {
161
+ const lowerStack = restoredError.stack || '';
162
+ // @ts-ignore
163
+ const indexNewLine = getNewLineIndex$2(lowerStack);
164
+ const parentStack = getParentStack(error);
165
+ // @ts-ignore
166
+ restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
386
167
  }
387
- if (Array.isArray(value)) {
388
- return 'array';
168
+ if (error.codeFrame) {
169
+ // @ts-ignore
170
+ restoredError.codeFrame = error.codeFrame;
389
171
  }
390
- return 'object';
391
- case 'boolean':
392
- return 'boolean';
393
- default:
394
- return 'unknown';
172
+ }
173
+ return restoredError;
395
174
  }
396
- };
397
- const number = value => {
398
- const type = getType$1(value);
399
- if (type !== 'number') {
400
- throw new AssertionError('expected value to be of type number');
175
+ if (typeof error === 'string') {
176
+ return new Error(`JsonRpc Error: ${error}`);
401
177
  }
178
+ return new Error(`JsonRpc Error: ${error}`);
402
179
  };
403
- const state$1 = {
404
- callbacks: Object.create(null)
405
- };
406
- const get = id => {
407
- return state$1.callbacks[id];
408
- };
409
- const remove = id => {
410
- delete state$1.callbacks[id];
411
- };
412
- const warn = (...args) => {
413
- console.warn(...args);
414
- };
415
- const resolve = (id, args) => {
416
- number(id);
417
- const fn = get(id);
418
- if (!fn) {
419
- console.log(args);
420
- warn(`callback ${id} may already be disposed`);
421
- return;
180
+ const unwrapJsonRpcResult = responseMessage => {
181
+ if ('error' in responseMessage) {
182
+ const restoredError = restoreJsonRpcError(responseMessage.error);
183
+ throw restoredError;
422
184
  }
423
- fn(args);
424
- remove(id);
425
- };
426
- class JsonRpcError extends Error {
427
- constructor(message) {
428
- super(message);
429
- this.name = 'JsonRpcError';
185
+ if ('result' in responseMessage) {
186
+ return responseMessage.result;
430
187
  }
431
- }
432
- const MethodNotFound = -32601;
433
- const Custom = -32001;
188
+ throw new JsonRpcError('unexpected response message');
189
+ };
434
190
  const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
435
- const getType = prettyError => {
191
+ const getErrorType = prettyError => {
436
192
  if (prettyError && prettyError.type) {
437
193
  return prettyError.type;
438
194
  }
@@ -455,13 +211,13 @@ const getErrorProperty = (error, prettyError) => {
455
211
  data: {
456
212
  stack: prettyError.stack,
457
213
  codeFrame: prettyError.codeFrame,
458
- type: getType(prettyError),
214
+ type: getErrorType(prettyError),
459
215
  code: prettyError.code,
460
216
  name: prettyError.name
461
217
  }
462
218
  };
463
219
  };
464
- const create$1 = (message, error) => {
220
+ const create$1$1 = (message, error) => {
465
221
  return {
466
222
  jsonrpc: Two,
467
223
  id: message.id,
@@ -472,7 +228,7 @@ const getErrorResponse = (message, error, preparePrettyError, logError) => {
472
228
  const prettyError = preparePrettyError(error);
473
229
  logError(error, prettyError);
474
230
  const errorProperty = getErrorProperty(error, prettyError);
475
- return create$1(message, errorProperty);
231
+ return create$1$1(message, errorProperty);
476
232
  };
477
233
  const create = (message, result) => {
478
234
  return {
@@ -503,32 +259,42 @@ const defaultRequiresSocket = () => {
503
259
  return false;
504
260
  };
505
261
  const defaultResolve = resolve;
506
- const handleJsonRpcMessage = async (...args) => {
507
- let message;
508
- let ipc;
509
- let execute;
510
- let preparePrettyError;
511
- let logError;
512
- let resolve;
513
- let requiresSocket;
262
+
263
+ // TODO maybe remove this in v6 or v7, only accept options object to simplify the code
264
+ const normalizeParams = args => {
514
265
  if (args.length === 1) {
515
- const arg = args[0];
516
- message = arg.message;
517
- ipc = arg.ipc;
518
- execute = arg.execute;
519
- preparePrettyError = arg.preparePrettyError || defaultPreparePrettyError;
520
- logError = arg.logError || defaultLogError;
521
- requiresSocket = arg.requiresSocket || defaultRequiresSocket;
522
- resolve = arg.resolve || defaultResolve;
523
- } else {
524
- ipc = args[0];
525
- message = args[1];
526
- execute = args[2];
527
- resolve = args[3];
528
- preparePrettyError = args[4];
529
- logError = args[5];
530
- requiresSocket = args[6];
266
+ const options = args[0];
267
+ return {
268
+ ipc: options.ipc,
269
+ message: options.message,
270
+ execute: options.execute,
271
+ resolve: options.resolve || defaultResolve,
272
+ preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
273
+ logError: options.logError || defaultLogError,
274
+ requiresSocket: options.requiresSocket || defaultRequiresSocket
275
+ };
531
276
  }
277
+ return {
278
+ ipc: args[0],
279
+ message: args[1],
280
+ execute: args[2],
281
+ resolve: args[3],
282
+ preparePrettyError: args[4],
283
+ logError: args[5],
284
+ requiresSocket: args[6]
285
+ };
286
+ };
287
+ const handleJsonRpcMessage = async (...args) => {
288
+ const options = normalizeParams(args);
289
+ const {
290
+ message,
291
+ ipc,
292
+ execute,
293
+ resolve,
294
+ preparePrettyError,
295
+ logError,
296
+ requiresSocket
297
+ } = options;
532
298
  if ('id' in message) {
533
299
  if ('method' in message) {
534
300
  const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
@@ -549,43 +315,65 @@ const handleJsonRpcMessage = async (...args) => {
549
315
  }
550
316
  throw new JsonRpcError('unexpected message');
551
317
  };
552
-
553
- const requiresSocket = () => {
554
- return false;
555
- };
556
- const preparePrettyError = error => {
557
- return error;
318
+ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
319
+ const {
320
+ message,
321
+ promise
322
+ } = create$2(method, params);
323
+ if (useSendAndTransfer && ipc.sendAndTransfer) {
324
+ ipc.sendAndTransfer(message);
325
+ } else {
326
+ ipc.send(message);
327
+ }
328
+ const responseMessage = await promise;
329
+ return unwrapJsonRpcResult(responseMessage);
558
330
  };
559
- const logError = error => {
560
- console.error(error);
331
+ const invoke = (ipc, method, ...params) => {
332
+ return invokeHelper(ipc, method, params, false);
561
333
  };
562
- const handleMessage = event => {
563
- return handleJsonRpcMessage(event.target, event.data, execute, resolve, preparePrettyError, logError, requiresSocket);
334
+ const invokeAndTransfer = (ipc, method, ...params) => {
335
+ return invokeHelper(ipc, method, params, true);
564
336
  };
565
337
 
566
- const handleIpc = ipc => {
567
- ipc.addEventListener('message', handleMessage);
338
+ const commands = Object.create(null);
339
+ const register = commandMap => {
340
+ Object.assign(commands, commandMap);
568
341
  };
569
-
570
- const MessagePort$1 = 1;
571
- const ModuleWorker = 2;
572
- const ReferencePort = 3;
573
- const ModuleWorkerAndMessagePort = 8;
574
- const Auto = () => {
575
- // @ts-ignore
576
- if (globalThis.acceptPort) {
577
- return MessagePort$1;
578
- }
579
- // @ts-ignore
580
- if (globalThis.acceptReferencePort) {
581
- return ReferencePort;
342
+ const getCommand = key => {
343
+ return commands[key];
344
+ };
345
+ const execute = (command, ...args) => {
346
+ const fn = getCommand(command);
347
+ if (!fn) {
348
+ throw new Error(`command not found ${command}`);
582
349
  }
583
- return ModuleWorkerAndMessagePort;
350
+ return fn(...args);
584
351
  };
585
352
 
586
353
  const getData$1 = event => {
587
354
  return event.data;
588
355
  };
356
+ const attachEvents = that => {
357
+ const handleMessage = (...args) => {
358
+ const data = that.getData(...args);
359
+ that.dispatchEvent(new MessageEvent('message', {
360
+ data
361
+ }));
362
+ };
363
+ that.onMessage(handleMessage);
364
+ const handleClose = event => {
365
+ that.dispatchEvent(new Event('close'));
366
+ };
367
+ that.onClose(handleClose);
368
+ };
369
+ class Ipc extends EventTarget {
370
+ constructor(rawIpc) {
371
+ super();
372
+ this._rawIpc = rawIpc;
373
+ attachEvents(this);
374
+ }
375
+ }
376
+ const readyMessage = 'ready';
589
377
  const walkValue = (value, transferrables, isTransferrable) => {
590
378
  if (!value) {
591
379
  return;
@@ -636,188 +424,575 @@ const getTransferrables = value => {
636
424
  walkValue(value, transferrables, isTransferrable);
637
425
  return transferrables;
638
426
  };
639
- const attachEvents = that => {
640
- const handleMessage = (...args) => {
641
- const data = that.getData(...args);
642
- that.dispatchEvent(new MessageEvent('message', {
643
- data
644
- }));
427
+ const listen$2 = () => {
428
+ // @ts-ignore
429
+ if (typeof WorkerGlobalScope === 'undefined') {
430
+ throw new TypeError('module is not in web worker scope');
431
+ }
432
+ return globalThis;
433
+ };
434
+ const signal$2 = global => {
435
+ global.postMessage(readyMessage);
436
+ };
437
+ class IpcChildWithModuleWorker extends Ipc {
438
+ getData(event) {
439
+ return getData$1(event);
440
+ }
441
+ send(message) {
442
+ // @ts-ignore
443
+ this._rawIpc.postMessage(message);
444
+ }
445
+ sendAndTransfer(message) {
446
+ const transfer = getTransferrables(message);
447
+ // @ts-ignore
448
+ this._rawIpc.postMessage(message, transfer);
449
+ }
450
+ dispose() {
451
+ // ignore
452
+ }
453
+ onClose(callback) {
454
+ // ignore
455
+ }
456
+ onMessage(callback) {
457
+ this._rawIpc.addEventListener('message', callback);
458
+ }
459
+ }
460
+ const wrap$5 = global => {
461
+ return new IpcChildWithModuleWorker(global);
462
+ };
463
+ const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
464
+ const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
465
+ const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
466
+ const NewLine$1 = '\n';
467
+ const joinLines = lines => {
468
+ return lines.join(NewLine$1);
469
+ };
470
+ const splitLines = lines => {
471
+ return lines.split(NewLine$1);
472
+ };
473
+ const isModuleNotFoundMessage = line => {
474
+ return line.includes('[ERR_MODULE_NOT_FOUND]');
475
+ };
476
+ const getModuleNotFoundError = stderr => {
477
+ const lines = splitLines(stderr);
478
+ const messageIndex = lines.findIndex(isModuleNotFoundMessage);
479
+ const message = lines[messageIndex];
480
+ return {
481
+ message,
482
+ code: ERR_MODULE_NOT_FOUND
645
483
  };
646
- that.onMessage(handleMessage);
647
- const handleClose = event => {
648
- that.dispatchEvent(new Event('close'));
484
+ };
485
+ const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
486
+ const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
487
+ const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
488
+ const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
489
+ const RE_AT = /^\s+at/;
490
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
491
+ const isUnhelpfulNativeModuleError = stderr => {
492
+ return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
493
+ };
494
+ const isMessageCodeBlockStartIndex = line => {
495
+ return RE_MESSAGE_CODE_BLOCK_START.test(line);
496
+ };
497
+ const isMessageCodeBlockEndIndex = line => {
498
+ return RE_MESSAGE_CODE_BLOCK_END.test(line);
499
+ };
500
+ const getMessageCodeBlock = stderr => {
501
+ const lines = splitLines(stderr);
502
+ const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
503
+ const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
504
+ const relevantLines = lines.slice(startIndex, endIndex);
505
+ const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
506
+ return relevantMessage;
507
+ };
508
+ const getNativeModuleErrorMessage = stderr => {
509
+ const message = getMessageCodeBlock(stderr);
510
+ return {
511
+ message: `Incompatible native node module: ${message}`,
512
+ code: E_INCOMPATIBLE_NATIVE_MODULE
649
513
  };
650
- that.onClose(handleClose);
651
514
  };
652
- class Ipc extends EventTarget {
653
- constructor(rawIpc) {
654
- super();
655
- this._rawIpc = rawIpc;
656
- attachEvents(this);
515
+ const isModulesSyntaxError = stderr => {
516
+ if (!stderr) {
517
+ return false;
518
+ }
519
+ return stderr.includes('SyntaxError: Cannot use import statement outside a module');
520
+ };
521
+ const getModuleSyntaxError = () => {
522
+ return {
523
+ message: `ES Modules are not supported in electron`,
524
+ code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
525
+ };
526
+ };
527
+ const isModuleNotFoundError = stderr => {
528
+ if (!stderr) {
529
+ return false;
530
+ }
531
+ return stderr.includes('ERR_MODULE_NOT_FOUND');
532
+ };
533
+ const isNormalStackLine = line => {
534
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
535
+ };
536
+ const getDetails = lines => {
537
+ const index = lines.findIndex(isNormalStackLine);
538
+ if (index === -1) {
539
+ return {
540
+ actualMessage: joinLines(lines),
541
+ rest: []
542
+ };
543
+ }
544
+ let lastIndex = index - 1;
545
+ while (++lastIndex < lines.length) {
546
+ if (!isNormalStackLine(lines[lastIndex])) {
547
+ break;
548
+ }
549
+ }
550
+ return {
551
+ actualMessage: lines[index - 1],
552
+ rest: lines.slice(index, lastIndex)
553
+ };
554
+ };
555
+ const getHelpfulChildProcessError = (stdout, stderr) => {
556
+ if (isUnhelpfulNativeModuleError(stderr)) {
557
+ return getNativeModuleErrorMessage(stderr);
558
+ }
559
+ if (isModulesSyntaxError(stderr)) {
560
+ return getModuleSyntaxError();
561
+ }
562
+ if (isModuleNotFoundError(stderr)) {
563
+ return getModuleNotFoundError(stderr);
564
+ }
565
+ const lines = splitLines(stderr);
566
+ const {
567
+ actualMessage,
568
+ rest
569
+ } = getDetails(lines);
570
+ return {
571
+ message: `${actualMessage}`,
572
+ code: '',
573
+ stack: rest
574
+ };
575
+ };
576
+ const normalizeLine$1 = line => {
577
+ if (line.startsWith('Error: ')) {
578
+ return line.slice('Error: '.length);
579
+ }
580
+ if (line.startsWith('VError: ')) {
581
+ return line.slice('VError: '.length);
582
+ }
583
+ return line;
584
+ };
585
+ const getCombinedMessage$1 = (error, message) => {
586
+ const stringifiedError = normalizeLine$1(`${error}`);
587
+ if (message) {
588
+ return `${message}: ${stringifiedError}`;
589
+ }
590
+ return stringifiedError;
591
+ };
592
+ const NewLine$2 = '\n';
593
+ const getNewLineIndex$1 = (string, startIndex = undefined) => {
594
+ return string.indexOf(NewLine$2, startIndex);
595
+ };
596
+ const mergeStacks$1 = (parent, child) => {
597
+ if (!child) {
598
+ return parent;
599
+ }
600
+ const parentNewLineIndex = getNewLineIndex$1(parent);
601
+ const childNewLineIndex = getNewLineIndex$1(child);
602
+ if (childNewLineIndex === -1) {
603
+ return parent;
604
+ }
605
+ const parentFirstLine = parent.slice(0, parentNewLineIndex);
606
+ const childRest = child.slice(childNewLineIndex);
607
+ const childFirstLine = normalizeLine$1(child.slice(0, childNewLineIndex));
608
+ if (parentFirstLine.includes(childFirstLine)) {
609
+ return parentFirstLine + childRest;
610
+ }
611
+ return child;
612
+ };
613
+ let VError$1 = class VError extends Error {
614
+ constructor(error, message) {
615
+ const combinedMessage = getCombinedMessage$1(error, message);
616
+ super(combinedMessage);
617
+ this.name = 'VError';
618
+ if (error instanceof Error) {
619
+ this.stack = mergeStacks$1(this.stack, error.stack);
620
+ }
621
+ if (error.codeFrame) {
622
+ // @ts-ignore
623
+ this.codeFrame = error.codeFrame;
624
+ }
625
+ if (error.code) {
626
+ // @ts-ignore
627
+ this.code = error.code;
628
+ }
629
+ }
630
+ };
631
+ class IpcError extends VError$1 {
632
+ // @ts-ignore
633
+ constructor(betterMessage, stdout = '', stderr = '') {
634
+ if (stdout || stderr) {
635
+ // @ts-ignore
636
+ const {
637
+ message,
638
+ code,
639
+ stack
640
+ } = getHelpfulChildProcessError(stdout, stderr);
641
+ const cause = new Error(message);
642
+ // @ts-ignore
643
+ cause.code = code;
644
+ cause.stack = stack;
645
+ super(cause, betterMessage);
646
+ } else {
647
+ super(betterMessage);
648
+ }
649
+ // @ts-ignore
650
+ this.name = 'IpcError';
651
+ // @ts-ignore
652
+ this.stdout = stdout;
653
+ // @ts-ignore
654
+ this.stderr = stderr;
655
+ }
656
+ }
657
+ const withResolvers = () => {
658
+ let _resolve;
659
+ const promise = new Promise(resolve => {
660
+ _resolve = resolve;
661
+ });
662
+ return {
663
+ resolve: _resolve,
664
+ promise
665
+ };
666
+ };
667
+ const waitForFirstMessage = async port => {
668
+ const {
669
+ resolve,
670
+ promise
671
+ } = withResolvers();
672
+ port.addEventListener('message', resolve, {
673
+ once: true
674
+ });
675
+ const event = await promise;
676
+ // @ts-ignore
677
+ return event.data;
678
+ };
679
+ const listen$1$1 = async () => {
680
+ const parentIpcRaw = listen$2();
681
+ signal$2(parentIpcRaw);
682
+ const parentIpc = wrap$5(parentIpcRaw);
683
+ const firstMessage = await waitForFirstMessage(parentIpc);
684
+ if (firstMessage.method !== 'initialize') {
685
+ throw new IpcError('unexpected first message');
657
686
  }
658
- }
659
- const readyMessage = 'ready';
660
- const listen$4 = () => {
661
- // @ts-ignore
662
- if (typeof WorkerGlobalScope === 'undefined') {
663
- throw new TypeError('module is not in web worker scope');
687
+ const type = firstMessage.params[0];
688
+ if (type === 'message-port') {
689
+ parentIpc.send({
690
+ jsonrpc: '2.0',
691
+ id: firstMessage.id,
692
+ result: null
693
+ });
694
+ parentIpc.dispose();
695
+ const port = firstMessage.params[1];
696
+ return port;
664
697
  }
665
698
  return globalThis;
666
699
  };
667
- const signal$3 = global => {
668
- global.postMessage(readyMessage);
669
- };
670
- class IpcChildWithModuleWorker extends Ipc {
700
+ class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
701
+ constructor(port) {
702
+ super(port);
703
+ }
671
704
  getData(event) {
672
705
  return getData$1(event);
673
706
  }
674
707
  send(message) {
675
- // @ts-ignore
676
708
  this._rawIpc.postMessage(message);
677
709
  }
678
710
  sendAndTransfer(message) {
679
711
  const transfer = getTransferrables(message);
680
- // @ts-ignore
681
712
  this._rawIpc.postMessage(message, transfer);
682
713
  }
683
714
  dispose() {
684
- // ignore
715
+ if (this._rawIpc.close) {
716
+ this._rawIpc.close();
717
+ }
685
718
  }
686
719
  onClose(callback) {
687
720
  // ignore
688
721
  }
689
722
  onMessage(callback) {
690
723
  this._rawIpc.addEventListener('message', callback);
724
+ this._rawIpc.start();
691
725
  }
692
726
  }
693
- const wrap$6 = global => {
694
- return new IpcChildWithModuleWorker(global);
727
+ const wrap$4 = port => {
728
+ return new IpcChildWithModuleWorkerAndMessagePort(port);
695
729
  };
696
- const IpcChildWithModuleWorker$1 = {
730
+ const IpcChildWithModuleWorkerAndMessagePort$1 = {
697
731
  __proto__: null,
698
- listen: listen$4,
699
- signal: signal$3,
700
- wrap: wrap$6
732
+ listen: listen$1$1,
733
+ wrap: wrap$4
701
734
  };
702
- const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
703
- const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
704
- const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
705
- const NewLine$1 = '\n';
706
- const joinLines = lines => {
707
- return lines.join(NewLine$1);
735
+
736
+ const createRpc = ipc => {
737
+ const rpc = {
738
+ invoke(method, ...params) {
739
+ return invoke(ipc, method, ...params);
740
+ },
741
+ invokeAndTransfer(method, ...params) {
742
+ return invokeAndTransfer(ipc, method, ...params);
743
+ }
744
+ };
745
+ return rpc;
708
746
  };
709
- const splitLines = lines => {
710
- return lines.split(NewLine$1);
747
+ const requiresSocket = () => {
748
+ return false;
711
749
  };
712
- const isModuleNotFoundMessage = line => {
713
- return line.includes('[ERR_MODULE_NOT_FOUND]');
750
+ const preparePrettyError = error => {
751
+ return error;
714
752
  };
715
- const getModuleNotFoundError = stderr => {
716
- const lines = splitLines(stderr);
717
- const messageIndex = lines.findIndex(isModuleNotFoundMessage);
718
- const message = lines[messageIndex];
719
- return {
720
- message,
721
- code: ERR_MODULE_NOT_FOUND
722
- };
753
+ const logError = () => {
754
+ // handled by renderer worker
723
755
  };
724
- const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
725
- const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
726
- const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
727
- const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
728
- const RE_AT = /^\s+at/;
729
- const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
730
- const isUnhelpfulNativeModuleError = stderr => {
731
- return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
756
+ const handleMessage = event => {
757
+ return handleJsonRpcMessage(event.target, event.data, execute, resolve, preparePrettyError, logError, requiresSocket);
732
758
  };
733
- const isMessageCodeBlockStartIndex = line => {
734
- return RE_MESSAGE_CODE_BLOCK_START.test(line);
759
+ const handleIpc = ipc => {
760
+ ipc.addEventListener('message', handleMessage);
735
761
  };
736
- const isMessageCodeBlockEndIndex = line => {
737
- return RE_MESSAGE_CODE_BLOCK_END.test(line);
762
+
763
+ // @ts-ignore
764
+ const listen$1 = async () => {
765
+ const module = IpcChildWithModuleWorkerAndMessagePort$1;
766
+ const rawIpc = await module.listen();
767
+ const ipc = module.wrap(rawIpc);
768
+ return ipc;
738
769
  };
739
- const getMessageCodeBlock = stderr => {
740
- const lines = splitLines(stderr);
741
- const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
742
- const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
743
- const relevantLines = lines.slice(startIndex, endIndex);
744
- const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
745
- return relevantMessage;
770
+ const create$1 = async ({
771
+ commandMap
772
+ }) => {
773
+ // TODO create a commandMap per rpc instance
774
+ register(commandMap);
775
+ const ipc = await listen$1();
776
+ handleIpc(ipc);
777
+ const rpc = createRpc(ipc);
778
+ return rpc;
746
779
  };
747
- const getNativeModuleErrorMessage = stderr => {
748
- const message = getMessageCodeBlock(stderr);
749
- return {
750
- message: `Incompatible native node module: ${message}`,
751
- code: E_INCOMPATIBLE_NATIVE_MODULE
752
- };
780
+ const WebWorkerRpcClient = {
781
+ __proto__: null,
782
+ create: create$1
753
783
  };
754
- const isModulesSyntaxError = stderr => {
755
- if (!stderr) {
756
- return false;
784
+
785
+ const createUrl = (protocol, host) => {
786
+ return protocol + '//' + host;
787
+ };
788
+
789
+ const createLocalHostUrl = (locationProtocol, locationHost, isGitpod, webViewPort) => {
790
+ if (isGitpod) {
791
+ return createUrl(locationProtocol, locationHost.replace('3000', `${webViewPort}`));
757
792
  }
758
- return stderr.includes('SyntaxError: Cannot use import statement outside a module');
793
+ return `http://localhost:${webViewPort}`;
759
794
  };
760
- const getModuleSyntaxError = () => {
795
+
796
+ const Web = 1;
797
+ const Electron = 2;
798
+ const Remote = 3;
799
+ const Test = 4;
800
+
801
+ /* istanbul ignore file */
802
+
803
+ // TODO this should always be completely tree shaken out during build, maybe need to be marked as @__Pure for terser to work
804
+
805
+ // TODO treeshake this function out when targeting electron
806
+
807
+ /**
808
+ * @returns {number}
809
+ */
810
+ const getPlatform = () => {
811
+ // @ts-ignore
812
+ if (typeof PLATFORM !== 'undefined') {
813
+ // @ts-ignore
814
+ return PLATFORM;
815
+ }
816
+ // @ts-ignore
817
+ if (typeof process !== 'undefined' && process.env.NODE_ENV === 'test') {
818
+ return Test;
819
+ }
820
+ // TODO find a better way to pass runtime environment
821
+ if (typeof name !== 'undefined' && name.endsWith('(Electron)')) {
822
+ return Electron;
823
+ }
824
+ if (typeof name !== 'undefined' && name.endsWith('(Web)')) {
825
+ return Web;
826
+ }
827
+ return Remote;
828
+ };
829
+ const platform = getPlatform();
830
+
831
+ const getAssetDir = () => {
832
+ // @ts-ignore
833
+ if (typeof ASSET_DIR !== 'undefined') {
834
+ // @ts-ignore
835
+ return ASSET_DIR;
836
+ }
837
+ if (platform === Electron) {
838
+ return '';
839
+ }
840
+ return '';
841
+ };
842
+ const assetDir = getAssetDir();
843
+
844
+ const getWebViewHtml = (baseUrl, locationOrigin, elements) => {
845
+ if (!elements) {
846
+ return '';
847
+ }
848
+ const middle = [];
849
+ middle.push('<meta charset="utf-8">');
850
+ for (const element of elements) {
851
+ if (element.type === 'title') {
852
+ middle.push(`<title>${element.value}</title>`);
853
+ } else if (element.type === 'script') {
854
+ middle.push(`<script type="module" src="${locationOrigin}${assetDir}/js/preview-injected.js"></script>`);
855
+ middle.push(`<script type="module" src="${locationOrigin}${baseUrl}/${element.path}"></script>`);
856
+ } else if (element.type === 'css') {
857
+ middle.push(`<link rel="stylesheet" href="${locationOrigin}${baseUrl}/${element.path}" />`);
858
+ }
859
+ }
860
+ const middleHtml = middle.join('\n ');
861
+ const html = `<!DOCTYPE html>
862
+ <html>
863
+ <head>
864
+ ${middleHtml}
865
+ </head>
866
+ </html>
867
+ `;
868
+ return html;
869
+ };
870
+
871
+ const WebView = 'lvce-oss-webview';
872
+
873
+ const getWebView$1 = (webViews, webViewId) => {
874
+ for (const webView of webViews) {
875
+ if (webView.id === webViewId) {
876
+ return webView;
877
+ }
878
+ }
879
+ return undefined;
880
+ };
881
+ const getWebViewPath = (webViews, webViewId) => {
882
+ const webView = getWebView$1(webViews, webViewId);
883
+ if (!webView) {
884
+ return '';
885
+ }
886
+ return webView.path;
887
+ };
888
+ const getWebViewUri = (webViews, webViewId) => {
889
+ const webViewPath = getWebViewPath(webViews, webViewId);
890
+ if (!webViewPath) {
891
+ return '';
892
+ }
893
+ if (webViewPath.startsWith('/')) {
894
+ // TODO make it work on windows also
895
+ return `file://${webViewPath}`;
896
+ }
897
+ return webViewPath;
898
+ };
899
+ const getIframeSrcRemote = (webViews, webViewPort, webViewId, locationProtocol, locationHost, isGitpod, root) => {
900
+ const webView = getWebView$1(webViews, webViewId);
901
+ const webViewUri = getWebViewUri(webViews, webViewId);
902
+ if (!webViewUri) {
903
+ return undefined;
904
+ }
905
+ let iframeSrc = webViewUri;
906
+ let webViewRoot = webViewUri;
907
+ if (platform === Electron) {
908
+ const relativePath = new URL(webViewUri).pathname.replace('/index.html', '');
909
+ iframeSrc = `${WebView}://-${relativePath}/`;
910
+ // TODO
911
+ } else if (platform === Remote) {
912
+ const relativePath = new URL(webViewUri).pathname.replace('/index.html', '');
913
+ if (webViewUri.startsWith('file://')) {
914
+ // ignore
915
+ webViewRoot = webViewUri.slice('file://'.length).replace('/index.html', '');
916
+ } else {
917
+ webViewRoot = root + relativePath;
918
+ }
919
+ iframeSrc = createLocalHostUrl(locationProtocol, locationHost, isGitpod, webViewPort);
920
+ }
921
+ let iframeContent = getWebViewHtml('', '', webView.elements);
922
+ // TODO either
923
+ // - load webviews the same as in web using blob urls
924
+ // - load webviews from a pattern like /webviews/:id/:fileName
925
+ iframeContent = iframeContent.replaceAll('/media/', '/').replaceAll('//', '/');
761
926
  return {
762
- message: `ES Modules are not supported in electron`,
763
- code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
927
+ srcDoc: '',
928
+ iframeSrc,
929
+ webViewRoot,
930
+ iframeContent
764
931
  };
765
932
  };
766
- const isModuleNotFoundError = stderr => {
767
- if (!stderr) {
768
- return false;
933
+
934
+ const getBlobUrl = (content, contentType) => {
935
+ const blob = new Blob([content], {
936
+ type: contentType
937
+ });
938
+ const url = URL.createObjectURL(blob); // TODO dispose
939
+ return url;
940
+ };
941
+
942
+ const getDefaultBaseUrl = webView => {
943
+ const {
944
+ remotePath,
945
+ path
946
+ } = webView;
947
+ if (remotePath) {
948
+ if (remotePath.endsWith('/index.html')) {
949
+ return remotePath.slice(0, -'/index.html'.length);
950
+ }
951
+ return remotePath;
769
952
  }
770
- return stderr.includes('ERR_MODULE_NOT_FOUND');
953
+ if (path) {
954
+ if (path.endsWith('/index.html')) {
955
+ return path.slice(0, -'/index.html'.length);
956
+ }
957
+ return path;
958
+ }
959
+ return '';
771
960
  };
772
- const isNormalStackLine = line => {
773
- return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
961
+ const getWebViewBaseUrl = webView => {
962
+ const defaultBaseUrl = getDefaultBaseUrl(webView);
963
+ return defaultBaseUrl;
774
964
  };
775
- const getDetails = lines => {
776
- const index = lines.findIndex(isNormalStackLine);
777
- if (index === -1) {
965
+
966
+ const getIframeSrc$1 = (webView, locationOrigin) => {
967
+ const baseUrl = getWebViewBaseUrl(webView);
968
+ const srcHtml = getWebViewHtml(baseUrl, locationOrigin, webView.elements);
969
+ if (srcHtml) {
970
+ const blobUrl = getBlobUrl(srcHtml, 'text/html');
778
971
  return {
779
- actualMessage: joinLines(lines),
780
- rest: []
972
+ srcDoc: '',
973
+ iframeSrc: blobUrl,
974
+ webViewRoot: '',
975
+ iframeContent: ''
781
976
  };
782
977
  }
783
- let lastIndex = index - 1;
784
- while (++lastIndex < lines.length) {
785
- if (!isNormalStackLine(lines[lastIndex])) {
786
- break;
787
- }
788
- }
789
- return {
790
- actualMessage: lines[index - 1],
791
- rest: lines.slice(index, lastIndex)
792
- };
978
+ return undefined;
793
979
  };
794
- const getHelpfulChildProcessError = (stdout, stderr) => {
795
- if (isUnhelpfulNativeModuleError(stderr)) {
796
- return getNativeModuleErrorMessage(stderr);
797
- }
798
- if (isModulesSyntaxError(stderr)) {
799
- return getModuleSyntaxError();
800
- }
801
- if (isModuleNotFoundError(stderr)) {
802
- return getModuleNotFoundError(stderr);
980
+
981
+ const getWebView = (webViews, webViewId) => {
982
+ for (const webView of webViews) {
983
+ if (webView.id === webViewId) {
984
+ return webView;
985
+ }
803
986
  }
804
- const lines = splitLines(stderr);
805
- const {
806
- actualMessage,
807
- rest
808
- } = getDetails(lines);
809
- return {
810
- message: `${actualMessage}`,
811
- code: '',
812
- stack: rest
813
- };
987
+ return undefined;
814
988
  };
989
+
815
990
  const normalizeLine = line => {
816
991
  if (line.startsWith('Error: ')) {
817
- return line.slice(`Error: `.length);
992
+ return line.slice('Error: '.length);
818
993
  }
819
994
  if (line.startsWith('VError: ')) {
820
- return line.slice(`VError: `.length);
995
+ return line.slice('VError: '.length);
821
996
  }
822
997
  return line;
823
998
  };
@@ -867,140 +1042,97 @@ class VError extends Error {
867
1042
  }
868
1043
  }
869
1044
  }
870
- class IpcError extends VError {
871
- // @ts-ignore
872
- constructor(betterMessage, stdout = '', stderr = '') {
873
- if (stdout || stderr) {
874
- // @ts-ignore
875
- const {
876
- message,
877
- code,
878
- stack
879
- } = getHelpfulChildProcessError(stdout, stderr);
880
- const cause = new Error(message);
881
- // @ts-ignore
882
- cause.code = code;
883
- cause.stack = stack;
884
- super(cause, betterMessage);
885
- } else {
886
- super(betterMessage);
1045
+
1046
+ const getIframeSrc = (webViews, webViewId, webViewPort, root, isGitpod, locationProtocol, locationHost, locationOrigin) => {
1047
+ try {
1048
+ const webView = getWebView(webViews, webViewId);
1049
+ if (platform === Web) {
1050
+ return getIframeSrc$1(webView, locationOrigin);
887
1051
  }
888
- // @ts-ignore
889
- this.name = 'IpcError';
890
- // @ts-ignore
891
- this.stdout = stdout;
892
- // @ts-ignore
893
- this.stderr = stderr;
1052
+ return getIframeSrcRemote(webViews, webViewPort, webViewId, locationProtocol, locationHost, isGitpod, root);
1053
+ } catch (error) {
1054
+ throw new VError(error, `Failed to construct webview iframe src`);
894
1055
  }
895
- }
896
- const withResolvers = () => {
897
- let _resolve;
898
- const promise = new Promise(resolve => {
899
- _resolve = resolve;
900
- });
901
- return {
902
- resolve: _resolve,
903
- promise
904
- };
905
1056
  };
906
- const waitForFirstMessage = async port => {
907
- const {
908
- resolve,
909
- promise
910
- } = withResolvers();
911
- port.addEventListener('message', resolve, {
912
- once: true
913
- });
914
- const event = await promise;
915
- // @ts-ignore
916
- return event.data;
1057
+
1058
+ const SemiColon = ';';
1059
+ const Space = ' ';
1060
+
1061
+ const addSemicolon = line => {
1062
+ return line + SemiColon;
917
1063
  };
918
- const listen$3 = async () => {
919
- const parentIpcRaw = listen$4();
920
- signal$3(parentIpcRaw);
921
- const parentIpc = wrap$6(parentIpcRaw);
922
- const firstMessage = await waitForFirstMessage(parentIpc);
923
- if (firstMessage.method !== 'initialize') {
924
- throw new IpcError('unexpected first message');
925
- }
926
- const type = firstMessage.params[0];
927
- if (type === 'message-port') {
928
- parentIpc.send({
929
- jsonrpc: '2.0',
930
- id: firstMessage.id,
931
- result: null
932
- });
933
- parentIpc.dispose();
934
- const port = firstMessage.params[1];
935
- return port;
936
- }
937
- return globalThis;
1064
+
1065
+ const getContentSecurityPolicy = items => {
1066
+ return items.map(addSemicolon).join(Space);
938
1067
  };
939
- class IpcChildWithModuleWorkerAndMessagePort extends Ipc {
940
- constructor(port) {
941
- super(port);
942
- }
943
- getData(event) {
944
- return getData$1(event);
945
- }
946
- send(message) {
947
- this._rawIpc.postMessage(message);
948
- }
949
- sendAndTransfer(message) {
950
- const transfer = getTransferrables(message);
951
- this._rawIpc.postMessage(message, transfer);
952
- }
953
- dispose() {
954
- if (this._rawIpc.close) {
955
- this._rawIpc.close();
956
- }
957
- }
958
- onClose(callback) {
959
- // ignore
960
- }
961
- onMessage(callback) {
962
- this._rawIpc.addEventListener('message', callback);
963
- this._rawIpc.start();
1068
+
1069
+ const getWebViewCsp = webView => {
1070
+ if (webView && webView.contentSecurityPolicy) {
1071
+ return getContentSecurityPolicy(webView.contentSecurityPolicy);
964
1072
  }
965
- }
966
- const wrap$5 = port => {
967
- return new IpcChildWithModuleWorkerAndMessagePort(port);
1073
+ const csp = getContentSecurityPolicy([`default-src 'none'`, `script-src 'self'`, `style-src 'self'`, `img-src 'self'`, `media-src 'self'`]);
1074
+ return csp;
968
1075
  };
969
- const IpcChildWithModuleWorkerAndMessagePort$1 = {
970
- __proto__: null,
971
- listen: listen$3,
972
- wrap: wrap$5
1076
+
1077
+ const getWebViewFrameAncestors = (locationProtocol, locationHost) => {
1078
+ const frameAncestors = createUrl(locationProtocol, locationHost);
1079
+ return frameAncestors;
973
1080
  };
974
1081
 
975
- const getModule = method => {
976
- switch (method) {
977
- case ModuleWorker:
978
- return IpcChildWithModuleWorker$1;
979
- case ModuleWorkerAndMessagePort:
980
- return IpcChildWithModuleWorkerAndMessagePort$1;
981
- default:
982
- throw new Error('unexpected ipc type');
1082
+ const getWebViewOrigin = webViewPort => {
1083
+ // TODO don't hardcode protocol
1084
+ let origin = '';
1085
+ if (platform === Electron) {
1086
+ origin = `${WebView}://-/`;
1087
+ } else if (platform === Remote) {
1088
+ origin = `http://localhost:${webViewPort}`;
1089
+ } else {
1090
+ origin = '*'; // TODO
983
1091
  }
1092
+ return origin;
984
1093
  };
985
1094
 
986
- const listen$1 = async ({
987
- method
988
- }) => {
989
- const module = await getModule(method);
990
- const rawIpc = await module.listen();
991
- if (module.signal) {
992
- module.signal(rawIpc);
1095
+ const AllowScripts = 'allow-scripts';
1096
+ const AllowSameOrigin = 'allow-same-origin';
1097
+
1098
+ const getIframeSandbox = (webView, platform) => {
1099
+ const extensionSandbox = webView.sandbox || [];
1100
+ if (platform === Remote) {
1101
+ return [AllowScripts, AllowSameOrigin, ...extensionSandbox]; // TODO maybe disallow same origin
993
1102
  }
994
- const ipc = module.wrap(rawIpc);
995
- return ipc;
1103
+ if (platform === Web) {
1104
+ return [AllowScripts, ...extensionSandbox];
1105
+ }
1106
+ return [AllowScripts, AllowSameOrigin, ...extensionSandbox];
1107
+ };
1108
+
1109
+ const getOrigin = () => {
1110
+ return location.origin;
1111
+ };
1112
+ const getHost = () => {
1113
+ return location.host;
1114
+ };
1115
+ const getProtocol = () => {
1116
+ return location.protocol;
1117
+ };
1118
+
1119
+ const commandMap = {
1120
+ 'Location.getHost': getHost,
1121
+ 'Location.getOrigin': getOrigin,
1122
+ 'Location.getProtocol': getProtocol,
1123
+ 'WebView.getBaseUrl': getWebViewBaseUrl,
1124
+ 'WebView.getFrameAncestors': getWebViewFrameAncestors,
1125
+ 'WebView.getHtml': getWebViewHtml,
1126
+ 'WebView.getIframeSrc': getIframeSrc,
1127
+ 'WebView.getOrigin': getWebViewOrigin,
1128
+ 'WebView.getSandbox': getIframeSandbox,
1129
+ 'WebView.getWebViewCsp': getWebViewCsp
996
1130
  };
997
1131
 
998
1132
  const listen = async () => {
999
- register(commandMap);
1000
- const ipc = await listen$1({
1001
- method: Auto()
1133
+ await WebWorkerRpcClient.create({
1134
+ commandMap: commandMap
1002
1135
  });
1003
- handleIpc(ipc);
1004
1136
  };
1005
1137
 
1006
1138
  const main = async () => {