constructor(provider, syncProvider, providerContext) {
		this._provider = provider;
		this._syncProvider = syncProvider;
		this._providerContext = providerContext;
		this._activeAsyncOperations = new Map();

		this.provide = this._provider
			? // Comment to align jsdoc
				/**
				 * @param {PathLike | PathOrFileDescriptor} path path
				 * @param {object | FileSystemCallback<EXPECTED_ANY> | undefined} options options
				 * @param {FileSystemCallback<EXPECTED_ANY>=} callback callback
				 * @returns {EXPECTED_ANY} result
				 */
				(path, options, callback) => {
					if (typeof options === "function") {
						callback =
							/** @type {FileSystemCallback<EXPECTED_ANY>} */
							(options);
						options = undefined;
					}
					if (
						typeof path !== "string" &&
						!Buffer.isBuffer(path) &&
						!(path instanceof URL) &&
						typeof path !== "number"
					) {
						/** @type {EXPECTED_FUNCTION} */
						(callback)(
							new TypeError("path must be a string, Buffer, URL or number"),
						);
						return;
					}
					if (options) {
						return /** @type {EXPECTED_FUNCTION} */ (this._provider).call(
							this._providerContext,
							path,
							options,
							callback,
						);
					}
					let callbacks = this._activeAsyncOperations.get(path);
					if (callbacks) {
						callbacks.push(callback);
						return;
					}
					this._activeAsyncOperations.set(path, (callbacks = [callback]));
					/** @type {EXPECTED_FUNCTION} */
					(provider)(
						path,
						/**
						 * @param {Error} err error
						 * @param {EXPECTED_ANY} result result
						 */
						(err, result) => {
							this._activeAsyncOperations.delete(path);
							runCallbacks(callbacks, err, result);
						},
					);
				}
			: null;
		this.provideSync = this._syncProvider
			? // Comment to align jsdoc
				/**
				 * @param {PathLike | PathOrFileDescriptor} path path
				 * @param {object=} options options
				 * @returns {EXPECTED_ANY} result
				 */
				(path, options) =>
					/** @type {EXPECTED_FUNCTION} */ (this._syncProvider).call(
						this._providerContext,
						path,
						options,
					)
			: null;
	}
@param {EXPECTED_FUNCTION | undefined} provider async method in filesystem
@param {EXPECTED_FUNCTION | undefined} syncProvider sync method in filesystem
@param {BaseFileSystem} providerContext call context for the provider methods