Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
IncompleteCompletionsCache,
IndentStyle,
isArray,
isExternalModuleNameRelative,
isIgnoredFileFromWildCardWatching,
isInsideNodeModules,
isJsonEqual,
Expand All @@ -89,7 +90,6 @@ import {
ParsedCommandLine,
parseJsonSourceFileConfigFileContent,
parseJsonText,
parsePackageName,
Path,
PerformanceEvent,
PluginImport,
Expand Down Expand Up @@ -4487,7 +4487,11 @@ export class ProjectService {
}

this.logger.info(`Enabling plugin ${pluginConfigEntry.name} from candidate paths: ${searchPaths.join(",")}`);
if (!pluginConfigEntry.name || parsePackageName(pluginConfigEntry.name).rest) {
if (
!pluginConfigEntry.name ||
isExternalModuleNameRelative(pluginConfigEntry.name) ||
/[\\/]\.\.?($|[\\/])/.test(pluginConfigEntry.name)
) {
this.logger.info(`Skipped loading plugin ${pluginConfigEntry.name || JSON.stringify(pluginConfigEntry)} because only package name is allowed plugin name`);
return;
}
Expand Down
32 changes: 28 additions & 4 deletions src/testRunner/unittests/tsserver/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,20 @@ describe("unittests:: tsserver:: plugins:: loading", () => {
}

it("With local plugins", () => {
const expectedToLoad = ["@myscoped/plugin", "unscopedPlugin"];
const notToLoad = ["../myPlugin", "myPlugin/../malicious"];
const expectedToLoad = [
"@myscoped/plugin",
"@myscoped/plugin/subpath",
"@myscoped/plugin/sub/path",
"unscopedPlugin",
"unscopedPlugin/subpath",
"unscopedPlugin/sub/path",
];
const notToLoad = [
"../myPlugin",
"@myscoped/plugin/../malicious",
"myPlugin/../malicious",
"myPlugin/subpath/../../malicious",
];
const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` };
const tsconfig: File = {
path: "/tsconfig.json",
Expand All @@ -65,8 +77,20 @@ describe("unittests:: tsserver:: plugins:: loading", () => {
});

it("With global plugins", () => {
const expectedToLoad = ["@myscoped/plugin", "unscopedPlugin"];
const notToLoad = ["../myPlugin", "myPlugin/../malicious"];
const expectedToLoad = [
"@myscoped/plugin",
"@myscoped/plugin/subpath",
"@myscoped/plugin/sub/path",
"unscopedPlugin",
"unscopedPlugin/subpath",
"unscopedPlugin/sub/path",
];
const notToLoad = [
"../myPlugin",
"@myscoped/plugin/../malicious",
"myPlugin/../malicious",
"myPlugin/subpath/../../malicious",
];
const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` };
const tsconfig: File = {
path: "/tsconfig.json",
Expand Down
26 changes: 26 additions & 0 deletions tests/baselines/reference/tsserver/plugins/With-global-plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,43 @@ Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin from candidate paths:
Info seq [hh:mm:ss:mss] Loading @myscoped/plugin from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: @myscoped/plugin
Info seq [hh:mm:ss:mss] Plugin validation succeeded
Info seq [hh:mm:ss:mss] Loading global plugin @myscoped/plugin/subpath
Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin/subpath from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading @myscoped/plugin/subpath from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: @myscoped/plugin/subpath
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Loading global plugin @myscoped/plugin/sub/path
Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin/sub/path from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading @myscoped/plugin/sub/path from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: @myscoped/plugin/sub/path
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Loading global plugin unscopedPlugin
Info seq [hh:mm:ss:mss] Enabling plugin unscopedPlugin from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading unscopedPlugin from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: unscopedPlugin
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Loading global plugin unscopedPlugin/subpath
Info seq [hh:mm:ss:mss] Enabling plugin unscopedPlugin/subpath from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading unscopedPlugin/subpath from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: unscopedPlugin/subpath
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Loading global plugin unscopedPlugin/sub/path
Info seq [hh:mm:ss:mss] Enabling plugin unscopedPlugin/sub/path from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading unscopedPlugin/sub/path from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: unscopedPlugin/sub/path
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Loading global plugin ../myPlugin
Info seq [hh:mm:ss:mss] Enabling plugin ../myPlugin from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin ../myPlugin because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Loading global plugin @myscoped/plugin/../malicious
Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin/../malicious from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin @myscoped/plugin/../malicious because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Loading global plugin myPlugin/../malicious
Info seq [hh:mm:ss:mss] Enabling plugin myPlugin/../malicious from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin myPlugin/../malicious because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Loading global plugin myPlugin/subpath/../../malicious
Info seq [hh:mm:ss:mss] Enabling plugin myPlugin/subpath/../../malicious from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin myPlugin/subpath/../../malicious because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /tsconfig.json
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /tsconfig.json Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Expand Down
62 changes: 62 additions & 0 deletions tests/baselines/reference/tsserver/plugins/With-local-plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,33 @@ class c { prop = "hello"; foo() { return this.prop; } }
{
"name": "@myscoped/plugin"
},
{
"name": "@myscoped/plugin/subpath"
},
{
"name": "@myscoped/plugin/sub/path"
},
{
"name": "unscopedPlugin"
},
{
"name": "unscopedPlugin/subpath"
},
{
"name": "unscopedPlugin/sub/path"
},
{
"name": "../myPlugin"
},
{
"name": "@myscoped/plugin/../malicious"
},
{
"name": "myPlugin/../malicious"
},
{
"name": "myPlugin/subpath/../../malicious"
},
{
"transform": "some-transform"
}
Expand Down Expand Up @@ -74,15 +92,33 @@ Info seq [hh:mm:ss:mss] Config: /tsconfig.json : {
{
"name": "@myscoped/plugin"
},
{
"name": "@myscoped/plugin/subpath"
},
{
"name": "@myscoped/plugin/sub/path"
},
{
"name": "unscopedPlugin"
},
{
"name": "unscopedPlugin/subpath"
},
{
"name": "unscopedPlugin/sub/path"
},
{
"name": "../myPlugin"
},
{
"name": "@myscoped/plugin/../malicious"
},
{
"name": "myPlugin/../malicious"
},
{
"name": "myPlugin/subpath/../../malicious"
},
{
"transform": "some-transform"
}
Expand All @@ -96,14 +132,34 @@ Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin from candidate paths:
Info seq [hh:mm:ss:mss] Loading @myscoped/plugin from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: @myscoped/plugin
Info seq [hh:mm:ss:mss] Plugin validation succeeded
Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin/subpath from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading @myscoped/plugin/subpath from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: @myscoped/plugin/subpath
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin/sub/path from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading @myscoped/plugin/sub/path from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: @myscoped/plugin/sub/path
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Enabling plugin unscopedPlugin from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading unscopedPlugin from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: unscopedPlugin
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Enabling plugin unscopedPlugin/subpath from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading unscopedPlugin/subpath from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: unscopedPlugin/subpath
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Enabling plugin unscopedPlugin/sub/path from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Loading unscopedPlugin/sub/path from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules)
Loading plugin: unscopedPlugin/sub/path
Info seq [hh:mm:ss:mss] Plugin activation failed: Error: Protocol handler already exists for command "testProtocolCommand"
Info seq [hh:mm:ss:mss] Enabling plugin ../myPlugin from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin ../myPlugin because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Enabling plugin @myscoped/plugin/../malicious from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin @myscoped/plugin/../malicious because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Enabling plugin myPlugin/../malicious from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin myPlugin/../malicious because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Enabling plugin myPlugin/subpath/../../malicious from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin myPlugin/subpath/../../malicious because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] Enabling plugin undefined from candidate paths: /a/lib/tsc.js/../../..
Info seq [hh:mm:ss:mss] Skipped loading plugin {"transform":"some-transform"} because only package name is allowed plugin name
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info
Expand Down Expand Up @@ -155,6 +211,12 @@ Info seq [hh:mm:ss:mss] event:
},
"compilerOptions": {
"plugins": [
"",
"",
"",
"",
"",
"",
"",
"",
"",
Expand Down