@vscode/test-web 0.0.57 → 0.0.59
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/CHANGELOG.md +3 -1
- package/README.md +1 -0
- package/fs-provider/dist/fsExtensionMain.js +27 -11
- package/fs-provider/package-lock.json +8 -10
- package/fs-provider/package.json +2 -1
- package/fs-provider/package.nls.json +2 -0
- package/out/browser/amd/main.js +207 -0
- package/out/browser/esm/main.js +204 -0
- package/out/server/download.js +41 -11
- package/out/{index.js → server/index.js} +24 -5
- package/out/server/workbench.js +50 -16
- package/package.json +7 -7
- package/views/callback.html +123 -0
- package/views/workbench-esm.html +1 -23
- package/views/workbench.html +7 -6
- package/out/index.d.ts +0 -134
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
## 0.0.58
|
|
3
|
+
* new option `--commit` to specify the build of VS Code to use. By default the latest build is used.
|
|
4
|
+
|
|
2
5
|
## 0.0.37
|
|
3
6
|
* new option `--testRunnerDataDir` to set the temporary folder for storing the VS Code builds used for running the tests
|
|
4
7
|
|
|
5
|
-
|
|
6
8
|
## 0.0.28
|
|
7
9
|
* new option `--coi` to enable cross origin isolation.
|
|
8
10
|
|
package/README.md
CHANGED
|
@@ -80,6 +80,7 @@ CLI options:
|
|
|
80
80
|
| --extensionDevelopmentPath | A path pointing to an extension under development to include. |
|
|
81
81
|
| --extensionTestsPath | A path to a test module to run. |
|
|
82
82
|
| --quality | `insiders` (default), or `stable`. Ignored when sourcesPath is provided. |
|
|
83
|
+
| --commit | commitHash The servion of the server to use. Defaults to latest build version of the given quality. Ignored when sourcesPath is provided. |
|
|
83
84
|
| --sourcesPath | If set, runs the server from VS Code sources located at the given path. Make sure the sources and extensions are compiled (`yarn compile` and `yarn compile-web`). |
|
|
84
85
|
| --headless | If set, hides the browser. Defaults to true when an extensionTestsPath is provided, otherwise false. |
|
|
85
86
|
| --permission | Permission granted to the opened browser: e.g. `clipboard-read`, `clipboard-write`. See [full list of options](https://playwright.dev/docs/api/class-browsercontext#browser-context-grant-permissions). Argument can be provided multiple times. |
|
|
@@ -35,14 +35,13 @@ function modifiedFileStat(stats, size) {
|
|
|
35
35
|
return Promise.resolve({ type: stats.type, ctime: stats.ctime, mtime: Date.now(), size: size ?? stats.size });
|
|
36
36
|
}
|
|
37
37
|
class MemFileSystemProvider {
|
|
38
|
+
scheme;
|
|
39
|
+
root;
|
|
40
|
+
extensionUri;
|
|
38
41
|
constructor(scheme, root, extensionUri) {
|
|
39
42
|
this.scheme = scheme;
|
|
40
43
|
this.root = root;
|
|
41
44
|
this.extensionUri = extensionUri;
|
|
42
|
-
// --- manage file events
|
|
43
|
-
this._onDidChangeFile = new vscode_1.EventEmitter();
|
|
44
|
-
this.onDidChangeFile = this._onDidChangeFile.event;
|
|
45
|
-
this._bufferedChanges = [];
|
|
46
45
|
}
|
|
47
46
|
// --- manage file metadata
|
|
48
47
|
async stat(resource) {
|
|
@@ -131,12 +130,14 @@ class MemFileSystemProvider {
|
|
|
131
130
|
// Pattern is always blank: https://github.com/microsoft/vscode/issues/200892
|
|
132
131
|
const glob = pattern ? new minimatch_1.Minimatch(pattern) : undefined;
|
|
133
132
|
const result = [];
|
|
134
|
-
const dive = async (
|
|
135
|
-
|
|
133
|
+
const dive = async (folderUri) => {
|
|
134
|
+
const directory = await this._lookupAsDirectory(folderUri, false);
|
|
135
|
+
for (const [name, entry] of await directory.entries) {
|
|
136
|
+
/* support options.includes && options.excludes */
|
|
136
137
|
if (typeof options.maxResults !== 'undefined' && result.length >= options.maxResults) {
|
|
137
138
|
break;
|
|
138
139
|
}
|
|
139
|
-
const uri = vscode_1.Uri.joinPath(
|
|
140
|
+
const uri = vscode_1.Uri.joinPath(folderUri, entry.name);
|
|
140
141
|
if (entry.type === vscode_1.FileType.File) {
|
|
141
142
|
const toMatch = uri.toString();
|
|
142
143
|
// Pattern is always blank: https://github.com/microsoft/vscode/issues/200892
|
|
@@ -145,11 +146,11 @@ class MemFileSystemProvider {
|
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
else if (entry.type === vscode_1.FileType.Directory) {
|
|
148
|
-
await dive(
|
|
149
|
+
await dive(uri);
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
};
|
|
152
|
-
await dive(
|
|
153
|
+
await dive(options.folder);
|
|
153
154
|
return result;
|
|
154
155
|
}
|
|
155
156
|
async _lookup(uri, silent) {
|
|
@@ -204,6 +205,11 @@ class MemFileSystemProvider {
|
|
|
204
205
|
const dirname = vscode_uri_1.Utils.dirname(uri);
|
|
205
206
|
return this._lookupAsDirectory(dirname, false);
|
|
206
207
|
}
|
|
208
|
+
// --- manage file events
|
|
209
|
+
_onDidChangeFile = new vscode_1.EventEmitter();
|
|
210
|
+
onDidChangeFile = this._onDidChangeFile.event;
|
|
211
|
+
_bufferedChanges = [];
|
|
212
|
+
_fireSoonHandle;
|
|
207
213
|
watch(resource, opts) {
|
|
208
214
|
// ignore, fires for all changes...
|
|
209
215
|
return vscode_1.Disposable.from();
|
|
@@ -2615,11 +2621,16 @@ function activate(context) {
|
|
|
2615
2621
|
}
|
|
2616
2622
|
exports.activate = activate;
|
|
2617
2623
|
class ServerBackedFile {
|
|
2624
|
+
_serverRoot;
|
|
2625
|
+
pathSegments;
|
|
2626
|
+
name;
|
|
2627
|
+
type = vscode_1.FileType.File;
|
|
2628
|
+
_stats;
|
|
2629
|
+
_content;
|
|
2618
2630
|
constructor(_serverRoot, pathSegments, name) {
|
|
2619
2631
|
this._serverRoot = _serverRoot;
|
|
2620
2632
|
this.pathSegments = pathSegments;
|
|
2621
2633
|
this.name = name;
|
|
2622
|
-
this.type = vscode_1.FileType.File;
|
|
2623
2634
|
}
|
|
2624
2635
|
get stats() {
|
|
2625
2636
|
if (this._stats === undefined) {
|
|
@@ -2641,11 +2652,16 @@ class ServerBackedFile {
|
|
|
2641
2652
|
}
|
|
2642
2653
|
}
|
|
2643
2654
|
class ServerBackedDirectory {
|
|
2655
|
+
_serverRoot;
|
|
2656
|
+
pathSegments;
|
|
2657
|
+
name;
|
|
2658
|
+
type = vscode_1.FileType.Directory;
|
|
2659
|
+
_stats;
|
|
2660
|
+
_entries;
|
|
2644
2661
|
constructor(_serverRoot, pathSegments, name) {
|
|
2645
2662
|
this._serverRoot = _serverRoot;
|
|
2646
2663
|
this.pathSegments = pathSegments;
|
|
2647
2664
|
this.name = name;
|
|
2648
|
-
this.type = vscode_1.FileType.Directory;
|
|
2649
2665
|
}
|
|
2650
2666
|
get stats() {
|
|
2651
2667
|
if (this._stats === undefined) {
|
|
@@ -936,14 +936,13 @@
|
|
|
936
936
|
"dev": true
|
|
937
937
|
},
|
|
938
938
|
"node_modules/micromatch": {
|
|
939
|
-
"version": "4.0.
|
|
940
|
-
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.
|
|
941
|
-
"integrity": "sha512-
|
|
939
|
+
"version": "4.0.8",
|
|
940
|
+
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
|
941
|
+
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
|
942
942
|
"dev": true,
|
|
943
|
-
"license": "MIT",
|
|
944
943
|
"dependencies": {
|
|
945
|
-
"braces": "^3.0.
|
|
946
|
-
"picomatch": "^2.
|
|
944
|
+
"braces": "^3.0.3",
|
|
945
|
+
"picomatch": "^2.3.1"
|
|
947
946
|
},
|
|
948
947
|
"engines": {
|
|
949
948
|
"node": ">=8.6"
|
|
@@ -1080,11 +1079,10 @@
|
|
|
1080
1079
|
"dev": true
|
|
1081
1080
|
},
|
|
1082
1081
|
"node_modules/picomatch": {
|
|
1083
|
-
"version": "2.3.
|
|
1084
|
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.
|
|
1085
|
-
"integrity": "sha512-
|
|
1082
|
+
"version": "2.3.1",
|
|
1083
|
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
|
1084
|
+
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
|
1086
1085
|
"dev": true,
|
|
1087
|
-
"license": "MIT",
|
|
1088
1086
|
"engines": {
|
|
1089
1087
|
"node": ">=8.6"
|
|
1090
1088
|
},
|
package/fs-provider/package.json
CHANGED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
define("vscode-web-browser-main", ["require", "exports", "./workbench.api"], function (require, exports, workbench_api_1) {
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
class WorkspaceProvider {
|
|
5
|
+
workspace;
|
|
6
|
+
payload;
|
|
7
|
+
static QUERY_PARAM_EMPTY_WINDOW = 'ew';
|
|
8
|
+
static QUERY_PARAM_FOLDER = 'folder';
|
|
9
|
+
static QUERY_PARAM_WORKSPACE = 'workspace';
|
|
10
|
+
static QUERY_PARAM_PAYLOAD = 'payload';
|
|
11
|
+
static create(config) {
|
|
12
|
+
let foundWorkspace = false;
|
|
13
|
+
let workspace;
|
|
14
|
+
let payload = Object.create(null);
|
|
15
|
+
const query = new URL(document.location.href).searchParams;
|
|
16
|
+
query.forEach((value, key) => {
|
|
17
|
+
switch (key) {
|
|
18
|
+
case WorkspaceProvider.QUERY_PARAM_FOLDER:
|
|
19
|
+
workspace = { folderUri: workbench_api_1.URI.parse(value) };
|
|
20
|
+
foundWorkspace = true;
|
|
21
|
+
break;
|
|
22
|
+
case WorkspaceProvider.QUERY_PARAM_WORKSPACE:
|
|
23
|
+
workspace = { workspaceUri: workbench_api_1.URI.parse(value) };
|
|
24
|
+
foundWorkspace = true;
|
|
25
|
+
break;
|
|
26
|
+
case WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW:
|
|
27
|
+
workspace = undefined;
|
|
28
|
+
foundWorkspace = true;
|
|
29
|
+
break;
|
|
30
|
+
case WorkspaceProvider.QUERY_PARAM_PAYLOAD:
|
|
31
|
+
try {
|
|
32
|
+
payload = JSON.parse(value);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error(error);
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
if (!foundWorkspace) {
|
|
41
|
+
if (config.folderUri) {
|
|
42
|
+
workspace = { folderUri: workbench_api_1.URI.revive(config.folderUri) };
|
|
43
|
+
}
|
|
44
|
+
else if (config.workspaceUri) {
|
|
45
|
+
workspace = { workspaceUri: workbench_api_1.URI.revive(config.workspaceUri) };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return new WorkspaceProvider(workspace, payload);
|
|
49
|
+
}
|
|
50
|
+
trusted = true;
|
|
51
|
+
constructor(workspace, payload) {
|
|
52
|
+
this.workspace = workspace;
|
|
53
|
+
this.payload = payload;
|
|
54
|
+
}
|
|
55
|
+
async open(workspace, options) {
|
|
56
|
+
if (options?.reuse && !options.payload && this.isSame(this.workspace, workspace)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const targetHref = this.createTargetUrl(workspace, options);
|
|
60
|
+
if (targetHref) {
|
|
61
|
+
if (options?.reuse) {
|
|
62
|
+
window.location.href = targetHref;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
return !!window.open(targetHref);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
createTargetUrl(workspace, options) {
|
|
72
|
+
let targetHref = undefined;
|
|
73
|
+
if (!workspace) {
|
|
74
|
+
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW}=true`;
|
|
75
|
+
}
|
|
76
|
+
else if ('folderUri' in workspace) {
|
|
77
|
+
const queryParamFolder = encodeURIComponent(workspace.folderUri.toString(true));
|
|
78
|
+
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_FOLDER}=${queryParamFolder}`;
|
|
79
|
+
}
|
|
80
|
+
else if ('workspaceUri' in workspace) {
|
|
81
|
+
const queryParamWorkspace = encodeURIComponent(workspace.workspaceUri.toString(true));
|
|
82
|
+
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_WORKSPACE}=${queryParamWorkspace}`;
|
|
83
|
+
}
|
|
84
|
+
if (options?.payload) {
|
|
85
|
+
targetHref += `&${WorkspaceProvider.QUERY_PARAM_PAYLOAD}=${encodeURIComponent(JSON.stringify(options.payload))}`;
|
|
86
|
+
}
|
|
87
|
+
return targetHref;
|
|
88
|
+
}
|
|
89
|
+
isSame(workspaceA, workspaceB) {
|
|
90
|
+
if (!workspaceA || !workspaceB) {
|
|
91
|
+
return workspaceA === workspaceB;
|
|
92
|
+
}
|
|
93
|
+
if ('folderUri' in workspaceA && 'folderUri' in workspaceB) {
|
|
94
|
+
return this.isEqualURI(workspaceA.folderUri, workspaceB.folderUri);
|
|
95
|
+
}
|
|
96
|
+
if ('workspaceUri' in workspaceA && 'workspaceUri' in workspaceB) {
|
|
97
|
+
return this.isEqualURI(workspaceA.workspaceUri, workspaceB.workspaceUri);
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
isEqualURI(a, b) {
|
|
102
|
+
return a.scheme === b.scheme && a.authority === b.authority && a.path === b.path;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
class LocalStorageURLCallbackProvider {
|
|
106
|
+
_callbackRoute;
|
|
107
|
+
static REQUEST_ID = 0;
|
|
108
|
+
static QUERY_KEYS = [
|
|
109
|
+
'scheme',
|
|
110
|
+
'authority',
|
|
111
|
+
'path',
|
|
112
|
+
'query',
|
|
113
|
+
'fragment'
|
|
114
|
+
];
|
|
115
|
+
_onCallback = new workbench_api_1.Emitter();
|
|
116
|
+
onCallback = this._onCallback.event;
|
|
117
|
+
pendingCallbacks = new Set();
|
|
118
|
+
lastTimeChecked = Date.now();
|
|
119
|
+
checkCallbacksTimeout = undefined;
|
|
120
|
+
onDidChangeLocalStorageDisposable;
|
|
121
|
+
constructor(_callbackRoute) {
|
|
122
|
+
this._callbackRoute = _callbackRoute;
|
|
123
|
+
}
|
|
124
|
+
create(options = {}) {
|
|
125
|
+
const id = ++LocalStorageURLCallbackProvider.REQUEST_ID;
|
|
126
|
+
const queryParams = [`vscode-reqid=${id}`];
|
|
127
|
+
for (const key of LocalStorageURLCallbackProvider.QUERY_KEYS) {
|
|
128
|
+
const value = options[key];
|
|
129
|
+
if (value) {
|
|
130
|
+
queryParams.push(`vscode-${key}=${encodeURIComponent(value)}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (!(options.authority === 'vscode.github-authentication' && options.path === '/dummy')) {
|
|
134
|
+
const key = `vscode-web.url-callbacks[${id}]`;
|
|
135
|
+
localStorage.removeItem(key);
|
|
136
|
+
this.pendingCallbacks.add(id);
|
|
137
|
+
this.startListening();
|
|
138
|
+
}
|
|
139
|
+
return workbench_api_1.URI.parse(window.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
|
|
140
|
+
}
|
|
141
|
+
startListening() {
|
|
142
|
+
if (this.onDidChangeLocalStorageDisposable) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const fn = () => this.onDidChangeLocalStorage();
|
|
146
|
+
window.addEventListener('storage', fn);
|
|
147
|
+
this.onDidChangeLocalStorageDisposable = { dispose: () => window.removeEventListener('storage', fn) };
|
|
148
|
+
}
|
|
149
|
+
stopListening() {
|
|
150
|
+
this.onDidChangeLocalStorageDisposable?.dispose();
|
|
151
|
+
this.onDidChangeLocalStorageDisposable = undefined;
|
|
152
|
+
}
|
|
153
|
+
async onDidChangeLocalStorage() {
|
|
154
|
+
const ellapsed = Date.now() - this.lastTimeChecked;
|
|
155
|
+
if (ellapsed > 1000) {
|
|
156
|
+
this.checkCallbacks();
|
|
157
|
+
}
|
|
158
|
+
else if (this.checkCallbacksTimeout === undefined) {
|
|
159
|
+
this.checkCallbacksTimeout = setTimeout(() => {
|
|
160
|
+
this.checkCallbacksTimeout = undefined;
|
|
161
|
+
this.checkCallbacks();
|
|
162
|
+
}, 1000 - ellapsed);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
checkCallbacks() {
|
|
166
|
+
let pendingCallbacks;
|
|
167
|
+
for (const id of this.pendingCallbacks) {
|
|
168
|
+
const key = `vscode-web.url-callbacks[${id}]`;
|
|
169
|
+
const result = localStorage.getItem(key);
|
|
170
|
+
if (result !== null) {
|
|
171
|
+
try {
|
|
172
|
+
this._onCallback.fire(workbench_api_1.URI.revive(JSON.parse(result)));
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
console.error(error);
|
|
176
|
+
}
|
|
177
|
+
pendingCallbacks = pendingCallbacks ?? new Set(this.pendingCallbacks);
|
|
178
|
+
pendingCallbacks.delete(id);
|
|
179
|
+
localStorage.removeItem(key);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (pendingCallbacks) {
|
|
183
|
+
this.pendingCallbacks = pendingCallbacks;
|
|
184
|
+
if (this.pendingCallbacks.size === 0) {
|
|
185
|
+
this.stopListening();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.lastTimeChecked = Date.now();
|
|
189
|
+
}
|
|
190
|
+
dispose() {
|
|
191
|
+
this._onCallback.dispose();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
(function () {
|
|
195
|
+
const configElement = window.document.getElementById('vscode-workbench-web-configuration');
|
|
196
|
+
const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined;
|
|
197
|
+
if (!configElement || !configElementAttribute) {
|
|
198
|
+
throw new Error('Missing web configuration element');
|
|
199
|
+
}
|
|
200
|
+
const config = JSON.parse(configElementAttribute);
|
|
201
|
+
(0, workbench_api_1.create)(window.document.body, {
|
|
202
|
+
...config,
|
|
203
|
+
workspaceProvider: WorkspaceProvider.create(config),
|
|
204
|
+
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute)
|
|
205
|
+
});
|
|
206
|
+
})();
|
|
207
|
+
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { create, URI, Emitter } from './workbench.api';
|
|
2
|
+
class WorkspaceProvider {
|
|
3
|
+
workspace;
|
|
4
|
+
payload;
|
|
5
|
+
static QUERY_PARAM_EMPTY_WINDOW = 'ew';
|
|
6
|
+
static QUERY_PARAM_FOLDER = 'folder';
|
|
7
|
+
static QUERY_PARAM_WORKSPACE = 'workspace';
|
|
8
|
+
static QUERY_PARAM_PAYLOAD = 'payload';
|
|
9
|
+
static create(config) {
|
|
10
|
+
let foundWorkspace = false;
|
|
11
|
+
let workspace;
|
|
12
|
+
let payload = Object.create(null);
|
|
13
|
+
const query = new URL(document.location.href).searchParams;
|
|
14
|
+
query.forEach((value, key) => {
|
|
15
|
+
switch (key) {
|
|
16
|
+
case WorkspaceProvider.QUERY_PARAM_FOLDER:
|
|
17
|
+
workspace = { folderUri: URI.parse(value) };
|
|
18
|
+
foundWorkspace = true;
|
|
19
|
+
break;
|
|
20
|
+
case WorkspaceProvider.QUERY_PARAM_WORKSPACE:
|
|
21
|
+
workspace = { workspaceUri: URI.parse(value) };
|
|
22
|
+
foundWorkspace = true;
|
|
23
|
+
break;
|
|
24
|
+
case WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW:
|
|
25
|
+
workspace = undefined;
|
|
26
|
+
foundWorkspace = true;
|
|
27
|
+
break;
|
|
28
|
+
case WorkspaceProvider.QUERY_PARAM_PAYLOAD:
|
|
29
|
+
try {
|
|
30
|
+
payload = JSON.parse(value);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(error);
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
if (!foundWorkspace) {
|
|
39
|
+
if (config.folderUri) {
|
|
40
|
+
workspace = { folderUri: URI.revive(config.folderUri) };
|
|
41
|
+
}
|
|
42
|
+
else if (config.workspaceUri) {
|
|
43
|
+
workspace = { workspaceUri: URI.revive(config.workspaceUri) };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return new WorkspaceProvider(workspace, payload);
|
|
47
|
+
}
|
|
48
|
+
trusted = true;
|
|
49
|
+
constructor(workspace, payload) {
|
|
50
|
+
this.workspace = workspace;
|
|
51
|
+
this.payload = payload;
|
|
52
|
+
}
|
|
53
|
+
async open(workspace, options) {
|
|
54
|
+
if (options?.reuse && !options.payload && this.isSame(this.workspace, workspace)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
const targetHref = this.createTargetUrl(workspace, options);
|
|
58
|
+
if (targetHref) {
|
|
59
|
+
if (options?.reuse) {
|
|
60
|
+
window.location.href = targetHref;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return !!window.open(targetHref);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
createTargetUrl(workspace, options) {
|
|
70
|
+
let targetHref = undefined;
|
|
71
|
+
if (!workspace) {
|
|
72
|
+
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_EMPTY_WINDOW}=true`;
|
|
73
|
+
}
|
|
74
|
+
else if ('folderUri' in workspace) {
|
|
75
|
+
const queryParamFolder = encodeURIComponent(workspace.folderUri.toString(true));
|
|
76
|
+
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_FOLDER}=${queryParamFolder}`;
|
|
77
|
+
}
|
|
78
|
+
else if ('workspaceUri' in workspace) {
|
|
79
|
+
const queryParamWorkspace = encodeURIComponent(workspace.workspaceUri.toString(true));
|
|
80
|
+
targetHref = `${document.location.origin}${document.location.pathname}?${WorkspaceProvider.QUERY_PARAM_WORKSPACE}=${queryParamWorkspace}`;
|
|
81
|
+
}
|
|
82
|
+
if (options?.payload) {
|
|
83
|
+
targetHref += `&${WorkspaceProvider.QUERY_PARAM_PAYLOAD}=${encodeURIComponent(JSON.stringify(options.payload))}`;
|
|
84
|
+
}
|
|
85
|
+
return targetHref;
|
|
86
|
+
}
|
|
87
|
+
isSame(workspaceA, workspaceB) {
|
|
88
|
+
if (!workspaceA || !workspaceB) {
|
|
89
|
+
return workspaceA === workspaceB;
|
|
90
|
+
}
|
|
91
|
+
if ('folderUri' in workspaceA && 'folderUri' in workspaceB) {
|
|
92
|
+
return this.isEqualURI(workspaceA.folderUri, workspaceB.folderUri);
|
|
93
|
+
}
|
|
94
|
+
if ('workspaceUri' in workspaceA && 'workspaceUri' in workspaceB) {
|
|
95
|
+
return this.isEqualURI(workspaceA.workspaceUri, workspaceB.workspaceUri);
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
isEqualURI(a, b) {
|
|
100
|
+
return a.scheme === b.scheme && a.authority === b.authority && a.path === b.path;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
class LocalStorageURLCallbackProvider {
|
|
104
|
+
_callbackRoute;
|
|
105
|
+
static REQUEST_ID = 0;
|
|
106
|
+
static QUERY_KEYS = [
|
|
107
|
+
'scheme',
|
|
108
|
+
'authority',
|
|
109
|
+
'path',
|
|
110
|
+
'query',
|
|
111
|
+
'fragment'
|
|
112
|
+
];
|
|
113
|
+
_onCallback = new Emitter();
|
|
114
|
+
onCallback = this._onCallback.event;
|
|
115
|
+
pendingCallbacks = new Set();
|
|
116
|
+
lastTimeChecked = Date.now();
|
|
117
|
+
checkCallbacksTimeout = undefined;
|
|
118
|
+
onDidChangeLocalStorageDisposable;
|
|
119
|
+
constructor(_callbackRoute) {
|
|
120
|
+
this._callbackRoute = _callbackRoute;
|
|
121
|
+
}
|
|
122
|
+
create(options = {}) {
|
|
123
|
+
const id = ++LocalStorageURLCallbackProvider.REQUEST_ID;
|
|
124
|
+
const queryParams = [`vscode-reqid=${id}`];
|
|
125
|
+
for (const key of LocalStorageURLCallbackProvider.QUERY_KEYS) {
|
|
126
|
+
const value = options[key];
|
|
127
|
+
if (value) {
|
|
128
|
+
queryParams.push(`vscode-${key}=${encodeURIComponent(value)}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (!(options.authority === 'vscode.github-authentication' && options.path === '/dummy')) {
|
|
132
|
+
const key = `vscode-web.url-callbacks[${id}]`;
|
|
133
|
+
localStorage.removeItem(key);
|
|
134
|
+
this.pendingCallbacks.add(id);
|
|
135
|
+
this.startListening();
|
|
136
|
+
}
|
|
137
|
+
return URI.parse(window.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
|
|
138
|
+
}
|
|
139
|
+
startListening() {
|
|
140
|
+
if (this.onDidChangeLocalStorageDisposable) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const fn = () => this.onDidChangeLocalStorage();
|
|
144
|
+
window.addEventListener('storage', fn);
|
|
145
|
+
this.onDidChangeLocalStorageDisposable = { dispose: () => window.removeEventListener('storage', fn) };
|
|
146
|
+
}
|
|
147
|
+
stopListening() {
|
|
148
|
+
this.onDidChangeLocalStorageDisposable?.dispose();
|
|
149
|
+
this.onDidChangeLocalStorageDisposable = undefined;
|
|
150
|
+
}
|
|
151
|
+
async onDidChangeLocalStorage() {
|
|
152
|
+
const ellapsed = Date.now() - this.lastTimeChecked;
|
|
153
|
+
if (ellapsed > 1000) {
|
|
154
|
+
this.checkCallbacks();
|
|
155
|
+
}
|
|
156
|
+
else if (this.checkCallbacksTimeout === undefined) {
|
|
157
|
+
this.checkCallbacksTimeout = setTimeout(() => {
|
|
158
|
+
this.checkCallbacksTimeout = undefined;
|
|
159
|
+
this.checkCallbacks();
|
|
160
|
+
}, 1000 - ellapsed);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
checkCallbacks() {
|
|
164
|
+
let pendingCallbacks;
|
|
165
|
+
for (const id of this.pendingCallbacks) {
|
|
166
|
+
const key = `vscode-web.url-callbacks[${id}]`;
|
|
167
|
+
const result = localStorage.getItem(key);
|
|
168
|
+
if (result !== null) {
|
|
169
|
+
try {
|
|
170
|
+
this._onCallback.fire(URI.revive(JSON.parse(result)));
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.error(error);
|
|
174
|
+
}
|
|
175
|
+
pendingCallbacks = pendingCallbacks ?? new Set(this.pendingCallbacks);
|
|
176
|
+
pendingCallbacks.delete(id);
|
|
177
|
+
localStorage.removeItem(key);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (pendingCallbacks) {
|
|
181
|
+
this.pendingCallbacks = pendingCallbacks;
|
|
182
|
+
if (this.pendingCallbacks.size === 0) {
|
|
183
|
+
this.stopListening();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
this.lastTimeChecked = Date.now();
|
|
187
|
+
}
|
|
188
|
+
dispose() {
|
|
189
|
+
this._onCallback.dispose();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
(function () {
|
|
193
|
+
const configElement = window.document.getElementById('vscode-workbench-web-configuration');
|
|
194
|
+
const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined;
|
|
195
|
+
if (!configElement || !configElementAttribute) {
|
|
196
|
+
throw new Error('Missing web configuration element');
|
|
197
|
+
}
|
|
198
|
+
const config = JSON.parse(configElementAttribute);
|
|
199
|
+
create(window.document.body, {
|
|
200
|
+
...config,
|
|
201
|
+
workspaceProvider: WorkspaceProvider.create(config),
|
|
202
|
+
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute)
|
|
203
|
+
});
|
|
204
|
+
})();
|
package/out/server/download.js
CHANGED
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getDownloadURL = getDownloadURL;
|
|
7
8
|
exports.downloadAndUnzipVSCode = downloadAndUnzipVSCode;
|
|
8
9
|
exports.fetch = fetch;
|
|
9
10
|
exports.fetchJSON = fetchJSON;
|
|
10
11
|
exports.directoryExists = directoryExists;
|
|
11
12
|
exports.fileExists = fileExists;
|
|
13
|
+
exports.readFileInRepo = readFileInRepo;
|
|
12
14
|
const fs_1 = require("fs");
|
|
13
15
|
const path = require("path");
|
|
14
16
|
const https = require("https");
|
|
@@ -16,9 +18,23 @@ const http = require("http");
|
|
|
16
18
|
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
17
19
|
const http_proxy_agent_1 = require("http-proxy-agent");
|
|
18
20
|
const url_1 = require("url");
|
|
19
|
-
async function
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
async function getLatestBuild(quality) {
|
|
22
|
+
return await fetchJSON(`https://update.code.visualstudio.com/api/update/web-standalone/${quality}/latest`);
|
|
23
|
+
}
|
|
24
|
+
async function getDownloadURL(quality, commit) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const url = `https://update.code.visualstudio.com/commit:${commit}/web-standalone/${quality}`;
|
|
27
|
+
const httpLibrary = url.startsWith('https') ? https : http;
|
|
28
|
+
httpLibrary.get(url, { method: 'HEAD', ...getAgent(url) }, res => {
|
|
29
|
+
console.log(res.statusCode, res.headers.location);
|
|
30
|
+
if ((res.statusCode === 301 || res.statusCode === 302 || res.statusCode === 307) && res.headers.location) {
|
|
31
|
+
resolve(res.headers.location);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
resolve(undefined);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
22
38
|
}
|
|
23
39
|
const reset = '\x1b[G\x1b[0K';
|
|
24
40
|
async function downloadAndUntar(downloadUrl, destination, message) {
|
|
@@ -58,27 +74,38 @@ async function downloadAndUntar(downloadUrl, destination, message) {
|
|
|
58
74
|
});
|
|
59
75
|
});
|
|
60
76
|
}
|
|
61
|
-
async function downloadAndUnzipVSCode(quality,
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
async function downloadAndUnzipVSCode(vscodeTestDir, quality, commit) {
|
|
78
|
+
let downloadURL;
|
|
79
|
+
if (!commit) {
|
|
80
|
+
const info = await getLatestBuild(quality);
|
|
81
|
+
commit = info.version;
|
|
82
|
+
downloadURL = info.url;
|
|
83
|
+
}
|
|
84
|
+
const folderName = `vscode-web-${quality}-${commit}`;
|
|
64
85
|
const downloadedPath = path.resolve(vscodeTestDir, folderName);
|
|
65
86
|
if ((0, fs_1.existsSync)(downloadedPath) && (0, fs_1.existsSync)(path.join(downloadedPath, 'version'))) {
|
|
66
|
-
return { type: 'static', location: downloadedPath, quality, version:
|
|
87
|
+
return { type: 'static', location: downloadedPath, quality, version: commit };
|
|
88
|
+
}
|
|
89
|
+
if (!downloadURL) {
|
|
90
|
+
downloadURL = await getDownloadURL(quality, commit);
|
|
91
|
+
if (!downloadURL) {
|
|
92
|
+
throw Error(`Failed to find a download for ${quality} and ${commit}`);
|
|
93
|
+
}
|
|
67
94
|
}
|
|
68
95
|
if ((0, fs_1.existsSync)(vscodeTestDir)) {
|
|
69
|
-
await fs_1.promises.
|
|
96
|
+
await fs_1.promises.rm(vscodeTestDir, { recursive: true, maxRetries: 5 });
|
|
70
97
|
}
|
|
71
98
|
await fs_1.promises.mkdir(vscodeTestDir, { recursive: true });
|
|
72
99
|
const productName = `VS Code ${quality === 'stable' ? 'Stable' : 'Insiders'}`;
|
|
73
100
|
try {
|
|
74
|
-
await downloadAndUntar(
|
|
101
|
+
await downloadAndUntar(downloadURL, downloadedPath, `Downloading ${productName}`);
|
|
75
102
|
await fs_1.promises.writeFile(path.join(downloadedPath, 'version'), folderName);
|
|
76
103
|
}
|
|
77
104
|
catch (err) {
|
|
78
105
|
console.error(err);
|
|
79
|
-
throw Error(`Failed to download and unpack ${productName}`);
|
|
106
|
+
throw Error(`Failed to download and unpack ${productName}.${commit ? ' Did you specify a valid commit?' : ''}`);
|
|
80
107
|
}
|
|
81
|
-
return { type: 'static', location: downloadedPath, quality, version:
|
|
108
|
+
return { type: 'static', location: downloadedPath, quality, version: commit };
|
|
82
109
|
}
|
|
83
110
|
async function fetch(api) {
|
|
84
111
|
return new Promise((resolve, reject) => {
|
|
@@ -147,3 +174,6 @@ async function fileExists(path) {
|
|
|
147
174
|
return false;
|
|
148
175
|
}
|
|
149
176
|
}
|
|
177
|
+
async function readFileInRepo(pathInRepo) {
|
|
178
|
+
return (await fs_1.promises.readFile(path.resolve(__dirname, '../..', pathInRepo))).toString();
|
|
179
|
+
}
|