extensions/typescript-language-features/web/webServer.ts/returnEmptyString
function serverCreateWebSystem(host: WebHost, args: string[], getExecutingFilePath: () => string):
	ts.server.ServerHost & {
		importPlugin?(root: string, moduleName: string): Promise<ts.server.ModuleImportResult>;
		getEnvironmentVariable(name: string): string;
	} {
	const returnEmptyString = () => '';
	const getExecutingDirectoryPath = memoize(() => memoize(() => ensureTrailingDirectorySeparator(getDirectoryPath(getExecutingFilePath()))));
	// Later we could map ^memfs:/ to do something special if we want to enable more functionality like module resolution or something like that
	const getWebPath = (path: string) => path.startsWith(directorySeparator) ? path.replace(directorySeparator, getExecutingDirectoryPath()) : undefined;

	return {
		args,
		newLine: '\r\n', // This can be configured by clients
		useCaseSensitiveFileNames: false, // Use false as the default on web since that is the safest option
		readFile: path => {
			const webPath = getWebPath(path);
			return webPath && host.readFile(webPath);
		},
		write: host.writeMessage.bind(host),
		watchFile: returnNoopFileWatcher,
		watchDirectory: returnNoopFileWatcher,

		getExecutingFilePath: () => directorySeparator,
		getCurrentDirectory: returnEmptyString, // For inferred project root if projectRoot path is not set, normalizing the paths

		/* eslint-disable no-restricted-globals */
		setTimeout: (cb, ms, ...args) => setTimeout(cb, ms, ...args),
		clearTimeout: handle => clearTimeout(handle),
		setImmediate: x => setTimeout(x, 0),
		clearImmediate: handle => clearTimeout(handle),
		/* eslint-enable no-restricted-globals */

		importPlugin: async (initialDir: string, moduleName: string): Promise<ts.server.ModuleImportResult> => {
			const packageRoot = combinePaths(initialDir, moduleName);

			let packageJson: any | undefined;
			try {
				const packageJsonResponse = await fetch(combinePaths(packageRoot, 'package.json'));
				packageJson = await packageJsonResponse.json();
			}
			catch (e) {
				return { module: undefined, error: new Error('Could not load plugin. Could not load "package.json".') };
			}

			const browser = packageJson.browser;
			if (!browser) {
				return { module: undefined, error: new Error('Could not load plugin. No "browser" field found in package.json.') };
			}

			const scriptPath = combinePaths(packageRoot, browser);
			try {
				const { default: module } = await import(/* webpackIgnore: true */scriptPath);
				return { module, error: undefined };
			}
			catch (e) {
				return { module: undefined, error: e };
			}
		},
		exit: notImplemented,

		// Debugging related
		getEnvironmentVariable: returnEmptyString, // TODO:: Used to enable debugging info
		// tryEnableSourceMapsForHost?(): void;
		// debugMode?: boolean;

		// For semantic server mode
		fileExists: path => {
			const webPath = getWebPath(path);
			return !!webPath && host.fileExists(webPath);
		},
		directoryExists: returnFalse, // Module resolution
		readDirectory: notImplemented, // Configured project, typing installer
		getDirectories: () => [], // For automatic type reference directives
		createDirectory: notImplemented, // compile On save
		writeFile: notImplemented, // compile on save
		resolvePath: identity, // Plugins
		// realpath? // Module resolution, symlinks
		// getModifiedTime // File watching
		// createSHA256Hash // telemetry of the project

		// Logging related
		// /*@internal*/ bufferFrom?(input: string, encoding?: string): Buffer;
		// gc?(): void;
		// getMemoryUsage?(): number;
	};
}