| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent bb09b4d commit 7229a29
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,6 +7,7 @@ const { | |||
| 7 | 7 | SafeMap, | |
| 8 | 8 | SafeSet, | |
| 9 | 9 | SafeWeakMap, | |
| 10 | + StringPrototypeEndsWith, | ||
| 10 | 11 | StringPrototypeStartsWith, | |
| 11 | 12 | } = primordials; | |
| 12 | 13 | ||
@@ -18,12 +19,19 @@ const EventEmitter = require('events'); | |||
| 18 | 19 | const { addAbortListener } = require('internal/events/abort_listener'); | |
| 19 | 20 | const { watch } = require('fs'); | |
| 20 | 21 | const { fileURLToPath } = require('internal/url'); | |
| 21 | - const { resolve, dirname } = require('path'); | ||
| 22 | + const { resolve, dirname, sep } = require('path'); | ||
| 22 | 23 | const { setTimeout, clearTimeout } = require('timers'); | |
| 23 | 24 | ||
| 24 | 25 | const supportsRecursiveWatching = process.platform === 'win32' || | |
| 25 | 26 | process.platform === 'darwin'; | |
| 26 | 27 | ||
| 28 | + const isParentPath = (parentCandidate, childCandidate) => { | ||
| 29 | + const parent = resolve(parentCandidate); | ||
| 30 | + const child = resolve(childCandidate); | ||
| 31 | + const normalizedParent = StringPrototypeEndsWith(parent, sep) ? parent : parent + sep; | ||
| 32 | + return StringPrototypeStartsWith(child, normalizedParent); | ||
| 33 | + }; | ||
| 34 | + | ||
| 27 | 35 | class FilesWatcher extends EventEmitter { | |
| 28 | 36 | #watchers = new SafeMap(); | |
| 29 | 37 | #filteredFiles = new SafeSet(); | |
@@ -58,7 +66,7 @@ class FilesWatcher extends EventEmitter { | |||
| 58 | 66 | } | |
| 59 | 67 | ||
| 60 | 68 | for (const { 0: watchedPath, 1: watcher } of this.#watchers.entries()) { | |
| 61 | - if (watcher.recursive && StringPrototypeStartsWith(path, watchedPath)) { | ||
| 69 | + if (watcher.recursive && isParentPath(watchedPath, path)) { | ||
| 62 | 70 | return true; | |
| 63 | 71 | } | |
| 64 | 72 | } | |
@@ -68,7 +76,7 @@ class FilesWatcher extends EventEmitter { | |||
| 68 | 76 | ||
| 69 | 77 | #removeWatchedChildren(path) { | |
| 70 | 78 | for (const { 0: watchedPath, 1: watcher } of this.#watchers.entries()) { | |
| 71 | - if (path !== watchedPath && StringPrototypeStartsWith(watchedPath, path)) { | ||
| 79 | + if (path !== watchedPath && isParentPath(path, watchedPath)) { | ||
| 72 | 80 | this.#unwatch(watcher); | |
| 73 | 81 | this.#watchers.delete(watchedPath); | |
| 74 | 82 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6,7 +6,8 @@ import path from 'node:path'; | |||
| 6 | 6 | import assert from 'node:assert'; | |
| 7 | 7 | import process from 'node:process'; | |
| 8 | 8 | import { describe, it, beforeEach, afterEach } from 'node:test'; | |
| 9 | - import { writeFileSync, mkdirSync } from 'node:fs'; | ||
| 9 | + import { writeFileSync, mkdirSync, appendFileSync } from 'node:fs'; | ||
| 10 | + import { createInterface } from 'node:readline'; | ||
| 10 | 11 | import { setTimeout } from 'node:timers/promises'; | |
| 11 | 12 | import { once } from 'node:events'; | |
| 12 | 13 | import { spawn } from 'node:child_process'; | |
@@ -51,6 +52,33 @@ describe('watch mode file watcher', () => { | |||
| 51 | 52 | assert.strictEqual(changesCount, 1); | |
| 52 | 53 | }); | |
| 53 | 54 | ||
| 55 | + it('should watch changed files with same prefix path string', async () => { | ||
| 56 | + mkdirSync(tmpdir.resolve('subdir')); | ||
| 57 | + mkdirSync(tmpdir.resolve('sub')); | ||
| 58 | + const file1 = tmpdir.resolve('subdir', 'file1.mjs'); | ||
| 59 | + const file2 = tmpdir.resolve('sub', 'file2.mjs'); | ||
| 60 | + writeFileSync(file2, 'export const hello = () => { return "hello world"; };'); | ||
| 61 | + writeFileSync(file1, 'import { hello } from "../sub/file2.mjs"; console.log(hello());'); | ||
| 62 | + | ||
| 63 | + const child = spawn(process.execPath, | ||
| 64 | + ['--watch', file1], | ||
| 65 | + { stdio: ['ignore', 'pipe', 'ignore'] }); | ||
| 66 | + let completeCount = 0; | ||
| 67 | + for await (const line of createInterface(child.stdout)) { | ||
| 68 | + if (!line.startsWith('Completed running')) { | ||
| 69 | + continue; | ||
| 70 | + } | ||
| 71 | + completeCount++; | ||
| 72 | + if (completeCount === 1) { | ||
| 73 | + appendFileSync(file1, '\n // append 1'); | ||
| 74 | + } | ||
| 75 | + // The file is reloaded due to file watching | ||
| 76 | + if (completeCount === 2) { | ||
| 77 | + child.kill(); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + }); | ||
| 81 | + | ||
| 54 | 82 | it('should debounce changes', async () => { | |
| 55 | 83 | const file = tmpdir.resolve('file2'); | |
| 56 | 84 | writeFileSync(file, 'written'); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments