diff --git a/src/compiler/core.ts b/src/compiler/core.ts index e69910846ecd2..93e5aaef932de 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2914,3 +2914,19 @@ function trimEndImpl(s: string) { } return s.slice(0, end + 1); } + +declare const process: any; + +/** @internal */ +export function isNodeLikeSystem(): boolean { + // This is defined here rather than in sys.ts to prevent a cycle from its + // use in performanceCore.ts. + // + // We don't use the presence of `require` to check if we are in Node; + // when bundled using esbuild, this function will be rewritten to `__require` + // and definitely exist. + return typeof process !== "undefined" + && process.nextTick + && !process.browser + && typeof module === "object"; +} diff --git a/src/compiler/performanceCore.ts b/src/compiler/performanceCore.ts index ce65f1d8894d6..3788da62b9072 100644 --- a/src/compiler/performanceCore.ts +++ b/src/compiler/performanceCore.ts @@ -1,4 +1,4 @@ -import { Version, VersionRange } from "./_namespaces/ts"; +import { isNodeLikeSystem, Version, VersionRange } from "./_namespaces/ts"; // The following definitions provide the minimum compatible support for the Web Performance User Timings API // between browsers and NodeJS: @@ -80,7 +80,7 @@ function tryGetWebPerformanceHooks(): PerformanceHooks | undefined { } function tryGetNodePerformanceHooks(): PerformanceHooks | undefined { - if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof module === "object" && typeof require === "function") { + if (isNodeLikeSystem()) { try { let performance: Performance; const { performance: nodePerformance, PerformanceObserver } = require("perf_hooks") as typeof import("perf_hooks"); diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 0fbddaaa95de9..84c75c9c390e3 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -2,7 +2,7 @@ import { AssertionLevel, closeFileWatcher, closeFileWatcherOf, combinePaths, Comparison, contains, containsPath, createGetCanonicalFileName, createMultiMap, Debug, directorySeparator, emptyArray, emptyFileSystemEntries, endsWith, enumerateInsertsAndDeletes, ESMap, FileSystemEntries, getDirectoryPath, getFallbackOptions, - getNormalizedAbsolutePath, getRelativePathToDirectoryOrUrl, getRootLength, getStringComparer, isArray, isString, + getNormalizedAbsolutePath, getRelativePathToDirectoryOrUrl, getRootLength, getStringComparer, isArray, isNodeLikeSystem, isString, Map, mapDefined, matchesExclude, matchFiles, memoize, noop, normalizePath, normalizeSlashes, orderedRemoveItem, Path, perfLogger, PollingWatchKind, RequireResult, resolveJSModule, some, startsWith, stringContains, timestamp, unorderedRemoveItem, WatchDirectoryKind, WatchFileKind, WatchOptions, writeFileEnsuringDirectories, @@ -1974,9 +1974,7 @@ export let sys: System = (() => { } let sys: System | undefined; - if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") { - // process and process.nextTick checks if current environment is node-like - // process.browser check excludes webpack and browserify + if (isNodeLikeSystem()) { sys = getNodeSystem(); } if (sys) { diff --git a/src/services/globalThisShim.ts b/src/services/globalThisShim.ts index 9a8978bdb2644..757442fb55ef7 100644 --- a/src/services/globalThisShim.ts +++ b/src/services/globalThisShim.ts @@ -1,4 +1,4 @@ -import { TypeScriptServicesFactory, versionMajorMinor } from "./_namespaces/ts"; +import { isNodeLikeSystem, TypeScriptServicesFactory, versionMajorMinor } from "./_namespaces/ts"; // We polyfill `globalThis` here so re can reliably patch the global scope // in the contexts we want to in the same way across script and module formats @@ -47,7 +47,7 @@ declare global { // if `process` is undefined, we're probably not running in node - patch legacy members onto the global scope // @ts-ignore -if (typeof process === "undefined" || process.browser) { +if (!isNodeLikeSystem()) { /// TODO: this is used by VS, clean this up on both sides of the interface //@ts-ignore