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