mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-15 07:28:05 +00:00
wip
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -18,6 +18,7 @@ import ts = require('typescript');
|
||||
import * as File from 'vinyl';
|
||||
import * as task from './task';
|
||||
import { Mangler } from './mangleTypeScript';
|
||||
import { RawSourceMap } from 'source-map';
|
||||
const watch = require('./watch');
|
||||
|
||||
|
||||
@@ -125,10 +126,11 @@ export function compileTask(src: string, out: string, build: boolean): () => Nod
|
||||
if (build) {
|
||||
let ts2tsMangler = new Mangler(compile.projectPath);
|
||||
const newContentsByFileName = ts2tsMangler.computeNewFileContents();
|
||||
mangleStream = es.through(function write(data: File) {
|
||||
mangleStream = es.through(function write(data: File & { sourceMap?: RawSourceMap }) {
|
||||
const newContents = newContentsByFileName.get(data.path);
|
||||
if (newContents !== undefined) {
|
||||
data.contents = Buffer.from(newContents);
|
||||
data.contents = Buffer.from(newContents.out);
|
||||
data.sourceMap = newContents.sourceMap && JSON.parse(newContents.sourceMap);
|
||||
}
|
||||
this.push(data);
|
||||
}, function end() {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -7,6 +7,8 @@ import * as ts from 'typescript';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { argv } from 'process';
|
||||
import { SourceMapGenerator } from 'source-map';
|
||||
import { pathToFileURL } from 'url';
|
||||
|
||||
class ShortIdent {
|
||||
|
||||
@@ -339,7 +341,7 @@ export class Mangler {
|
||||
this.service = ts.createLanguageService(new StaticLanguageServiceHost(projectPath));
|
||||
}
|
||||
|
||||
computeNewFileContents(): Map<string, string> {
|
||||
computeNewFileContents(): Map<string, { out: string; sourceMap?: string }> {
|
||||
|
||||
// STEP: find all classes and their field info
|
||||
|
||||
@@ -467,11 +469,18 @@ export class Mangler {
|
||||
this.log(`done preparing EDITS for ${editsByFile.size} files`);
|
||||
|
||||
// STEP: apply all rename edits (per file)
|
||||
const result = new Map<string, string>();
|
||||
const result = new Map<string, { out: string; sourceMap?: string }>();
|
||||
let savedBytes = 0;
|
||||
|
||||
for (const item of this.service.getProgram()!.getSourceFiles()) {
|
||||
|
||||
const { mapRoot, sourceRoot } = this.service.getProgram()!.getCompilerOptions();
|
||||
const projectDir = path.dirname(this.projectPath);
|
||||
const sourceMapRoot = mapRoot ?? pathToFileURL(sourceRoot ?? projectDir).toString();
|
||||
|
||||
// source maps
|
||||
let generator: SourceMapGenerator | undefined;
|
||||
|
||||
let newFullText: string;
|
||||
const edits = editsByFile.get(item.fileName);
|
||||
if (!edits) {
|
||||
@@ -479,6 +488,13 @@ export class Mangler {
|
||||
newFullText = item.getFullText();
|
||||
|
||||
} else {
|
||||
// source map generator
|
||||
const relativeFileName = path.relative(projectDir, item.fileName);
|
||||
generator = new SourceMapGenerator({
|
||||
file: path.basename(item.fileName),
|
||||
sourceRoot: sourceMapRoot
|
||||
});
|
||||
|
||||
// apply renames
|
||||
edits.sort((a, b) => b.offset - a.offset);
|
||||
const characters = item.getFullText().split('');
|
||||
@@ -498,12 +514,27 @@ export class Mangler {
|
||||
}
|
||||
}
|
||||
lastEdit = edit;
|
||||
const removed = characters.splice(edit.offset, edit.length, edit.newText);
|
||||
savedBytes += removed.length - edit.newText.length;
|
||||
const mangledName = characters.splice(edit.offset, edit.length, edit.newText).join('');
|
||||
savedBytes += mangledName.length - edit.newText.length;
|
||||
|
||||
// source maps
|
||||
const pos = item.getLineAndCharacterOfPosition(edit.offset);
|
||||
generator.addMapping({
|
||||
source: relativeFileName,
|
||||
original: { line: pos.line + 1, column: pos.character },
|
||||
generated: { line: pos.line + 1, column: pos.character },
|
||||
name: mangledName
|
||||
});
|
||||
generator.addMapping({
|
||||
source: relativeFileName,
|
||||
original: { line: pos.line + 1, column: pos.character + edit.length },
|
||||
generated: { line: pos.line + 1, column: pos.character + edit.newText.length }
|
||||
});
|
||||
generator.setSourceContent(relativeFileName, item.getFullText());
|
||||
}
|
||||
newFullText = characters.join('');
|
||||
}
|
||||
result.set(item.fileName, newFullText);
|
||||
result.set(item.fileName, { out: newFullText, sourceMap: generator?.toString() });
|
||||
}
|
||||
|
||||
this.log(`DONE saved ${savedBytes / 1000}kb`);
|
||||
@@ -523,12 +554,15 @@ async function _run() {
|
||||
|
||||
const projectPath = path.join(__dirname, '../../src/tsconfig.json');
|
||||
const projectBase = path.dirname(projectPath);
|
||||
const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '-mangle');
|
||||
const newProjectBase = path.join(path.dirname(projectBase), path.basename(projectBase) + '2');
|
||||
|
||||
for await (const [fileName, contents] of new Mangler(projectPath, console.log).computeNewFileContents()) {
|
||||
const newFilePath = path.join(newProjectBase, path.relative(projectBase, fileName));
|
||||
await fs.promises.mkdir(path.dirname(newFilePath), { recursive: true });
|
||||
await fs.promises.writeFile(newFilePath, contents);
|
||||
await fs.promises.writeFile(newFilePath, contents.out);
|
||||
if (contents.sourceMap) {
|
||||
await fs.promises.writeFile(newFilePath + '.map', contents.sourceMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,13 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { statSync, readFileSync } from 'fs';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as crypto from 'crypto';
|
||||
import * as utils from './utils';
|
||||
import * as colors from 'ansi-colors';
|
||||
import * as ts from 'typescript';
|
||||
import * as Vinyl from 'vinyl';
|
||||
import { RawSourceMap, SourceMapConsumer, SourceMapGenerator } from 'source-map';
|
||||
|
||||
export interface IConfiguration {
|
||||
logFn: (topic: string, message: string) => void;
|
||||
@@ -158,8 +159,63 @@ export function createTypeScriptBuilder(config: IConfiguration, projectFile: str
|
||||
const dirname = path.dirname(vinyl.relative);
|
||||
const tsname = (dirname === '.' ? '' : dirname + '/') + basename + '.ts';
|
||||
|
||||
const sourceMap = JSON.parse(sourcemapFile.text);
|
||||
let sourceMap = <RawSourceMap>JSON.parse(sourcemapFile.text);
|
||||
sourceMap.sources[0] = tsname.replace(/\\/g, '/');
|
||||
|
||||
// check for an input source map and combine them
|
||||
const snapshot = host.getScriptSnapshot(fileName);
|
||||
if (snapshot instanceof VinylScriptSnapshot && snapshot.sourceMap) {
|
||||
const inputSMC = new SourceMapConsumer(snapshot.sourceMap);
|
||||
const tsSMC = new SourceMapConsumer(sourceMap);
|
||||
let didChange = false;
|
||||
const smg = new SourceMapGenerator({
|
||||
file: sourceMap.file,
|
||||
sourceRoot: sourceMap.sourceRoot
|
||||
});
|
||||
tsSMC.eachMapping(m => {
|
||||
didChange = true;
|
||||
const original = { line: m.originalLine, column: m.originalColumn };
|
||||
const generated = { line: m.generatedLine, column: m.generatedColumn };
|
||||
// JS-out position -> input original position
|
||||
const inputOriginal = inputSMC.originalPositionFor(original);
|
||||
if (inputOriginal.source !== null) {
|
||||
const inputSource = inputOriginal.source;
|
||||
smg.addMapping({
|
||||
source: inputSource,
|
||||
name: inputOriginal.name,
|
||||
generated: generated,
|
||||
original: inputOriginal
|
||||
});
|
||||
smg.setSourceContent(
|
||||
inputSource,
|
||||
inputSMC.sourceContentFor(inputSource)
|
||||
);
|
||||
} else {
|
||||
smg.addMapping({
|
||||
source: m.source,
|
||||
name: m.name,
|
||||
generated: generated,
|
||||
original: original
|
||||
});
|
||||
smg.setSourceContent(
|
||||
m.source,
|
||||
tsSMC.sourceContentFor(m.source)
|
||||
);
|
||||
|
||||
}
|
||||
}, null, SourceMapConsumer.GENERATED_ORDER);
|
||||
|
||||
if (didChange) {
|
||||
sourceMap = JSON.parse(smg.toString());
|
||||
|
||||
// const filename = '/Users/jrieken/Code/vscode/src2/' + vinyl.relative + '.map';
|
||||
// fs.promises.mkdir(path.dirname(filename), { recursive: true }).then(async () => {
|
||||
// await fs.promises.writeFile(filename, smg.toString());
|
||||
// await fs.promises.writeFile('/Users/jrieken/Code/vscode/src2/' + vinyl.relative, vinyl.contents);
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
(<any>vinyl).sourceMap = sourceMap;
|
||||
}
|
||||
}
|
||||
@@ -397,9 +453,12 @@ class VinylScriptSnapshot extends ScriptSnapshot {
|
||||
|
||||
private readonly _base: string;
|
||||
|
||||
constructor(file: Vinyl) {
|
||||
readonly sourceMap?: RawSourceMap;
|
||||
|
||||
constructor(file: Vinyl & { sourceMap?: RawSourceMap }) {
|
||||
super(file.contents!.toString(), file.stat!.mtime);
|
||||
this._base = file.base;
|
||||
this.sourceMap = file.sourceMap;
|
||||
}
|
||||
|
||||
getBase(): string {
|
||||
@@ -474,9 +533,9 @@ class LanguageServiceHost implements ts.LanguageServiceHost {
|
||||
try {
|
||||
result = new VinylScriptSnapshot(new Vinyl(<any>{
|
||||
path: filename,
|
||||
contents: readFileSync(filename),
|
||||
contents: fs.readFileSync(filename),
|
||||
base: this.getCompilationSettings().outDir,
|
||||
stat: statSync(filename)
|
||||
stat: fs.statSync(filename)
|
||||
}));
|
||||
this.addScriptSnapshot(filename, result);
|
||||
} catch (e) {
|
||||
|
||||
@@ -11,7 +11,7 @@ const { Mangler } = require('../build/lib/mangleTypeScript');
|
||||
/**
|
||||
* Map of project paths to mangled file contents
|
||||
*
|
||||
* @type {Map<string, Map<string, string>>}
|
||||
* @type {Map<string, Map<string, { out: string; sourceMap?: string }>>}
|
||||
*/
|
||||
const mangleMap = new Map();
|
||||
|
||||
@@ -46,5 +46,5 @@ module.exports = async function (source, sourceMap, meta) {
|
||||
const fileContentsMap = getMangledFileContents(options.configFile);
|
||||
|
||||
const newContents = fileContentsMap.get(this.resourcePath);
|
||||
callback(null, newContents ?? source, sourceMap, meta);
|
||||
callback(null, newContents?.out ?? source, sourceMap, meta);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user