@theia/filesystem 1.77.0-next.1 → 1.77.0-next.108
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/browser/breadcrumbs/filepath-breadcrumb.js +4 -8
- package/lib/browser/breadcrumbs/filepath-breadcrumb.js.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js +18 -25
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-container.js.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.d.ts +5 -5
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.d.ts.map +1 -1
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.js +27 -33
- package/lib/browser/breadcrumbs/filepath-breadcrumbs-contribution.js.map +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser/download/file-download-command-contribution.js +28 -33
- package/lib/browser/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser/download/file-download-frontend-module.js +8 -10
- package/lib/browser/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser/download/file-download-service.d.ts +1 -1
- package/lib/browser/download/file-download-service.d.ts.map +1 -1
- package/lib/browser/download/file-download-service.js +19 -25
- package/lib/browser/download/file-download-service.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-container.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-container.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-container.js +25 -30
- package/lib/browser/file-dialog/file-dialog-container.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.d.ts +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.js +13 -21
- package/lib/browser/file-dialog/file-dialog-hidden-files-renderer.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-model.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-model.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-model.js +20 -27
- package/lib/browser/file-dialog/file-dialog-model.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-module.js +21 -23
- package/lib/browser/file-dialog/file-dialog-module.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-service.d.ts +4 -4
- package/lib/browser/file-dialog/file-dialog-service.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-service.js +29 -38
- package/lib/browser/file-dialog/file-dialog-service.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.d.ts +3 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.js +17 -22
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.d.ts +2 -0
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.d.ts.map +1 -0
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.js +35 -0
- package/lib/browser/file-dialog/file-dialog-tree-filters-renderer.spec.js.map +1 -0
- package/lib/browser/file-dialog/file-dialog-tree.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-tree.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-tree.js +8 -11
- package/lib/browser/file-dialog/file-dialog-tree.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog-widget.d.ts +2 -2
- package/lib/browser/file-dialog/file-dialog-widget.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog-widget.js +18 -23
- package/lib/browser/file-dialog/file-dialog-widget.js.map +1 -1
- package/lib/browser/file-dialog/file-dialog.d.ts +11 -6
- package/lib/browser/file-dialog/file-dialog.d.ts.map +1 -1
- package/lib/browser/file-dialog/file-dialog.js +109 -126
- package/lib/browser/file-dialog/file-dialog.js.map +1 -1
- package/lib/browser/file-dialog/index.d.ts +4 -4
- package/lib/browser/file-dialog/index.d.ts.map +1 -1
- package/lib/browser/file-dialog/index.js +4 -7
- package/lib/browser/file-dialog/index.js.map +1 -1
- package/lib/browser/file-resource.d.ts +2 -2
- package/lib/browser/file-resource.d.ts.map +1 -1
- package/lib/browser/file-resource.js +64 -71
- package/lib/browser/file-resource.js.map +1 -1
- package/lib/browser/file-resource.spec.js +39 -41
- package/lib/browser/file-resource.spec.js.map +1 -1
- package/lib/browser/file-selection.d.ts +1 -1
- package/lib/browser/file-selection.d.ts.map +1 -1
- package/lib/browser/file-selection.js +7 -10
- package/lib/browser/file-selection.js.map +1 -1
- package/lib/browser/file-service-activation.spec.d.ts +2 -0
- package/lib/browser/file-service-activation.spec.d.ts.map +1 -0
- package/lib/browser/file-service-activation.spec.js +79 -0
- package/lib/browser/file-service-activation.spec.js.map +1 -0
- package/lib/browser/file-service-copy.spec.d.ts +2 -0
- package/lib/browser/file-service-copy.spec.d.ts.map +1 -0
- package/lib/browser/file-service-copy.spec.js +193 -0
- package/lib/browser/file-service-copy.spec.js.map +1 -0
- package/lib/browser/file-service-watcher.spec.js +199 -201
- package/lib/browser/file-service-watcher.spec.js.map +1 -1
- package/lib/browser/file-service.d.ts +4 -4
- package/lib/browser/file-service.d.ts.map +1 -1
- package/lib/browser/file-service.js +179 -182
- package/lib/browser/file-service.js.map +1 -1
- package/lib/browser/file-tree/file-tree-container.js +12 -15
- package/lib/browser/file-tree/file-tree-container.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.js +23 -31
- package/lib/browser/file-tree/file-tree-decorator-adapter.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js +26 -28
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js.map +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.d.ts +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-label-provider.js +13 -18
- package/lib/browser/file-tree/file-tree-label-provider.js.map +1 -1
- package/lib/browser/file-tree/file-tree-model.d.ts +5 -5
- package/lib/browser/file-tree/file-tree-model.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-model.js +48 -52
- package/lib/browser/file-tree/file-tree-model.js.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.d.ts +3 -3
- package/lib/browser/file-tree/file-tree-widget.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-widget.js +66 -72
- package/lib/browser/file-tree/file-tree-widget.js.map +1 -1
- package/lib/browser/file-tree/file-tree.d.ts +3 -3
- package/lib/browser/file-tree/file-tree.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree.js +26 -31
- package/lib/browser/file-tree/file-tree.js.map +1 -1
- package/lib/browser/file-tree/index.d.ts +6 -6
- package/lib/browser/file-tree/index.d.ts.map +1 -1
- package/lib/browser/file-tree/index.js +6 -9
- package/lib/browser/file-tree/index.js.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.d.ts +6 -6
- package/lib/browser/filesystem-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/filesystem-frontend-contribution.js +75 -90
- package/lib/browser/filesystem-frontend-contribution.js.map +1 -1
- package/lib/browser/filesystem-frontend-module.js +47 -50
- package/lib/browser/filesystem-frontend-module.js.map +1 -1
- package/lib/browser/filesystem-saveable-service.d.ts +2 -2
- package/lib/browser/filesystem-saveable-service.d.ts.map +1 -1
- package/lib/browser/filesystem-saveable-service.js +35 -44
- package/lib/browser/filesystem-saveable-service.js.map +1 -1
- package/lib/browser/filesystem-watcher-error-handler.js +13 -18
- package/lib/browser/filesystem-watcher-error-handler.js.map +1 -1
- package/lib/browser/index.d.ts +4 -4
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +4 -7
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/location/index.d.ts +2 -2
- package/lib/browser/location/index.d.ts.map +1 -1
- package/lib/browser/location/index.js +2 -5
- package/lib/browser/location/index.js.map +1 -1
- package/lib/browser/location/location-renderer.d.ts +3 -3
- package/lib/browser/location/location-renderer.d.ts.map +1 -1
- package/lib/browser/location/location-renderer.js +42 -51
- package/lib/browser/location/location-renderer.js.map +1 -1
- package/lib/browser/location/location-renderer.spec.js +61 -63
- package/lib/browser/location/location-renderer.spec.js.map +1 -1
- package/lib/browser/location/location-service.js +1 -2
- package/lib/browser/location/location-service.js.map +1 -1
- package/lib/browser/remote-file-service-contribution.d.ts +2 -2
- package/lib/browser/remote-file-service-contribution.d.ts.map +1 -1
- package/lib/browser/remote-file-service-contribution.js +8 -12
- package/lib/browser/remote-file-service-contribution.js.map +1 -1
- package/lib/browser/upload/file-upload-service-impl.d.ts +3 -3
- package/lib/browser/upload/file-upload-service-impl.d.ts.map +1 -1
- package/lib/browser/upload/file-upload-service-impl.js +55 -64
- package/lib/browser/upload/file-upload-service-impl.js.map +1 -1
- package/lib/browser/vscode-file-service-contribution.d.ts +2 -2
- package/lib/browser/vscode-file-service-contribution.d.ts.map +1 -1
- package/lib/browser/vscode-file-service-contribution.js +23 -28
- package/lib/browser/vscode-file-service-contribution.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-frontend-module.js +21 -23
- package/lib/browser-only/browser-only-filesystem-frontend-module.js.map +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.d.ts +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.d.ts.map +1 -1
- package/lib/browser-only/browser-only-filesystem-provider-server.js +10 -13
- package/lib/browser-only/browser-only-filesystem-provider-server.js.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts +1 -1
- package/lib/browser-only/download/file-download-command-contribution.d.ts.map +1 -1
- package/lib/browser-only/download/file-download-command-contribution.js +14 -19
- package/lib/browser-only/download/file-download-command-contribution.js.map +1 -1
- package/lib/browser-only/download/file-download-frontend-module.js +8 -10
- package/lib/browser-only/download/file-download-frontend-module.js.map +1 -1
- package/lib/browser-only/download/file-download-service.d.ts +3 -3
- package/lib/browser-only/download/file-download-service.d.ts.map +1 -1
- package/lib/browser-only/download/file-download-service.js +26 -33
- package/lib/browser-only/download/file-download-service.js.map +1 -1
- package/lib/browser-only/file-search.d.ts.map +1 -1
- package/lib/browser-only/file-search.js +9 -14
- package/lib/browser-only/file-search.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-initialization.js +6 -9
- package/lib/browser-only/opfs-filesystem-initialization.js.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.d.ts +2 -2
- package/lib/browser-only/opfs-filesystem-provider.d.ts.map +1 -1
- package/lib/browser-only/opfs-filesystem-provider.js +60 -68
- package/lib/browser-only/opfs-filesystem-provider.js.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.d.ts +3 -3
- package/lib/browser-only/upload/file-upload-service-impl.d.ts.map +1 -1
- package/lib/browser-only/upload/file-upload-service-impl.js +51 -60
- package/lib/browser-only/upload/file-upload-service-impl.js.map +1 -1
- package/lib/common/delegating-file-system-provider.d.ts +1 -1
- package/lib/common/delegating-file-system-provider.d.ts.map +1 -1
- package/lib/common/delegating-file-system-provider.js +18 -22
- package/lib/common/delegating-file-system-provider.js.map +1 -1
- package/lib/common/download/file-download.js +5 -8
- package/lib/common/download/file-download.js.map +1 -1
- package/lib/common/file-upload.js +1 -4
- package/lib/common/file-upload.js.map +1 -1
- package/lib/common/files.js +38 -58
- package/lib/common/files.js.map +1 -1
- package/lib/common/files.spec.js +22 -24
- package/lib/common/files.spec.js.map +1 -1
- package/lib/common/filesystem-preferences.js +39 -44
- package/lib/common/filesystem-preferences.js.map +1 -1
- package/lib/common/filesystem-utils.d.ts +1 -1
- package/lib/common/filesystem-utils.d.ts.map +1 -1
- package/lib/common/filesystem-utils.js +2 -5
- package/lib/common/filesystem-utils.js.map +1 -1
- package/lib/common/filesystem-utils.spec.js +227 -229
- package/lib/common/filesystem-utils.spec.js.map +1 -1
- package/lib/common/filesystem-watcher-protocol.d.ts +5 -1
- package/lib/common/filesystem-watcher-protocol.d.ts.map +1 -1
- package/lib/common/filesystem-watcher-protocol.js +2 -5
- package/lib/common/filesystem-watcher-protocol.js.map +1 -1
- package/lib/common/filesystem.js +2 -5
- package/lib/common/filesystem.js.map +1 -1
- package/lib/common/index.d.ts +3 -3
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -6
- package/lib/common/index.js.map +1 -1
- package/lib/common/io.d.ts +2 -2
- package/lib/common/io.d.ts.map +1 -1
- package/lib/common/io.js +10 -13
- package/lib/common/io.js.map +1 -1
- package/lib/common/remote-file-system-provider.d.ts +1 -1
- package/lib/common/remote-file-system-provider.d.ts.map +1 -1
- package/lib/common/remote-file-system-provider.js +81 -93
- package/lib/common/remote-file-system-provider.js.map +1 -1
- package/lib/common/upload/file-upload.js +1 -4
- package/lib/common/upload/file-upload.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-module.js +6 -8
- package/lib/electron-browser/file-dialog/electron-file-dialog-module.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.d.ts +3 -3
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.d.ts.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.js +20 -24
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.js.map +1 -1
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.d.ts +2 -0
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.d.ts.map +1 -0
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.js +46 -0
- package/lib/electron-browser/file-dialog/electron-file-dialog-service.spec.js.map +1 -0
- package/lib/electron-browser/preload.js +6 -9
- package/lib/electron-browser/preload.js.map +1 -1
- package/lib/electron-common/electron-api.js +2 -5
- package/lib/electron-common/electron-api.js.map +1 -1
- package/lib/electron-main/electron-api-main.js +15 -18
- package/lib/electron-main/electron-api-main.js.map +1 -1
- package/lib/electron-main/electron-main-module.js +6 -8
- package/lib/electron-main/electron-main-module.js.map +1 -1
- package/lib/node/disk-file-system-provider.d.ts +2 -2
- package/lib/node/disk-file-system-provider.d.ts.map +1 -1
- package/lib/node/disk-file-system-provider.js +116 -121
- package/lib/node/disk-file-system-provider.js.map +1 -1
- package/lib/node/disk-file-system-provider.spec.js +77 -54
- package/lib/node/disk-file-system-provider.spec.js.map +1 -1
- package/lib/node/download/directory-archiver.js +13 -16
- package/lib/node/download/directory-archiver.js.map +1 -1
- package/lib/node/download/directory-archiver.spec.js +20 -22
- package/lib/node/download/directory-archiver.spec.js.map +1 -1
- package/lib/node/download/file-download-backend-module.js +14 -16
- package/lib/node/download/file-download-backend-module.js.map +1 -1
- package/lib/node/download/file-download-cache.js +12 -16
- package/lib/node/download/file-download-cache.js.map +1 -1
- package/lib/node/download/file-download-endpoint.d.ts +1 -1
- package/lib/node/download/file-download-endpoint.d.ts.map +1 -1
- package/lib/node/download/file-download-endpoint.js +25 -31
- package/lib/node/download/file-download-endpoint.js.map +1 -1
- package/lib/node/download/file-download-handler.d.ts +2 -2
- package/lib/node/download/file-download-handler.d.ts.map +1 -1
- package/lib/node/download/file-download-handler.js +70 -77
- package/lib/node/download/file-download-handler.js.map +1 -1
- package/lib/node/download/test/mock-directory-archiver.d.ts +1 -1
- package/lib/node/download/test/mock-directory-archiver.d.ts.map +1 -1
- package/lib/node/download/test/mock-directory-archiver.js +2 -6
- package/lib/node/download/test/mock-directory-archiver.js.map +1 -1
- package/lib/node/file-change-collection.d.ts +1 -1
- package/lib/node/file-change-collection.d.ts.map +1 -1
- package/lib/node/file-change-collection.js +1 -5
- package/lib/node/file-change-collection.js.map +1 -1
- package/lib/node/file-change-collection.spec.js +5 -7
- package/lib/node/file-change-collection.spec.js.map +1 -1
- package/lib/node/filesystem-backend-module.d.ts +3 -3
- package/lib/node/filesystem-backend-module.d.ts.map +1 -1
- package/lib/node/filesystem-backend-module.js +57 -62
- package/lib/node/filesystem-backend-module.js.map +1 -1
- package/lib/node/filesystem-watcher-client.d.ts +2 -2
- package/lib/node/filesystem-watcher-client.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-client.js +11 -16
- package/lib/node/filesystem-watcher-client.js.map +1 -1
- package/lib/node/filesystem-watcher-dispatcher.d.ts +1 -1
- package/lib/node/filesystem-watcher-dispatcher.d.ts.map +1 -1
- package/lib/node/filesystem-watcher-dispatcher.js +9 -13
- package/lib/node/filesystem-watcher-dispatcher.js.map +1 -1
- package/lib/node/filesystem-watcher-service-impl.d.ts +30 -0
- package/lib/node/filesystem-watcher-service-impl.d.ts.map +1 -0
- package/lib/node/filesystem-watcher-service-impl.js +88 -0
- package/lib/node/filesystem-watcher-service-impl.js.map +1 -0
- package/lib/node/filesystem-watcher-service-impl.spec.d.ts +2 -0
- package/lib/node/filesystem-watcher-service-impl.spec.d.ts.map +1 -0
- package/lib/node/filesystem-watcher-service-impl.spec.js +199 -0
- package/lib/node/filesystem-watcher-service-impl.spec.js.map +1 -0
- package/lib/node/filesystem-watcher.d.ts +93 -0
- package/lib/node/filesystem-watcher.d.ts.map +1 -0
- package/lib/node/filesystem-watcher.js +129 -0
- package/lib/node/filesystem-watcher.js.map +1 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.d.ts +175 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.d.ts.map +1 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.js +574 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.js.map +1 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.d.ts +2 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.d.ts.map +1 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.js +1281 -0
- package/lib/node/nodejs-watcher/node-directory-watcher.spec.js.map +1 -0
- package/lib/node/nodejs-watcher/watch-request-router.d.ts +63 -0
- package/lib/node/nodejs-watcher/watch-request-router.d.ts.map +1 -0
- package/lib/node/nodejs-watcher/watch-request-router.js +178 -0
- package/lib/node/nodejs-watcher/watch-request-router.js.map +1 -0
- package/lib/node/nodejs-watcher/watcher-host.d.ts +50 -0
- package/lib/node/nodejs-watcher/watcher-host.d.ts.map +1 -0
- package/lib/node/nodejs-watcher/watcher-host.js +94 -0
- package/lib/node/nodejs-watcher/watcher-host.js.map +1 -0
- package/lib/node/parcel-watcher/index.js +6 -8
- package/lib/node/parcel-watcher/index.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts +14 -194
- package/lib/node/parcel-watcher/parcel-filesystem-service.d.ts.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-service.js +5 -426
- package/lib/node/parcel-watcher/parcel-filesystem-service.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-filesystem-watcher.spec.js +23 -25
- package/lib/node/parcel-watcher/parcel-filesystem-watcher.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-options.js +1 -4
- package/lib/node/parcel-watcher/parcel-options.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher-exclude.spec.js +12 -16
- package/lib/node/parcel-watcher/parcel-watcher-exclude.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher-retry.spec.js +11 -15
- package/lib/node/parcel-watcher/parcel-watcher-retry.spec.js.map +1 -1
- package/lib/node/parcel-watcher/parcel-watcher.d.ts +165 -0
- package/lib/node/parcel-watcher/parcel-watcher.d.ts.map +1 -0
- package/lib/node/parcel-watcher/parcel-watcher.js +366 -0
- package/lib/node/parcel-watcher/parcel-watcher.js.map +1 -0
- package/lib/node/test/watcher-test-helper.d.ts +21 -0
- package/lib/node/test/watcher-test-helper.d.ts.map +1 -0
- package/lib/node/test/watcher-test-helper.js +51 -0
- package/lib/node/test/watcher-test-helper.js.map +1 -0
- package/lib/node/upload/node-file-upload-service.d.ts +1 -1
- package/lib/node/upload/node-file-upload-service.d.ts.map +1 -1
- package/lib/node/upload/node-file-upload-service.js +20 -25
- package/lib/node/upload/node-file-upload-service.js.map +1 -1
- package/lib/node/upload/node-file-upload-service.spec.js +21 -23
- package/lib/node/upload/node-file-upload-service.spec.js.map +1 -1
- package/package.json +21 -7
- package/src/browser/breadcrumbs/filepath-breadcrumb.ts +1 -1
- package/src/browser/breadcrumbs/filepath-breadcrumbs-container.ts +1 -1
- package/src/browser/breadcrumbs/filepath-breadcrumbs-contribution.ts +5 -5
- package/src/browser/download/file-download-command-contribution.ts +1 -1
- package/src/browser/download/file-download-frontend-module.ts +3 -3
- package/src/browser/download/file-download-service.ts +1 -2
- package/src/browser/file-dialog/file-dialog-container.ts +5 -5
- package/src/browser/file-dialog/file-dialog-hidden-files-renderer.tsx +1 -1
- package/src/browser/file-dialog/file-dialog-model.ts +2 -2
- package/src/browser/file-dialog/file-dialog-module.ts +5 -5
- package/src/browser/file-dialog/file-dialog-service.ts +4 -4
- package/src/browser/file-dialog/file-dialog-tree-filters-renderer.spec.ts +43 -0
- package/src/browser/file-dialog/file-dialog-tree-filters-renderer.tsx +4 -2
- package/src/browser/file-dialog/file-dialog-tree.ts +2 -2
- package/src/browser/file-dialog/file-dialog-widget.ts +2 -2
- package/src/browser/file-dialog/file-dialog.ts +17 -7
- package/src/browser/file-dialog/index.ts +4 -4
- package/src/browser/file-resource.spec.ts +3 -3
- package/src/browser/file-resource.ts +3 -3
- package/src/browser/file-selection.ts +1 -1
- package/src/browser/file-service-activation.spec.ts +93 -0
- package/src/browser/file-service-copy.spec.ts +226 -0
- package/src/browser/file-service-watcher.spec.ts +2 -2
- package/src/browser/file-service.ts +22 -11
- package/src/browser/file-tree/file-tree-container.ts +3 -3
- package/src/browser/file-tree/file-tree-decorator-adapter.spec.ts +1 -1
- package/src/browser/file-tree/file-tree-decorator-adapter.ts +1 -1
- package/src/browser/file-tree/file-tree-label-provider.ts +1 -1
- package/src/browser/file-tree/file-tree-model.ts +12 -6
- package/src/browser/file-tree/file-tree-widget.tsx +8 -5
- package/src/browser/file-tree/file-tree.ts +3 -3
- package/src/browser/file-tree/index.ts +6 -6
- package/src/browser/filesystem-frontend-contribution.ts +6 -6
- package/src/browser/filesystem-frontend-module.ts +14 -14
- package/src/browser/filesystem-saveable-service.ts +2 -2
- package/src/browser/index.ts +4 -4
- package/src/browser/location/index.ts +2 -2
- package/src/browser/location/location-renderer.spec.ts +3 -3
- package/src/browser/location/location-renderer.tsx +3 -3
- package/src/browser/remote-file-service-contribution.ts +2 -2
- package/src/browser/upload/file-upload-service-impl.ts +5 -5
- package/src/browser/vscode-file-service-contribution.ts +2 -2
- package/src/browser-only/browser-only-filesystem-frontend-module.ts +7 -7
- package/src/browser-only/browser-only-filesystem-provider-server.ts +1 -1
- package/src/browser-only/download/file-download-command-contribution.ts +2 -2
- package/src/browser-only/download/file-download-frontend-module.ts +3 -3
- package/src/browser-only/download/file-download-service.ts +3 -3
- package/src/browser-only/file-search.ts +2 -1
- package/src/browser-only/opfs-filesystem-initialization.ts +1 -1
- package/src/browser-only/opfs-filesystem-provider.ts +3 -3
- package/src/browser-only/upload/file-upload-service-impl.ts +4 -4
- package/src/common/delegating-file-system-provider.ts +1 -1
- package/src/common/files.spec.ts +1 -1
- package/src/common/filesystem-utils.spec.ts +2 -2
- package/src/common/filesystem-utils.ts +1 -1
- package/src/common/filesystem-watcher-protocol.ts +5 -1
- package/src/common/index.ts +3 -3
- package/src/common/io.ts +2 -2
- package/src/common/remote-file-system-provider.ts +1 -1
- package/src/electron-browser/file-dialog/electron-file-dialog-module.ts +2 -2
- package/src/electron-browser/file-dialog/electron-file-dialog-service.spec.ts +57 -0
- package/src/electron-browser/file-dialog/electron-file-dialog-service.ts +5 -5
- package/src/electron-browser/preload.ts +1 -1
- package/src/electron-main/electron-api-main.ts +1 -1
- package/src/electron-main/electron-main-module.ts +1 -1
- package/src/node/disk-file-system-provider.spec.ts +32 -3
- package/src/node/disk-file-system-provider.ts +12 -8
- package/src/node/download/directory-archiver.spec.ts +1 -1
- package/src/node/download/file-download-backend-module.ts +4 -4
- package/src/node/download/file-download-cache.ts +1 -1
- package/src/node/download/file-download-endpoint.ts +4 -3
- package/src/node/download/file-download-handler.ts +3 -4
- package/src/node/download/test/mock-directory-archiver.ts +1 -1
- package/src/node/file-change-collection.spec.ts +2 -2
- package/src/node/file-change-collection.ts +1 -1
- package/src/node/filesystem-backend-module.ts +15 -14
- package/src/node/filesystem-watcher-client.ts +2 -2
- package/src/node/filesystem-watcher-dispatcher.ts +1 -1
- package/src/node/filesystem-watcher-service-impl.spec.ts +272 -0
- package/src/node/filesystem-watcher-service-impl.ts +109 -0
- package/src/node/filesystem-watcher.ts +197 -0
- package/src/node/nodejs-watcher/node-directory-watcher.spec.ts +1594 -0
- package/src/node/nodejs-watcher/node-directory-watcher.ts +664 -0
- package/src/node/nodejs-watcher/watch-request-router.ts +224 -0
- package/src/node/nodejs-watcher/watcher-host.ts +126 -0
- package/src/node/parcel-watcher/index.ts +3 -3
- package/src/node/parcel-watcher/parcel-filesystem-service.ts +14 -500
- package/src/node/parcel-watcher/parcel-filesystem-watcher.spec.ts +5 -5
- package/src/node/parcel-watcher/parcel-watcher-exclude.spec.ts +7 -11
- package/src/node/parcel-watcher/parcel-watcher-retry.spec.ts +6 -8
- package/src/node/parcel-watcher/parcel-watcher.ts +433 -0
- package/src/node/test/watcher-test-helper.ts +58 -0
- package/src/node/upload/node-file-upload-service.spec.ts +1 -1
- package/src/node/upload/node-file-upload-service.ts +6 -6
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// *****************************************************************************
|
|
3
2
|
// Copyright (C) 2026 Safi Seid-Ahmad, K2view and others.
|
|
4
3
|
//
|
|
@@ -14,30 +13,29 @@
|
|
|
14
13
|
//
|
|
15
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
15
|
// *****************************************************************************
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const file_service_1 = require("./file-service");
|
|
16
|
+
import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
|
|
17
|
+
let disableJSDOM = enableJSDOM();
|
|
18
|
+
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
|
19
|
+
FrontendApplicationConfigProvider.set({});
|
|
20
|
+
import { Disposable, Emitter, URI } from '@theia/core';
|
|
21
|
+
import { expect } from 'chai';
|
|
22
|
+
import * as sinon from 'sinon';
|
|
23
|
+
import { FileService } from './file-service.js';
|
|
26
24
|
disableJSDOM();
|
|
27
25
|
function createMockProvider(caseSensitive = true) {
|
|
28
26
|
const watchers = [];
|
|
29
27
|
return {
|
|
30
28
|
watchers,
|
|
31
29
|
capabilities: caseSensitive ? 1024 /* FileSystemProviderCapabilities.PathCaseSensitive */ : 0,
|
|
32
|
-
onDidChangeCapabilities: () =>
|
|
33
|
-
onDidChangeFile: () =>
|
|
34
|
-
onFileWatchError: () =>
|
|
30
|
+
onDidChangeCapabilities: () => Disposable.NULL,
|
|
31
|
+
onDidChangeFile: () => Disposable.NULL,
|
|
32
|
+
onFileWatchError: () => Disposable.NULL,
|
|
35
33
|
watch(resource, options) {
|
|
36
34
|
const watcher = {
|
|
37
35
|
resource,
|
|
38
36
|
options,
|
|
39
37
|
disposed: false,
|
|
40
|
-
disposable:
|
|
38
|
+
disposable: Disposable.create(() => { watcher.disposed = true; }),
|
|
41
39
|
};
|
|
42
40
|
watchers.push(watcher);
|
|
43
41
|
return watcher.disposable;
|
|
@@ -60,14 +58,14 @@ describe('FileService watcher deduplication', () => {
|
|
|
60
58
|
let fileService;
|
|
61
59
|
let mockProvider;
|
|
62
60
|
before(() => {
|
|
63
|
-
disableJSDOM =
|
|
61
|
+
disableJSDOM = enableJSDOM();
|
|
64
62
|
});
|
|
65
63
|
after(() => {
|
|
66
64
|
disableJSDOM();
|
|
67
65
|
});
|
|
68
66
|
beforeEach(() => {
|
|
69
67
|
sandbox.restore();
|
|
70
|
-
fileService = new
|
|
68
|
+
fileService = new FileService();
|
|
71
69
|
mockProvider = createMockProvider();
|
|
72
70
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
71
|
sandbox.stub(fileService, 'withProvider').resolves(mockProvider);
|
|
@@ -78,22 +76,22 @@ describe('FileService watcher deduplication', () => {
|
|
|
78
76
|
// ── (A) Exact-match dedup ──────────────────────────────────────────
|
|
79
77
|
describe('exact-match dedup', () => {
|
|
80
78
|
it('should reuse an existing watcher for the same resource and options', async () => {
|
|
81
|
-
const uri = new
|
|
79
|
+
const uri = new URI('file:///project/src');
|
|
82
80
|
const opts = { recursive: true, excludes: [] };
|
|
83
81
|
const d1 = await fileService.doWatch(uri, opts);
|
|
84
82
|
const d2 = await fileService.doWatch(uri, opts);
|
|
85
83
|
// Only one real OS watcher should have been created
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
85
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
88
86
|
// Disposing one handle should NOT dispose the real watcher
|
|
89
87
|
d2.dispose();
|
|
90
|
-
|
|
88
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
91
89
|
// Disposing the last handle should dispose it
|
|
92
90
|
d1.dispose();
|
|
93
|
-
|
|
91
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
94
92
|
});
|
|
95
93
|
it('should not let a restrictive parent subsume a permissive child at the same URI', async () => {
|
|
96
|
-
const uri = new
|
|
94
|
+
const uri = new URI('file:///project/src');
|
|
97
95
|
const opts1 = { recursive: true, excludes: ['**/node_modules'] };
|
|
98
96
|
const opts2 = { recursive: true, excludes: [] };
|
|
99
97
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
@@ -101,164 +99,164 @@ describe('FileService watcher deduplication', () => {
|
|
|
101
99
|
// The first watcher (with excludes) cannot subsume the second (no excludes),
|
|
102
100
|
// but the second (watching everything) CAN subsume the first via subsumeExistingChildren.
|
|
103
101
|
// Two real watchers were created, but only the permissive one (d2) remains live.
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
103
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
106
104
|
// Disposing d1 (already subsumed, no real watcher) should have no OS-level effect
|
|
107
105
|
d1.dispose();
|
|
108
|
-
|
|
106
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
109
107
|
d2.dispose();
|
|
110
|
-
|
|
108
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
111
109
|
});
|
|
112
110
|
it('should subsume a watcher with matching excludes on the same URI', async () => {
|
|
113
|
-
const uri = new
|
|
111
|
+
const uri = new URI('file:///project/src');
|
|
114
112
|
const opts1 = { recursive: true, excludes: ['**/node_modules'] };
|
|
115
113
|
const opts2 = { recursive: true, excludes: ['**/node_modules'] };
|
|
116
114
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
117
115
|
const d2 = await fileService.doWatch(uri, opts2);
|
|
118
116
|
// Same excludes — exact-match dedup applies
|
|
119
|
-
|
|
117
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
120
118
|
d2.dispose();
|
|
121
|
-
|
|
119
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
122
120
|
d1.dispose();
|
|
123
|
-
|
|
121
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
124
122
|
});
|
|
125
123
|
it('should subsume a watcher with more excludes (superset) on the same URI', async () => {
|
|
126
|
-
const uri = new
|
|
124
|
+
const uri = new URI('file:///project/src');
|
|
127
125
|
const opts1 = { recursive: true, excludes: [] };
|
|
128
126
|
const opts2 = { recursive: true, excludes: ['**/node_modules'] };
|
|
129
127
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
130
128
|
const d2 = await fileService.doWatch(uri, opts2);
|
|
131
129
|
// Parent has no excludes, so it watches everything the child needs — subsumption is safe
|
|
132
|
-
|
|
130
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
133
131
|
d2.dispose();
|
|
134
|
-
|
|
132
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
135
133
|
d1.dispose();
|
|
136
|
-
|
|
134
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
137
135
|
});
|
|
138
136
|
it('should subsume a non-recursive watcher on the same URI as a recursive watcher', async () => {
|
|
139
|
-
const uri = new
|
|
137
|
+
const uri = new URI('file:///project/src');
|
|
140
138
|
const opts1 = { recursive: true, excludes: [] };
|
|
141
139
|
const opts2 = { recursive: false, excludes: [] };
|
|
142
140
|
const d1 = await fileService.doWatch(uri, opts1);
|
|
143
141
|
const d2 = await fileService.doWatch(uri, opts2);
|
|
144
142
|
// The recursive watcher subsumes the non-recursive one on the same URI
|
|
145
|
-
|
|
143
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
146
144
|
d2.dispose();
|
|
147
|
-
|
|
145
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
148
146
|
d1.dispose();
|
|
149
|
-
|
|
147
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
150
148
|
});
|
|
151
149
|
it('should support three refs and only dispose when all are gone', async () => {
|
|
152
|
-
const uri = new
|
|
150
|
+
const uri = new URI('file:///project/src');
|
|
153
151
|
const opts = { recursive: false, excludes: [] };
|
|
154
152
|
const d1 = await fileService.doWatch(uri, opts);
|
|
155
153
|
const d2 = await fileService.doWatch(uri, opts);
|
|
156
154
|
const d3 = await fileService.doWatch(uri, opts);
|
|
157
|
-
|
|
155
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
158
156
|
d1.dispose();
|
|
159
|
-
|
|
157
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
160
158
|
d2.dispose();
|
|
161
|
-
|
|
159
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
162
160
|
d3.dispose();
|
|
163
|
-
|
|
161
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
164
162
|
});
|
|
165
163
|
});
|
|
166
164
|
// ── (B) Parent subsumption of new child ────────────────────────────
|
|
167
165
|
describe('parent subsumption', () => {
|
|
168
166
|
it('should not create an OS watcher when a recursive parent already covers the child', async () => {
|
|
169
|
-
const parentUri = new
|
|
170
|
-
const childUri = new
|
|
167
|
+
const parentUri = new URI('file:///project');
|
|
168
|
+
const childUri = new URI('file:///project/src');
|
|
171
169
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
172
170
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
173
171
|
// Only the parent's OS watcher should exist
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
173
|
+
expect(mockProvider.watchers[0].resource.toString()).to.equal(parentUri.toString());
|
|
176
174
|
});
|
|
177
175
|
it('should not subsume a child that is excluded by the parent', async () => {
|
|
178
|
-
const parentUri = new
|
|
179
|
-
const childUri = new
|
|
176
|
+
const parentUri = new URI('file:///project');
|
|
177
|
+
const childUri = new URI('file:///project/node_modules/foo');
|
|
180
178
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
181
179
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
182
180
|
// The child should get its own real watcher
|
|
183
|
-
|
|
181
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
184
182
|
});
|
|
185
183
|
it('should not subsume when the parent is non-recursive', async () => {
|
|
186
|
-
const parentUri = new
|
|
187
|
-
const childUri = new
|
|
184
|
+
const parentUri = new URI('file:///project');
|
|
185
|
+
const childUri = new URI('file:///project/src');
|
|
188
186
|
await fileService.doWatch(parentUri, { recursive: false, excludes: [] });
|
|
189
187
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
190
|
-
|
|
188
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
191
189
|
});
|
|
192
190
|
it('should subsume a deeply nested child', async () => {
|
|
193
|
-
const parentUri = new
|
|
194
|
-
const childUri = new
|
|
191
|
+
const parentUri = new URI('file:///project');
|
|
192
|
+
const childUri = new URI('file:///project/src/main/java/com/example');
|
|
195
193
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
196
194
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
197
|
-
|
|
195
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
198
196
|
});
|
|
199
197
|
it('should not subsume a sibling directory', async () => {
|
|
200
|
-
const parentUri = new
|
|
201
|
-
const siblingUri = new
|
|
198
|
+
const parentUri = new URI('file:///project/src');
|
|
199
|
+
const siblingUri = new URI('file:///project/test');
|
|
202
200
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
203
201
|
await fileService.doWatch(siblingUri, { recursive: false, excludes: [] });
|
|
204
|
-
|
|
202
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
205
203
|
});
|
|
206
204
|
it('should not subsume a child when it is under an excluded ancestor directory', async () => {
|
|
207
|
-
const parentUri = new
|
|
205
|
+
const parentUri = new URI('file:///project');
|
|
208
206
|
// node_modules is excluded, so anything under it should not be subsumed
|
|
209
|
-
const childUri = new
|
|
207
|
+
const childUri = new URI('file:///project/node_modules/pkg/lib');
|
|
210
208
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
211
209
|
await fileService.doWatch(childUri, { recursive: true, excludes: [] });
|
|
212
210
|
// Child needs its own watcher since it's under an excluded directory
|
|
213
|
-
|
|
211
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
214
212
|
});
|
|
215
213
|
});
|
|
216
214
|
// ── (D) New recursive parent subsumes existing children ────────────
|
|
217
215
|
describe('child subsumption by new parent', () => {
|
|
218
216
|
it('should subsume existing non-recursive children when a new recursive parent is created', async () => {
|
|
219
|
-
const childUri1 = new
|
|
220
|
-
const childUri2 = new
|
|
221
|
-
const parentUri = new
|
|
217
|
+
const childUri1 = new URI('file:///project/src');
|
|
218
|
+
const childUri2 = new URI('file:///project/test');
|
|
219
|
+
const parentUri = new URI('file:///project');
|
|
222
220
|
await fileService.doWatch(childUri1, { recursive: false, excludes: [] });
|
|
223
221
|
await fileService.doWatch(childUri2, { recursive: false, excludes: [] });
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
223
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
226
224
|
// Adding a recursive parent should subsume both children
|
|
227
225
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
228
226
|
// Three watchers created total, but only the parent should remain live
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
227
|
+
expect(mockProvider.watchers).to.have.lengthOf(3);
|
|
228
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
229
|
+
expect(mockProvider.watchers[0].disposed).to.be.true; // child1 real watcher disposed
|
|
230
|
+
expect(mockProvider.watchers[1].disposed).to.be.true; // child2 real watcher disposed
|
|
231
|
+
expect(mockProvider.watchers[2].disposed).to.be.false; // parent alive
|
|
234
232
|
});
|
|
235
233
|
it('should subsume existing recursive children and re-parent grandchildren', async () => {
|
|
236
|
-
const grandchildUri = new
|
|
237
|
-
const childUri = new
|
|
238
|
-
const parentUri = new
|
|
234
|
+
const grandchildUri = new URI('file:///project/src/deep');
|
|
235
|
+
const childUri = new URI('file:///project/src');
|
|
236
|
+
const parentUri = new URI('file:///project');
|
|
239
237
|
// Create a recursive child first, then a grandchild under it
|
|
240
238
|
await fileService.doWatch(childUri, { recursive: true, excludes: [] });
|
|
241
239
|
await fileService.doWatch(grandchildUri, { recursive: false, excludes: [] });
|
|
242
240
|
// Grandchild should already be subsumed by the child
|
|
243
|
-
|
|
241
|
+
expect(mockProvider.watchers).to.have.lengthOf(1); // only child has a real watcher
|
|
244
242
|
// Now create a parent that covers everything
|
|
245
243
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
246
244
|
// Child's real watcher gets disposed, parent takes over
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
245
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
246
|
+
expect(mockProvider.watchers[0].disposed).to.be.true; // child disposed
|
|
247
|
+
expect(mockProvider.watchers[1].disposed).to.be.false; // parent alive
|
|
250
248
|
});
|
|
251
249
|
it('should promote and re-index a recursive grandchild excluded by the new parent', async () => {
|
|
252
|
-
const childUri = new
|
|
253
|
-
const grandchildUri = new
|
|
254
|
-
const parentUri = new
|
|
250
|
+
const childUri = new URI('file:///project/src');
|
|
251
|
+
const grandchildUri = new URI('file:///project/src/vendor');
|
|
252
|
+
const parentUri = new URI('file:///project');
|
|
255
253
|
// Child and grandchild share the same excludes — grandchild is compatible with child.
|
|
256
254
|
// The pattern '**/src/vendor' does NOT match the relative path from child to grandchild
|
|
257
255
|
// ('vendor'), so isExcludedByParent(child, grandchild) is false — grandchild is subsumed.
|
|
258
256
|
await fileService.doWatch(childUri, { recursive: true, excludes: ['**/src/vendor'] });
|
|
259
257
|
await fileService.doWatch(grandchildUri, { recursive: true, excludes: ['**/src/vendor'] });
|
|
260
|
-
|
|
261
|
-
|
|
258
|
+
expect(mockProvider.watchers).to.have.lengthOf(1); // only child has a real watcher
|
|
259
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
262
260
|
// Create a parent with the same excludes. The parent subsumes the child
|
|
263
261
|
// (areExcludesCompatible passes). But the grandchild at /project/src/vendor has
|
|
264
262
|
// relative path 'src/vendor' from /project, which DOES match '**/src/vendor'.
|
|
@@ -266,20 +264,20 @@ describe('FileService watcher deduplication', () => {
|
|
|
266
264
|
// with its own real watcher and re-indexed.
|
|
267
265
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/src/vendor'] });
|
|
268
266
|
// Parent is live (subsumes child). Grandchild is promoted with its own real watcher.
|
|
269
|
-
|
|
267
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
270
268
|
// A new watcher under the promoted grandchild should be subsumed by it,
|
|
271
269
|
// which only works if the grandchild was re-indexed after promotion.
|
|
272
|
-
const deepUri = new
|
|
270
|
+
const deepUri = new URI('file:///project/src/vendor/utils');
|
|
273
271
|
await fileService.doWatch(deepUri, { recursive: false, excludes: [] });
|
|
274
272
|
// No new OS watcher — the promoted grandchild covers it
|
|
275
|
-
|
|
273
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
276
274
|
});
|
|
277
275
|
it('should not delete parent index when subsuming a recursive child at the same URI', async () => {
|
|
278
|
-
const uri = new
|
|
279
|
-
const childUri = new
|
|
276
|
+
const uri = new URI('file:///project');
|
|
277
|
+
const childUri = new URI('file:///project/src');
|
|
280
278
|
// Create a recursive watcher with excludes
|
|
281
279
|
await fileService.doWatch(uri, { recursive: true, excludes: ['**/node_modules'] });
|
|
282
|
-
|
|
280
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
283
281
|
// Create a new recursive watcher at the SAME URI with no excludes.
|
|
284
282
|
// Different key (different excludes), so it's a new entry. The new watcher
|
|
285
283
|
// subsumes the old one via subsumeExistingChildren. The old watcher is recursive,
|
|
@@ -287,193 +285,193 @@ describe('FileService watcher deduplication', () => {
|
|
|
287
285
|
// index entry (they share the same URI).
|
|
288
286
|
await fileService.doWatch(uri, { recursive: true, excludes: [] });
|
|
289
287
|
// Old watcher's OS watcher is disposed; new parent is live
|
|
290
|
-
|
|
288
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
291
289
|
// A child watcher should be subsumed by the new parent. Without the fix,
|
|
292
290
|
// the parent's index entry was deleted, causing unnecessary OS watchers.
|
|
293
291
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
294
292
|
// No new OS watcher — parent's index entry is intact
|
|
295
|
-
|
|
293
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
296
294
|
});
|
|
297
295
|
it('should not subsume excluded children when creating a new parent', async () => {
|
|
298
|
-
const childUri = new
|
|
299
|
-
const parentUri = new
|
|
296
|
+
const childUri = new URI('file:///project/node_modules/pkg');
|
|
297
|
+
const parentUri = new URI('file:///project');
|
|
300
298
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
301
|
-
|
|
299
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
302
300
|
// Parent excludes node_modules
|
|
303
301
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
304
302
|
// Child should NOT be subsumed — both watchers should remain live
|
|
305
|
-
|
|
303
|
+
expect(liveWatcherCount(mockProvider)).to.equal(2);
|
|
306
304
|
});
|
|
307
305
|
});
|
|
308
306
|
// ── Disposal and promotion ─────────────────────────────────────────
|
|
309
307
|
describe('disposal and promotion', () => {
|
|
310
308
|
it('should promote subsumed children by creating real watchers when the parent is disposed', async () => {
|
|
311
|
-
const parentUri = new
|
|
312
|
-
const childUri = new
|
|
309
|
+
const parentUri = new URI('file:///project');
|
|
310
|
+
const childUri = new URI('file:///project/src');
|
|
313
311
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
314
312
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
315
313
|
// Only parent watcher is real
|
|
316
|
-
|
|
314
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
317
315
|
// Dispose the parent
|
|
318
316
|
parentDisposable.dispose();
|
|
319
317
|
// Child should now have its own real watcher
|
|
320
|
-
|
|
318
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
321
319
|
// The new watcher (index 1) should be for the child
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
320
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
321
|
+
expect(mockProvider.watchers[0].disposed).to.be.true; // parent
|
|
322
|
+
expect(mockProvider.watchers[1].disposed).to.be.false; // child promoted
|
|
323
|
+
expect(mockProvider.watchers[1].resource.toString()).to.equal(childUri.toString());
|
|
326
324
|
});
|
|
327
325
|
it('should re-parent children to another existing parent on disposal', async () => {
|
|
328
|
-
const grandparentUri = new
|
|
329
|
-
const parentUri = new
|
|
330
|
-
const childUri = new
|
|
326
|
+
const grandparentUri = new URI('file:///project');
|
|
327
|
+
const parentUri = new URI('file:///project/src');
|
|
328
|
+
const childUri = new URI('file:///project/src/components');
|
|
331
329
|
// Create grandparent, then parent, then child
|
|
332
330
|
await fileService.doWatch(grandparentUri, { recursive: true, excludes: [] });
|
|
333
331
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
334
332
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
335
333
|
// Grandparent subsumed parent; parent did not get a real watcher.
|
|
336
334
|
// Child was also subsumed (by grandparent after re-parenting).
|
|
337
|
-
|
|
335
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
338
336
|
// Dispose the parent
|
|
339
337
|
parentDisposable.dispose();
|
|
340
338
|
// Grandparent still covers the child — no new OS watcher needed
|
|
341
|
-
|
|
339
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
342
340
|
});
|
|
343
341
|
it('should promote multiple children when a parent is disposed', async () => {
|
|
344
|
-
const parentUri = new
|
|
345
|
-
const child1Uri = new
|
|
346
|
-
const child2Uri = new
|
|
347
|
-
const child3Uri = new
|
|
342
|
+
const parentUri = new URI('file:///project');
|
|
343
|
+
const child1Uri = new URI('file:///project/src');
|
|
344
|
+
const child2Uri = new URI('file:///project/test');
|
|
345
|
+
const child3Uri = new URI('file:///project/docs');
|
|
348
346
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
349
347
|
await fileService.doWatch(child1Uri, { recursive: false, excludes: [] });
|
|
350
348
|
await fileService.doWatch(child2Uri, { recursive: false, excludes: [] });
|
|
351
349
|
await fileService.doWatch(child3Uri, { recursive: false, excludes: [] });
|
|
352
|
-
|
|
350
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
353
351
|
parentDisposable.dispose();
|
|
354
352
|
// All three children should now have their own real watchers
|
|
355
|
-
|
|
353
|
+
expect(liveWatcherCount(mockProvider)).to.equal(3);
|
|
356
354
|
});
|
|
357
355
|
it('should not corrupt index when disposing a subsumed recursive watcher at the same URI', async () => {
|
|
358
|
-
const uri = new
|
|
359
|
-
const childUri = new
|
|
356
|
+
const uri = new URI('file:///project');
|
|
357
|
+
const childUri = new URI('file:///project/src');
|
|
360
358
|
// Watcher A: recursive, no excludes — gets indexed
|
|
361
359
|
await fileService.doWatch(uri, { recursive: true, excludes: [] });
|
|
362
360
|
// Watcher B: recursive, with excludes at the same URI — subsumed by A (not indexed)
|
|
363
361
|
const bDisposable = await fileService.doWatch(uri, { recursive: true, excludes: ['**/node_modules'] });
|
|
364
|
-
|
|
362
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
365
363
|
// Disposing B must NOT remove A's index entry.
|
|
366
364
|
// Without the fix, removeFromRecursiveIndex would delete /project from
|
|
367
365
|
// the tree, causing subsequent child watchers to miss A as a parent.
|
|
368
366
|
bDisposable.dispose();
|
|
369
367
|
// A child watcher should still be subsumed by A
|
|
370
368
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
371
|
-
|
|
369
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
372
370
|
});
|
|
373
371
|
it('should handle disposing a subsumed child cleanly', async () => {
|
|
374
|
-
const parentUri = new
|
|
375
|
-
const childUri = new
|
|
372
|
+
const parentUri = new URI('file:///project');
|
|
373
|
+
const childUri = new URI('file:///project/src');
|
|
376
374
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
377
375
|
const childDisposable = await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
378
|
-
|
|
376
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
379
377
|
// Disposing the subsumed child should not affect the parent's watcher
|
|
380
378
|
childDisposable.dispose();
|
|
381
|
-
|
|
379
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
382
380
|
});
|
|
383
381
|
it('should handle dispose-then-rewatch correctly', async () => {
|
|
384
|
-
const parentUri = new
|
|
385
|
-
const childUri = new
|
|
382
|
+
const parentUri = new URI('file:///project');
|
|
383
|
+
const childUri = new URI('file:///project/src');
|
|
386
384
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
387
385
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
388
386
|
parentDisposable.dispose();
|
|
389
387
|
// Child is promoted, now re-create the parent
|
|
390
388
|
const parentDisposable2 = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
391
389
|
// The child should be subsumed again — its promoted watcher should be disposed
|
|
392
|
-
|
|
390
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
393
391
|
parentDisposable2.dispose();
|
|
394
392
|
// Child promoted again
|
|
395
|
-
|
|
393
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
396
394
|
});
|
|
397
395
|
});
|
|
398
396
|
// ── Exclude pattern matching ───────────────────────────────────────
|
|
399
397
|
describe('exclude pattern matching', () => {
|
|
400
398
|
it('should exclude with glob patterns using **', async () => {
|
|
401
|
-
const parentUri = new
|
|
402
|
-
const excludedChild = new
|
|
399
|
+
const parentUri = new URI('file:///project');
|
|
400
|
+
const excludedChild = new URI('file:///project/dist/bundle.js');
|
|
403
401
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/dist'] });
|
|
404
402
|
await fileService.doWatch(excludedChild, { recursive: false, excludes: [] });
|
|
405
403
|
// Should not be subsumed because dist is excluded
|
|
406
|
-
|
|
404
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
407
405
|
});
|
|
408
406
|
it('should handle multiple exclude patterns', async () => {
|
|
409
|
-
const parentUri = new
|
|
410
|
-
const nmChild = new
|
|
411
|
-
const distChild = new
|
|
412
|
-
const srcChild = new
|
|
407
|
+
const parentUri = new URI('file:///project');
|
|
408
|
+
const nmChild = new URI('file:///project/node_modules/pkg');
|
|
409
|
+
const distChild = new URI('file:///project/dist/out');
|
|
410
|
+
const srcChild = new URI('file:///project/src/main');
|
|
413
411
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules', '**/dist'] });
|
|
414
412
|
await fileService.doWatch(nmChild, { recursive: false, excludes: [] });
|
|
415
413
|
await fileService.doWatch(distChild, { recursive: false, excludes: [] });
|
|
416
414
|
await fileService.doWatch(srcChild, { recursive: false, excludes: [] });
|
|
417
415
|
// nm and dist children need their own watchers; src is subsumed
|
|
418
|
-
|
|
416
|
+
expect(mockProvider.watchers).to.have.lengthOf(3); // parent + nm + dist
|
|
419
417
|
});
|
|
420
418
|
it('should exclude based on ancestor directory matching', async () => {
|
|
421
|
-
const parentUri = new
|
|
419
|
+
const parentUri = new URI('file:///project');
|
|
422
420
|
// The exclude is for node_modules — anything under it should also be excluded
|
|
423
|
-
const deepChild = new
|
|
421
|
+
const deepChild = new URI('file:///project/node_modules/pkg/lib/index.js');
|
|
424
422
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
425
423
|
await fileService.doWatch(deepChild, { recursive: false, excludes: [] });
|
|
426
|
-
|
|
424
|
+
expect(mockProvider.watchers).to.have.lengthOf(2);
|
|
427
425
|
});
|
|
428
426
|
it('should not exclude a non-matching path', async () => {
|
|
429
|
-
const parentUri = new
|
|
430
|
-
const childUri = new
|
|
427
|
+
const parentUri = new URI('file:///project');
|
|
428
|
+
const childUri = new URI('file:///project/src/node_modules_backup/file.ts');
|
|
431
429
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
432
430
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
433
431
|
// 'node_modules_backup' does not match '**/node_modules', so child should be subsumed
|
|
434
|
-
|
|
432
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
435
433
|
});
|
|
436
434
|
});
|
|
437
435
|
// ── Edge cases ─────────────────────────────────────────────────────
|
|
438
436
|
describe('edge cases', () => {
|
|
439
437
|
it('should promote a non-recursive watcher when its recursive same-URI subsumer is disposed', async () => {
|
|
440
|
-
const uri = new
|
|
438
|
+
const uri = new URI('file:///project/src');
|
|
441
439
|
const recursiveOpts = { recursive: true, excludes: [] };
|
|
442
440
|
const nonRecursiveOpts = { recursive: false, excludes: [] };
|
|
443
441
|
const d1 = await fileService.doWatch(uri, recursiveOpts);
|
|
444
442
|
const d2 = await fileService.doWatch(uri, nonRecursiveOpts);
|
|
445
443
|
// findSubstr matches exact URIs, so the recursive watcher subsumes the non-recursive one
|
|
446
|
-
|
|
444
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
447
445
|
// Disposing the recursive watcher promotes the non-recursive one
|
|
448
446
|
d1.dispose();
|
|
449
|
-
|
|
447
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
450
448
|
d2.dispose();
|
|
451
|
-
|
|
449
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
452
450
|
});
|
|
453
451
|
it('should handle double dispose gracefully', async () => {
|
|
454
|
-
const uri = new
|
|
452
|
+
const uri = new URI('file:///project/src');
|
|
455
453
|
const d1 = await fileService.doWatch(uri, { recursive: false, excludes: [] });
|
|
456
454
|
d1.dispose();
|
|
457
455
|
// Double dispose should not throw
|
|
458
456
|
d1.dispose();
|
|
459
|
-
|
|
457
|
+
expect(liveWatcherCount(mockProvider)).to.equal(0);
|
|
460
458
|
});
|
|
461
459
|
it('should handle many watchers under one parent', async () => {
|
|
462
|
-
const parentUri = new
|
|
460
|
+
const parentUri = new URI('file:///project');
|
|
463
461
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
464
462
|
const childDisposables = [];
|
|
465
463
|
for (let i = 0; i < 20; i++) {
|
|
466
|
-
const d = await fileService.doWatch(new
|
|
464
|
+
const d = await fileService.doWatch(new URI(`file:///project/dir${i}`), { recursive: false, excludes: [] });
|
|
467
465
|
childDisposables.push(d);
|
|
468
466
|
}
|
|
469
467
|
// Only the parent's real watcher exists
|
|
470
|
-
|
|
471
|
-
|
|
468
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
469
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
472
470
|
// Dispose all children — parent still alive
|
|
473
471
|
for (const d of childDisposables) {
|
|
474
472
|
d.dispose();
|
|
475
473
|
}
|
|
476
|
-
|
|
474
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
477
475
|
});
|
|
478
476
|
});
|
|
479
477
|
});
|
|
@@ -483,18 +481,18 @@ describe('FileService watcher deduplication', () => {
|
|
|
483
481
|
*/
|
|
484
482
|
function createEventMockProvider(caseSensitive = true) {
|
|
485
483
|
const watchers = [];
|
|
486
|
-
const fileChangeEmitter = new
|
|
484
|
+
const fileChangeEmitter = new Emitter();
|
|
487
485
|
const provider = {
|
|
488
486
|
watchers,
|
|
489
487
|
fileChangeEmitter,
|
|
490
488
|
capabilities: caseSensitive ? 1024 /* FileSystemProviderCapabilities.PathCaseSensitive */ : 0,
|
|
491
|
-
onDidChangeCapabilities: () =>
|
|
489
|
+
onDidChangeCapabilities: () => Disposable.NULL,
|
|
492
490
|
onDidChangeFile: fileChangeEmitter.event,
|
|
493
|
-
onFileWatchError: () =>
|
|
491
|
+
onFileWatchError: () => Disposable.NULL,
|
|
494
492
|
watch(resource, options) {
|
|
495
493
|
const watcher = {
|
|
496
494
|
resource, options, disposed: false,
|
|
497
|
-
disposable:
|
|
495
|
+
disposable: Disposable.create(() => { watcher.disposed = true; }),
|
|
498
496
|
};
|
|
499
497
|
watchers.push(watcher);
|
|
500
498
|
return watcher.disposable;
|
|
@@ -517,13 +515,13 @@ describe('FileService watcher event delivery', () => {
|
|
|
517
515
|
let provider;
|
|
518
516
|
let disJSDOM;
|
|
519
517
|
before(() => {
|
|
520
|
-
disJSDOM =
|
|
518
|
+
disJSDOM = enableJSDOM();
|
|
521
519
|
});
|
|
522
520
|
after(() => {
|
|
523
521
|
disJSDOM();
|
|
524
522
|
});
|
|
525
523
|
beforeEach(() => {
|
|
526
|
-
fileService = new
|
|
524
|
+
fileService = new FileService();
|
|
527
525
|
provider = createEventMockProvider();
|
|
528
526
|
fileService.registerProvider('file', provider);
|
|
529
527
|
});
|
|
@@ -534,17 +532,17 @@ describe('FileService watcher event delivery', () => {
|
|
|
534
532
|
received.push(change.resource);
|
|
535
533
|
}
|
|
536
534
|
});
|
|
537
|
-
const parentUri = new
|
|
538
|
-
const childUri = new
|
|
535
|
+
const parentUri = new URI('file:///project');
|
|
536
|
+
const childUri = new URI('file:///project/src');
|
|
539
537
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
540
538
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
541
539
|
// Child is subsumed — only parent has a real watcher
|
|
542
|
-
|
|
540
|
+
expect(liveWatcherCount(provider)).to.equal(1);
|
|
543
541
|
// Simulate a change under the child path — should be delivered through the parent
|
|
544
|
-
const changedFile = new
|
|
542
|
+
const changedFile = new URI('file:///project/src/index.ts');
|
|
545
543
|
provider.simulateChange(changedFile);
|
|
546
|
-
|
|
547
|
-
|
|
544
|
+
expect(received).to.have.lengthOf(1);
|
|
545
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
548
546
|
});
|
|
549
547
|
it('should deliver events after a child is promoted due to parent disposal', async () => {
|
|
550
548
|
const received = [];
|
|
@@ -553,18 +551,18 @@ describe('FileService watcher event delivery', () => {
|
|
|
553
551
|
received.push(change.resource);
|
|
554
552
|
}
|
|
555
553
|
});
|
|
556
|
-
const parentUri = new
|
|
557
|
-
const childUri = new
|
|
554
|
+
const parentUri = new URI('file:///project');
|
|
555
|
+
const childUri = new URI('file:///project/src');
|
|
558
556
|
const parentDisposable = await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
559
557
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
560
558
|
// Dispose parent — child gets promoted with its own real watcher
|
|
561
559
|
parentDisposable.dispose();
|
|
562
|
-
|
|
560
|
+
expect(liveWatcherCount(provider)).to.equal(1);
|
|
563
561
|
// Simulate a change — should still be delivered
|
|
564
|
-
const changedFile = new
|
|
562
|
+
const changedFile = new URI('file:///project/src/index.ts');
|
|
565
563
|
provider.simulateChange(changedFile);
|
|
566
|
-
|
|
567
|
-
|
|
564
|
+
expect(received).to.have.lengthOf(1);
|
|
565
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
568
566
|
});
|
|
569
567
|
it('should not let a parent with excludes suppress events for a child that needs them', async () => {
|
|
570
568
|
const received = [];
|
|
@@ -573,18 +571,18 @@ describe('FileService watcher event delivery', () => {
|
|
|
573
571
|
received.push(change.resource);
|
|
574
572
|
}
|
|
575
573
|
});
|
|
576
|
-
const parentUri = new
|
|
577
|
-
const childUri = new
|
|
574
|
+
const parentUri = new URI('file:///project');
|
|
575
|
+
const childUri = new URI('file:///project/src');
|
|
578
576
|
await fileService.doWatch(parentUri, { recursive: true, excludes: ['**/node_modules'] });
|
|
579
577
|
await fileService.doWatch(childUri, { recursive: true, excludes: [] });
|
|
580
578
|
// Child is recursive with no excludes, parent has excludes — child should NOT be subsumed
|
|
581
579
|
// Both should have their own real watchers
|
|
582
|
-
|
|
580
|
+
expect(liveWatcherCount(provider)).to.equal(2);
|
|
583
581
|
// Simulate a change inside node_modules under the child — only the child's watcher would catch it
|
|
584
|
-
const changedFile = new
|
|
582
|
+
const changedFile = new URI('file:///project/src/node_modules/pkg/index.js');
|
|
585
583
|
provider.simulateChange(changedFile);
|
|
586
|
-
|
|
587
|
-
|
|
584
|
+
expect(received).to.have.lengthOf(1);
|
|
585
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
588
586
|
});
|
|
589
587
|
it('should preserve recursive watcher state through subsumption and promotion', async () => {
|
|
590
588
|
const received = [];
|
|
@@ -593,24 +591,24 @@ describe('FileService watcher event delivery', () => {
|
|
|
593
591
|
received.push(change.resource);
|
|
594
592
|
}
|
|
595
593
|
});
|
|
596
|
-
const grandparentUri = new
|
|
597
|
-
const parentUri = new
|
|
598
|
-
const childUri = new
|
|
594
|
+
const grandparentUri = new URI('file:///project');
|
|
595
|
+
const parentUri = new URI('file:///project/src');
|
|
596
|
+
const childUri = new URI('file:///project/src/lib');
|
|
599
597
|
// Create parent (recursive), then child under it
|
|
600
598
|
await fileService.doWatch(parentUri, { recursive: true, excludes: [] });
|
|
601
599
|
await fileService.doWatch(childUri, { recursive: false, excludes: [] });
|
|
602
|
-
|
|
600
|
+
expect(liveWatcherCount(provider)).to.equal(1); // only parent has real watcher
|
|
603
601
|
// Now create a grandparent that subsumes the parent
|
|
604
602
|
const gpDisposable = await fileService.doWatch(grandparentUri, { recursive: true, excludes: [] });
|
|
605
|
-
|
|
603
|
+
expect(liveWatcherCount(provider)).to.equal(1); // only grandparent is live
|
|
606
604
|
// Dispose the grandparent — parent should be promoted, child should re-parent to parent
|
|
607
605
|
gpDisposable.dispose();
|
|
608
|
-
|
|
606
|
+
expect(liveWatcherCount(provider)).to.equal(1); // promoted parent is live
|
|
609
607
|
// Simulate a change under the child — should still be delivered
|
|
610
|
-
const changedFile = new
|
|
608
|
+
const changedFile = new URI('file:///project/src/lib/utils.ts');
|
|
611
609
|
provider.simulateChange(changedFile);
|
|
612
|
-
|
|
613
|
-
|
|
610
|
+
expect(received).to.have.lengthOf(1);
|
|
611
|
+
expect(received[0].toString()).to.equal(changedFile.toString());
|
|
614
612
|
});
|
|
615
613
|
});
|
|
616
614
|
// ── files.watcherExclude applied to every watcher (#17247, #10794) ──────────
|
|
@@ -629,11 +627,11 @@ describe('FileService applies files.watcherExclude to all watchers', () => {
|
|
|
629
627
|
get: (name) => (name === 'files.watcherExclude' ? value : undefined)
|
|
630
628
|
};
|
|
631
629
|
}
|
|
632
|
-
before(() => { disJSDOM =
|
|
630
|
+
before(() => { disJSDOM = enableJSDOM(); });
|
|
633
631
|
after(() => { disJSDOM(); });
|
|
634
632
|
beforeEach(() => {
|
|
635
633
|
sandbox.restore();
|
|
636
|
-
fileService = new
|
|
634
|
+
fileService = new FileService();
|
|
637
635
|
mockProvider = createMockProvider();
|
|
638
636
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
639
637
|
sandbox.stub(fileService, 'withProvider').resolves(mockProvider);
|
|
@@ -645,42 +643,42 @@ describe('FileService applies files.watcherExclude to all watchers', () => {
|
|
|
645
643
|
'**/.git/objects/**': true,
|
|
646
644
|
'**/disabled/**': false
|
|
647
645
|
});
|
|
648
|
-
fileService.watch(new
|
|
646
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: [] });
|
|
649
647
|
await flush();
|
|
650
|
-
|
|
648
|
+
expect(mockProvider.watchers).to.have.lengthOf(1);
|
|
651
649
|
const excludes = mockProvider.watchers[0].options.excludes;
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
650
|
+
expect(excludes).to.include('**/node_modules/**');
|
|
651
|
+
expect(excludes).to.include('**/.git/objects/**');
|
|
652
|
+
expect(excludes).to.not.include('**/disabled/**');
|
|
655
653
|
// the temporary-upload exclude is still always applied
|
|
656
|
-
|
|
654
|
+
expect(excludes).to.include('**/theia_upload_*');
|
|
657
655
|
});
|
|
658
656
|
it('keeps the caller-supplied excludes alongside the configured ones', async () => {
|
|
659
657
|
stubWatcherExclude({ '**/node_modules/**': true });
|
|
660
|
-
fileService.watch(new
|
|
658
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: ['**/custom/**'] });
|
|
661
659
|
await flush();
|
|
662
660
|
const excludes = mockProvider.watchers[0].options.excludes;
|
|
663
|
-
|
|
664
|
-
|
|
661
|
+
expect(excludes).to.include('**/custom/**');
|
|
662
|
+
expect(excludes).to.include('**/node_modules/**');
|
|
665
663
|
});
|
|
666
664
|
it('still applies the temporary-upload exclude when no files.watcherExclude is configured', async () => {
|
|
667
665
|
stubWatcherExclude(undefined);
|
|
668
|
-
fileService.watch(new
|
|
666
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: [] });
|
|
669
667
|
await flush();
|
|
670
|
-
|
|
668
|
+
expect(mockProvider.watchers[0].options.excludes).to.deep.equal(['**/theia_upload_*']);
|
|
671
669
|
});
|
|
672
670
|
it('lets the workspace root watcher subsume an internal child watcher once excludes are consistent', async () => {
|
|
673
671
|
stubWatcherExclude({ '**/node_modules/**': true });
|
|
674
672
|
// The workspace root watcher already carries the configured excludes...
|
|
675
|
-
fileService.watch(new
|
|
673
|
+
fileService.watch(new URI('file:///project'), { recursive: true, excludes: ['**/node_modules/**'] });
|
|
676
674
|
// ...while an internal recursive watcher (e.g. @theia/ai-core) requests a child directory
|
|
677
675
|
// with empty excludes. Previously their exclude lists differed, so the child was not
|
|
678
676
|
// subsumed and produced a second OS watcher (and duplicate change events, see #17247).
|
|
679
|
-
fileService.watch(new
|
|
677
|
+
fileService.watch(new URI('file:///project/.prompts'), { recursive: true, excludes: [] });
|
|
680
678
|
await flush();
|
|
681
679
|
// With files.watcherExclude applied uniformly, the child's excludes now match the parent's,
|
|
682
680
|
// so the root watcher subsumes it — a single OS watcher instead of two.
|
|
683
|
-
|
|
681
|
+
expect(liveWatcherCount(mockProvider)).to.equal(1);
|
|
684
682
|
});
|
|
685
683
|
});
|
|
686
684
|
//# sourceMappingURL=file-service-watcher.spec.js.map
|