@theia/plugin-ext 1.34.2 → 1.36.0-next.21
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/common/plugin-api-rpc-model.d.ts +18 -1
- package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc-model.js.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +10 -5
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +44 -10
- package/lib/common/plugin-protocol.d.ts.map +1 -1
- package/lib/common/plugin-protocol.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +16 -21
- package/lib/hosted/browser/hosted-plugin.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-deployer-handler.js +1 -1
- package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
- package/lib/hosted/node/plugin-activation-events.d.ts +7 -0
- package/lib/hosted/node/plugin-activation-events.d.ts.map +1 -0
- package/lib/hosted/node/plugin-activation-events.js +96 -0
- package/lib/hosted/node/plugin-activation-events.js.map +1 -0
- package/lib/hosted/node/plugin-host-rpc.js +2 -2
- package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
- package/lib/hosted/node/plugin-manifest-loader.d.ts +2 -1
- package/lib/hosted/node/plugin-manifest-loader.d.ts.map +1 -1
- package/lib/hosted/node/plugin-manifest-loader.js +2 -1
- package/lib/hosted/node/plugin-manifest-loader.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +27 -36
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/main/browser/data-transfer/data-transfer-type-converters.d.ts +9 -0
- package/lib/main/browser/data-transfer/data-transfer-type-converters.d.ts.map +1 -0
- package/lib/main/browser/data-transfer/data-transfer-type-converters.js +65 -0
- package/lib/main/browser/data-transfer/data-transfer-type-converters.js.map +1 -0
- package/lib/main/browser/dialogs/modal-notification.d.ts.map +1 -1
- package/lib/main/browser/dialogs/modal-notification.js +4 -2
- package/lib/main/browser/dialogs/modal-notification.js.map +1 -1
- package/lib/main/browser/languages-main.d.ts +8 -1
- package/lib/main/browser/languages-main.d.ts.map +1 -1
- package/lib/main/browser/languages-main.js +26 -2
- package/lib/main/browser/languages-main.js.map +1 -1
- package/lib/main/browser/main-file-system-event-service.d.ts.map +1 -1
- package/lib/main/browser/main-file-system-event-service.js +6 -9
- package/lib/main/browser/main-file-system-event-service.js.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.js +4 -1
- package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.js +3 -0
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/text-editors-main.d.ts +2 -2
- package/lib/main/browser/text-editors-main.d.ts.map +1 -1
- package/lib/main/browser/text-editors-main.js +2 -2
- package/lib/main/browser/text-editors-main.js.map +1 -1
- package/lib/main/browser/webview/webview-context-keys.d.ts +13 -0
- package/lib/main/browser/webview/webview-context-keys.d.ts.map +1 -0
- package/lib/main/browser/webview/webview-context-keys.js +64 -0
- package/lib/main/browser/webview/webview-context-keys.js.map +1 -0
- package/lib/main/node/handlers/plugin-theia-directory-handler.js +1 -1
- package/lib/main/node/handlers/plugin-theia-directory-handler.js.map +1 -1
- package/lib/plugin/dialogs.js +2 -2
- package/lib/plugin/dialogs.js.map +1 -1
- package/lib/plugin/file-system-ext-impl.d.ts +11 -5
- package/lib/plugin/file-system-ext-impl.d.ts.map +1 -1
- package/lib/plugin/file-system-ext-impl.js +8 -16
- package/lib/plugin/file-system-ext-impl.js.map +1 -1
- package/lib/plugin/known-commands.d.ts.map +1 -1
- package/lib/plugin/known-commands.js +13 -0
- package/lib/plugin/known-commands.js.map +1 -1
- package/lib/plugin/languages/document-drop-edit.d.ts +16 -0
- package/lib/plugin/languages/document-drop-edit.d.ts.map +1 -0
- package/lib/plugin/languages/document-drop-edit.js +23 -0
- package/lib/plugin/languages/document-drop-edit.js.map +1 -0
- package/lib/plugin/languages.d.ts +9 -2
- package/lib/plugin/languages.d.ts.map +1 -1
- package/lib/plugin/languages.js +27 -1
- package/lib/plugin/languages.js.map +1 -1
- package/lib/plugin/plugin-context.d.ts +2 -1
- package/lib/plugin/plugin-context.d.ts.map +1 -1
- package/lib/plugin/plugin-context.js +16 -6
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/preference-registry.d.ts +5 -3
- package/lib/plugin/preference-registry.d.ts.map +1 -1
- package/lib/plugin/preference-registry.js +31 -42
- package/lib/plugin/preference-registry.js.map +1 -1
- package/lib/plugin/preference-registry.spec.js +29 -41
- package/lib/plugin/preference-registry.spec.js.map +1 -1
- package/lib/plugin/text-editors.d.ts +1 -1
- package/lib/plugin/text-editors.d.ts.map +1 -1
- package/lib/plugin/text-editors.js +2 -2
- package/lib/plugin/text-editors.js.map +1 -1
- package/lib/plugin/type-converters.d.ts +6 -0
- package/lib/plugin/type-converters.d.ts.map +1 -1
- package/lib/plugin/type-converters.js +37 -1
- package/lib/plugin/type-converters.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +6 -1
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js +16 -3
- package/lib/plugin/types-impl.js.map +1 -1
- package/lib/plugin/webview-views.js +2 -2
- package/lib/plugin/webview-views.js.map +1 -1
- package/package.json +27 -27
- package/src/common/plugin-api-rpc-model.ts +22 -1
- package/src/common/plugin-api-rpc.ts +18 -5
- package/src/common/plugin-protocol.ts +47 -14
- package/src/hosted/browser/hosted-plugin.ts +15 -20
- package/src/hosted/node/hosted-plugin-deployer-handler.ts +1 -1
- package/src/hosted/node/hosted-plugin-process.ts +2 -2
- package/src/hosted/node/plugin-activation-events.ts +111 -0
- package/src/hosted/node/plugin-host-rpc.ts +2 -2
- package/src/hosted/node/plugin-manifest-loader.ts +4 -3
- package/src/hosted/node/scanners/scanner-theia.ts +59 -75
- package/src/main/browser/data-transfer/data-transfer-type-converters.ts +70 -0
- package/src/main/browser/dialogs/modal-notification.ts +4 -2
- package/src/main/browser/languages-main.ts +34 -4
- package/src/main/browser/main-file-system-event-service.ts +6 -9
- package/src/main/browser/plugin-contribution-handler.ts +6 -3
- package/src/main/browser/plugin-ext-frontend-module.ts +3 -0
- package/src/main/browser/text-editors-main.ts +3 -2
- package/src/main/browser/webview/webview-context-keys.ts +49 -0
- package/src/main/node/handlers/plugin-theia-directory-handler.ts +1 -1
- package/src/plugin/dialogs.ts +2 -2
- package/src/plugin/file-system-ext-impl.ts +8 -18
- package/src/plugin/known-commands.ts +16 -1
- package/src/plugin/languages/document-drop-edit.ts +44 -0
- package/src/plugin/languages.ts +41 -3
- package/src/plugin/plugin-context.ts +18 -6
- package/src/plugin/preference-registry.spec.ts +29 -45
- package/src/plugin/preference-registry.ts +33 -45
- package/src/plugin/text-editors.ts +2 -2
- package/src/plugin/type-converters.ts +37 -0
- package/src/plugin/types-impl.ts +15 -1
- package/src/plugin/webview-views.ts +2 -2
|
@@ -87,6 +87,7 @@ import {
|
|
|
87
87
|
DocumentHighlightKind,
|
|
88
88
|
DocumentHighlight,
|
|
89
89
|
DocumentLink,
|
|
90
|
+
DocumentDropEdit,
|
|
90
91
|
CodeLens,
|
|
91
92
|
CodeActionKind,
|
|
92
93
|
CodeActionTrigger,
|
|
@@ -257,11 +258,11 @@ export function createAPIFactory(
|
|
|
257
258
|
const statusBarMessageRegistryExt = new StatusBarMessageRegistryExt(rpc);
|
|
258
259
|
const terminalExt = rpc.set(MAIN_RPC_CONTEXT.TERMINAL_EXT, new TerminalServiceExtImpl(rpc));
|
|
259
260
|
const outputChannelRegistryExt = rpc.set(MAIN_RPC_CONTEXT.OUTPUT_CHANNEL_REGISTRY_EXT, new OutputChannelRegistryExtImpl(rpc));
|
|
260
|
-
const languagesExt = rpc.set(MAIN_RPC_CONTEXT.LANGUAGES_EXT, new LanguagesExtImpl(rpc, documents, commandRegistry));
|
|
261
261
|
const treeViewsExt = rpc.set(MAIN_RPC_CONTEXT.TREE_VIEWS_EXT, new TreeViewsExtImpl(rpc, commandRegistry));
|
|
262
262
|
const tasksExt = rpc.set(MAIN_RPC_CONTEXT.TASKS_EXT, new TasksExtImpl(rpc, terminalExt));
|
|
263
263
|
const connectionExt = rpc.set(MAIN_RPC_CONTEXT.CONNECTION_EXT, new ConnectionImpl(rpc.getProxy(PLUGIN_RPC_CONTEXT.CONNECTION_MAIN)));
|
|
264
|
-
const fileSystemExt = rpc.set(MAIN_RPC_CONTEXT.FILE_SYSTEM_EXT, new FileSystemExtImpl(rpc
|
|
264
|
+
const fileSystemExt = rpc.set(MAIN_RPC_CONTEXT.FILE_SYSTEM_EXT, new FileSystemExtImpl(rpc));
|
|
265
|
+
const languagesExt = rpc.set(MAIN_RPC_CONTEXT.LANGUAGES_EXT, new LanguagesExtImpl(rpc, documents, commandRegistry, fileSystemExt));
|
|
265
266
|
const extHostFileSystemEvent = rpc.set(MAIN_RPC_CONTEXT.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpc, editorsAndDocumentsExt));
|
|
266
267
|
const scmExt = rpc.set(MAIN_RPC_CONTEXT.SCM_EXT, new ScmExtImpl(rpc, commandRegistry));
|
|
267
268
|
const decorationsExt = rpc.set(MAIN_RPC_CONTEXT.DECORATIONS_EXT, new DecorationsExtImpl(rpc));
|
|
@@ -669,8 +670,8 @@ export function createAPIFactory(
|
|
|
669
670
|
saveAll(includeUntitled?: boolean): PromiseLike<boolean> {
|
|
670
671
|
return editors.saveAll(includeUntitled);
|
|
671
672
|
},
|
|
672
|
-
applyEdit(edit: theia.WorkspaceEdit): PromiseLike<boolean> {
|
|
673
|
-
return editors.applyWorkspaceEdit(edit);
|
|
673
|
+
applyEdit(edit: theia.WorkspaceEdit, metadata?: theia.WorkspaceEditMetadata): PromiseLike<boolean> {
|
|
674
|
+
return editors.applyWorkspaceEdit(edit, metadata);
|
|
674
675
|
},
|
|
675
676
|
registerTextDocumentContentProvider(scheme: string, provider: theia.TextDocumentContentProvider): theia.Disposable {
|
|
676
677
|
return workspaceExt.registerTextDocumentContentProvider(scheme, provider);
|
|
@@ -752,7 +753,8 @@ export function createAPIFactory(
|
|
|
752
753
|
|
|
753
754
|
const extensions: typeof theia.extensions = Object.freeze({
|
|
754
755
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
755
|
-
getExtension<T = any>(extensionId: string): theia.Extension<T> | undefined {
|
|
756
|
+
getExtension<T = any>(extensionId: string, includeFromDifferentExtensionHosts: boolean = false): theia.Extension<T> | undefined {
|
|
757
|
+
includeFromDifferentExtensionHosts = false;
|
|
756
758
|
const plg = pluginManager.getPluginById(extensionId.toLowerCase());
|
|
757
759
|
if (plg) {
|
|
758
760
|
return new PluginExt(pluginManager, plg);
|
|
@@ -763,6 +765,10 @@ export function createAPIFactory(
|
|
|
763
765
|
get all(): readonly theia.Extension<any>[] {
|
|
764
766
|
return pluginManager.getAllPlugins().map(plg => new PluginExt(pluginManager, plg));
|
|
765
767
|
},
|
|
768
|
+
get allAcrossExtensionHosts(): readonly theia.Extension<any>[] {
|
|
769
|
+
// we only support one extension host ATM so equivalent to calling "all()"
|
|
770
|
+
return this.all;
|
|
771
|
+
},
|
|
766
772
|
get onDidChange(): theia.Event<void> {
|
|
767
773
|
return pluginManager.onDidChange;
|
|
768
774
|
}
|
|
@@ -853,6 +859,9 @@ export function createAPIFactory(
|
|
|
853
859
|
): theia.Disposable {
|
|
854
860
|
return languagesExt.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters), pluginToPluginInfo(plugin));
|
|
855
861
|
},
|
|
862
|
+
registerDocumentDropEditProvider(selector: theia.DocumentSelector, provider: theia.DocumentDropEditProvider) {
|
|
863
|
+
return languagesExt.registerDocumentDropEditProvider(selector, provider);
|
|
864
|
+
},
|
|
856
865
|
registerDocumentLinkProvider(selector: theia.DocumentSelector, provider: theia.DocumentLinkProvider): theia.Disposable {
|
|
857
866
|
return languagesExt.registerDocumentLinkProvider(selector, provider, pluginToPluginInfo(plugin));
|
|
858
867
|
},
|
|
@@ -1195,6 +1204,7 @@ export function createAPIFactory(
|
|
|
1195
1204
|
DocumentHighlightKind,
|
|
1196
1205
|
DocumentHighlight,
|
|
1197
1206
|
DocumentLink,
|
|
1207
|
+
DocumentDropEdit,
|
|
1198
1208
|
CodeLens,
|
|
1199
1209
|
CodeActionKind,
|
|
1200
1210
|
CodeActionTrigger,
|
|
@@ -1364,13 +1374,15 @@ export class PluginExt<T> extends Plugin<T> implements ExtensionPlugin<T> {
|
|
|
1364
1374
|
extensionPath: string;
|
|
1365
1375
|
extensionUri: theia.Uri;
|
|
1366
1376
|
extensionKind: ExtensionKind;
|
|
1377
|
+
isFromDifferentExtensionHost: boolean;
|
|
1367
1378
|
|
|
1368
|
-
constructor(protected override readonly pluginManager: PluginManager, plugin: InternalPlugin) {
|
|
1379
|
+
constructor(protected override readonly pluginManager: PluginManager, plugin: InternalPlugin, isFromDifferentExtensionHost = false) {
|
|
1369
1380
|
super(pluginManager, plugin);
|
|
1370
1381
|
|
|
1371
1382
|
this.extensionPath = this.pluginPath;
|
|
1372
1383
|
this.extensionUri = this.pluginUri;
|
|
1373
1384
|
this.extensionKind = ExtensionKind.UI; // stub as a local extension (not running on a remote workspace)
|
|
1385
|
+
this.isFromDifferentExtensionHost = isFromDifferentExtensionHost;
|
|
1374
1386
|
}
|
|
1375
1387
|
|
|
1376
1388
|
override get isActive(): boolean {
|
|
@@ -41,36 +41,6 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
41
41
|
preferenceRegistryExtImpl = new PreferenceRegistryExtImpl(mockRPC, mockWorkspace);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
it('should parse configuration data without overrides', () => {
|
|
45
|
-
const value: Record<string, any> = {
|
|
46
|
-
'my.key1.foo': 'value1',
|
|
47
|
-
'my.key1.bar': 'value2',
|
|
48
|
-
};
|
|
49
|
-
const result = preferenceRegistryExtImpl['parseConfigurationData'](value);
|
|
50
|
-
expect(result.contents.my).to.be.an('object');
|
|
51
|
-
expect(result.contents.my.key1).to.be.an('object');
|
|
52
|
-
|
|
53
|
-
expect(result.contents.my.key1.foo).to.be.an('string');
|
|
54
|
-
expect(result.contents.my.key1.foo).to.equal('value1');
|
|
55
|
-
|
|
56
|
-
expect(result.contents.my.key1.bar).to.be.an('string');
|
|
57
|
-
expect(result.contents.my.key1.bar).to.equal('value2');
|
|
58
|
-
expect(result.keys).deep.equal(['my.key1.foo', 'my.key1.bar']);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should parse configuration with overrides', () => {
|
|
62
|
-
const value: Record<string, any> = {
|
|
63
|
-
'editor.tabSize': 2,
|
|
64
|
-
'[typescript].editor.tabSize': 4,
|
|
65
|
-
};
|
|
66
|
-
const result = preferenceRegistryExtImpl['parseConfigurationData'](value);
|
|
67
|
-
expect(result.contents.editor.tabSize).to.equal(2);
|
|
68
|
-
const tsOverride = result.overrides[0];
|
|
69
|
-
expect(tsOverride.contents.editor.tabSize).to.equal(4);
|
|
70
|
-
expect(tsOverride.identifiers).deep.equal(['typescript']);
|
|
71
|
-
expect(tsOverride.keys).deep.equal(['editor.tabSize']);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
44
|
describe('Prototype pollution', () => {
|
|
75
45
|
it('Ignores key `__proto__`', () => {
|
|
76
46
|
const value: Record<string, any> = {
|
|
@@ -80,16 +50,18 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
80
50
|
'__proto__': {},
|
|
81
51
|
'[typescript].someKey.foo': 'value',
|
|
82
52
|
'[typescript].__proto__.injectedParsedPrototype': true,
|
|
53
|
+
'b': { '__proto__.injectedParsedPrototype': true },
|
|
54
|
+
'c': { '__proto__': { 'injectedParsedPrototype': true } }
|
|
83
55
|
};
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
expect(result.
|
|
87
|
-
expect(result.
|
|
88
|
-
expect(result.
|
|
56
|
+
const configuration = preferenceRegistryExtImpl['getConfigurationModel']('test', value);
|
|
57
|
+
const result = configuration['_contents'];
|
|
58
|
+
expect(result.my, 'Safe keys are preserved.').to.be.an('object');
|
|
59
|
+
expect(result.__proto__, 'Keys containing __proto__ are ignored').to.be.an('undefined');
|
|
60
|
+
expect(result.my.key1.foo, 'Safe keys are dendrified.').to.equal('value1');
|
|
89
61
|
const prototypeObject = Object.prototype as any;
|
|
90
|
-
expect(prototypeObject.injectedParsedPrototype).to.be.an('undefined');
|
|
62
|
+
expect(prototypeObject.injectedParsedPrototype, 'Object.prototype is unaffected').to.be.an('undefined');
|
|
91
63
|
const rawObject = {} as any;
|
|
92
|
-
expect(rawObject.injectedParsedPrototype).to.be.an('undefined');
|
|
64
|
+
expect(rawObject.injectedParsedPrototype, 'Instantiated objects are unaffected.').to.be.an('undefined');
|
|
93
65
|
});
|
|
94
66
|
|
|
95
67
|
it('Ignores key `constructor.prototype`', () => {
|
|
@@ -98,17 +70,19 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
98
70
|
'a.constructor.prototype.injectedParsedConstructorPrototype': true,
|
|
99
71
|
'constructor.prototype.injectedParsedConstructorPrototype': true,
|
|
100
72
|
'[python].some.key.foo': 'value',
|
|
101
|
-
'[python].a.constructor.prototype.injectedParsedConstructorPrototype': true
|
|
73
|
+
'[python].a.constructor.prototype.injectedParsedConstructorPrototype': true,
|
|
74
|
+
'constructor': { 'prototype.injectedParsedConstructorPrototype': true },
|
|
75
|
+
'b': { 'constructor': { 'prototype': { 'injectedParsedConstructorPrototype': true } } }
|
|
102
76
|
};
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
expect(result.
|
|
106
|
-
expect(result.
|
|
77
|
+
const configuration = preferenceRegistryExtImpl['getConfigurationModel']('test', value);
|
|
78
|
+
const result = configuration['_contents'];
|
|
79
|
+
expect(result.my, 'Safe keys are preserved').to.be.an('object');
|
|
80
|
+
expect(result.__proto__, 'Keys containing __proto__ are ignored').to.be.an('undefined');
|
|
81
|
+
expect(result.my.key1.foo, 'Safe keys are dendrified.').to.equal('value1');
|
|
107
82
|
const prototypeObject = Object.prototype as any;
|
|
108
|
-
expect(prototypeObject.injectedParsedConstructorPrototype).to.be.an('undefined');
|
|
109
|
-
expect(result.overrides[0].contents.__proto__).to.be.an('undefined');
|
|
83
|
+
expect(prototypeObject.injectedParsedConstructorPrototype, 'Object.prototype is unaffected').to.be.an('undefined');
|
|
110
84
|
const rawObject = {} as any;
|
|
111
|
-
expect(rawObject.injectedParsedConstructorPrototype).to.be.an('undefined');
|
|
85
|
+
expect(rawObject.injectedParsedConstructorPrototype, 'Instantiated objects are unaffected.').to.be.an('undefined');
|
|
112
86
|
});
|
|
113
87
|
});
|
|
114
88
|
|
|
@@ -250,6 +224,16 @@ describe('PreferenceRegistryExtImpl:', () => {
|
|
|
250
224
|
const valuesRetrieved = preferenceRegistryExtImpl.getConfiguration(undefined, { uri: workspaceRoot, languageId: 'python' }).get('editor') as Record<string, unknown>;
|
|
251
225
|
expect(valuesRetrieved.tabSize).equal(4);
|
|
252
226
|
});
|
|
227
|
+
it('Allows access to language overrides in bracket form', () => {
|
|
228
|
+
const pythonOverrides = preferenceRegistryExtImpl.getConfiguration().get<Record<string, any>>('[python]');
|
|
229
|
+
expect(pythonOverrides).not.to.be.undefined;
|
|
230
|
+
expect(pythonOverrides?.['editor.renderWhitespace']).equal('all');
|
|
231
|
+
});
|
|
232
|
+
// https://github.com/eclipse-theia/theia/issues/12043
|
|
233
|
+
it('Allows access to preferences without specifying the section', () => {
|
|
234
|
+
const inspection = preferenceRegistryExtImpl.getConfiguration().inspect('editor.fontSize');
|
|
235
|
+
expect(inspection?.defaultValue).equal(14);
|
|
236
|
+
});
|
|
253
237
|
});
|
|
254
238
|
|
|
255
239
|
describe('Proxy Behavior', () => {
|
|
@@ -20,8 +20,8 @@ import { Emitter, Event } from '@theia/core/lib/common/event';
|
|
|
20
20
|
import { isOSX, isWindows } from '@theia/core/lib/common/os';
|
|
21
21
|
import { URI } from '@theia/core/shared/vscode-uri';
|
|
22
22
|
import { ResourceMap } from '@theia/monaco-editor-core/esm/vs/base/common/map';
|
|
23
|
-
import { IConfigurationOverrides
|
|
24
|
-
import { Configuration, ConfigurationModel } from '@theia/monaco-editor-core/esm/vs/platform/configuration/common/configurationModels';
|
|
23
|
+
import { IConfigurationOverrides } from '@theia/monaco-editor-core/esm/vs/platform/configuration/common/configuration';
|
|
24
|
+
import { Configuration, ConfigurationModel, ConfigurationModelParser } from '@theia/monaco-editor-core/esm/vs/platform/configuration/common/configurationModels';
|
|
25
25
|
import { Workspace, WorkspaceFolder } from '@theia/monaco-editor-core/esm/vs/platform/workspace/common/workspace';
|
|
26
26
|
import * as theia from '@theia/plugin';
|
|
27
27
|
import { v4 } from 'uuid';
|
|
@@ -234,12 +234,12 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
private parse(data: PreferenceData): Configuration {
|
|
237
|
-
const defaultConfiguration = this.getConfigurationModel(data[PreferenceScope.Default]);
|
|
238
|
-
const userConfiguration = this.getConfigurationModel(data[PreferenceScope.User]);
|
|
239
|
-
const workspaceConfiguration = this.getConfigurationModel(data[PreferenceScope.Workspace]);
|
|
237
|
+
const defaultConfiguration = this.getConfigurationModel('Default', data[PreferenceScope.Default]);
|
|
238
|
+
const userConfiguration = this.getConfigurationModel('User', data[PreferenceScope.User]);
|
|
239
|
+
const workspaceConfiguration = this.getConfigurationModel('Workspace', data[PreferenceScope.Workspace]);
|
|
240
240
|
const folderConfigurations = new ResourceMap<ConfigurationModel>();
|
|
241
241
|
Object.keys(data[PreferenceScope.Folder]).forEach(resource => {
|
|
242
|
-
folderConfigurations.set(URI.parse(resource), this.getConfigurationModel(data[PreferenceScope.Folder][resource]));
|
|
242
|
+
folderConfigurations.set(URI.parse(resource), this.getConfigurationModel(`Folder: ${resource}`, data[PreferenceScope.Folder][resource]));
|
|
243
243
|
});
|
|
244
244
|
return new Configuration(
|
|
245
245
|
defaultConfiguration,
|
|
@@ -252,53 +252,41 @@ export class PreferenceRegistryExtImpl implements PreferenceRegistryExt {
|
|
|
252
252
|
);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
private getConfigurationModel(data: { [key: string]: any }): ConfigurationModel {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return new ConfigurationModel(configData.contents, configData.keys, configData.overrides);
|
|
255
|
+
private getConfigurationModel(label: string, data: { [key: string]: any }): ConfigurationModel {
|
|
256
|
+
const parser = new ConfigurationModelParser(label);
|
|
257
|
+
const sanitized = this.sanitize(data);
|
|
258
|
+
parser.parseRaw(sanitized);
|
|
259
|
+
return parser.configurationModel;
|
|
261
260
|
}
|
|
262
261
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
private
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
for (let i = 0; i < parts.length; i++) {
|
|
281
|
-
if (i === 0 && isOverride) {
|
|
282
|
-
const identifier = this.OVERRIDE_PROPERTY_PATTERN.exec(parts[i])![1];
|
|
283
|
-
if (!overrides[identifier]) {
|
|
284
|
-
overrides[identifier] = { keys: [], identifiers: [identifier], contents: Object.create(null) };
|
|
262
|
+
/**
|
|
263
|
+
* Creates a new object and assigns those keys of raw to it that are not likely to cause prototype polution.
|
|
264
|
+
* Also preprocesses override identifiers so that they take the form [identifier]: {...contents}.
|
|
265
|
+
*/
|
|
266
|
+
private sanitize<T = unknown>(raw: T): T {
|
|
267
|
+
if (!isObject(raw)) { return raw; }
|
|
268
|
+
const asObject = raw as Record<string, unknown>;
|
|
269
|
+
const sanitized = Object.create(null);
|
|
270
|
+
for (const key of Object.keys(asObject)) {
|
|
271
|
+
if (!injectionRe.test(key)) {
|
|
272
|
+
const override = this.OVERRIDE_KEY_TEST.exec(key);
|
|
273
|
+
if (override) {
|
|
274
|
+
const overrideKey = `[${override[1]}]`;
|
|
275
|
+
const remainder = key.slice(override[0].length);
|
|
276
|
+
if (!isObject(sanitized[overrideKey])) {
|
|
277
|
+
sanitized[overrideKey] = Object.create(null);
|
|
285
278
|
}
|
|
286
|
-
|
|
287
|
-
overrides[identifier].keys.push(key.slice(parts[i].length + 1));
|
|
288
|
-
} else if (i === parts.length - 1) {
|
|
289
|
-
branch[parts[i]] = data[key];
|
|
279
|
+
sanitized[overrideKey][remainder] = this.sanitize(asObject[key]);
|
|
290
280
|
} else {
|
|
291
|
-
|
|
292
|
-
branch[parts[i]] = Object.create(null);
|
|
293
|
-
}
|
|
294
|
-
branch = branch[parts[i]];
|
|
281
|
+
sanitized[key] = this.sanitize(asObject[key]);
|
|
295
282
|
}
|
|
296
283
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
return { contents, keys, overrides: Object.values(overrides) };
|
|
284
|
+
}
|
|
285
|
+
return sanitized;
|
|
300
286
|
}
|
|
301
287
|
|
|
288
|
+
private readonly OVERRIDE_KEY_TEST = /^\[([^\]]+)\]\./;
|
|
289
|
+
|
|
302
290
|
private toConfigurationChangeEvent(eventData: PreferenceChangeExt[]): theia.ConfigurationChangeEvent {
|
|
303
291
|
return Object.freeze({
|
|
304
292
|
affectsConfiguration: (section: string, scope?: theia.ConfigurationScope): boolean => {
|
|
@@ -119,9 +119,9 @@ export class TextEditorsExtImpl implements TextEditorsExt {
|
|
|
119
119
|
return new TextEditorDecorationType(this.proxy, options);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
applyWorkspaceEdit(edit: theia.WorkspaceEdit): Promise<boolean> {
|
|
122
|
+
applyWorkspaceEdit(edit: theia.WorkspaceEdit, metadata?: theia.WorkspaceEditMetadata): Promise<boolean> {
|
|
123
123
|
const dto = Converters.fromWorkspaceEdit(edit, this.editorsAndDocuments);
|
|
124
|
-
return this.proxy.$tryApplyWorkspaceEdit(dto);
|
|
124
|
+
return this.proxy.$tryApplyWorkspaceEdit(dto, metadata);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
saveAll(includeUntitled?: boolean): PromiseLike<boolean> {
|
|
@@ -1348,3 +1348,40 @@ export namespace InlayHintKind {
|
|
|
1348
1348
|
return kind;
|
|
1349
1349
|
}
|
|
1350
1350
|
}
|
|
1351
|
+
|
|
1352
|
+
export namespace DataTransferItem {
|
|
1353
|
+
export function to(mime: string, item: model.DataTransferItemDTO, resolveFileData: (itemId: string) => Promise<Uint8Array>): theia.DataTransferItem {
|
|
1354
|
+
const file = item.fileData;
|
|
1355
|
+
if (file) {
|
|
1356
|
+
return new class extends types.DataTransferItem {
|
|
1357
|
+
override asFile(): theia.DataTransferFile {
|
|
1358
|
+
return {
|
|
1359
|
+
name: file.name,
|
|
1360
|
+
uri: URI.revive(file.uri),
|
|
1361
|
+
data: () => resolveFileData(item.id),
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
}('');
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
if (mime === 'text/uri-list' && item.uriListData) {
|
|
1368
|
+
return new types.DataTransferItem(reviveUriList(item.uriListData));
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
return new types.DataTransferItem(item.asString);
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
function reviveUriList(parts: ReadonlyArray<string | UriComponents>): string {
|
|
1375
|
+
return parts.map(part => typeof part === 'string' ? part : URI.revive(part).toString()).join('\r\n');
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
export namespace DataTransfer {
|
|
1380
|
+
export function toDataTransfer(value: model.DataTransferDTO, resolveFileData: (itemId: string) => Promise<Uint8Array>): theia.DataTransfer {
|
|
1381
|
+
const dataTransfer = new types.DataTransfer();
|
|
1382
|
+
for (const [mimeType, item] of value.items) {
|
|
1383
|
+
dataTransfer.set(mimeType, DataTransferItem.to(mimeType, item, resolveFileData));
|
|
1384
|
+
}
|
|
1385
|
+
return dataTransfer;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
package/src/plugin/types-impl.ts
CHANGED
|
@@ -404,10 +404,13 @@ export class Position {
|
|
|
404
404
|
return result!;
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
-
static isPosition(other:
|
|
407
|
+
static isPosition(other: unknown): other is Position {
|
|
408
408
|
if (!other) {
|
|
409
409
|
return false;
|
|
410
410
|
}
|
|
411
|
+
if (typeof other !== 'object' || Array.isArray(other)) {
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
411
414
|
if (other instanceof Position) {
|
|
412
415
|
return true;
|
|
413
416
|
}
|
|
@@ -1530,6 +1533,17 @@ export class DocumentLink {
|
|
|
1530
1533
|
}
|
|
1531
1534
|
}
|
|
1532
1535
|
|
|
1536
|
+
@es5ClassCompat
|
|
1537
|
+
export class DocumentDropEdit {
|
|
1538
|
+
insertText: string | SnippetString;
|
|
1539
|
+
|
|
1540
|
+
additionalEdit?: WorkspaceEdit;
|
|
1541
|
+
|
|
1542
|
+
constructor(insertText: string | SnippetString) {
|
|
1543
|
+
this.insertText = insertText;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1533
1547
|
@es5ClassCompat
|
|
1534
1548
|
export class CodeLens {
|
|
1535
1549
|
|
|
@@ -167,8 +167,8 @@ export class WebviewViewExtImpl implements theia.WebviewView {
|
|
|
167
167
|
|
|
168
168
|
set title(value: string | undefined) {
|
|
169
169
|
this.assertNotDisposed();
|
|
170
|
-
if (this.
|
|
171
|
-
this.
|
|
170
|
+
if (this._title !== value) {
|
|
171
|
+
this._title = value;
|
|
172
172
|
this.proxy.$setWebviewViewTitle(this.handle, value);
|
|
173
173
|
}
|
|
174
174
|
}
|