mirror of
https://github.com/Microsoft/vscode
synced 2024-07-04 16:58:49 +00:00
Switch webview service-worker to use message channel (#138811)
* Switch webview service-worker to use message channel This change hooks the service worker used for loading webview resources directly up to the main VS Code process over a message channel. Previously this communication had to go through an extra hop through the webview This simplifies the logic somewhat (although this change required adding extra logic to exchange the message port). It also improves performance a little * Update webview content commit version
This commit is contained in:
parent
86ee106054
commit
66b6adf035
|
@ -25,7 +25,7 @@
|
|||
"licenseFileName": "LICENSE.txt",
|
||||
"reportIssueUrl": "https://github.com/microsoft/vscode/issues/new",
|
||||
"urlProtocol": "code-oss",
|
||||
"webviewContentExternalBaseUrlTemplate": "https://{{uuid}}.vscode-webview.net/insider/9acd320edad7cea2c062d339fa04822c5eeb9e1d/out/vs/workbench/contrib/webview/browser/pre/",
|
||||
"webviewContentExternalBaseUrlTemplate": "https://{{uuid}}.vscode-webview.net/insider/69df0500a8963fc469161c038a14a39384d5a303/out/vs/workbench/contrib/webview/browser/pre/",
|
||||
"extensionAllowedProposedApi": [
|
||||
"ms-vscode.vscode-js-profile-flame",
|
||||
"ms-vscode.vscode-js-profile-table",
|
||||
|
|
|
@ -204,40 +204,28 @@ const workerReady = new Promise((resolve, reject) => {
|
|||
return reject(new Error('Service Workers are not enabled. Webviews will not work. Try disabling private/incognito mode.'));
|
||||
}
|
||||
|
||||
const swPath = `service-worker.js?vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}`;
|
||||
const swPath = `service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}`;
|
||||
|
||||
navigator.serviceWorker.register(swPath).then(
|
||||
async registration => {
|
||||
await navigator.serviceWorker.ready;
|
||||
|
||||
/**
|
||||
* @param {MessageEvent} event
|
||||
*/
|
||||
const versionHandler = async (event) => {
|
||||
if (event.data.channel !== 'version') {
|
||||
if (event.data.channel !== 'init') {
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.serviceWorker.removeEventListener('message', versionHandler);
|
||||
if (event.data.version === expectedWorkerVersion) {
|
||||
return resolve();
|
||||
} else {
|
||||
console.log(`Found unexpected service worker version. Found: ${event.data.version}. Expected: ${expectedWorkerVersion}`);
|
||||
console.log(`Attempting to reload service worker`);
|
||||
|
||||
// If we have the wrong version, try once (and only once) to unregister and re-register
|
||||
// Note that `.update` doesn't seem to work desktop electron at the moment so we use
|
||||
// `unregister` and `register` here.
|
||||
return registration.unregister()
|
||||
.then(() => navigator.serviceWorker.register(swPath))
|
||||
.then(() => navigator.serviceWorker.ready)
|
||||
.finally(() => { resolve(); });
|
||||
}
|
||||
// Forward the port back to VS Code
|
||||
hostMessaging.onMessage('did-init-service-worker', () => resolve());
|
||||
hostMessaging.postMessage('init-service-worker', {}, event.ports);
|
||||
};
|
||||
navigator.serviceWorker.addEventListener('message', versionHandler);
|
||||
|
||||
const postVersionMessage = () => {
|
||||
assertIsDefined(navigator.serviceWorker.controller).postMessage({ channel: 'version' });
|
||||
assertIsDefined(navigator.serviceWorker.controller).postMessage({ channel: 'init' });
|
||||
};
|
||||
|
||||
// At this point, either the service worker is ready and
|
||||
|
@ -388,26 +376,7 @@ const initData = {
|
|||
themeName: undefined,
|
||||
};
|
||||
|
||||
hostMessaging.onMessage('did-load-resource', (_event, data) => {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
assertIsDefined(registration.active).postMessage({ channel: 'did-load-resource', data }, data.data?.buffer ? [data.data.buffer] : []);
|
||||
});
|
||||
});
|
||||
|
||||
hostMessaging.onMessage('did-load-localhost', (_event, data) => {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
assertIsDefined(registration.active).postMessage({ channel: 'did-load-localhost', data });
|
||||
});
|
||||
});
|
||||
|
||||
navigator.serviceWorker.addEventListener('message', event => {
|
||||
switch (event.data.channel) {
|
||||
case 'load-resource':
|
||||
case 'load-localhost':
|
||||
hostMessaging.postMessage(event.data.channel, event.data);
|
||||
return;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* @param {HTMLDocument?} document
|
||||
* @param {HTMLElement?} body
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
|
||||
const sw = /** @type {ServiceWorkerGlobalScope} */ (/** @type {any} */ (self));
|
||||
|
||||
const VERSION = 2;
|
||||
const VERSION = 3;
|
||||
|
||||
const resourceCacheName = `vscode-resource-cache-${VERSION}`;
|
||||
|
||||
const rootPath = sw.location.pathname.replace(/\/service-worker.js$/, '');
|
||||
|
||||
|
||||
const searchParams = new URL(location.toString()).searchParams;
|
||||
|
||||
/**
|
||||
|
@ -98,11 +97,16 @@ class RequestStore {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {{ readonly status: 200; id: number; path: string; mime: string; data: Uint8Array; etag: string | undefined; mtime: number | undefined; }
|
||||
* | { readonly status: 304; id: number; path: string; mime: string; mtime: number | undefined }
|
||||
* | { readonly status: 401; id: number; path: string }
|
||||
* | { readonly status: 404; id: number; path: string }} ResourceResponse
|
||||
*/
|
||||
|
||||
/**
|
||||
* Map of requested paths to responses.
|
||||
* @typedef {{ type: 'response', body: Uint8Array, mime: string, etag: string | undefined, mtime: number | undefined } |
|
||||
* { type: 'not-modified', mime: string, mtime: number | undefined } |
|
||||
* undefined} ResourceResponse
|
||||
*
|
||||
* @type {RequestStore<ResourceResponse>}
|
||||
*/
|
||||
const resourceRequestStore = new RequestStore();
|
||||
|
@ -120,48 +124,41 @@ const notFound = () =>
|
|||
const methodNotAllowed = () =>
|
||||
new Response('Method Not Allowed', { status: 405, });
|
||||
|
||||
sw.addEventListener('message', async (event) => {
|
||||
const vscodeMessageChannel = new MessageChannel();
|
||||
|
||||
sw.addEventListener('message', event => {
|
||||
switch (event.data.channel) {
|
||||
case 'version':
|
||||
case 'init':
|
||||
{
|
||||
const source = /** @type {Client} */ (event.source);
|
||||
sw.clients.get(source.id).then(client => {
|
||||
if (client) {
|
||||
client.postMessage({
|
||||
channel: 'version',
|
||||
version: VERSION
|
||||
});
|
||||
}
|
||||
client?.postMessage({
|
||||
channel: 'init',
|
||||
version: VERSION
|
||||
}, [vscodeMessageChannel.port2]);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Unknown message');
|
||||
});
|
||||
|
||||
vscodeMessageChannel.port1.onmessage = (event) => {
|
||||
switch (event.data.channel) {
|
||||
case 'did-load-resource':
|
||||
{
|
||||
|
||||
/** @type {ResourceResponse} */
|
||||
let response = undefined;
|
||||
|
||||
const data = event.data.data;
|
||||
switch (data.status) {
|
||||
case 200:
|
||||
{
|
||||
response = { type: 'response', body: data.data, mime: data.mime, etag: data.etag, mtime: data.mtime };
|
||||
break;
|
||||
}
|
||||
case 304:
|
||||
{
|
||||
response = { type: 'not-modified', mime: data.mime, mtime: data.mtime };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!resourceRequestStore.resolve(data.id, response)) {
|
||||
console.log('Could not resolve unknown resource', data.path);
|
||||
const response = event.data;
|
||||
if (!resourceRequestStore.resolve(response.id, response)) {
|
||||
console.log('Could not resolve unknown resource', response.path);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 'did-load-localhost':
|
||||
{
|
||||
const data = event.data.data;
|
||||
const data = event.data;
|
||||
if (!localhostRequestStore.resolve(data.id, data.location)) {
|
||||
console.log('Could not resolve unknown localhost', data.origin);
|
||||
}
|
||||
|
@ -170,7 +167,7 @@ sw.addEventListener('message', async (event) => {
|
|||
}
|
||||
|
||||
console.log('Unknown message');
|
||||
});
|
||||
};
|
||||
|
||||
sw.addEventListener('fetch', (event) => {
|
||||
const requestUrl = new URL(event.request.url);
|
||||
|
@ -192,7 +189,7 @@ sw.addEventListener('fetch', (event) => {
|
|||
});
|
||||
|
||||
sw.addEventListener('install', (event) => {
|
||||
event.waitUntil(sw.skipWaiting()); // Activate worker immediately
|
||||
event.waitUntil(sw.skipWaiting());
|
||||
});
|
||||
|
||||
sw.addEventListener('activate', (event) => {
|
||||
|
@ -210,12 +207,6 @@ async function processResourceRequest(event, requestUrl) {
|
|||
return notFound();
|
||||
}
|
||||
|
||||
const webviewId = getWebviewIdForClient(client);
|
||||
if (!webviewId) {
|
||||
console.error('Could not resolve webview id');
|
||||
return notFound();
|
||||
}
|
||||
|
||||
const shouldTryCaching = (event.request.method === 'GET');
|
||||
|
||||
/**
|
||||
|
@ -223,11 +214,7 @@ async function processResourceRequest(event, requestUrl) {
|
|||
* @param {Response | undefined} cachedResponse
|
||||
*/
|
||||
async function resolveResourceEntry(entry, cachedResponse) {
|
||||
if (!entry) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
if (entry.type === 'not-modified') {
|
||||
if (entry.status === 304) { // Not modified
|
||||
if (cachedResponse) {
|
||||
return cachedResponse.clone();
|
||||
} else {
|
||||
|
@ -235,10 +222,14 @@ async function processResourceRequest(event, requestUrl) {
|
|||
}
|
||||
}
|
||||
|
||||
if (entry.status !== 200) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
const headers = {
|
||||
'Content-Type': entry.mime,
|
||||
'Content-Length': entry.body.byteLength.toString(),
|
||||
'Content-Length': entry.data.byteLength.toString(),
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
if (entry.etag) {
|
||||
|
@ -248,7 +239,7 @@ async function processResourceRequest(event, requestUrl) {
|
|||
if (entry.mtime) {
|
||||
headers['Last-Modified'] = new Date(entry.mtime).toUTCString();
|
||||
}
|
||||
const response = new Response(entry.body, {
|
||||
const response = new Response(entry.data, {
|
||||
status: 200,
|
||||
headers
|
||||
});
|
||||
|
@ -261,12 +252,6 @@ async function processResourceRequest(event, requestUrl) {
|
|||
return response.clone();
|
||||
}
|
||||
|
||||
const parentClients = await getOuterIframeClient(webviewId);
|
||||
if (!parentClients.length) {
|
||||
console.log('Could not find parent client for request');
|
||||
return notFound();
|
||||
}
|
||||
|
||||
/** @type {Response | undefined} */
|
||||
let cached;
|
||||
if (shouldTryCaching) {
|
||||
|
@ -280,17 +265,15 @@ async function processResourceRequest(event, requestUrl) {
|
|||
const scheme = firstHostSegment.split('+', 1)[0];
|
||||
const authority = firstHostSegment.slice(scheme.length + 1); // may be empty
|
||||
|
||||
for (const parentClient of parentClients) {
|
||||
parentClient.postMessage({
|
||||
channel: 'load-resource',
|
||||
id: requestId,
|
||||
path: requestUrl.pathname,
|
||||
scheme,
|
||||
authority,
|
||||
query: requestUrl.search.replace(/^\?/, ''),
|
||||
ifNoneMatch: cached?.headers.get('ETag'),
|
||||
});
|
||||
}
|
||||
vscodeMessageChannel.port1.postMessage({
|
||||
channel: 'load-resource',
|
||||
id: requestId,
|
||||
path: requestUrl.pathname,
|
||||
scheme,
|
||||
authority,
|
||||
query: requestUrl.search.replace(/^\?/, ''),
|
||||
ifNoneMatch: cached?.headers.get('ETag'),
|
||||
});
|
||||
|
||||
return promise.then(entry => resolveResourceEntry(entry, cached));
|
||||
}
|
||||
|
@ -307,11 +290,6 @@ async function processLocalhostRequest(event, requestUrl) {
|
|||
// that are not spawned by vs code
|
||||
return fetch(event.request);
|
||||
}
|
||||
const webviewId = getWebviewIdForClient(client);
|
||||
if (!webviewId) {
|
||||
console.error('Could not resolve webview id');
|
||||
return fetch(event.request);
|
||||
}
|
||||
|
||||
const origin = requestUrl.origin;
|
||||
|
||||
|
@ -332,42 +310,13 @@ async function processLocalhostRequest(event, requestUrl) {
|
|||
});
|
||||
};
|
||||
|
||||
const parentClients = await getOuterIframeClient(webviewId);
|
||||
if (!parentClients.length) {
|
||||
console.log('Could not find parent client for request');
|
||||
return notFound();
|
||||
}
|
||||
|
||||
const { requestId, promise } = localhostRequestStore.create();
|
||||
for (const parentClient of parentClients) {
|
||||
parentClient.postMessage({
|
||||
channel: 'load-localhost',
|
||||
origin: origin,
|
||||
id: requestId,
|
||||
});
|
||||
}
|
||||
|
||||
vscodeMessageChannel.port1.postMessage({
|
||||
channel: 'load-localhost',
|
||||
origin: origin,
|
||||
id: requestId,
|
||||
});
|
||||
|
||||
return promise.then(resolveRedirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Client} client
|
||||
* @returns {string | null}
|
||||
*/
|
||||
function getWebviewIdForClient(client) {
|
||||
const requesterClientUrl = new URL(client.url);
|
||||
return requesterClientUrl.searchParams.get('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} webviewId
|
||||
* @returns {Promise<Client[]>}
|
||||
*/
|
||||
async function getOuterIframeClient(webviewId) {
|
||||
const allClients = await sw.clients.matchAll({ includeUncontrolled: true });
|
||||
return allClients.filter(client => {
|
||||
const clientUrl = new URL(client.url);
|
||||
const hasExpectedPathName = (clientUrl.pathname === `${rootPath}/` || clientUrl.pathname === `${rootPath}/index.html`);
|
||||
return hasExpectedPathName && clientUrl.searchParams.get('id') === webviewId;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ export const enum WebviewMessageChannels {
|
|||
doUpdateState = 'do-update-state',
|
||||
doReload = 'do-reload',
|
||||
setConfirmBeforeClose = 'set-confirm-before-close',
|
||||
loadResource = 'load-resource',
|
||||
loadLocalhost = 'load-localhost',
|
||||
webviewReady = 'webview-ready',
|
||||
wheel = 'did-scroll-wheel',
|
||||
fatalError = 'fatal-error',
|
||||
|
@ -57,8 +55,29 @@ export const enum WebviewMessageChannels {
|
|||
didKeydown = 'did-keydown',
|
||||
didKeyup = 'did-keyup',
|
||||
didContextMenu = 'did-context-menu',
|
||||
|
||||
// Service worker
|
||||
initServiceWorker = 'init-service-worker',
|
||||
didInitServiceWorker = 'did-init-service-worker',
|
||||
}
|
||||
|
||||
const enum ServiceWorkerMessages {
|
||||
// From
|
||||
loadResource = 'load-resource',
|
||||
loadLocalhost = 'load-localhost',
|
||||
|
||||
// To
|
||||
didLoadLocalHost = 'did-load-localhost',
|
||||
didLoadResource = 'did-load-resource',
|
||||
}
|
||||
|
||||
type ResponseResponse =
|
||||
| { readonly status: 200; id: number; path: string; mime: string; data: Uint8Array; etag: string | undefined; mtime: number | undefined; } // success
|
||||
| { readonly status: 304; id: number; path: string; mime: string; mtime: number | undefined } // not modified
|
||||
| { readonly status: 401; id: number; path: string } // unauthorized
|
||||
| { readonly status: 404; id: number; path: string } // not found
|
||||
;
|
||||
|
||||
interface IKeydownEvent {
|
||||
key: string;
|
||||
keyCode: number;
|
||||
|
@ -99,7 +118,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
|
|||
|
||||
protected get platform(): string { return 'browser'; }
|
||||
|
||||
private readonly _expectedServiceWorkerVersion = 2; // Keep this in sync with the version in service-worker.js
|
||||
private readonly _expectedServiceWorkerVersion = 3; // Keep this in sync with the version in service-worker.js
|
||||
|
||||
private _element: HTMLIFrameElement | undefined;
|
||||
protected get element(): HTMLIFrameElement | undefined { return this._element; }
|
||||
|
@ -294,28 +313,57 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
|
|||
});
|
||||
}));
|
||||
|
||||
this._register(this.on(WebviewMessageChannels.loadResource, (entry: { id: number, path: string, query: string, scheme: string, authority: string, ifNoneMatch?: string }) => {
|
||||
try {
|
||||
// Restore the authority we previously encoded
|
||||
const authority = decodeAuthority(entry.authority);
|
||||
const uri = URI.from({
|
||||
scheme: entry.scheme,
|
||||
authority: authority,
|
||||
path: decodeURIComponent(entry.path), // This gets re-encoded
|
||||
query: entry.query ? decodeURIComponent(entry.query) : entry.query,
|
||||
});
|
||||
this.loadResource(entry.id, uri, entry.ifNoneMatch);
|
||||
} catch (e) {
|
||||
this._send('did-load-resource', {
|
||||
id: entry.id,
|
||||
status: 404,
|
||||
path: entry.path,
|
||||
});
|
||||
}
|
||||
}));
|
||||
this._register(this.on(WebviewMessageChannels.initServiceWorker, (_, e) => {
|
||||
const swPort = e.ports[0];
|
||||
swPort.onmessage = async (e) => {
|
||||
switch (e.data.channel) {
|
||||
case ServiceWorkerMessages.loadResource:
|
||||
const entry = e.data;
|
||||
try {
|
||||
// Restore the authority we previously encoded
|
||||
const authority = decodeAuthority(entry.authority);
|
||||
const uri = URI.from({
|
||||
scheme: entry.scheme,
|
||||
authority: authority,
|
||||
path: decodeURIComponent(entry.path), // This gets re-encoded
|
||||
query: entry.query ? decodeURIComponent(entry.query) : entry.query,
|
||||
});
|
||||
|
||||
this._register(this.on(WebviewMessageChannels.loadLocalhost, (entry: any) => {
|
||||
this.localLocalhost(entry.id, entry.origin);
|
||||
const body = await this.loadResource(entry.id, uri, entry.ifNoneMatch);
|
||||
return swPort.postMessage({
|
||||
channel: ServiceWorkerMessages.didLoadResource,
|
||||
...body
|
||||
});
|
||||
} catch (e) {
|
||||
return swPort.postMessage({
|
||||
channel: ServiceWorkerMessages.didLoadResource,
|
||||
id: entry.id,
|
||||
status: 404,
|
||||
path: entry.path,
|
||||
});
|
||||
}
|
||||
|
||||
case ServiceWorkerMessages.loadLocalhost:
|
||||
try {
|
||||
const redirect = await this.getLocalhostRedirect(entry.id, entry.origin);
|
||||
return swPort.postMessage({
|
||||
chanel: ServiceWorkerMessages.didLoadLocalHost,
|
||||
id: entry.id,
|
||||
origin: entry.origin,
|
||||
location: redirect
|
||||
});
|
||||
} catch (e) {
|
||||
return swPort.postMessage({
|
||||
chanel: ServiceWorkerMessages.didLoadLocalHost,
|
||||
id: entry.id,
|
||||
origin: entry.origin,
|
||||
location: undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._send(WebviewMessageChannels.didInitServiceWorker);
|
||||
}));
|
||||
|
||||
this.style();
|
||||
|
@ -698,7 +746,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
|
|||
}
|
||||
}
|
||||
|
||||
private async loadResource(id: number, uri: URI, ifNoneMatch: string | undefined) {
|
||||
private async loadResource(id: number, uri: URI, ifNoneMatch: string | undefined): Promise<ResponseResponse> {
|
||||
try {
|
||||
const result = await loadLocalResource(uri, {
|
||||
ifNoneMatch,
|
||||
|
@ -707,57 +755,48 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
|
|||
|
||||
switch (result.type) {
|
||||
case WebviewResourceResponse.Type.Success:
|
||||
{
|
||||
const { buffer } = await streamToBuffer(result.stream);
|
||||
return this._send('did-load-resource', {
|
||||
id,
|
||||
status: 200,
|
||||
path: uri.path,
|
||||
mime: result.mimeType,
|
||||
data: buffer,
|
||||
etag: result.etag,
|
||||
mtime: result.mtime
|
||||
});
|
||||
}
|
||||
const { buffer } = await streamToBuffer(result.stream);
|
||||
return {
|
||||
id,
|
||||
status: 200,
|
||||
path: uri.path,
|
||||
mime: result.mimeType,
|
||||
data: buffer,
|
||||
etag: result.etag,
|
||||
mtime: result.mtime
|
||||
};
|
||||
|
||||
case WebviewResourceResponse.Type.NotModified:
|
||||
{
|
||||
return this._send('did-load-resource', {
|
||||
id,
|
||||
status: 304, // not modified
|
||||
path: uri.path,
|
||||
mime: result.mimeType,
|
||||
mtime: result.mtime
|
||||
});
|
||||
}
|
||||
return {
|
||||
id,
|
||||
status: 304, // not modified
|
||||
path: uri.path,
|
||||
mime: result.mimeType,
|
||||
mtime: result.mtime
|
||||
};
|
||||
|
||||
case WebviewResourceResponse.Type.AccessDenied:
|
||||
{
|
||||
return this._send('did-load-resource', {
|
||||
id,
|
||||
status: 401, // unauthorized
|
||||
path: uri.path,
|
||||
});
|
||||
}
|
||||
return {
|
||||
id,
|
||||
status: 401, // unauthorized
|
||||
path: uri.path,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
|
||||
return this._send('did-load-resource', {
|
||||
return {
|
||||
id,
|
||||
status: 404,
|
||||
path: uri.path,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private async localLocalhost(id: string, origin: string) {
|
||||
private async getLocalhostRedirect(id: string, origin: string) {
|
||||
const authority = this._environmentService.remoteAuthority;
|
||||
const resolveAuthority = authority ? await this._remoteAuthorityResolverService.resolveAuthority(authority) : undefined;
|
||||
const redirect = resolveAuthority ? await this._portMappingManager.getRedirect(resolveAuthority.authority, origin) : undefined;
|
||||
return this._send('did-load-localhost', {
|
||||
id,
|
||||
origin,
|
||||
location: redirect
|
||||
});
|
||||
return resolveAuthority ? this._portMappingManager.getRedirect(resolveAuthority.authority, origin) : undefined;
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
|
|
|
@ -235,7 +235,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
|||
|
||||
const webviewExternalEndpointCommit = this.payload?.get('webviewExternalEndpointCommit');
|
||||
return endpoint
|
||||
.replace('{{commit}}', webviewExternalEndpointCommit ?? this.productService.commit ?? '9acd320edad7cea2c062d339fa04822c5eeb9e1d')
|
||||
.replace('{{commit}}', webviewExternalEndpointCommit ?? this.productService.commit ?? '69df0500a8963fc469161c038a14a39384d5a303')
|
||||
.replace('{{quality}}', (webviewExternalEndpointCommit ? 'insider' : this.productService.quality) ?? 'insider');
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWith
|
|||
const testExtensionUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionDevelopmentPath)).path, protocol, host, slashes: true });
|
||||
const testFilesUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionTestsPath)).path, protocol, host, slashes: true });
|
||||
|
||||
const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","9acd320edad7cea2c062d339fa04822c5eeb9e1d"],["skipWelcome","true"]]`;
|
||||
const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","69df0500a8963fc469161c038a14a39384d5a303"],["skipWelcome","true"]]`;
|
||||
|
||||
if (path.extname(testWorkspaceUri) === '.code-workspace') {
|
||||
await page.goto(`${endpoint.href}&workspace=${testWorkspaceUri}&payload=${payloadParam}`);
|
||||
|
|
Loading…
Reference in New Issue
Block a user