1namespace ts.projectSystem { 2 describe("unittests:: tsserver:: plugins loading", () => { 3 function createHostWithPlugin(files: readonly File[]) { 4 const host = createServerHost(files); 5 const pluginsLoaded: string[] = []; 6 host.require = (_initialPath, moduleName) => { 7 pluginsLoaded.push(moduleName); 8 return { 9 module: () => ({ 10 create(info: server.PluginCreateInfo) { 11 return Harness.LanguageService.makeDefaultProxy(info); 12 } 13 }), 14 error: undefined 15 }; 16 }; 17 return { host, pluginsLoaded }; 18 } 19 20 it("With local plugins", () => { 21 const expectedToLoad = ["@myscoped/plugin", "unscopedPlugin"]; 22 const notToLoad = ["../myPlugin", "myPlugin/../malicious"]; 23 const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; 24 const tsconfig: File = { 25 path: "/tsconfig.json", 26 content: JSON.stringify({ 27 compilerOptions: { 28 plugins: [ 29 ...[...expectedToLoad, ...notToLoad].map(name => ({ name })), 30 { transform: "some-transform" } 31 ] 32 } 33 }) 34 }; 35 const { host, pluginsLoaded } = createHostWithPlugin([aTs, tsconfig, libFile]); 36 const service = createProjectService(host); 37 service.openClientFile(aTs.path); 38 assert.deepEqual(pluginsLoaded, expectedToLoad); 39 }); 40 41 it("With global plugins", () => { 42 const expectedToLoad = ["@myscoped/plugin", "unscopedPlugin"]; 43 const notToLoad = ["../myPlugin", "myPlugin/../malicious"]; 44 const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; 45 const tsconfig: File = { 46 path: "/tsconfig.json", 47 content: "{}" 48 }; 49 const { host, pluginsLoaded } = createHostWithPlugin([aTs, tsconfig, libFile]); 50 const service = createProjectService(host, { globalPlugins: [...expectedToLoad, ...notToLoad] }); 51 service.openClientFile(aTs.path); 52 assert.deepEqual(pluginsLoaded, expectedToLoad); 53 }); 54 }); 55}