Reduce size of parser-typescript.js (#13431)
This commit is contained in:
1 parent
371c7093d0
commit
cd3e530c2e
2 files changed
+486
-55
No files matched your search
@@ -2,6 +2,7 @@ import path from "node:path";
|
||||
import { createRequire } from "node:module";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import { PROJECT_ROOT } from "../utils/index.mjs";
|
||||
import modifyTypescriptModule from "./modify-typescript-module.mjs";
|
||||
|
||||
const { require } = createEsmUtils(import.meta);
|
||||
|
||||
@@ -101,62 +102,8 @@ const parsers = [
|
||||
},
|
||||
{
|
||||
module: require.resolve("typescript"),
|
||||
process(text) {
|
||||
return text.replace(
|
||||
/(?<=\n)(?<indentString>\s+)function tryGetNodePerformanceHooks\(\) {.*?\n\k<indentString>}(?=\n)/s,
|
||||
"function tryGetNodePerformanceHooks() {}"
|
||||
);
|
||||
},
|
||||
process: modifyTypescriptModule,
|
||||
},
|
||||
|
||||
...Object.entries({
|
||||
// `typescript/lib/typescript.js` expose extra global objects
|
||||
// `TypeScript`, `toolsVersion`, `globalThis`
|
||||
'typeof process === "undefined" || process.browser': "false",
|
||||
'typeof globalThis === "object"': "true",
|
||||
|
||||
"_fs.realpathSync.native":
|
||||
"_fs.realpathSync && _fs.realpathSync.native",
|
||||
// Remove useless `ts.sys`
|
||||
"ts.sys = ": "ts.sys = undefined && ",
|
||||
|
||||
// Remove useless language service
|
||||
"ts.realizeDiagnostics = ": "ts.realizeDiagnostics = undefined && ",
|
||||
"ts.TypeScriptServicesFactory = ":
|
||||
"ts.TypeScriptServicesFactory = undefined && ",
|
||||
"var ShimBase = ": "var ShimBase = undefined && ",
|
||||
"var TypeScriptServicesFactory = ":
|
||||
"var TypeScriptServicesFactory = undefined && ",
|
||||
"var LanguageServiceShimObject = ":
|
||||
"var LanguageServiceShimObject = undefined && ",
|
||||
"var CoreServicesShimHostAdapter = ":
|
||||
"var CoreServicesShimHostAdapter = undefined && ",
|
||||
"var LanguageServiceShimHostAdapter = ":
|
||||
"var LanguageServiceShimHostAdapter = undefined && ",
|
||||
"var ScriptSnapshotShimAdapter = ":
|
||||
"var ScriptSnapshotShimAdapter = undefined && ",
|
||||
"var ClassifierShimObject = ":
|
||||
"var ClassifierShimObject = undefined && ",
|
||||
"var CoreServicesShimObject = ":
|
||||
"var CoreServicesShimObject = undefined && ",
|
||||
"function simpleForwardCall(": "0 && function simpleForwardCall(",
|
||||
"function forwardJSONCall(": "0 && function forwardJSONCall(",
|
||||
"function forwardCall(": "0 && function forwardCall(",
|
||||
"function realizeDiagnostics(": "0 && function realizeDiagnostics(",
|
||||
"function realizeDiagnostic(": "0 && function realizeDiagnostic(",
|
||||
"function convertClassifications(":
|
||||
"0 && function convertClassifications(",
|
||||
|
||||
// Dynamic `require()`s
|
||||
"ts.sys && ts.sys.require": "false",
|
||||
"require(etwModulePath)": "undefined",
|
||||
'require("source-map-support").install()': "",
|
||||
"require(modulePath)": "undefined",
|
||||
}).map(([find, replacement]) => ({
|
||||
module: require.resolve("typescript"),
|
||||
find,
|
||||
replacement,
|
||||
})),
|
||||
{
|
||||
module: require.resolve("debug/src/browser.js"),
|
||||
path: require.resolve("./shims/debug.cjs"),
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
import path from "node:path";
|
||||
import escapeStringRegexp from "escape-string-regexp";
|
||||
import { outdent } from "outdent";
|
||||
import { writeFile, PROJECT_ROOT } from "../utils/index.mjs";
|
||||
|
||||
/*
|
||||
Root submodule in `typescript.js` are bundled like
|
||||
|
||||
```js
|
||||
var ts;
|
||||
(function (ts) {
|
||||
// Submodule
|
||||
})(ts || (ts = {}));
|
||||
```
|
||||
*/
|
||||
|
||||
const SUBMODULE_START = escapeStringRegexp("var ts;\n(function (ts) {");
|
||||
const SUBMODULE_END = escapeStringRegexp("})(ts || (ts = {}));");
|
||||
|
||||
function getSubmodules(text, testFunction) {
|
||||
const regexp = new RegExp(
|
||||
[
|
||||
"(?<=\n)",
|
||||
`(?<before>${SUBMODULE_START})`,
|
||||
"(?=\n)",
|
||||
"(?<text>.*?)",
|
||||
"(?<=\n)",
|
||||
`(?<after>${SUBMODULE_END})`,
|
||||
"(?=\n)",
|
||||
].join(""),
|
||||
"gsu"
|
||||
);
|
||||
|
||||
return [...text.matchAll(regexp)]
|
||||
.filter((match) => testFunction(match.groups.text))
|
||||
.map((match) => ({
|
||||
start: match.index,
|
||||
end: match.index + match[0].length,
|
||||
...match.groups,
|
||||
}));
|
||||
}
|
||||
|
||||
function removeSubmodule(text, testFunction) {
|
||||
return replaceSubmodule(text, testFunction, "");
|
||||
}
|
||||
|
||||
function replaceSubmodule(text, testFunction, replacement) {
|
||||
const modules = getSubmodules(text, testFunction);
|
||||
if (modules.length !== 1) {
|
||||
return text;
|
||||
// TODO: Enable this check when merge to `next` branch
|
||||
// throw Object.assign(
|
||||
// new Error(
|
||||
// `Expect exactly one submodule to be found, got ${modules.length} submodules.`
|
||||
// ),
|
||||
// { modules }
|
||||
// );
|
||||
}
|
||||
|
||||
const [{ start, end, before, after }] = modules;
|
||||
if (replacement) {
|
||||
replacement = before + "\n" + replacement + "\n" + after;
|
||||
}
|
||||
|
||||
return text.slice(0, start) + replacement + text.slice(end);
|
||||
}
|
||||
|
||||
function removeMultipleSubmodules(text, testFunction) {
|
||||
let modules = getSubmodules(text, testFunction);
|
||||
|
||||
if (modules.length < 2) {
|
||||
throw new Error("Expect more than one submodules to be found");
|
||||
}
|
||||
|
||||
for (; modules.length > 0; modules = getSubmodules(text, testFunction)) {
|
||||
const [{ start, end }] = modules;
|
||||
text = text.slice(0, start) + text.slice(end);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function replaceAlignedCode(text, { start, end, replacement = "" }) {
|
||||
const regexp = new RegExp(
|
||||
[
|
||||
"(?<=\n)",
|
||||
"(?<indentString>\\s*)",
|
||||
escapeStringRegexp(start),
|
||||
".*?",
|
||||
"(?<=\n)",
|
||||
"\\k<indentString>",
|
||||
escapeStringRegexp(end),
|
||||
"(?=\n)",
|
||||
].join(""),
|
||||
"gsu"
|
||||
);
|
||||
|
||||
return text.replaceAll(regexp, replacement);
|
||||
}
|
||||
|
||||
function modifyTypescriptModule(text) {
|
||||
// Code after `globalThis` shim are useless
|
||||
const positionOfGlobalThisShim = text.indexOf(
|
||||
"// We polyfill `globalThis` here so re can reliably patch the global scope"
|
||||
);
|
||||
if (positionOfGlobalThisShim === -1) {
|
||||
throw new Error("Unexpected source.");
|
||||
}
|
||||
text = text.slice(0, positionOfGlobalThisShim) + "module.exports = ts;";
|
||||
|
||||
// File system
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.generateDjb2Hash = generateDjb2Hash;")
|
||||
);
|
||||
|
||||
// Language service
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.TypeScriptServicesFactory = TypeScriptServicesFactory;")
|
||||
);
|
||||
|
||||
// `ts.Version`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.Version = Version;")
|
||||
);
|
||||
|
||||
// `ts.transform`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transform = transform;")
|
||||
);
|
||||
|
||||
// `ts.BreakpointResolver`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.trimStart().startsWith("var BreakpointResolver;")
|
||||
);
|
||||
|
||||
// `ts.textChanges`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.trimStart().startsWith("var textChanges;")
|
||||
);
|
||||
|
||||
// `ts.preProcessFile`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.preProcessFile = preProcessFile;")
|
||||
);
|
||||
|
||||
// `ts.Rename`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.trimStart().startsWith("var Rename;")
|
||||
);
|
||||
|
||||
// `ts.SmartSelectionRange`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.trimStart().startsWith("var SmartSelectionRange;")
|
||||
);
|
||||
|
||||
// `ts.SignatureHelp`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.trimStart().startsWith("var SignatureHelp;")
|
||||
);
|
||||
|
||||
// `ts.InlayHints`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.trimStart().startsWith("var InlayHints;")
|
||||
);
|
||||
|
||||
// Sourcemap
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.getSourceMapper = getSourceMapper;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createSourceMapGenerator = createSourceMapGenerator;")
|
||||
);
|
||||
|
||||
// Suggestion
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes(
|
||||
"ts.computeSuggestionDiagnostics = computeSuggestionDiagnostics;"
|
||||
)
|
||||
);
|
||||
|
||||
// Tracing
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.startTracing = tracingEnabled.startTracing;")
|
||||
);
|
||||
|
||||
// Diagnostics
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createProgramHost = createProgramHost;")
|
||||
);
|
||||
|
||||
// `ts.transformTypeScript`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformTypeScript = transformTypeScript;")
|
||||
);
|
||||
|
||||
// `ts.createRuntimeTypeSerializer`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes(
|
||||
"ts.createRuntimeTypeSerializer = createRuntimeTypeSerializer;"
|
||||
)
|
||||
);
|
||||
|
||||
// Transform
|
||||
// `ts.transformLegacyDecorators`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformLegacyDecorators = transformLegacyDecorators;")
|
||||
);
|
||||
// `ts.transformES5`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES5 = transformES5;")
|
||||
);
|
||||
// `ts.transformES2015`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES2015 = transformES2015;")
|
||||
);
|
||||
// `ts.transformES2016`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES2016 = transformES2016;")
|
||||
);
|
||||
// `ts.transformES2017` & `ts.createSuperAccessVariableStatement`
|
||||
text = removeSubmodule(
|
||||
text,
|
||||
(text) =>
|
||||
text.includes("ts.transformES2017 = transformES2017;") &&
|
||||
text.includes(
|
||||
"ts.createSuperAccessVariableStatement = createSuperAccessVariableStatement;"
|
||||
)
|
||||
);
|
||||
// `ts.transformES2018`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES2018 = transformES2018;")
|
||||
);
|
||||
// `ts.transformES2019`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES2019 = transformES2019;")
|
||||
);
|
||||
// `ts.transformES2020`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES2020 = transformES2020;")
|
||||
);
|
||||
// `ts.transformES2021`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformES2021 = transformES2021;")
|
||||
);
|
||||
// `ts.transformESNext`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformESNext = transformESNext;")
|
||||
);
|
||||
// `ts.transformJsx`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformJsx = transformJsx;")
|
||||
);
|
||||
// `ts.transformGenerators`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformGenerators = transformGenerators;")
|
||||
);
|
||||
// `ts.transformModule`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformModule = transformModule;")
|
||||
);
|
||||
// `ts.transformSystemModule`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformSystemModule = transformSystemModule;")
|
||||
);
|
||||
// `ts.transformECMAScriptModule`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformECMAScriptModule = transformECMAScriptModule;")
|
||||
);
|
||||
// `ts.transformNodeModule`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformNodeModule = transformNodeModule;")
|
||||
);
|
||||
// `ts.transformClassFields`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformClassFields = transformClassFields;")
|
||||
);
|
||||
// `ts.transformDeclarations`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformDeclarations = transformDeclarations;")
|
||||
);
|
||||
// `ts.transformNodes` and more
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transformNodes = transformNodes;")
|
||||
);
|
||||
|
||||
// `ts.server`
|
||||
text = removeSubmodule(text, (text) => text.includes("(ts.server = {})"));
|
||||
|
||||
// `ts.JsTyping`
|
||||
text = removeSubmodule(text, (text) => text.includes("(ts.JsTyping = {})"));
|
||||
|
||||
// `ts.ClassificationType`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.ClassificationType = {})")
|
||||
);
|
||||
|
||||
// Build
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createSolutionBuilder = createSolutionBuilder;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.parseBuildCommand = parseBuildCommand;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createBuilderProgram = createBuilderProgram;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes(
|
||||
"ts.createSemanticDiagnosticsBuilderProgram = createSemanticDiagnosticsBuilderProgram;"
|
||||
)
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createResolutionCache = createResolutionCache;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createWatchCompilerHost = createWatchCompilerHost;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes(
|
||||
"ts.resolveConfigFileProjectName = resolveConfigFileProjectName;"
|
||||
)
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.getBuildInfo = getBuildInfo;")
|
||||
);
|
||||
|
||||
// Compile
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createCompilerHost = createCompilerHost;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.BuilderState = {})")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.transpile = transpile;")
|
||||
);
|
||||
|
||||
// Watch
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.getWatchFactory = getWatchFactory;")
|
||||
);
|
||||
|
||||
// `ts.canProduceDiagnostics`, `ts.createGetSymbolAccessibilityDiagnosticForNode`, and `ts.createGetSymbolAccessibilityDiagnosticForNode`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.canProduceDiagnostics = canProduceDiagnostics;")
|
||||
);
|
||||
|
||||
// `ts.moduleSpecifiers`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.moduleSpecifiers = {})")
|
||||
);
|
||||
|
||||
// `ts.trace`
|
||||
text = removeSubmodule(text, (text) => text.includes("ts.trace = trace;"));
|
||||
|
||||
// `ts.createTypeChecker`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createTypeChecker = createTypeChecker;")
|
||||
);
|
||||
|
||||
// `ts.DocumentHighlights`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.DocumentHighlights = {})")
|
||||
);
|
||||
|
||||
// `ts.createDocumentRegistry`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createDocumentRegistry = createDocumentRegistry;")
|
||||
);
|
||||
|
||||
// `ts.CallHierarchy`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.CallHierarchy = {})")
|
||||
);
|
||||
|
||||
// `ts.flattenDestructuringAssignment` and `ts.flattenDestructuringBinding`
|
||||
text = removeSubmodule(
|
||||
text,
|
||||
(text) =>
|
||||
text.includes(
|
||||
"ts.flattenDestructuringAssignment = flattenDestructuringAssignment"
|
||||
) &&
|
||||
text.includes(
|
||||
"ts.flattenDestructuringBinding = flattenDestructuringBinding"
|
||||
)
|
||||
);
|
||||
|
||||
// `ts.processTaggedTemplateExpression`
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes(
|
||||
"ts.processTaggedTemplateExpression = processTaggedTemplateExpression"
|
||||
)
|
||||
);
|
||||
|
||||
// Editor
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.getEditsForFileRename = getEditsForFileRename;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.GoToDefinition = {})")
|
||||
);
|
||||
text = removeSubmodule(text, (text) => text.includes("(ts.JsDoc = {})"));
|
||||
text = removeSubmodule(text, (text) => text.includes("(ts.NavigateTo = {})"));
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.NavigationBar = {})")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.OrganizeImports = {})")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.OutliningElementsCollector = {})")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("ts.createPatternMatcher = createPatternMatcher;")
|
||||
);
|
||||
text = removeSubmodule(text, (text) =>
|
||||
text.includes("(ts.SymbolDisplay = {})")
|
||||
);
|
||||
|
||||
// `ts.refactor` (multiple)
|
||||
text = removeMultipleSubmodules(text, (text) =>
|
||||
text.trimStart().startsWith("var refactor;")
|
||||
);
|
||||
|
||||
// `ts.codefix` (multiple)
|
||||
text = removeMultipleSubmodules(text, (text) =>
|
||||
text.trimStart().startsWith("var codefix;")
|
||||
);
|
||||
|
||||
// `ts.formatting` (multiple)
|
||||
text = removeMultipleSubmodules(text, (text) =>
|
||||
text.trimStart().startsWith("var formatting;")
|
||||
);
|
||||
|
||||
// `ts.Completions` (multiple)
|
||||
text = removeMultipleSubmodules(text, (text) =>
|
||||
text.trimStart().startsWith("var Completions;")
|
||||
);
|
||||
|
||||
// `ts.FindAllReferences` (multiple)
|
||||
text = removeMultipleSubmodules(text, (text) =>
|
||||
text.trimStart().startsWith("var FindAllReferences;")
|
||||
);
|
||||
|
||||
// Performance
|
||||
text = replaceSubmodule(
|
||||
text,
|
||||
(text) =>
|
||||
text.includes(
|
||||
"ts.tryGetNativePerformanceHooks = tryGetNativePerformanceHooks;"
|
||||
),
|
||||
outdent`
|
||||
ts.tryGetNativePerformanceHooks = () => {};
|
||||
ts.timestamp = Date.now;
|
||||
`
|
||||
);
|
||||
|
||||
for (const [find, replacement] of Object.entries({
|
||||
// yarn pnp
|
||||
"process.versions.pnp": "undefined",
|
||||
|
||||
// Dynamic `require()`s
|
||||
"ts.sys && ts.sys.require": "false",
|
||||
"require(etwModulePath)": "undefined",
|
||||
})) {
|
||||
text = text.replaceAll(find, replacement);
|
||||
}
|
||||
|
||||
text = replaceAlignedCode(text, {
|
||||
start: "var debugObjectHost = (function () {",
|
||||
end: "})();",
|
||||
});
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
// Save modified code to `{PROJECT_ROOT}/.tmp/modified-typescript.js` for debug
|
||||
const saveOutputToDisk = (process) => (text) => {
|
||||
const result = process(text);
|
||||
writeFile(path.join(PROJECT_ROOT, ".tmp/modified-typescript.js"), result);
|
||||
return result;
|
||||
};
|
||||
|
||||
export default saveOutputToDisk(modifyTypescriptModule);
|
||||
Reference in new issue
Block a user