Skip to content

Commit c9fadf1

Browse files
committed
Ignore wild card directory watchers with node_modules file or folder starting with .
1 parent d32c1b0 commit c9fadf1

File tree

5 files changed

+92
-27
lines changed

5 files changed

+92
-27
lines changed

src/compiler/watch.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,8 @@ namespace ts {
938938
}
939939
nextSourceFileVersion(fileOrDirectoryPath);
940940

941+
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
942+
941943
// If the the added or created file or directory is not supported file name, ignore the file
942944
// But when watched directory is added/removed, we need to reload the file list
943945
if (fileOrDirectoryPath !== directory && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, compilerOptions)) {

src/harness/virtualFileSystemWithWatch.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,8 @@ interface Array<T> {}`
587587
}
588588
this.invokeFileWatcher(fileOrDirectory.fullPath, FileWatcherEventKind.Created);
589589
if (isFsFolder(fileOrDirectory)) {
590-
this.invokeDirectoryWatcher(fileOrDirectory.fullPath, "");
591-
this.invokeWatchedDirectoriesRecursiveCallback(fileOrDirectory.fullPath, "");
590+
this.invokeDirectoryWatcher(fileOrDirectory.fullPath, fileOrDirectory.fullPath);
591+
this.invokeWatchedDirectoriesRecursiveCallback(fileOrDirectory.fullPath, fileOrDirectory.fullPath);
592592
}
593593
this.invokeDirectoryWatcher(folder.fullPath, fileOrDirectory.fullPath);
594594
}

src/server/editorServices.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,7 @@ namespace ts.server {
962962
fileOrDirectory => {
963963
const fileOrDirectoryPath = this.toPath(fileOrDirectory);
964964
project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
965+
if (isPathInNodeModulesStartingWithDot(fileOrDirectoryPath)) return;
965966
const configFilename = project.getConfigFilePath();
966967

967968
// If the the added or created file or directory is not supported file name, ignore the file

src/testRunner/unittests/tscWatchMode.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ namespace ts.tscWatch {
3434
return () => watch.getCurrentProgram().getProgram();
3535
}
3636

37-
function createWatchOfFilesAndCompilerOptions(rootFiles: string[], host: WatchedSystem, options: CompilerOptions = {}) {
38-
const watch = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, host));
37+
function createWatchOfFilesAndCompilerOptions(rootFiles: string[], host: WatchedSystem, options: CompilerOptions = {}, maxNumberOfFilesToIterateForInvalidation?: number) {
38+
const compilerHost = createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles, options, host);
39+
compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation;
40+
const watch = createWatchProgram(compilerHost);
3941
return () => watch.getCurrentProgram().getProgram();
4042
}
4143

@@ -2467,6 +2469,46 @@ declare module "fs" {
24672469
checkProgramActualFiles(watch(), [file.path, libFile.path, `${currentDirectory}/node_modules/@types/qqq/index.d.ts`]);
24682470
checkOutputErrorsIncremental(host, emptyArray);
24692471
});
2472+
2473+
describe("ignores files/folder changes in node_modules that start with '.'", () => {
2474+
const projectPath = "/user/username/projects/project";
2475+
const npmCacheFile: File = {
2476+
path: `${projectPath}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
2477+
content: JSON.stringify({ something: 10 })
2478+
};
2479+
const file1: File = {
2480+
path: `${projectPath}/test.ts`,
2481+
content: `import { x } from "somemodule";`
2482+
};
2483+
const file2: File = {
2484+
path: `${projectPath}/node_modules/somemodule/index.d.ts`,
2485+
content: `export const x = 10;`
2486+
};
2487+
const files = [libFile, file1, file2];
2488+
const expectedFiles = files.map(f => f.path);
2489+
it("when watching node_modules in inferred project for failed lookup", () => {
2490+
const host = createWatchedSystem(files);
2491+
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host, {}, /*maxNumberOfFilesToIterateForInvalidation*/ 1);
2492+
checkProgramActualFiles(watch(), expectedFiles);
2493+
host.checkTimeoutQueueLength(0);
2494+
2495+
host.ensureFileOrFolder(npmCacheFile);
2496+
host.checkTimeoutQueueLength(0);
2497+
});
2498+
it("when watching node_modules as part of wild card directories in config project", () => {
2499+
const config: File = {
2500+
path: `${projectPath}/tsconfig.json`,
2501+
content: "{}"
2502+
};
2503+
const host = createWatchedSystem(files.concat(config));
2504+
const watch = createWatchOfConfigFile(config.path, host);
2505+
checkProgramActualFiles(watch(), expectedFiles);
2506+
host.checkTimeoutQueueLength(0);
2507+
2508+
host.ensureFileOrFolder(npmCacheFile);
2509+
host.checkTimeoutQueueLength(0);
2510+
});
2511+
});
24702512
});
24712513

