@theia/core 1.77.0-next.1 → 1.77.0-next.14
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/lib/browser/catalog.json +130 -9
- package/lib/browser/tree/tree-widget.d.ts +28 -0
- package/lib/browser/tree/tree-widget.d.ts.map +1 -1
- package/lib/browser/tree/tree-widget.js +59 -3
- package/lib/browser/tree/tree-widget.js.map +1 -1
- package/lib/browser/tree/tree-widget.spec.js +53 -3
- package/lib/browser/tree/tree-widget.spec.js.map +1 -1
- package/lib/common/core-preferences.js +5 -5
- package/lib/common/core-preferences.js.map +1 -1
- package/lib/node/backend-application-module.d.ts.map +1 -1
- package/lib/node/backend-application-module.js +3 -0
- package/lib/node/backend-application-module.js.map +1 -1
- package/lib/node/bundled-resource-provider.d.ts +86 -0
- package/lib/node/bundled-resource-provider.d.ts.map +1 -0
- package/lib/node/bundled-resource-provider.js +241 -0
- package/lib/node/bundled-resource-provider.js.map +1 -0
- package/lib/node/bundled-resource-provider.spec.d.ts +2 -0
- package/lib/node/bundled-resource-provider.spec.d.ts.map +1 -0
- package/lib/node/bundled-resource-provider.spec.js +160 -0
- package/lib/node/bundled-resource-provider.spec.js.map +1 -0
- package/lib/node/index.d.ts +1 -0
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +3 -1
- package/lib/node/index.js.map +1 -1
- package/package.json +4 -4
- package/src/browser/tree/tree-widget.spec.tsx +59 -3
- package/src/browser/tree/tree-widget.tsx +64 -2
- package/src/common/core-preferences.ts +5 -5
- package/src/node/backend-application-module.ts +4 -0
- package/src/node/bundled-resource-provider.spec.ts +196 -0
- package/src/node/bundled-resource-provider.ts +266 -0
- package/src/node/index.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled-resource-provider.spec.d.ts","sourceRoot":"","sources":["../../src/node/bundled-resource-provider.spec.ts"],"names":[],"mappings":"AAgBA,OAAO,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
require("reflect-metadata");
|
|
19
|
+
const chai_1 = require("chai");
|
|
20
|
+
const fs = require("fs");
|
|
21
|
+
const os = require("os");
|
|
22
|
+
const path = require("path");
|
|
23
|
+
const temp = require("temp");
|
|
24
|
+
const inversify_1 = require("inversify");
|
|
25
|
+
const env_variables_1 = require("../common/env-variables");
|
|
26
|
+
const logger_1 = require("../common/logger");
|
|
27
|
+
const mock_logger_1 = require("../common/test/mock-logger");
|
|
28
|
+
const file_uri_1 = require("../common/file-uri");
|
|
29
|
+
const bundled_resource_provider_1 = require("./bundled-resource-provider");
|
|
30
|
+
const filesystem_locking_1 = require("./filesystem-locking");
|
|
31
|
+
/**
|
|
32
|
+
* The provider recognizes archives by their `.asar` path segment and reads them through `fs`, which Electron
|
|
33
|
+
* patches to transparently read from the archive. Plain directories named `*.asar` therefore behave like
|
|
34
|
+
* archives from the point of view of the provider and let us test it outside of Electron.
|
|
35
|
+
*/
|
|
36
|
+
describe('BundledResourceProvider', () => {
|
|
37
|
+
const track = temp.track();
|
|
38
|
+
let configDir;
|
|
39
|
+
let appDir;
|
|
40
|
+
let provider;
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
const root = track.mkdirSync();
|
|
43
|
+
configDir = path.join(root, 'config');
|
|
44
|
+
appDir = path.join(root, 'app');
|
|
45
|
+
fs.mkdirSync(configDir);
|
|
46
|
+
fs.mkdirSync(appDir);
|
|
47
|
+
provider = createProvider();
|
|
48
|
+
});
|
|
49
|
+
/** Each provider instance stands for one run of the application, as resolved paths are cached. */
|
|
50
|
+
function createProvider() {
|
|
51
|
+
const container = new inversify_1.Container();
|
|
52
|
+
container.bind(logger_1.ILogger).toConstantValue(new mock_logger_1.MockLogger());
|
|
53
|
+
container.bind(filesystem_locking_1.FileSystemLocking).to(filesystem_locking_1.FileSystemLockingImpl).inSingletonScope();
|
|
54
|
+
container.bind(env_variables_1.EnvVariablesServer).toConstantValue({
|
|
55
|
+
getConfigDirUri: async () => file_uri_1.FileUri.create(configDir).toString()
|
|
56
|
+
});
|
|
57
|
+
container.bind(bundled_resource_provider_1.BundledResourceProviderImpl).toSelf().inSingletonScope();
|
|
58
|
+
container.bind(bundled_resource_provider_1.BundledResourceProvider).toService(bundled_resource_provider_1.BundledResourceProviderImpl);
|
|
59
|
+
return container.get(bundled_resource_provider_1.BundledResourceProvider);
|
|
60
|
+
}
|
|
61
|
+
afterEach(() => track.cleanupSync());
|
|
62
|
+
/**
|
|
63
|
+
* Assert that the given path is nested in the given directory. The provider derives the configuration
|
|
64
|
+
* directory from a URI, which on Windows yields a lower-case drive letter, so the paths cannot simply be
|
|
65
|
+
* compared by prefix. `path.relative` ignores the case of a path on Windows.
|
|
66
|
+
*/
|
|
67
|
+
function expectNestedIn(directoryPath, nestedPath) {
|
|
68
|
+
const relativePath = path.relative(directoryPath, nestedPath);
|
|
69
|
+
(0, chai_1.expect)(relativePath).to.not.be.empty;
|
|
70
|
+
(0, chai_1.expect)(relativePath.split(path.sep)).to.not.contain('..');
|
|
71
|
+
}
|
|
72
|
+
function writeResources(rootPath, files) {
|
|
73
|
+
for (const [relativePath, content] of Object.entries(files)) {
|
|
74
|
+
const filePath = path.join(rootPath, relativePath);
|
|
75
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
76
|
+
fs.writeFileSync(filePath, content);
|
|
77
|
+
}
|
|
78
|
+
return rootPath;
|
|
79
|
+
}
|
|
80
|
+
it('returns the path of a resource that is not packaged into an archive', async () => {
|
|
81
|
+
const resourcePath = path.join(writeResources(appDir, { 'scripts/greet.sh': 'echo hello' }), 'scripts');
|
|
82
|
+
(0, chai_1.expect)(await provider.resolveExternalPath(resourcePath)).to.equal(resourcePath);
|
|
83
|
+
});
|
|
84
|
+
it('rejects for a resource that does not exist', async () => {
|
|
85
|
+
const resourcePath = path.join(appDir, 'scripts');
|
|
86
|
+
await provider.resolveExternalPath(resourcePath).then(() => chai_1.expect.fail('should have been rejected'), error => (0, chai_1.expect)(String(error)).to.contain(resourcePath));
|
|
87
|
+
});
|
|
88
|
+
it('extracts a packaged resource into the configuration directory', async () => {
|
|
89
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
90
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello', 'scripts/nested/.hidden': 'secret' });
|
|
91
|
+
const resolvedPath = await provider.resolveExternalPath(path.join(archivePath, 'scripts'));
|
|
92
|
+
(0, chai_1.expect)(resolvedPath).to.not.contain('.asar');
|
|
93
|
+
expectNestedIn(configDir, resolvedPath);
|
|
94
|
+
(0, chai_1.expect)(fs.readFileSync(path.join(resolvedPath, 'greet.sh'), 'utf8')).to.equal('echo hello');
|
|
95
|
+
(0, chai_1.expect)(fs.readFileSync(path.join(resolvedPath, 'nested', '.hidden'), 'utf8')).to.equal('secret');
|
|
96
|
+
});
|
|
97
|
+
it('extracts a packaged resource that is a plain file', async () => {
|
|
98
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
99
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello' });
|
|
100
|
+
const resolvedPath = await provider.resolveExternalPath(path.join(archivePath, 'scripts', 'greet.sh'));
|
|
101
|
+
expectNestedIn(configDir, resolvedPath);
|
|
102
|
+
(0, chai_1.expect)(fs.readFileSync(resolvedPath, 'utf8')).to.equal('echo hello');
|
|
103
|
+
});
|
|
104
|
+
it('extracts a packaged file as executable', async function () {
|
|
105
|
+
if (process.platform === 'win32') {
|
|
106
|
+
this.skip();
|
|
107
|
+
}
|
|
108
|
+
// Electron reports the files of an asar archive with this mode, even executables.
|
|
109
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
110
|
+
writeResources(archivePath, { 'native/tool': 'binary' });
|
|
111
|
+
fs.chmodSync(path.join(archivePath, 'native', 'tool'), 0o644);
|
|
112
|
+
const resolvedPath = await provider.resolveExternalPath(path.join(archivePath, 'native', 'tool'));
|
|
113
|
+
(0, chai_1.expect)(fs.statSync(resolvedPath).mode & 0o700).to.equal(0o700);
|
|
114
|
+
});
|
|
115
|
+
it('prefers the copy that the packaging step has left outside of the archive', async () => {
|
|
116
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
117
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello' });
|
|
118
|
+
const unpackedPath = writeResources(`${archivePath}.unpacked`, { 'scripts/greet.sh': 'echo hello' });
|
|
119
|
+
const resolvedPath = await provider.resolveExternalPath(path.join(archivePath, 'scripts'));
|
|
120
|
+
(0, chai_1.expect)(resolvedPath).to.equal(path.join(unpackedPath, 'scripts'));
|
|
121
|
+
});
|
|
122
|
+
it('extracts a packaged resource that was only unpacked partially', async () => {
|
|
123
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
124
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello', 'scripts/farewell.sh': 'echo bye' });
|
|
125
|
+
writeResources(`${archivePath}.unpacked`, { 'scripts/greet.sh': 'echo hello' });
|
|
126
|
+
const resolvedPath = await provider.resolveExternalPath(path.join(archivePath, 'scripts'));
|
|
127
|
+
expectNestedIn(configDir, resolvedPath);
|
|
128
|
+
(0, chai_1.expect)(fs.readFileSync(path.join(resolvedPath, 'farewell.sh'), 'utf8')).to.equal('echo bye');
|
|
129
|
+
});
|
|
130
|
+
it('re-extracts a resource that was removed from the configuration directory', async () => {
|
|
131
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
132
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello' });
|
|
133
|
+
const resourcePath = path.join(archivePath, 'scripts');
|
|
134
|
+
const resolvedPath = await provider.resolveExternalPath(resourcePath);
|
|
135
|
+
fs.rmSync(resolvedPath, { recursive: true });
|
|
136
|
+
(0, chai_1.expect)(await provider.resolveExternalPath(resourcePath)).to.equal(resolvedPath);
|
|
137
|
+
(0, chai_1.expect)(fs.readFileSync(path.join(resolvedPath, 'greet.sh'), 'utf8')).to.equal('echo hello');
|
|
138
|
+
});
|
|
139
|
+
it('extracts into a temporary directory if the configuration directory cannot be written to', async () => {
|
|
140
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
141
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello' });
|
|
142
|
+
// a configuration directory that is a regular file cannot hold the extracted resources
|
|
143
|
+
configDir = path.join(appDir, 'not-a-directory');
|
|
144
|
+
fs.writeFileSync(configDir, '');
|
|
145
|
+
const resolvedPath = await createProvider().resolveExternalPath(path.join(archivePath, 'scripts'));
|
|
146
|
+
expectNestedIn(os.tmpdir(), resolvedPath);
|
|
147
|
+
(0, chai_1.expect)(fs.readFileSync(path.join(resolvedPath, 'greet.sh'), 'utf8')).to.equal('echo hello');
|
|
148
|
+
fs.rmSync(resolvedPath, { recursive: true, force: true });
|
|
149
|
+
});
|
|
150
|
+
it('updates an extracted resource when the application has been updated', async () => {
|
|
151
|
+
const archivePath = path.join(appDir, 'app.asar');
|
|
152
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello' });
|
|
153
|
+
const resourcePath = path.join(archivePath, 'scripts');
|
|
154
|
+
await provider.resolveExternalPath(resourcePath);
|
|
155
|
+
writeResources(archivePath, { 'scripts/greet.sh': 'echo hello again' });
|
|
156
|
+
const resolvedPath = await createProvider().resolveExternalPath(resourcePath);
|
|
157
|
+
(0, chai_1.expect)(fs.readFileSync(path.join(resolvedPath, 'greet.sh'), 'utf8')).to.equal('echo hello again');
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=bundled-resource-provider.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled-resource-provider.spec.js","sourceRoot":"","sources":["../../src/node/bundled-resource-provider.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,oDAAoD;AACpD,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAEhF,4BAA0B;AAC1B,+BAA8B;AAC9B,yBAAyB;AACzB,yBAAyB;AACzB,6BAA6B;AAC7B,6BAA6B;AAC7B,yCAAsC;AACtC,2DAA6D;AAC7D,6CAA2C;AAC3C,4DAAwD;AACxD,iDAA6C;AAC7C,2EAAmG;AACnG,6DAAgF;AAEhF;;;;GAIG;AACH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IAErC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;IAE3B,IAAI,SAAiB,CAAC;IACtB,IAAI,MAAc,CAAC;IACnB,IAAI,QAAiC,CAAC;IAEtC,UAAU,CAAC,GAAG,EAAE;QACZ,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;QAC/B,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACrB,QAAQ,GAAG,cAAc,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,kGAAkG;IAClG,SAAS,cAAc;QACnB,MAAM,SAAS,GAAG,IAAI,qBAAS,EAAE,CAAC;QAClC,SAAS,CAAC,IAAI,CAAC,gBAAO,CAAC,CAAC,eAAe,CAAC,IAAI,wBAAU,EAAE,CAAC,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,sCAAiB,CAAC,CAAC,EAAE,CAAC,0CAAqB,CAAC,CAAC,gBAAgB,EAAE,CAAC;QAC/E,SAAS,CAAC,IAAI,CAAC,kCAAkB,CAAC,CAAC,eAAe,CAAC;YAC/C,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,kBAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE;SACnC,CAAC,CAAC;QACpC,SAAS,CAAC,IAAI,CAAC,uDAA2B,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACxE,SAAS,CAAC,IAAI,CAAC,mDAAuB,CAAC,CAAC,SAAS,CAAC,uDAA2B,CAAC,CAAC;QAC/E,OAAO,SAAS,CAAC,GAAG,CAAC,mDAAuB,CAAC,CAAC;IAClD,CAAC;IAED,SAAS,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAErC;;;;OAIG;IACH,SAAS,cAAc,CAAC,aAAqB,EAAE,UAAkB;QAC7D,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAC9D,IAAA,aAAM,EAAC,YAAY,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC;QACrC,IAAA,aAAM,EAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,SAAS,cAAc,CAAC,QAAgB,EAAE,KAA6B;QACnE,KAAK,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACnD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACxG,IAAA,aAAM,EAAC,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAClD,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,IAAI,CACjD,GAAG,EAAE,CAAC,aAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,EAC9C,KAAK,CAAC,EAAE,CAAC,IAAA,aAAM,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAC1D,CAAC;IACN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtG,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QAE3F,IAAA,aAAM,EAAC,YAAY,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACxC,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC5F,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAElE,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;QAEvG,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACxC,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK;QAC9C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;QAChB,CAAC;QACD,kFAAkF;QAClF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;QAE9D,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAElG,IAAA,aAAM,EAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,cAAc,CAAC,GAAG,WAAW,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAErG,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QAE3F,IAAA,aAAM,EAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,qBAAqB,EAAE,UAAU,EAAE,CAAC,CAAC;QACrG,cAAc,CAAC,GAAG,WAAW,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAEhF,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QAE3F,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACxC,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAEvD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;QACtE,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,IAAA,aAAM,EAAC,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAChF,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;QACrG,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAClE,uFAAuF;QACvF,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;QACjD,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAEhC,MAAM,YAAY,GAAG,MAAM,cAAc,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QAEnG,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC;QAC1C,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC5F,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAEvD,MAAM,QAAQ,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;QACjD,cAAc,CAAC,WAAW,EAAE,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,MAAM,cAAc,EAAE,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;QAE9E,IAAA,aAAM,EAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;AAEP,CAAC,CAAC,CAAC"}
|
package/lib/node/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './messaging';
|
|
|
6
6
|
export * from './cli';
|
|
7
7
|
export * from './setting-service';
|
|
8
8
|
export { FileSystemLocking } from './filesystem-locking';
|
|
9
|
+
export { BundledResourceProvider } from './bundled-resource-provider';
|
|
9
10
|
export { BackendRequestAllowedContribution } from './request/backend-request-facade';
|
|
10
11
|
export { HttpConnectionValidator } from './hosting/browser-connection-token';
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/node/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAgBA,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,OAAO,CAAC;AACtB,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAgBA,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,OAAO,CAAC;AACtB,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,iCAAiC,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC"}
|
package/lib/node/index.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
16
|
// *****************************************************************************
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.HttpConnectionValidator = exports.BackendRequestAllowedContribution = exports.FileSystemLocking = void 0;
|
|
18
|
+
exports.HttpConnectionValidator = exports.BackendRequestAllowedContribution = exports.BundledResourceProvider = exports.FileSystemLocking = void 0;
|
|
19
19
|
const tslib_1 = require("tslib");
|
|
20
20
|
tslib_1.__exportStar(require("./backend-application"), exports);
|
|
21
21
|
tslib_1.__exportStar(require("./backend-global"), exports);
|
|
@@ -26,6 +26,8 @@ tslib_1.__exportStar(require("./cli"), exports);
|
|
|
26
26
|
tslib_1.__exportStar(require("./setting-service"), exports);
|
|
27
27
|
var filesystem_locking_1 = require("./filesystem-locking");
|
|
28
28
|
Object.defineProperty(exports, "FileSystemLocking", { enumerable: true, get: function () { return filesystem_locking_1.FileSystemLocking; } });
|
|
29
|
+
var bundled_resource_provider_1 = require("./bundled-resource-provider");
|
|
30
|
+
Object.defineProperty(exports, "BundledResourceProvider", { enumerable: true, get: function () { return bundled_resource_provider_1.BundledResourceProvider; } });
|
|
29
31
|
var backend_request_facade_1 = require("./request/backend-request-facade");
|
|
30
32
|
Object.defineProperty(exports, "BackendRequestAllowedContribution", { enumerable: true, get: function () { return backend_request_facade_1.BackendRequestAllowedContribution; } });
|
|
31
33
|
var browser_connection_token_1 = require("./hosting/browser-connection-token");
|
package/lib/node/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,gEAAsC;AACtC,2DAAiC;AACjC,kDAAwB;AACxB,6DAAmC;AACnC,sDAA4B;AAC5B,gDAAsB;AACtB,4DAAkC;AAClC,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,2EAAqF;AAA5E,2IAAA,iCAAiC,OAAA;AAC1C,+EAA6E;AAApE,mIAAA,uBAAuB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,gEAAsC;AACtC,2DAAiC;AACjC,kDAAwB;AACxB,6DAAmC;AACnC,sDAA4B;AAC5B,gDAAsB;AACtB,4DAAkC;AAClC,2DAAyD;AAAhD,uHAAA,iBAAiB,OAAA;AAC1B,yEAAsE;AAA7D,oIAAA,uBAAuB,OAAA;AAChC,2EAAqF;AAA5E,2IAAA,iCAAiC,OAAA;AAC1C,+EAA6E;AAApE,mIAAA,uBAAuB,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/core",
|
|
3
|
-
"version": "1.77.0-next.
|
|
3
|
+
"version": "1.77.0-next.14+b315294d3",
|
|
4
4
|
"description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.",
|
|
5
5
|
"main": "lib/common/index.js",
|
|
6
6
|
"typings": "lib/common/index.d.ts",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"@lumino/virtualdom": "^2.0.5",
|
|
18
18
|
"@lumino/widgets": "2.7.5",
|
|
19
19
|
"@parcel/watcher": "^2.6.0",
|
|
20
|
-
"@theia/application-package": "1.77.0-next.
|
|
21
|
-
"@theia/request": "1.77.0-next.
|
|
20
|
+
"@theia/application-package": "1.77.0-next.14+b315294d3",
|
|
21
|
+
"@theia/request": "1.77.0-next.14+b315294d3",
|
|
22
22
|
"@types/body-parser": "^1.19.6",
|
|
23
23
|
"@types/express": "^4.17.25",
|
|
24
24
|
"@types/fs-extra": "^4.0.15",
|
|
@@ -233,5 +233,5 @@
|
|
|
233
233
|
"nyc": {
|
|
234
234
|
"extends": "../../configs/nyc.json"
|
|
235
235
|
},
|
|
236
|
-
"gitHead": "
|
|
236
|
+
"gitHead": "b315294d3c24f8480548d8769f7de024c4ad8efb"
|
|
237
237
|
}
|
|
@@ -38,6 +38,14 @@ class CountingView extends TreeWidget.View {
|
|
|
38
38
|
this.scrollCount++;
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
+
/** Reports the list height the way Virtuoso does once it has measured the list. */
|
|
42
|
+
measure(height: number, renderedHeight = height): void {
|
|
43
|
+
this.setRenderedHeight(renderedHeight);
|
|
44
|
+
this.onTotalListHeightChanged(height);
|
|
45
|
+
}
|
|
46
|
+
setRenderedHeight(scrollHeight: number): void {
|
|
47
|
+
this.scroller = { scrollHeight } as HTMLElement;
|
|
48
|
+
}
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
class TestTreeWidget extends TreeWidget {
|
|
@@ -190,6 +198,8 @@ describe('TreeWidget', () => {
|
|
|
190
198
|
let container: HTMLElement;
|
|
191
199
|
let root: Root;
|
|
192
200
|
let view: CountingView | undefined;
|
|
201
|
+
let frames: FrameRequestCallback[];
|
|
202
|
+
let requestAnimationFrame: typeof window.requestAnimationFrame;
|
|
193
203
|
const rows: TreeWidget.NodeRow[] = [0, 1, 2].map(index => ({ index, depth: 0, node: leaf(`node-${index}`) }));
|
|
194
204
|
|
|
195
205
|
const render = (props: Partial<TreeWidget.ViewProps>): void => flushSync(() => root.render(
|
|
@@ -202,20 +212,66 @@ describe('TreeWidget', () => {
|
|
|
202
212
|
{...props}
|
|
203
213
|
/>
|
|
204
214
|
));
|
|
215
|
+
const runFrames = (): void => frames.splice(0).forEach(frame => frame(0));
|
|
216
|
+
/** Mount and measure the list, and serve the mount-time request. */
|
|
217
|
+
const mount = (props: Partial<TreeWidget.ViewProps>): void => {
|
|
218
|
+
render(props);
|
|
219
|
+
view!.measure(300);
|
|
220
|
+
runFrames();
|
|
221
|
+
};
|
|
205
222
|
|
|
206
223
|
beforeEach(() => {
|
|
207
224
|
container = document.createElement('div');
|
|
208
225
|
document.body.appendChild(container);
|
|
209
226
|
root = createRoot(container);
|
|
227
|
+
frames = [];
|
|
228
|
+
requestAnimationFrame = window.requestAnimationFrame;
|
|
229
|
+
window.requestAnimationFrame = frame => frames.push(frame);
|
|
210
230
|
});
|
|
211
231
|
|
|
212
232
|
afterEach(() => {
|
|
233
|
+
window.requestAnimationFrame = requestAnimationFrame;
|
|
213
234
|
flushSync(() => root.unmount());
|
|
214
235
|
document.body.removeChild(container);
|
|
215
236
|
});
|
|
216
237
|
|
|
217
|
-
it('
|
|
238
|
+
it('holds a scroll request made before the list is measured until the list is rendered at its height', () => {
|
|
239
|
+
render({ scrollToRow: 2, scrollToRowRequestId: 1 });
|
|
240
|
+
expect(view!.scrollCount).to.equal(0);
|
|
241
|
+
|
|
242
|
+
view!.measure(300, 100);
|
|
243
|
+
runFrames();
|
|
244
|
+
expect(view!.scrollCount).to.equal(0);
|
|
245
|
+
|
|
246
|
+
view!.setRenderedHeight(300);
|
|
247
|
+
runFrames();
|
|
248
|
+
expect(view!.scrollCount).to.equal(1);
|
|
249
|
+
|
|
250
|
+
runFrames();
|
|
251
|
+
expect(view!.scrollCount).to.equal(1);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('waits for the latest list height when the first reported height shrinks', () => {
|
|
255
|
+
render({ scrollToRow: 2, scrollToRowRequestId: 1 });
|
|
256
|
+
view!.measure(300, 100);
|
|
257
|
+
view!.measure(200, 200);
|
|
258
|
+
runFrames();
|
|
259
|
+
expect(view!.scrollCount).to.equal(1);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('serves a held scroll request when the list is never rendered at its height', () => {
|
|
218
263
|
render({ scrollToRow: 2, scrollToRowRequestId: 1 });
|
|
264
|
+
view!.measure(300, 100);
|
|
265
|
+
for (let frame = 0; frame < 30; frame++) {
|
|
266
|
+
runFrames();
|
|
267
|
+
expect(view!.scrollCount).to.equal(0);
|
|
268
|
+
}
|
|
269
|
+
runFrames();
|
|
270
|
+
expect(view!.scrollCount).to.equal(1);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('does not scroll again when re-rendered without a new scroll request', () => {
|
|
274
|
+
mount({ scrollToRow: 2, scrollToRowRequestId: 1 });
|
|
219
275
|
const scrollsAfterMount = view!.scrollCount;
|
|
220
276
|
|
|
221
277
|
render({ scrollToRow: 2, scrollToRowRequestId: 1 });
|
|
@@ -225,7 +281,7 @@ describe('TreeWidget', () => {
|
|
|
225
281
|
});
|
|
226
282
|
|
|
227
283
|
it('scrolls again when a new scroll request arrives for the same row', () => {
|
|
228
|
-
|
|
284
|
+
mount({ scrollToRow: 2, scrollToRowRequestId: 1 });
|
|
229
285
|
const scrollsAfterMount = view!.scrollCount;
|
|
230
286
|
|
|
231
287
|
render({ scrollToRow: 2, scrollToRowRequestId: 2 });
|
|
@@ -234,7 +290,7 @@ describe('TreeWidget', () => {
|
|
|
234
290
|
});
|
|
235
291
|
|
|
236
292
|
it('scrolls when the row to scroll to changes', () => {
|
|
237
|
-
|
|
293
|
+
mount({ scrollToRow: 1 });
|
|
238
294
|
const scrollsAfterMount = view!.scrollCount;
|
|
239
295
|
|
|
240
296
|
render({ scrollToRow: 2 });
|
|
@@ -1655,13 +1655,73 @@ export namespace TreeWidget {
|
|
|
1655
1655
|
}
|
|
1656
1656
|
};
|
|
1657
1657
|
|
|
1658
|
+
/**
|
|
1659
|
+
* `true` once Virtuoso has measured the list. Before that, `scrollIntoView` sees every row as visible and does nothing.
|
|
1660
|
+
*/
|
|
1661
|
+
protected measured = false;
|
|
1662
|
+
/**
|
|
1663
|
+
* `true` while a scroll request made before the list was measured waits to be served.
|
|
1664
|
+
*/
|
|
1665
|
+
protected scrollHeld = false;
|
|
1666
|
+
/**
|
|
1667
|
+
* The latest list height reported by Virtuoso. It can still change after the first report, as more rows are measured.
|
|
1668
|
+
*/
|
|
1669
|
+
protected listHeight = 0;
|
|
1670
|
+
/**
|
|
1671
|
+
* How many frames a held scroll request waits for the list to be rendered at its height, about half a second at 60 Hz.
|
|
1672
|
+
*/
|
|
1673
|
+
protected readonly maxRenderWaitFrames = 30;
|
|
1674
|
+
protected scroller: HTMLElement | undefined;
|
|
1675
|
+
|
|
1676
|
+
/**
|
|
1677
|
+
* Scroll now, or hold the request until the list is measured, e.g. for the focus restored when the view mounts.
|
|
1678
|
+
*/
|
|
1679
|
+
protected requestScroll(): void {
|
|
1680
|
+
if (this.measured) {
|
|
1681
|
+
this.scrollIntoViewIfNeeded();
|
|
1682
|
+
} else {
|
|
1683
|
+
this.scrollHeld = this.props.scrollToRow !== undefined;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
protected readonly onTotalListHeightChanged = (height: number): void => {
|
|
1688
|
+
this.listHeight = height;
|
|
1689
|
+
if (!this.measured && height > 0) {
|
|
1690
|
+
this.measured = true;
|
|
1691
|
+
if (this.scrollHeld) {
|
|
1692
|
+
this.scrollHeld = false;
|
|
1693
|
+
this.scrollWhenRendered();
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
this.props.totalListHeightChanged?.(height);
|
|
1697
|
+
};
|
|
1698
|
+
|
|
1699
|
+
protected readonly setScroller = (scroller: HTMLElement | Window | null): void => {
|
|
1700
|
+
this.scroller = scroller instanceof HTMLElement ? scroller : undefined;
|
|
1701
|
+
this.props.scrollerRef?.(scroller);
|
|
1702
|
+
};
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* Virtuoso reports the list height before React renders the list at it, and a scroll before that is clamped
|
|
1706
|
+
* to the old height. Wait for the rendered height, at most `maxRenderWaitFrames` frames.
|
|
1707
|
+
*/
|
|
1708
|
+
protected scrollWhenRendered(framesLeft = this.maxRenderWaitFrames): void {
|
|
1709
|
+
window.requestAnimationFrame(() => {
|
|
1710
|
+
if (this.scroller && this.scroller.scrollHeight < this.listHeight && framesLeft > 0) {
|
|
1711
|
+
this.scrollWhenRendered(framesLeft - 1);
|
|
1712
|
+
} else {
|
|
1713
|
+
this.scrollIntoViewIfNeeded();
|
|
1714
|
+
}
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1658
1718
|
override componentDidMount(): void {
|
|
1659
|
-
this.
|
|
1719
|
+
this.requestScroll();
|
|
1660
1720
|
}
|
|
1661
1721
|
|
|
1662
1722
|
override componentDidUpdate(prevProps: ViewProps): void {
|
|
1663
1723
|
if (this.props.scrollToRow !== prevProps.scrollToRow || this.props.scrollToRowRequestId !== prevProps.scrollToRowRequestId) {
|
|
1664
|
-
this.
|
|
1724
|
+
this.requestScroll();
|
|
1665
1725
|
}
|
|
1666
1726
|
}
|
|
1667
1727
|
|
|
@@ -1681,6 +1741,8 @@ export namespace TreeWidget {
|
|
|
1681
1741
|
// Higher value provides smoother scrolling experience especially during inference, but uses more memory
|
|
1682
1742
|
overscan={800}
|
|
1683
1743
|
{...other}
|
|
1744
|
+
totalListHeightChanged={this.onTotalListHeightChanged}
|
|
1745
|
+
scrollerRef={this.setScroller}
|
|
1684
1746
|
/>;
|
|
1685
1747
|
}
|
|
1686
1748
|
}
|
|
@@ -153,18 +153,18 @@ export const corePreferenceSchema: PreferenceSchema = {
|
|
|
153
153
|
'http.proxy': {
|
|
154
154
|
type: 'string',
|
|
155
155
|
pattern: '^https?://([^:]*(:[^@]*)?@)?([^:]+|\\[[:0-9a-fA-F]+\\])(:\\d+)?/?$|^$',
|
|
156
|
-
markdownDescription: nls.
|
|
156
|
+
markdownDescription: nls.localize('theia/core/http/proxy', 'The proxy setting to use. If not set, will be inherited from the `http_proxy` and `https_proxy` environment variables.'),
|
|
157
157
|
scope: PreferenceScope.User
|
|
158
158
|
},
|
|
159
159
|
'http.proxyStrictSSL': {
|
|
160
160
|
type: 'boolean',
|
|
161
161
|
default: true,
|
|
162
|
-
description: nls.
|
|
162
|
+
description: nls.localize('theia/core/http/proxyStrictSSL', 'Controls whether the proxy server certificate should be verified against the list of supplied CAs.'),
|
|
163
163
|
scope: PreferenceScope.User
|
|
164
164
|
},
|
|
165
165
|
'http.proxyAuthorization': {
|
|
166
166
|
type: 'string',
|
|
167
|
-
markdownDescription: nls.
|
|
167
|
+
markdownDescription: nls.localize('theia/core/http/proxyAuthorization', 'The value to send as the `Proxy-Authorization` header for every network request.'),
|
|
168
168
|
scope: PreferenceScope.User
|
|
169
169
|
},
|
|
170
170
|
'http.proxySupport': {
|
|
@@ -177,13 +177,13 @@ export const corePreferenceSchema: PreferenceSchema = {
|
|
|
177
177
|
nls.localizeByDefault('Enable proxy support for extensions, override request options.'),
|
|
178
178
|
],
|
|
179
179
|
default: 'override',
|
|
180
|
-
description: nls.
|
|
180
|
+
description: nls.localize('theia/core/http/proxySupport', 'Use the proxy support for extensions.'),
|
|
181
181
|
scope: PreferenceScope.User
|
|
182
182
|
},
|
|
183
183
|
'http.systemCertificates': {
|
|
184
184
|
type: 'boolean',
|
|
185
185
|
default: true,
|
|
186
|
-
description: nls.
|
|
186
|
+
description: nls.localize('theia/core/http/systemCertificates', 'Controls whether CA certificates should be loaded from the OS. On Windows and macOS, a reload of the window is required after turning this off.'),
|
|
187
187
|
scope: PreferenceScope.User
|
|
188
188
|
},
|
|
189
189
|
'workbench.list.openMode': {
|
|
@@ -57,6 +57,7 @@ import { bindNodeStopwatch, bindBackendStopwatchServer } from './performance';
|
|
|
57
57
|
import { OSBackendProviderImpl } from './os-backend-provider';
|
|
58
58
|
import { BackendRequestFacade, BackendRequestAllowedContribution } from './request/backend-request-facade';
|
|
59
59
|
import { FileSystemLocking, FileSystemLockingImpl } from './filesystem-locking';
|
|
60
|
+
import { BundledResourceProvider, BundledResourceProviderImpl } from './bundled-resource-provider';
|
|
60
61
|
import { BackendRemoteService } from './remote/backend-remote-service';
|
|
61
62
|
import { RemoteCliContribution } from './remote/remote-cli-contribution';
|
|
62
63
|
import { SettingService, SettingServiceImpl } from './setting-service';
|
|
@@ -164,6 +165,9 @@ export const backendApplicationModule = new ContainerModule(bind => {
|
|
|
164
165
|
|
|
165
166
|
bind(FileSystemLocking).to(FileSystemLockingImpl).inSingletonScope();
|
|
166
167
|
|
|
168
|
+
bind(BundledResourceProviderImpl).toSelf().inSingletonScope();
|
|
169
|
+
bind(BundledResourceProvider).toService(BundledResourceProviderImpl);
|
|
170
|
+
|
|
167
171
|
bind(SettingServiceImpl).toSelf().inSingletonScope();
|
|
168
172
|
bind(SettingService).toService(SettingServiceImpl);
|
|
169
173
|
|