mirror of
https://github.com/Microsoft/vscode
synced 2024-10-04 02:14:06 +00:00
Mangle exported symbols (#182935)
* Mangle exported functions For #180461 This prototype tries to mangle exported functions, saving a further 440kb from the bundle size * Fix missing call * Also try mangling top level exported consts too * Fixing errors * Don't run on build files * Skip a few more manglings and revert change to namespace * Skip a few more monaco files * Also mangle consts that shadow types This increases savings up to 3325 * Also mangle exported classes * Skip mangling more localization functions for now * Opt out pfs * Update build script * Run find locations task in parallel This should speed up compile * Cleanup before close * Limit workers to avoid hitting memory limit * Limit pool size * Skip one more mangling * Exclude entrypoints from mangling * Try to fix web build and clean up code * Exempt a few more projects * Exempt another file * Also exempt html * Skip mangling ext entrypoints * Use prefix that can't be confused with rpc calls * Fix max call stack error * Switch prefixes * Don't mangle ambient declarations * Use correct way of checking modifier flags * Workaround getCombinedModifierFlags not doing what I'd expect Maybe needs the checker to be enabled too? Just check parent chain instead for now * Clean up code and add logic showing how enum mangling could work * Remove a few more skipMangles Use entrypoints instead * Fix entrypoint name
This commit is contained in:
parent
79c4092768
commit
debcf16fcd
File diff suppressed because one or more lines are too long
|
@ -17,7 +17,7 @@ import * as os from 'os';
|
||||||
import ts = require('typescript');
|
import ts = require('typescript');
|
||||||
import * as File from 'vinyl';
|
import * as File from 'vinyl';
|
||||||
import * as task from './task';
|
import * as task from './task';
|
||||||
import { Mangler } from './mangleTypeScript';
|
import { Mangler } from './mangle/index';
|
||||||
import { RawSourceMap } from 'source-map';
|
import { RawSourceMap } from 'source-map';
|
||||||
const watch = require('./watch');
|
const watch = require('./watch');
|
||||||
|
|
||||||
|
@ -124,21 +124,22 @@ export function compileTask(src: string, out: string, build: boolean, options: {
|
||||||
// mangle: TypeScript to TypeScript
|
// mangle: TypeScript to TypeScript
|
||||||
let mangleStream = es.through();
|
let mangleStream = es.through();
|
||||||
if (build && !options.disableMangle) {
|
if (build && !options.disableMangle) {
|
||||||
let ts2tsMangler = new Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data));
|
let ts2tsMangler = new Mangler(compile.projectPath, (...data) => fancyLog(ansiColors.blue('[mangler]'), ...data), { mangleExports: true, manglePrivateFields: true });
|
||||||
const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState']));
|
const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState']));
|
||||||
mangleStream = es.through(function write(data: File & { sourceMap?: RawSourceMap }) {
|
mangleStream = es.through(async function write(data: File & { sourceMap?: RawSourceMap }) {
|
||||||
type TypeScriptExt = typeof ts & { normalizePath(path: string): string };
|
type TypeScriptExt = typeof ts & { normalizePath(path: string): string };
|
||||||
const tsNormalPath = (<TypeScriptExt>ts).normalizePath(data.path);
|
const tsNormalPath = (<TypeScriptExt>ts).normalizePath(data.path);
|
||||||
const newContents = newContentsByFileName.get(tsNormalPath);
|
const newContents = (await newContentsByFileName).get(tsNormalPath);
|
||||||
if (newContents !== undefined) {
|
if (newContents !== undefined) {
|
||||||
data.contents = Buffer.from(newContents.out);
|
data.contents = Buffer.from(newContents.out);
|
||||||
data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap);
|
data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap);
|
||||||
}
|
}
|
||||||
this.push(data);
|
this.push(data);
|
||||||
}, function end() {
|
}, async function end() {
|
||||||
this.push(null);
|
|
||||||
// free resources
|
// free resources
|
||||||
newContentsByFileName.clear();
|
(await newContentsByFileName).clear();
|
||||||
|
|
||||||
|
this.push(null);
|
||||||
(<any>ts2tsMangler) = undefined;
|
(<any>ts2tsMangler) = undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
665
build/lib/mangle/index.js
Normal file
665
build/lib/mangle/index.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -3,12 +3,15 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
|
||||||
import * as path from 'path';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
import { argv } from 'process';
|
import { argv } from 'process';
|
||||||
import { Mapping, SourceMapGenerator } from 'source-map';
|
import { Mapping, SourceMapGenerator } from 'source-map';
|
||||||
|
import * as ts from 'typescript';
|
||||||
import { pathToFileURL } from 'url';
|
import { pathToFileURL } from 'url';
|
||||||
|
import * as workerpool from 'workerpool';
|
||||||
|
import { StaticLanguageServiceHost } from './staticLanguageServiceHost';
|
||||||
|
const buildfile = require('../../../src/buildfile');
|
||||||
|
|
||||||
class ShortIdent {
|
class ShortIdent {
|
||||||
|
|
||||||
|
@ -17,21 +20,20 @@ class ShortIdent {
|
||||||
'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw',
|
'import', 'in', 'instanceof', 'let', 'new', 'null', 'return', 'static', 'super', 'switch', 'this', 'throw',
|
||||||
'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']);
|
'true', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield']);
|
||||||
|
|
||||||
private static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
private static _alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$_'.split('');
|
||||||
|
|
||||||
private _value = 0;
|
private _value = 0;
|
||||||
private readonly _isNameTaken: (name: string) => boolean;
|
|
||||||
|
|
||||||
constructor(isNameTaken: (name: string) => boolean) {
|
constructor(
|
||||||
this._isNameTaken = name => ShortIdent._keywords.has(name) || isNameTaken(name);
|
private readonly prefix: string
|
||||||
}
|
) { }
|
||||||
|
|
||||||
next(): string {
|
next(isNameTaken?: (name: string) => boolean): string {
|
||||||
const candidate = ShortIdent.convert(this._value);
|
const candidate = this.prefix + ShortIdent.convert(this._value);
|
||||||
this._value++;
|
this._value++;
|
||||||
if (this._isNameTaken(candidate)) {
|
if (ShortIdent._keywords.has(candidate) || /^[_0-9]/.test(candidate) || isNameTaken?.(candidate)) {
|
||||||
// try again
|
// try again
|
||||||
return this.next();
|
return this.next(isNameTaken);
|
||||||
}
|
}
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
@ -181,8 +183,7 @@ class ClassData {
|
||||||
|
|
||||||
data.replacements = new Map();
|
data.replacements = new Map();
|
||||||
|
|
||||||
const identPool = new ShortIdent(name => {
|
const isNameTaken = (name: string) => {
|
||||||
|
|
||||||
// locally taken
|
// locally taken
|
||||||
if (data._isNameTaken(name)) {
|
if (data._isNameTaken(name)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -212,11 +213,12 @@ class ClassData {
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
};
|
||||||
|
const identPool = new ShortIdent('');
|
||||||
|
|
||||||
for (const [name, info] of data.fields) {
|
for (const [name, info] of data.fields) {
|
||||||
if (ClassData._shouldMangle(info.type)) {
|
if (ClassData._shouldMangle(info.type)) {
|
||||||
const shortName = identPool.next();
|
const shortName = identPool.next(isNameTaken);
|
||||||
data.replacements.set(name, shortName);
|
data.replacements.set(name, shortName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,12 +239,11 @@ class ClassData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((<any>this.node.getSourceFile()).identifiers instanceof Map) {
|
|
||||||
// taken by any other usage
|
if (isNameTakenInFile(this.node, name)) {
|
||||||
if ((<any>this.node.getSourceFile()).identifiers.has(name)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,59 +268,122 @@ class ClassData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticLanguageServiceHost implements ts.LanguageServiceHost {
|
function isNameTakenInFile(node: ts.Node, name: string): boolean {
|
||||||
|
const identifiers = (<any>node.getSourceFile()).identifiers;
|
||||||
private readonly _cmdLine: ts.ParsedCommandLine;
|
if (identifiers instanceof Map) {
|
||||||
private readonly _scriptSnapshots: Map<string, ts.IScriptSnapshot> = new Map();
|
if (identifiers.has(name)) {
|
||||||
|
return true;
|
||||||
constructor(readonly projectPath: string) {
|
|
||||||
const existingOptions: Partial<ts.CompilerOptions> = {};
|
|
||||||
const parsed = ts.readConfigFile(projectPath, ts.sys.readFile);
|
|
||||||
if (parsed.error) {
|
|
||||||
throw parsed.error;
|
|
||||||
}
|
|
||||||
this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions);
|
|
||||||
if (this._cmdLine.errors.length > 0) {
|
|
||||||
throw parsed.error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getCompilationSettings(): ts.CompilerOptions {
|
return false;
|
||||||
return this._cmdLine.options;
|
}
|
||||||
|
|
||||||
|
const fileIdents = new class {
|
||||||
|
private readonly idents = new ShortIdent('$');
|
||||||
|
|
||||||
|
next() {
|
||||||
|
return this.idents.next();
|
||||||
}
|
}
|
||||||
getScriptFileNames(): string[] {
|
};
|
||||||
return this._cmdLine.fileNames;
|
|
||||||
|
const skippedExportMangledFiles = [
|
||||||
|
// Build
|
||||||
|
'css.build',
|
||||||
|
'nls.build',
|
||||||
|
|
||||||
|
// Monaco
|
||||||
|
'editorCommon',
|
||||||
|
'editorOptions',
|
||||||
|
'editorZoom',
|
||||||
|
'standaloneEditor',
|
||||||
|
'standaloneEnums',
|
||||||
|
'standaloneLanguages',
|
||||||
|
|
||||||
|
// Generated
|
||||||
|
'extensionsApiProposals',
|
||||||
|
|
||||||
|
// Module passed around as type
|
||||||
|
'pfs',
|
||||||
|
|
||||||
|
// entry points
|
||||||
|
...[
|
||||||
|
buildfile.entrypoint('vs/server/node/server.main', []),
|
||||||
|
buildfile.entrypoint('vs/workbench/workbench.desktop.main', []),
|
||||||
|
buildfile.base,
|
||||||
|
buildfile.workerExtensionHost,
|
||||||
|
buildfile.workerNotebook,
|
||||||
|
buildfile.workerLanguageDetection,
|
||||||
|
buildfile.workerLocalFileSearch,
|
||||||
|
buildfile.workerProfileAnalysis,
|
||||||
|
buildfile.workbenchDesktop,
|
||||||
|
buildfile.workbenchWeb,
|
||||||
|
buildfile.code
|
||||||
|
].flat().map(x => x.name),
|
||||||
|
];
|
||||||
|
|
||||||
|
const skippedExportMangledProjects = [
|
||||||
|
// Test projects
|
||||||
|
'vscode-api-tests',
|
||||||
|
|
||||||
|
// These projects use webpack to dynamically rewrite imports, which messes up our mangling
|
||||||
|
'configuration-editing',
|
||||||
|
'microsoft-authentication',
|
||||||
|
'github-authentication',
|
||||||
|
'html-language-features/server',
|
||||||
|
];
|
||||||
|
|
||||||
|
const skippedExportMangledSymbols = [
|
||||||
|
// Don't mangle extension entry points
|
||||||
|
'activate',
|
||||||
|
'deactivate',
|
||||||
|
];
|
||||||
|
|
||||||
|
class DeclarationData {
|
||||||
|
|
||||||
|
readonly replacementName: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly fileName: string,
|
||||||
|
readonly node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.EnumDeclaration | ts.VariableDeclaration,
|
||||||
|
private readonly service: ts.LanguageService,
|
||||||
|
) {
|
||||||
|
// Todo: generate replacement names based on usage count, with more used names getting shorter identifiers
|
||||||
|
this.replacementName = fileIdents.next();
|
||||||
}
|
}
|
||||||
getScriptVersion(_fileName: string): string {
|
|
||||||
return '1';
|
get locations(): Iterable<{ fileName: string; offset: number }> {
|
||||||
}
|
if (ts.isVariableDeclaration(this.node)) {
|
||||||
getProjectVersion(): string {
|
// If the const aliases any types, we need to rename those too
|
||||||
return '1';
|
const definitionResult = this.service.getDefinitionAndBoundSpan(this.fileName, this.node.name.getStart());
|
||||||
}
|
if (definitionResult?.definitions && definitionResult.definitions.length > 1) {
|
||||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
|
return definitionResult.definitions.map(x => ({ fileName: x.fileName, offset: x.textSpan.start }));
|
||||||
let result: ts.IScriptSnapshot | undefined = this._scriptSnapshots.get(fileName);
|
|
||||||
if (result === undefined) {
|
|
||||||
const content = ts.sys.readFile(fileName);
|
|
||||||
if (content === undefined) {
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
result = ts.ScriptSnapshot.fromString(content);
|
|
||||||
this._scriptSnapshots.set(fileName, result);
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
return [{
|
||||||
|
fileName: this.fileName,
|
||||||
|
offset: this.node.name!.getStart()
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
getCurrentDirectory(): string {
|
|
||||||
return path.dirname(this.projectPath);
|
shouldMangle(newName: string): boolean {
|
||||||
|
const currentName = this.node.name!.getText();
|
||||||
|
if (currentName.startsWith('$') || skippedExportMangledSymbols.includes(currentName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New name is longer the existing one :'(
|
||||||
|
if (newName.length >= currentName.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't mangle functions we've explicitly opted out
|
||||||
|
if (this.node.getFullText().includes('@skipMangle')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
getDefaultLibFileName(options: ts.CompilerOptions): string {
|
|
||||||
return ts.getDefaultLibFilePath(options);
|
|
||||||
}
|
|
||||||
directoryExists = ts.sys.directoryExists;
|
|
||||||
getDirectories = ts.sys.getDirectories;
|
|
||||||
fileExists = ts.sys.fileExists;
|
|
||||||
readFile = ts.sys.readFile;
|
|
||||||
readDirectory = ts.sys.readDirectory;
|
|
||||||
// this is necessary to make source references work.
|
|
||||||
realpath = ts.sys.realpath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MangleOutput {
|
export interface MangleOutput {
|
||||||
|
@ -339,26 +403,82 @@ export interface MangleOutput {
|
||||||
export class Mangler {
|
export class Mangler {
|
||||||
|
|
||||||
private readonly allClassDataByKey = new Map<string, ClassData>();
|
private readonly allClassDataByKey = new Map<string, ClassData>();
|
||||||
|
private readonly allExportedSymbols = new Set<DeclarationData>();
|
||||||
|
|
||||||
private readonly service: ts.LanguageService;
|
private readonly service: ts.LanguageService;
|
||||||
|
private readonly renameWorkerPool: workerpool.WorkerPool;
|
||||||
|
|
||||||
constructor(readonly projectPath: string, readonly log: typeof console.log = () => { }) {
|
constructor(
|
||||||
|
private readonly projectPath: string,
|
||||||
|
private readonly log: typeof console.log = () => { },
|
||||||
|
private readonly config: { readonly manglePrivateFields: boolean; readonly mangleExports: boolean },
|
||||||
|
) {
|
||||||
this.service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
|
this.service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
|
||||||
|
|
||||||
|
this.renameWorkerPool = workerpool.pool(path.join(__dirname, 'renameWorker.js'), {
|
||||||
|
maxWorkers: 2,
|
||||||
|
minWorkers: 'max'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
computeNewFileContents(strictImplicitPublicHandling?: Set<string>): Map<string, MangleOutput> {
|
async computeNewFileContents(strictImplicitPublicHandling?: Set<string>): Promise<Map<string, MangleOutput>> {
|
||||||
|
|
||||||
// STEP: find all classes and their field info
|
// STEP:
|
||||||
|
// - Find all classes and their field info.
|
||||||
|
// - Find exported symbols.
|
||||||
|
|
||||||
const visit = (node: ts.Node): void => {
|
const visit = (node: ts.Node): void => {
|
||||||
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
|
if (this.config.manglePrivateFields) {
|
||||||
const anchor = node.name ?? node;
|
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
|
||||||
const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`;
|
const anchor = node.name ?? node;
|
||||||
if (this.allClassDataByKey.has(key)) {
|
const key = `${node.getSourceFile().fileName}|${anchor.getStart()}`;
|
||||||
throw new Error('DUPE?');
|
if (this.allClassDataByKey.has(key)) {
|
||||||
|
throw new Error('DUPE?');
|
||||||
|
}
|
||||||
|
this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node));
|
||||||
}
|
}
|
||||||
this.allClassDataByKey.set(key, new ClassData(node.getSourceFile().fileName, node));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.config.mangleExports) {
|
||||||
|
// Find exported classes, functions, and vars
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
// Exported class
|
||||||
|
ts.isClassDeclaration(node)
|
||||||
|
&& hasModifier(node, ts.SyntaxKind.ExportKeyword)
|
||||||
|
&& node.name
|
||||||
|
) || (
|
||||||
|
// Exported function
|
||||||
|
ts.isFunctionDeclaration(node)
|
||||||
|
&& ts.isSourceFile(node.parent)
|
||||||
|
&& hasModifier(node, ts.SyntaxKind.ExportKeyword)
|
||||||
|
&& node.name && node.body // On named function and not on the overload
|
||||||
|
) || (
|
||||||
|
// Exported variable
|
||||||
|
ts.isVariableDeclaration(node)
|
||||||
|
&& hasModifier(node.parent.parent, ts.SyntaxKind.ExportKeyword) // Variable statement is exported
|
||||||
|
&& ts.isSourceFile(node.parent.parent.parent)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Disabled for now because we need to figure out how to handle
|
||||||
|
// enums that are used in monaco or extHost interfaces.
|
||||||
|
/* || (
|
||||||
|
// Exported enum
|
||||||
|
ts.isEnumDeclaration(node)
|
||||||
|
&& ts.isSourceFile(node.parent)
|
||||||
|
&& hasModifier(node, ts.SyntaxKind.ExportKeyword)
|
||||||
|
&& !hasModifier(node, ts.SyntaxKind.ConstKeyword) // Don't bother mangling const enums because these are inlined
|
||||||
|
&& node.name
|
||||||
|
*/
|
||||||
|
) {
|
||||||
|
if (isInAmbientContext(node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.allExportedSymbols.add(new DeclarationData(node.getSourceFile().fileName, node, this.service));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ts.forEachChild(node, visit);
|
ts.forEachChild(node, visit);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -367,7 +487,7 @@ export class Mangler {
|
||||||
ts.forEachChild(file, visit);
|
ts.forEachChild(file, visit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.log(`Done collecting classes: ${this.allClassDataByKey.size}`);
|
this.log(`Done collecting. Classes: ${this.allClassDataByKey.size}. Exported symbols: ${this.allExportedSymbols.size}`);
|
||||||
|
|
||||||
|
|
||||||
// STEP: connect sub and super-types
|
// STEP: connect sub and super-types
|
||||||
|
@ -433,9 +553,11 @@ export class Mangler {
|
||||||
for (const data of this.allClassDataByKey.values()) {
|
for (const data of this.allClassDataByKey.values()) {
|
||||||
ClassData.fillInReplacement(data);
|
ClassData.fillInReplacement(data);
|
||||||
}
|
}
|
||||||
this.log(`Done creating replacements`);
|
this.log(`Done creating class replacements`);
|
||||||
|
|
||||||
// STEP: prepare rename edits
|
// STEP: prepare rename edits
|
||||||
|
this.log(`Starting prepare rename edits`);
|
||||||
|
|
||||||
type Edit = { newText: string; offset: number; length: number };
|
type Edit = { newText: string; offset: number; length: number };
|
||||||
const editsByFile = new Map<string, Edit[]>();
|
const editsByFile = new Map<string, Edit[]>();
|
||||||
|
|
||||||
|
@ -447,9 +569,24 @@ export class Mangler {
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const appendRename = (newText: string, loc: ts.RenameLocation) => {
|
||||||
|
appendEdit(loc.fileName, {
|
||||||
|
newText: (loc.prefixText || '') + newText + (loc.suffixText || ''),
|
||||||
|
offset: loc.textSpan.start,
|
||||||
|
length: loc.textSpan.length
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
type RenameFn = (projectName: string, fileName: string, pos: number) => ts.RenameLocation[];
|
||||||
|
|
||||||
|
const renameResults: Array<Promise<{ readonly newName: string; readonly locations: readonly ts.RenameLocation[] }>> = [];
|
||||||
|
|
||||||
|
const queueRename = (fileName: string, pos: number, newName: string) => {
|
||||||
|
renameResults.push(Promise.resolve(this.renameWorkerPool.exec<RenameFn>('findRenameLocations', [this.projectPath, fileName, pos]))
|
||||||
|
.then((locations) => ({ newName, locations })));
|
||||||
|
};
|
||||||
|
|
||||||
for (const data of this.allClassDataByKey.values()) {
|
for (const data of this.allClassDataByKey.values()) {
|
||||||
|
|
||||||
if (hasModifier(data.node, ts.SyntaxKind.DeclareKeyword)) {
|
if (hasModifier(data.node, ts.SyntaxKind.DeclareKeyword)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -469,18 +606,39 @@ export class Mangler {
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newText = data.lookupShortName(name);
|
const newName = data.lookupShortName(name);
|
||||||
const locations = this.service.findRenameLocations(data.fileName, info.pos, false, false, true) ?? [];
|
queueRename(data.fileName, info.pos, newName);
|
||||||
for (const loc of locations) {
|
|
||||||
appendEdit(loc.fileName, {
|
|
||||||
newText: (loc.prefixText || '') + newText + (loc.suffixText || ''),
|
|
||||||
offset: loc.textSpan.start,
|
|
||||||
length: loc.textSpan.length
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const data of this.allExportedSymbols.values()) {
|
||||||
|
if (data.fileName.endsWith('.d.ts')
|
||||||
|
|| skippedExportMangledProjects.some(proj => data.fileName.includes(proj))
|
||||||
|
|| skippedExportMangledFiles.some(file => data.fileName.endsWith(file + '.ts'))
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.shouldMangle(data.replacementName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newText = data.replacementName;
|
||||||
|
for (const { fileName, offset } of data.locations) {
|
||||||
|
queueRename(fileName, offset, newText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(renameResults).then((result) => {
|
||||||
|
for (const { newName, locations } of result) {
|
||||||
|
for (const loc of locations) {
|
||||||
|
appendRename(newName, loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.renameWorkerPool.terminate();
|
||||||
|
|
||||||
this.log(`Done preparing edits: ${editsByFile.size} files`);
|
this.log(`Done preparing edits: ${editsByFile.size} files`);
|
||||||
|
|
||||||
// STEP: apply all rename edits (per file)
|
// STEP: apply all rename edits (per file)
|
||||||
|
@ -579,17 +737,32 @@ function hasModifier(node: ts.Node, kind: ts.SyntaxKind) {
|
||||||
return Boolean(modifiers?.find(mode => mode.kind === kind));
|
return Boolean(modifiers?.find(mode => mode.kind === kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isInAmbientContext(node: ts.Node): boolean {
|
||||||
|
for (let p = node.parent; p; p = p.parent) {
|
||||||
|
if (ts.isModuleDeclaration(p)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function normalize(path: string): string {
|
function normalize(path: string): string {
|
||||||
return path.replace(/\\/g, '/');
|
return path.replace(/\\/g, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _run() {
|
async function _run() {
|
||||||
|
const root = path.join(__dirname, '..', '..', '..');
|
||||||
const projectPath = path.join(__dirname, '../../src/tsconfig.json');
|
const projectBase = path.join(root, 'src');
|
||||||
const projectBase = path.dirname(projectPath);
|
const projectPath = path.join(projectBase, 'tsconfig.json');
|
||||||
const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2');
|
const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2');
|
||||||
|
|
||||||
for await (const [fileName, contents] of new Mangler(projectPath, console.log).computeNewFileContents(new Set(['saveState']))) {
|
fs.cpSync(projectBase, newProjectBase, { recursive: true });
|
||||||
|
|
||||||
|
const mangler = new Mangler(projectPath, console.log, {
|
||||||
|
mangleExports: true,
|
||||||
|
manglePrivateFields: true,
|
||||||
|
});
|
||||||
|
for (const [fileName, contents] of await mangler.computeNewFileContents(new Set(['saveState']))) {
|
||||||
const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName));
|
const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName));
|
||||||
await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true });
|
await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true });
|
||||||
await fs.promises.writeFile(newFilePath, contents.out);
|
await fs.promises.writeFile(newFilePath, contents.out);
|
20
build/lib/mangle/renameWorker.js
Normal file
20
build/lib/mangle/renameWorker.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
"use strict";
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const ts = require("typescript");
|
||||||
|
const workerpool = require("workerpool");
|
||||||
|
const staticLanguageServiceHost_1 = require("./staticLanguageServiceHost");
|
||||||
|
let service; // = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
|
||||||
|
function findRenameLocations(projectPath, fileName, position) {
|
||||||
|
if (!service) {
|
||||||
|
service = ts.createLanguageService(new staticLanguageServiceHost_1.StaticLanguageServiceHost(projectPath));
|
||||||
|
}
|
||||||
|
return service.findRenameLocations(fileName, position, false, false, true) ?? [];
|
||||||
|
}
|
||||||
|
workerpool.worker({
|
||||||
|
findRenameLocations
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuYW1lV29ya2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVuYW1lV29ya2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7QUFFaEcsaUNBQWlDO0FBQ2pDLHlDQUF5QztBQUN6QywyRUFBd0U7QUFFeEUsSUFBSSxPQUF1QyxDQUFDLENBQUEsMEVBQTBFO0FBRXRILFNBQVMsbUJBQW1CLENBQzNCLFdBQW1CLEVBQ25CLFFBQWdCLEVBQ2hCLFFBQWdCO0lBRWhCLElBQUksQ0FBQyxPQUFPLEVBQUU7UUFDYixPQUFPLEdBQUcsRUFBRSxDQUFDLHFCQUFxQixDQUFDLElBQUkscURBQXlCLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztLQUMvRTtJQUVELE9BQU8sT0FBTyxDQUFDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDbEYsQ0FBQztBQUVELFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDakIsbUJBQW1CO0NBQ25CLENBQUMsQ0FBQyJ9
|
26
build/lib/mangle/renameWorker.ts
Normal file
26
build/lib/mangle/renameWorker.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as ts from 'typescript';
|
||||||
|
import * as workerpool from 'workerpool';
|
||||||
|
import { StaticLanguageServiceHost } from './staticLanguageServiceHost';
|
||||||
|
|
||||||
|
let service: ts.LanguageService | undefined;// = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
|
||||||
|
|
||||||
|
function findRenameLocations(
|
||||||
|
projectPath: string,
|
||||||
|
fileName: string,
|
||||||
|
position: number,
|
||||||
|
): readonly ts.RenameLocation[] {
|
||||||
|
if (!service) {
|
||||||
|
service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.findRenameLocations(fileName, position, false, false, true) ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
workerpool.worker({
|
||||||
|
findRenameLocations
|
||||||
|
});
|
65
build/lib/mangle/staticLanguageServiceHost.js
Normal file
65
build/lib/mangle/staticLanguageServiceHost.js
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
"use strict";
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.StaticLanguageServiceHost = void 0;
|
||||||
|
const ts = require("typescript");
|
||||||
|
const path = require("path");
|
||||||
|
class StaticLanguageServiceHost {
|
||||||
|
projectPath;
|
||||||
|
_cmdLine;
|
||||||
|
_scriptSnapshots = new Map();
|
||||||
|
constructor(projectPath) {
|
||||||
|
this.projectPath = projectPath;
|
||||||
|
const existingOptions = {};
|
||||||
|
const parsed = ts.readConfigFile(projectPath, ts.sys.readFile);
|
||||||
|
if (parsed.error) {
|
||||||
|
throw parsed.error;
|
||||||
|
}
|
||||||
|
this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions);
|
||||||
|
if (this._cmdLine.errors.length > 0) {
|
||||||
|
throw parsed.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getCompilationSettings() {
|
||||||
|
return this._cmdLine.options;
|
||||||
|
}
|
||||||
|
getScriptFileNames() {
|
||||||
|
return this._cmdLine.fileNames;
|
||||||
|
}
|
||||||
|
getScriptVersion(_fileName) {
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
|
getProjectVersion() {
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
|
getScriptSnapshot(fileName) {
|
||||||
|
let result = this._scriptSnapshots.get(fileName);
|
||||||
|
if (result === undefined) {
|
||||||
|
const content = ts.sys.readFile(fileName);
|
||||||
|
if (content === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
result = ts.ScriptSnapshot.fromString(content);
|
||||||
|
this._scriptSnapshots.set(fileName, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
getCurrentDirectory() {
|
||||||
|
return path.dirname(this.projectPath);
|
||||||
|
}
|
||||||
|
getDefaultLibFileName(options) {
|
||||||
|
return ts.getDefaultLibFilePath(options);
|
||||||
|
}
|
||||||
|
directoryExists = ts.sys.directoryExists;
|
||||||
|
getDirectories = ts.sys.getDirectories;
|
||||||
|
fileExists = ts.sys.fileExists;
|
||||||
|
readFile = ts.sys.readFile;
|
||||||
|
readDirectory = ts.sys.readDirectory;
|
||||||
|
// this is necessary to make source references work.
|
||||||
|
realpath = ts.sys.realpath;
|
||||||
|
}
|
||||||
|
exports.StaticLanguageServiceHost = StaticLanguageServiceHost;
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljTGFuZ3VhZ2VTZXJ2aWNlSG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInN0YXRpY0xhbmd1YWdlU2VydmljZUhvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Z0dBR2dHOzs7QUFFaEcsaUNBQWlDO0FBQ2pDLDZCQUE2QjtBQUU3QixNQUFhLHlCQUF5QjtJQUtoQjtJQUhKLFFBQVEsQ0FBdUI7SUFDL0IsZ0JBQWdCLEdBQW9DLElBQUksR0FBRyxFQUFFLENBQUM7SUFFL0UsWUFBcUIsV0FBbUI7UUFBbkIsZ0JBQVcsR0FBWCxXQUFXLENBQVE7UUFDdkMsTUFBTSxlQUFlLEdBQWdDLEVBQUUsQ0FBQztRQUN4RCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQy9ELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRTtZQUNqQixNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUM7U0FDbkI7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUNqSCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDcEMsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDO1NBQ25CO0lBQ0YsQ0FBQztJQUNELHNCQUFzQjtRQUNyQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0lBQzlCLENBQUM7SUFDRCxrQkFBa0I7UUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztJQUNoQyxDQUFDO0lBQ0QsZ0JBQWdCLENBQUMsU0FBaUI7UUFDakMsT0FBTyxHQUFHLENBQUM7SUFDWixDQUFDO0lBQ0QsaUJBQWlCO1FBQ2hCLE9BQU8sR0FBRyxDQUFDO0lBQ1osQ0FBQztJQUNELGlCQUFpQixDQUFDLFFBQWdCO1FBQ2pDLElBQUksTUFBTSxHQUFtQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pGLElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUN6QixNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUMxQyxJQUFJLE9BQU8sS0FBSyxTQUFTLEVBQUU7Z0JBQzFCLE9BQU8sU0FBUyxDQUFDO2FBQ2pCO1lBQ0QsTUFBTSxHQUFHLEVBQUUsQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9DLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzVDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDZixDQUFDO0lBQ0QsbUJBQW1CO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUNELHFCQUFxQixDQUFDLE9BQTJCO1FBQ2hELE9BQU8sRUFBRSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFDRCxlQUFlLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUM7SUFDekMsY0FBYyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO0lBQ3ZDLFVBQVUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQztJQUMvQixRQUFRLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7SUFDM0IsYUFBYSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDO0lBQ3JDLG9EQUFvRDtJQUNwRCxRQUFRLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUM7Q0FDM0I7QUFyREQsOERBcURDIn0=
|
62
build/lib/mangle/staticLanguageServiceHost.ts
Normal file
62
build/lib/mangle/staticLanguageServiceHost.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as ts from 'typescript';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export class StaticLanguageServiceHost implements ts.LanguageServiceHost {
|
||||||
|
|
||||||
|
private readonly _cmdLine: ts.ParsedCommandLine;
|
||||||
|
private readonly _scriptSnapshots: Map<string, ts.IScriptSnapshot> = new Map();
|
||||||
|
|
||||||
|
constructor(readonly projectPath: string) {
|
||||||
|
const existingOptions: Partial<ts.CompilerOptions> = {};
|
||||||
|
const parsed = ts.readConfigFile(projectPath, ts.sys.readFile);
|
||||||
|
if (parsed.error) {
|
||||||
|
throw parsed.error;
|
||||||
|
}
|
||||||
|
this._cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, path.dirname(projectPath), existingOptions);
|
||||||
|
if (this._cmdLine.errors.length > 0) {
|
||||||
|
throw parsed.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getCompilationSettings(): ts.CompilerOptions {
|
||||||
|
return this._cmdLine.options;
|
||||||
|
}
|
||||||
|
getScriptFileNames(): string[] {
|
||||||
|
return this._cmdLine.fileNames;
|
||||||
|
}
|
||||||
|
getScriptVersion(_fileName: string): string {
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
|
getProjectVersion(): string {
|
||||||
|
return '1';
|
||||||
|
}
|
||||||
|
getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined {
|
||||||
|
let result: ts.IScriptSnapshot | undefined = this._scriptSnapshots.get(fileName);
|
||||||
|
if (result === undefined) {
|
||||||
|
const content = ts.sys.readFile(fileName);
|
||||||
|
if (content === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
result = ts.ScriptSnapshot.fromString(content);
|
||||||
|
this._scriptSnapshots.set(fileName, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
getCurrentDirectory(): string {
|
||||||
|
return path.dirname(this.projectPath);
|
||||||
|
}
|
||||||
|
getDefaultLibFileName(options: ts.CompilerOptions): string {
|
||||||
|
return ts.getDefaultLibFilePath(options);
|
||||||
|
}
|
||||||
|
directoryExists = ts.sys.directoryExists;
|
||||||
|
getDirectories = ts.sys.getDirectories;
|
||||||
|
fileExists = ts.sys.fileExists;
|
||||||
|
readFile = ts.sys.readFile;
|
||||||
|
readDirectory = ts.sys.readDirectory;
|
||||||
|
// this is necessary to make source references work.
|
||||||
|
realpath = ts.sys.realpath;
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
|
@ -38,6 +38,7 @@
|
||||||
"@types/through2": "^2.0.36",
|
"@types/through2": "^2.0.36",
|
||||||
"@types/tmp": "^0.2.1",
|
"@types/tmp": "^0.2.1",
|
||||||
"@types/underscore": "^1.8.9",
|
"@types/underscore": "^1.8.9",
|
||||||
|
"@types/workerpool": "^6.4.0",
|
||||||
"@types/xml2js": "0.0.33",
|
"@types/xml2js": "0.0.33",
|
||||||
"@vscode/iconv-lite-umd": "0.7.0",
|
"@vscode/iconv-lite-umd": "0.7.0",
|
||||||
"@vscode/vsce": "^2.16.0",
|
"@vscode/vsce": "^2.16.0",
|
||||||
|
@ -70,5 +71,8 @@
|
||||||
"tree-sitter": "https://github.com/joaomoreno/node-tree-sitter/releases/download/v0.20.0/tree-sitter-0.20.0.tgz",
|
"tree-sitter": "https://github.com/joaomoreno/node-tree-sitter/releases/download/v0.20.0/tree-sitter-0.20.0.tgz",
|
||||||
"tree-sitter-typescript": "^0.20.1",
|
"tree-sitter-typescript": "^0.20.1",
|
||||||
"vscode-gulp-watch": "^5.0.3"
|
"vscode-gulp-watch": "^5.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"workerpool": "^6.4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,6 +646,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/workerpool@^6.4.0":
|
||||||
|
version "6.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/workerpool/-/workerpool-6.4.0.tgz#c79292915dd08350d10e78e74687b6f401f270b8"
|
||||||
|
integrity sha512-SIF2/169pDsLKeM8GQGHkOFifGalDbZgiBSaLUnnlVSRsAOenkAvQ6h4uhV2W+PZZczS+8LQxACwNkSykdT91A==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/xml2js@0.0.33":
|
"@types/xml2js@0.0.33":
|
||||||
version "0.0.33"
|
version "0.0.33"
|
||||||
resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de"
|
resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.0.33.tgz#20c5dd6460245284d64a55690015b95e409fb7de"
|
||||||
|
@ -3017,6 +3024,11 @@ wide-align@^1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width "^1.0.2 || 2 || 3 || 4"
|
string-width "^1.0.2 || 2 || 3 || 4"
|
||||||
|
|
||||||
|
workerpool@^6.4.0:
|
||||||
|
version "6.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.4.0.tgz#f8d5cfb45fde32fa3b7af72ad617c3369567a462"
|
||||||
|
integrity sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A==
|
||||||
|
|
||||||
wrappy@1:
|
wrappy@1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
|
|
@ -8,12 +8,12 @@ const fs = require('fs');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const fancyLog = require('fancy-log');
|
const fancyLog = require('fancy-log');
|
||||||
const ansiColors = require('ansi-colors');
|
const ansiColors = require('ansi-colors');
|
||||||
const { Mangler } = require('../build/lib/mangleTypeScript');
|
const { Mangler } = require('../build/lib/mangle/index');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of project paths to mangled file contents
|
* Map of project paths to mangled file contents
|
||||||
*
|
*
|
||||||
* @type {Map<string, Map<string, { out: string; sourceMap?: string }>>}
|
* @type {Map<string, Promise<Map<string, { out: string; sourceMap?: string }>>>}
|
||||||
*/
|
*/
|
||||||
const mangleMap = new Map();
|
const mangleMap = new Map();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ module.exports = async function (source, sourceMap, meta) {
|
||||||
|
|
||||||
const callback = this.async();
|
const callback = this.async();
|
||||||
|
|
||||||
const fileContentsMap = getMangledFileContents(options.configFile);
|
const fileContentsMap = await getMangledFileContents(options.configFile);
|
||||||
|
|
||||||
const newContents = fileContentsMap.get(this.resourcePath);
|
const newContents = fileContentsMap.get(this.resourcePath);
|
||||||
callback(null, newContents?.out ?? source, sourceMap, meta);
|
callback(null, newContents?.out ?? source, sourceMap, meta);
|
||||||
|
|
|
@ -74,6 +74,7 @@ export class ErrorHandler {
|
||||||
|
|
||||||
export const errorHandler = new ErrorHandler();
|
export const errorHandler = new ErrorHandler();
|
||||||
|
|
||||||
|
/** @skipMangle */
|
||||||
export function setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void {
|
export function setUnexpectedErrorHandler(newUnexpectedErrorHandler: (e: any) => void): void {
|
||||||
errorHandler.setUnexpectedErrorHandler(newUnexpectedErrorHandler);
|
errorHandler.setUnexpectedErrorHandler(newUnexpectedErrorHandler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ else {
|
||||||
* environments.
|
* environments.
|
||||||
*
|
*
|
||||||
* Note: in web, this property is hardcoded to be `/`.
|
* Note: in web, this property is hardcoded to be `/`.
|
||||||
|
*
|
||||||
|
* @skipMangle
|
||||||
*/
|
*/
|
||||||
export const cwd = safeProcess.cwd;
|
export const cwd = safeProcess.cwd;
|
||||||
|
|
||||||
|
|
2
src/vs/base/common/stripComments.d.ts
vendored
2
src/vs/base/common/stripComments.d.ts
vendored
|
@ -10,5 +10,5 @@
|
||||||
* supported in JSON.
|
* supported in JSON.
|
||||||
* @param content the content to strip comments from
|
* @param content the content to strip comments from
|
||||||
* @returns the content without comments
|
* @returns the content without comments
|
||||||
*/
|
*/
|
||||||
export function stripComments(content: string): string;
|
export function stripComments(content: string): string;
|
||||||
|
|
|
@ -558,6 +558,7 @@ export class SimpleWorkerServer<H extends object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called on the worker side
|
* Called on the worker side
|
||||||
|
* @skipMangle
|
||||||
*/
|
*/
|
||||||
export function create(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void): SimpleWorkerServer<any> {
|
export function create(postMessage: (msg: Message, transfer?: ArrayBuffer[]) => void): SimpleWorkerServer<any> {
|
||||||
return new SimpleWorkerServer(postMessage, null);
|
return new SimpleWorkerServer(postMessage, null);
|
||||||
|
|
|
@ -9,6 +9,8 @@ interface ICSSPluginConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked by the loader at run-time
|
* Invoked by the loader at run-time
|
||||||
|
*
|
||||||
|
* @skipMangle
|
||||||
*/
|
*/
|
||||||
export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void {
|
export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void {
|
||||||
config = config || {};
|
config = config || {};
|
||||||
|
|
|
@ -297,7 +297,12 @@ export class TextAreaHandler extends ViewPart {
|
||||||
};
|
};
|
||||||
|
|
||||||
const textAreaWrapper = this._register(new TextAreaWrapper(this.textArea.domNode));
|
const textAreaWrapper = this._register(new TextAreaWrapper(this.textArea.domNode));
|
||||||
this._textAreaInput = this._register(new TextAreaInput(textAreaInputHost, textAreaWrapper, platform.OS, browser));
|
this._textAreaInput = this._register(new TextAreaInput(textAreaInputHost, textAreaWrapper, platform.OS, {
|
||||||
|
isAndroid: browser.isAndroid,
|
||||||
|
isChrome: browser.isChrome,
|
||||||
|
isFirefox: browser.isFirefox,
|
||||||
|
isSafari: browser.isSafari,
|
||||||
|
}));
|
||||||
|
|
||||||
this._register(this._textAreaInput.onKeyDown((e: IKeyboardEvent) => {
|
this._register(this._textAreaInput.onKeyDown((e: IKeyboardEvent) => {
|
||||||
this._viewController.emitKeyDown(e);
|
this._viewController.emitKeyDown(e);
|
||||||
|
|
|
@ -121,7 +121,12 @@ function doCreateTest(description: string, inputStr: string, expectedStr: string
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handler = new TextAreaInput(textAreaInputHost, new TextAreaWrapper(input), platform.OS, browser);
|
const handler = new TextAreaInput(textAreaInputHost, new TextAreaWrapper(input), platform.OS, {
|
||||||
|
isAndroid: browser.isAndroid,
|
||||||
|
isFirefox: browser.isFirefox,
|
||||||
|
isChrome: browser.isChrome,
|
||||||
|
isSafari: browser.isSafari,
|
||||||
|
});
|
||||||
|
|
||||||
const output = document.createElement('pre');
|
const output = document.createElement('pre');
|
||||||
output.className = 'output';
|
output.className = 'output';
|
||||||
|
|
|
@ -123,6 +123,9 @@ export function localize(info: ILocalizeInfo, message: string, ...args: (string
|
||||||
*/
|
*/
|
||||||
export function localize(key: string, message: string, ...args: (string | number | boolean | undefined | null)[]): string;
|
export function localize(key: string, message: string, ...args: (string | number | boolean | undefined | null)[]): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @skipMangle
|
||||||
|
*/
|
||||||
export function localize(data: ILocalizeInfo | string, message: string, ...args: (string | number | boolean | undefined | null)[]): string {
|
export function localize(data: ILocalizeInfo | string, message: string, ...args: (string | number | boolean | undefined | null)[]): string {
|
||||||
return _format(message, args);
|
return _format(message, args);
|
||||||
}
|
}
|
||||||
|
@ -133,18 +136,25 @@ export function localize(data: ILocalizeInfo | string, message: string, ...args:
|
||||||
* in order to ensure the loader plugin has been initialized before this function is called.
|
* in order to ensure the loader plugin has been initialized before this function is called.
|
||||||
*/
|
*/
|
||||||
export function getConfiguredDefaultLocale(stringFromLocalizeCall: string): string | undefined;
|
export function getConfiguredDefaultLocale(stringFromLocalizeCall: string): string | undefined;
|
||||||
|
/**
|
||||||
|
* @skipMangle
|
||||||
|
*/
|
||||||
export function getConfiguredDefaultLocale(_: string): string | undefined {
|
export function getConfiguredDefaultLocale(_: string): string | undefined {
|
||||||
// This returns undefined because this implementation isn't used and is overwritten by the loader
|
// This returns undefined because this implementation isn't used and is overwritten by the loader
|
||||||
// when loaded.
|
// when loaded.
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @skipMangle
|
||||||
|
*/
|
||||||
export function setPseudoTranslation(value: boolean) {
|
export function setPseudoTranslation(value: boolean) {
|
||||||
isPseudo = value;
|
isPseudo = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked in a built product at run-time
|
* Invoked in a built product at run-time
|
||||||
|
* @skipMangle
|
||||||
*/
|
*/
|
||||||
export function create(key: string, data: IBundledStrings & IConsumerAPI): IConsumerAPI {
|
export function create(key: string, data: IBundledStrings & IConsumerAPI): IConsumerAPI {
|
||||||
return {
|
return {
|
||||||
|
@ -155,10 +165,12 @@ export function create(key: string, data: IBundledStrings & IConsumerAPI): ICons
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked by the loader at run-time
|
* Invoked by the loader at run-time
|
||||||
|
* @skipMangle
|
||||||
*/
|
*/
|
||||||
export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void {
|
export function load(name: string, req: AMDLoader.IRelativeRequire, load: AMDLoader.IPluginLoadCallback, config: AMDLoader.IConfigurationOptions): void {
|
||||||
const pluginConfig: INLSPluginConfig = config['vs/nls'] ?? {};
|
const pluginConfig: INLSPluginConfig = config['vs/nls'] ?? {};
|
||||||
if (!name || name.length === 0) {
|
if (!name || name.length === 0) {
|
||||||
|
// TODO: We need to give back the mangled names here
|
||||||
return load({
|
return load({
|
||||||
localize: localize,
|
localize: localize,
|
||||||
getConfiguredDefaultLocale: () => pluginConfig.availableLanguages?.['*']
|
getConfiguredDefaultLocale: () => pluginConfig.availableLanguages?.['*']
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { IV8Profile, Utils } from 'vs/platform/profiling/common/profiling';
|
||||||
import { IProfileModel, BottomUpSample, buildModel, BottomUpNode, processNode, CdpCallFrame } from 'vs/platform/profiling/common/profilingModel';
|
import { IProfileModel, BottomUpSample, buildModel, BottomUpNode, processNode, CdpCallFrame } from 'vs/platform/profiling/common/profilingModel';
|
||||||
import { BottomUpAnalysis, IProfileAnalysisWorker, ProfilingOutput } from 'vs/platform/profiling/electron-sandbox/profileAnalysisWorkerService';
|
import { BottomUpAnalysis, IProfileAnalysisWorker, ProfilingOutput } from 'vs/platform/profiling/electron-sandbox/profileAnalysisWorkerService';
|
||||||
|
|
||||||
|
|
||||||
export function create(): IRequestHandler {
|
export function create(): IRequestHandler {
|
||||||
return new ProfileAnalysisWorker();
|
return new ProfileAnalysisWorker();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ import { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry';
|
||||||
* and can be used to add assertions. e.g. that registries are empty, etc.
|
* and can be used to add assertions. e.g. that registries are empty, etc.
|
||||||
*
|
*
|
||||||
* !! This is called directly by the testing framework.
|
* !! This is called directly by the testing framework.
|
||||||
|
*
|
||||||
|
* @skipMangle
|
||||||
*/
|
*/
|
||||||
export function assertCleanState(): void {
|
export function assertCleanState(): void {
|
||||||
// If this test fails, it is a clear indication that
|
// If this test fails, it is a clear indication that
|
||||||
|
|
Loading…
Reference in a new issue