24722514
describe("tsc-watch with when module emit is specified as node", () => {

src/testRunner/unittests/tsserverProjectSystem.ts

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7389,7 +7389,7 @@ namespace ts.projectSystem {
73897389
const recursiveWatchedDirectories: string[] = [`${appFolder}`, `${appFolder}/node_modules`].concat(getNodeModuleDirectories(getDirectoryPath(appFolder)));
73907390
verifyProject();
73917391

7392-
let timeoutAfterReloadFs = timeoutDuringPartialInstallation;
7392+
let npmInstallComplete = false;
73937393

73947394
// Simulate npm install
73957395
const filesAndFoldersToAdd: File[] = [
@@ -7418,8 +7418,8 @@ namespace ts.projectSystem {
74187418
{ path: "/a/b/node_modules/.staging/lodash-b0733faa/index.js", content: "module.exports = require('./lodash');" },
74197419
{ path: "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" }
74207420
].map(getRootedFileOrFolder));
7421-
// Since we added/removed folder, scheduled project update
7422-
verifyAfterPartialOrCompleteNpmInstall(2);
7421+
// Since we added/removed in .staging no timeout
7422+
verifyAfterPartialOrCompleteNpmInstall(0);
74237423

74247424
// Remove file "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594"
74257425
filesAndFoldersToAdd.length--;
@@ -7431,7 +7431,7 @@ namespace ts.projectSystem {
74317431
{ path: "/a/b/node_modules/.staging/rxjs-22375c61/src/add/observable/dom" },
74327432
{ path: "/a/b/node_modules/.staging/@types/lodash-e56c4fe7/index.d.ts", content: "\n// Stub for lodash\nexport = _;\nexport as namespace _;\ndeclare var _: _.LoDashStatic;\ndeclare namespace _ {\n interface LoDashStatic {\n someProp: string;\n }\n class SomeClass {\n someMethod(): void;\n }\n}" }
74337433
].map(getRootedFileOrFolder));
7434-
verifyAfterPartialOrCompleteNpmInstall(2);
7434+
verifyAfterPartialOrCompleteNpmInstall(0);
74357435

74367436
filesAndFoldersToAdd.push(...[
74377437
{ path: "/a/b/node_modules/.staging/rxjs-22375c61/src/scheduler" },
@@ -7440,7 +7440,7 @@ namespace ts.projectSystem {
74407440
{ path: "/a/b/node_modules/.staging/rxjs-22375c61/testing" },
74417441
{ path: "/a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041", content: "{\n \"_args\": [\n [\n {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\"\n ]\n ],\n \"_from\": \"rxjs@>=5.4.2 <6.0.0\",\n \"_id\": \"[email protected]\",\n \"_inCache\": true,\n \"_location\": \"/rxjs\",\n \"_nodeVersion\": \"7.7.2\",\n \"_npmOperationalInternal\": {\n \"host\": \"s3://npm-registry-packages\",\n \"tmp\": \"tmp/rxjs-5.4.3.tgz_1502407898166_0.6800217325799167\"\n },\n \"_npmUser\": {\n \"name\": \"blesh\",\n \"email\": \"[email protected]\"\n },\n \"_npmVersion\": \"5.3.0\",\n \"_phantomChildren\": {},\n \"_requested\": {\n \"raw\": \"rxjs@^5.4.2\",\n \"scope\": null,\n \"escapedName\": \"rxjs\",\n \"name\": \"rxjs\",\n \"rawSpec\": \"^5.4.2\",\n \"spec\": \">=5.4.2 <6.0.0\",\n \"type\": \"range\"\n },\n \"_requiredBy\": [\n \"/\"\n ],\n \"_resolved\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\",\n \"_shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"_shrinkwrap\": null,\n \"_spec\": \"rxjs@^5.4.2\",\n \"_where\": \"C:\\\\Users\\\\shkamat\\\\Desktop\\\\app\",\n \"author\": {\n \"name\": \"Ben Lesh\",\n \"email\": \"[email protected]\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n },\n \"config\": {\n \"commitizen\": {\n \"path\": \"cz-conventional-changelog\"\n }\n },\n \"contributors\": [\n {\n \"name\": \"Ben Lesh\",\n \"email\": \"[email protected]\"\n },\n {\n \"name\": \"Paul Taylor\",\n \"email\": \"[email protected]\"\n },\n {\n \"name\": \"Jeff Cross\",\n \"email\": \"[email protected]\"\n },\n {\n \"name\": \"Matthew Podwysocki\",\n \"email\": \"[email protected]\"\n },\n {\n \"name\": \"OJ Kwon\",\n \"email\": \"[email protected]\"\n },\n {\n \"name\": \"Andre Staltz\",\n \"email\": \"[email protected]\"\n }\n ],\n \"dependencies\": {\n \"symbol-observable\": \"^1.0.1\"\n },\n \"description\": \"Reactive Extensions for modern JavaScript\",\n \"devDependencies\": {\n \"babel-polyfill\": \"^6.23.0\",\n \"benchmark\": \"^2.1.0\",\n \"benchpress\": \"2.0.0-beta.1\",\n \"chai\": \"^3.5.0\",\n \"color\": \"^0.11.1\",\n \"colors\": \"1.1.2\",\n \"commitizen\": \"^2.8.6\",\n \"coveralls\": \"^2.11.13\",\n \"cz-conventional-changelog\": \"^1.2.0\",\n \"danger\": \"^1.1.0\",\n \"doctoc\": \"^1.0.0\",\n \"escape-string-regexp\": \"^1.0.5 \",\n \"esdoc\": \"^0.4.7\",\n \"eslint\": \"^3.8.0\",\n \"fs-extra\": \"^2.1.2\",\n \"get-folder-size\": \"^1.0.0\",\n \"glob\": \"^7.0.3\",\n \"gm\": \"^1.22.0\",\n \"google-closure-compiler-js\": \"^20170218.0.0\",\n \"gzip-size\": \"^3.0.0\",\n \"http-server\": \"^0.9.0\",\n \"husky\": \"^0.13.3\",\n \"lint-staged\": \"3.2.5\",\n \"lodash\": \"^4.15.0\",\n \"madge\": \"^1.4.3\",\n \"markdown-doctest\": \"^0.9.1\",\n \"minimist\": \"^1.2.0\",\n \"mkdirp\": \"^0.5.1\",\n \"mocha\": \"^3.0.2\",\n \"mocha-in-sauce\": \"0.0.1\",\n \"npm-run-all\": \"^4.0.2\",\n \"npm-scripts-info\": \"^0.3.4\",\n \"nyc\": \"^10.2.0\",\n \"opn-cli\": \"^3.1.0\",\n \"platform\": \"^1.3.1\",\n \"promise\": \"^7.1.1\",\n \"protractor\": \"^3.1.1\",\n \"rollup\": \"0.36.3\",\n \"rollup-plugin-inject\": \"^2.0.0\",\n \"rollup-plugin-node-resolve\": \"^2.0.0\",\n \"rx\": \"latest\",\n \"rxjs\": \"latest\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^2.1.0\",\n \"sinon-chai\": \"^2.9.0\",\n \"source-map-support\": \"^0.4.0\",\n \"tslib\": \"^1.5.0\",\n \"tslint\": \"^4.4.2\",\n \"typescript\": \"~2.0.6\",\n \"typings\": \"^2.0.0\",\n \"validate-commit-msg\": \"^2.14.0\",\n \"watch\": \"^1.0.1\",\n \"webpack\": \"^1.13.1\",\n \"xmlhttprequest\": \"1.8.0\"\n },\n \"directories\": {},\n \"dist\": {\n \"integrity\": \"sha512-fSNi+y+P9ss+EZuV0GcIIqPUK07DEaMRUtLJvdcvMyFjc9dizuDjere+A4V7JrLGnm9iCc+nagV/4QdMTkqC4A==\",\n \"shasum\": \"0758cddee6033d68e0fd53676f0f3596ce3d483f\",\n \"tarball\": \"https://registry.npmjs.org/rxjs/-/rxjs-5.4.3.tgz\"\n },\n \"engines\": {\n \"npm\": \">=2.0.0\"\n },\n \"homepage\": \"https://github.com/ReactiveX/RxJS\",\n \"keywords\": [\n \"Rx\",\n \"RxJS\",\n \"ReactiveX\",\n \"ReactiveExtensions\",\n \"Streams\",\n \"Observables\",\n \"Observable\",\n \"Stream\",\n \"ES6\",\n \"ES2015\"\n ],\n \"license\": \"Apache-2.0\",\n \"lint-staged\": {\n \"*.@(js)\": [\n \"eslint --fix\",\n \"git add\"\n ],\n \"*.@(ts)\": [\n \"tslint --fix\",\n \"git add\"\n ]\n },\n \"main\": \"Rx.js\",\n \"maintainers\": [\n {\n \"name\": \"blesh\",\n \"email\": \"[email protected]\"\n }\n ],\n \"name\": \"rxjs\",\n \"optionalDependencies\": {},\n \"readme\": \"ERROR: No README data found!\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+ssh://[email protected]/ReactiveX/RxJS.git\"\n },\n \"scripts-info\": {\n \"info\": \"List available script\",\n \"build_all\": \"Build all packages (ES6, CJS, UMD) and generate packages\",\n \"build_cjs\": \"Build CJS package with clean up existing build, copy source into dist\",\n \"build_es6\": \"Build ES6 package with clean up existing build, copy source into dist\",\n \"build_closure_core\": \"Minify Global core build using closure compiler\",\n \"build_global\": \"Build Global package, then minify build\",\n \"build_perf\": \"Build CJS & Global build, run macro performance test\",\n \"build_test\": \"Build CJS package & test spec, execute mocha test runner\",\n \"build_cover\": \"Run lint to current code, build CJS & test spec, execute test coverage\",\n \"build_docs\": \"Build ES6 & global package, create documentation using it\",\n \"build_spec\": \"Build test specs\",\n \"check_circular_dependencies\": \"Check codebase has circular dependencies\",\n \"clean_spec\": \"Clean up existing test spec build output\",\n \"clean_dist_cjs\": \"Clean up existing CJS package output\",\n \"clean_dist_es6\": \"Clean up existing ES6 package output\",\n \"clean_dist_global\": \"Clean up existing Global package output\",\n \"commit\": \"Run git commit wizard\",\n \"compile_dist_cjs\": \"Compile codebase into CJS module\",\n \"compile_module_es6\": \"Compile codebase into ES6\",\n \"cover\": \"Execute test coverage\",\n \"lint_perf\": \"Run lint against performance test suite\",\n \"lint_spec\": \"Run lint against test spec\",\n \"lint_src\": \"Run lint against source\",\n \"lint\": \"Run lint against everything\",\n \"perf\": \"Run macro performance benchmark\",\n \"perf_micro\": \"Run micro performance benchmark\",\n \"test_mocha\": \"Execute mocha test runner against existing test spec build\",\n \"test_browser\": \"Execute mocha test runner on browser against existing test spec build\",\n \"test\": \"Clean up existing test spec build, build test spec and execute mocha test runner\",\n \"tests2png\": \"Generate marble diagram image from test spec\",\n \"watch\": \"Watch codebase, trigger compile when source code changes\"\n },\n \"typings\": \"Rx.d.ts\",\n \"version\": \"5.4.3\"\n}\n" }
74427442
].map(getRootedFileOrFolder));
7443-
verifyAfterPartialOrCompleteNpmInstall(2);
7443+
verifyAfterPartialOrCompleteNpmInstall(0);
74447444

74457445
// remove /a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041
74467446
filesAndFoldersToAdd.length--;
@@ -7468,12 +7468,12 @@ namespace ts.projectSystem {
74687468
// we would now not have failed lookup in the parent of appFolder since lodash is available
74697469
recursiveWatchedDirectories.length = 2;
74707470
// npm installation complete, timeout after reload fs
7471-
timeoutAfterReloadFs = true;
7471+
npmInstallComplete = true;
74727472
verifyAfterPartialOrCompleteNpmInstall(2);
74737473

74747474
function verifyAfterPartialOrCompleteNpmInstall(timeoutQueueLengthWhenRunningTimeouts: number) {
74757475
host.reloadFS(projectFiles.concat(otherFiles, filesAndFoldersToAdd));
7476-
if (timeoutAfterReloadFs) {
7476+
if (npmInstallComplete || timeoutDuringPartialInstallation) {
74777477
host.checkTimeoutQueueLengthAndRun(timeoutQueueLengthWhenRunningTimeouts);
74787478
}
74797479
else {
@@ -9040,31 +9040,51 @@ export const x = 10;`
90409040
});
90419041
});
90429042

9043-
it("ignores files/folder changes in node_modules that start with '.'", () => {
9043+
describe("ignores files/folder changes in node_modules that start with '.'", () => {
90449044
const projectPath = "/user/username/projects/project";
9045+
const npmCacheFile: File = {
9046+
path: `${projectPath}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
9047+
content: JSON.stringify({ something: 10 })
9048+
};
90459049
const file1: File = {
9046-
path: `${projectPath}/test.js`,
9050+
path: `${projectPath}/test.ts`,
90479051
content: `import { x } from "somemodule";`
90489052
};
90499053
const file2: File = {
90509054
path: `${projectPath}/node_modules/somemodule/index.d.ts`,
90519055
content: `export const x = 10;`
90529056
};
9053-
const files = [libFile, file1, file2];
9054-
const host = createServerHost(files);
9055-
const service = createProjectService(host);
9056-
service.openClientFile(file1.path);
9057-
checkNumberOfProjects(service, { inferredProjects: 1 });
9058-
const project = service.inferredProjects[0];
9059-
(project as ResolutionCacheHost).maxNumberOfFilesToIterateForInvalidation = 1;
9060-
host.checkTimeoutQueueLength(0);
9057+
it("when watching node_modules in inferred project for failed lookup/closed script infos", () => {
9058+
const files = [libFile, file1, file2];
9059+
const host = createServerHost(files);
9060+
const service = createProjectService(host);
9061+
service.openClientFile(file1.path);
9062+
checkNumberOfProjects(service, { inferredProjects: 1 });
9063+
const project = service.inferredProjects[0];
9064+
checkProjectActualFiles(project, files.map(f => f.path));
9065+
(project as ResolutionCacheHost).maxNumberOfFilesToIterateForInvalidation = 1;
9066+
host.checkTimeoutQueueLength(0);
90619067

9062-
const npmCacheFile: File = {
9063-
path: `${projectPath}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.json`,
9064-
content: JSON.stringify({ something: 10 })
9065-
};
9066-
host.ensureFileOrFolder(npmCacheFile);
9067-
host.checkTimeoutQueueLength(0);
9068+
host.ensureFileOrFolder(npmCacheFile);
9069+
host.checkTimeoutQueueLength(0);
9070+
});
9071+
it("when watching node_modules as part of wild card directories in config project", () => {
9072+
const config: File = {
9073+
path: `${projectPath}/tsconfig.json`,
9074+
content: "{}"
9075+
};
9076+
const files = [libFile, file1, file2, config];
9077+
const host = createServerHost(files);
9078+
const service = createProjectService(host);
9079+
service.openClientFile(file1.path);
9080+
checkNumberOfProjects(service, { configuredProjects: 1 });
9081+
const project = Debug.assertDefined(service.configuredProjects.get(config.path));
9082+
checkProjectActualFiles(project, files.map(f => f.path));
9083+
host.checkTimeoutQueueLength(0);
9084+
9085+
host.ensureFileOrFolder(npmCacheFile);
9086+
host.checkTimeoutQueueLength(0);
9087+
});
90689088
});
90699089
});
90709090

0 commit comments

Comments
 (0)