feat: improve transpiler infrastructure
This commit is contained in:
parent
74f08b7483
commit
6c8c329992
@ -31,7 +31,7 @@ task compileEnv(type: NpmTask) {
|
|||||||
}
|
}
|
||||||
task compileTypescript(type: NpmTask) {
|
task compileTypescript(type: NpmTask) {
|
||||||
inputs.files('rollup.config.js');
|
inputs.files('rollup.config.js');
|
||||||
inputs.dir('src/lib/ts');
|
inputs.dir('src/lib/transpiler');
|
||||||
outputs.files("build/js/ts.js");
|
outputs.files("build/js/ts.js");
|
||||||
// nom nom tasty ram
|
// nom nom tasty ram
|
||||||
environment.put("NODE_OPTIONS", "--max-old-space-size=4096");
|
environment.put("NODE_OPTIONS", "--max-old-space-size=4096");
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
{
|
{
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-env": "rollup -c --environment INPUT:src/lib/libs/_entry.ts,OUTPUT:build/js/index.js,POLYFILLS:src/lib/libs/polyfills",
|
"build-env": "rollup -c --environment INPUT:src/lib/libs/_entry.ts,OUTPUT:build/js/index.js,POLYFILLS:src/lib/libs/polyfills",
|
||||||
"build-ts": "rollup -c --environment INPUT:src/lib/ts/_entry.ts,OUTPUT:build/js/ts.js"
|
"build-ts": "rollup -c --environment INPUT:src/lib/transpiler/_entry.ts,OUTPUT:build/js/ts.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.26.0",
|
||||||
"@babel/runtime": "^7.26.0",
|
"@babel/runtime": "^7.26.0",
|
||||||
|
"@babel/standalone": "^7.26.4",
|
||||||
|
"@rollup/plugin-json": "^6.1.0",
|
||||||
|
"@types/babel__preset-env": "^7.9.7",
|
||||||
|
"@types/babel__standalone": "^7.1.9",
|
||||||
|
"@types/coffeescript": "^2.5.7",
|
||||||
|
"coffeescript": "^2.7.0",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -4,6 +4,7 @@ const typescript = require("@rollup/plugin-typescript");
|
|||||||
const babel = require("@rollup/plugin-babel");
|
const babel = require("@rollup/plugin-babel");
|
||||||
const commonjs = require("@rollup/plugin-commonjs");
|
const commonjs = require("@rollup/plugin-commonjs");
|
||||||
const nodeResolve = require("@rollup/plugin-node-resolve");
|
const nodeResolve = require("@rollup/plugin-node-resolve");
|
||||||
|
const json = require("@rollup/plugin-json");
|
||||||
const { resolve } = require("path");
|
const { resolve } = require("path");
|
||||||
|
|
||||||
const shouldMinify = () => false;
|
const shouldMinify = () => false;
|
||||||
@ -21,6 +22,7 @@ const construct = (input, output) => defineConfig({
|
|||||||
},
|
},
|
||||||
commonjs(),
|
commonjs(),
|
||||||
nodeResolve(),
|
nodeResolve(),
|
||||||
|
json(),
|
||||||
babel({
|
babel({
|
||||||
extensions: [],
|
extensions: [],
|
||||||
exclude: ["node_modules/**"],
|
exclude: ["node_modules/**"],
|
||||||
@ -107,6 +109,14 @@ const construct = (input, output) => defineConfig({
|
|||||||
path: "null",
|
path: "null",
|
||||||
os: "null",
|
os: "null",
|
||||||
inspector: "null",
|
inspector: "null",
|
||||||
|
tty: "null",
|
||||||
|
util: "null",
|
||||||
|
assert: "null",
|
||||||
|
url: "null",
|
||||||
|
"@babel/preset-typescript/package.json": "null",
|
||||||
|
module: "null",
|
||||||
|
process: "null",
|
||||||
|
v8: "null",
|
||||||
},
|
},
|
||||||
// plugins: [babel.getBabelOutputPlugin({
|
// plugins: [babel.getBabelOutputPlugin({
|
||||||
// allowAllFormats: true,
|
// allowAllFormats: true,
|
||||||
|
4
src/lib/transpiler/_entry.ts
Normal file
4
src/lib/transpiler/_entry.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import coffeescript from "./coffeescript.ts";
|
||||||
|
import babel from "./babel.ts";
|
||||||
|
|
||||||
|
register(v => coffeescript(babel(v)));
|
25
src/lib/transpiler/babel.ts
Normal file
25
src/lib/transpiler/babel.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { SourceMap } from "./map.ts";
|
||||||
|
import { transform } from "@babel/standalone";
|
||||||
|
// import presetEnv from "@babel/preset-env";
|
||||||
|
|
||||||
|
export default function babel(next: Compiler): Compiler {
|
||||||
|
print("Loaded babel!");
|
||||||
|
|
||||||
|
return (filename, code, prevMap) => {
|
||||||
|
const res = transform(code, {
|
||||||
|
filename,
|
||||||
|
sourceMaps: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const map = SourceMap.parse({
|
||||||
|
file: "babel-internal://" + filename,
|
||||||
|
mappings: res.map!.mappings,
|
||||||
|
sources: [filename],
|
||||||
|
});
|
||||||
|
|
||||||
|
const compiled = next("babel-internal://" + filename, res.code!, SourceMap.chain(map, prevMap));
|
||||||
|
registerSource(filename, code);
|
||||||
|
return compiled;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
28
src/lib/transpiler/coffeescript.ts
Normal file
28
src/lib/transpiler/coffeescript.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { compile } from "coffeescript";
|
||||||
|
import { SourceMap } from "./map.ts";
|
||||||
|
|
||||||
|
export default function coffee(next: Compiler): Compiler {
|
||||||
|
print("Loaded coffeescript!");
|
||||||
|
|
||||||
|
return (filename, code, prevMap) => {
|
||||||
|
const {
|
||||||
|
js: result,
|
||||||
|
v3SourceMap: rawMap,
|
||||||
|
} = compile(code, {
|
||||||
|
filename,
|
||||||
|
sourceMap: true,
|
||||||
|
bare: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const map = SourceMap.parse({
|
||||||
|
file: "coffee-internal://" + filename,
|
||||||
|
mappings: JSON.parse(rawMap).mappings,
|
||||||
|
sources: [filename],
|
||||||
|
});
|
||||||
|
|
||||||
|
const compiled = next("coffee-internal://" + filename, result, SourceMap.chain(map, prevMap));
|
||||||
|
registerSource(filename, code);
|
||||||
|
return compiled;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -123,13 +123,16 @@ export class VLQSourceMap {
|
|||||||
|
|
||||||
public static parseVLQ(compiled: string, filenames: string[], raw: string): VLQSourceMap {
|
public static parseVLQ(compiled: string, filenames: string[], raw: string): VLQSourceMap {
|
||||||
const mapping = decodeVLQ(raw);
|
const mapping = decodeVLQ(raw);
|
||||||
const res = new Map<string, [start: number, dst: Location][][]>();
|
const file: [start: number, dst: Location][][] = [];
|
||||||
|
const res = new Map<string, [start: number, dst: Location][][]>([[compiled, file]]);
|
||||||
|
|
||||||
let originalRow = 0;
|
let originalRow = 0;
|
||||||
let originalCol = 0;
|
let originalCol = 0;
|
||||||
let originalFile = 0;
|
let originalFile = 0;
|
||||||
|
const lastCols = new Set<number>();
|
||||||
|
|
||||||
for (let compiledRow = 0; compiledRow < mapping.length; compiledRow++) {
|
for (let compiledRow = 0; compiledRow < mapping.length; compiledRow++) {
|
||||||
|
const line = file[compiledRow] ??= [];
|
||||||
let compiledCol = 0;
|
let compiledCol = 0;
|
||||||
|
|
||||||
for (const rawSeg of mapping[compiledRow]) {
|
for (const rawSeg of mapping[compiledRow]) {
|
||||||
@ -138,12 +141,13 @@ export class VLQSourceMap {
|
|||||||
originalRow += rawSeg.length > 2 ? rawSeg[2] : 0;
|
originalRow += rawSeg.length > 2 ? rawSeg[2] : 0;
|
||||||
originalCol += rawSeg.length > 3 ? rawSeg[3] : 0;
|
originalCol += rawSeg.length > 3 ? rawSeg[3] : 0;
|
||||||
|
|
||||||
let file = res.get(compiled);
|
if (!lastCols.has(compiledCol)) {
|
||||||
if (file == null) res.set(compiled, file = []);
|
|
||||||
|
|
||||||
const line = file[compiledRow] ??= [];
|
|
||||||
line[line.length] = [compiledCol, [filenames[originalFile], originalRow, originalCol]];
|
line[line.length] = [compiledCol, [filenames[originalFile], originalRow, originalCol]];
|
||||||
}
|
}
|
||||||
|
lastCols.add(compiledCol);
|
||||||
|
}
|
||||||
|
|
||||||
|
line.sort((a, b) => a[0] - b[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new VLQSourceMap(res);
|
return new VLQSourceMap(res);
|
10
src/lib/transpiler/types.ts
Normal file
10
src/lib/transpiler/types.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { type SourceMap } from "./map.ts";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
type CompilerFactory = (next: Compiler) => Compiler;
|
||||||
|
type Compiler = (filename: string, src: string, mapper: SourceMap) => Function;
|
||||||
|
|
||||||
|
function print(...args: any[]): void;
|
||||||
|
function register(factory: CompilerFactory): void;
|
||||||
|
function registerSource(filename: string, src: string): void;
|
||||||
|
}
|
@ -17,7 +17,7 @@ function resource(name: string) {
|
|||||||
else return resources[name] = getResource(name);
|
else return resources[name] = getResource(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
register(next => {
|
export default function typescript(next: Compiler): Compiler {
|
||||||
const files: Record<string, IScriptSnapshot> = {};
|
const files: Record<string, IScriptSnapshot> = {};
|
||||||
const versions: Record<string, number> = {};
|
const versions: Record<string, number> = {};
|
||||||
let declI = 0;
|
let declI = 0;
|
||||||
@ -34,6 +34,7 @@ register(next => {
|
|||||||
forceConsistentCasingInFileNames: true,
|
forceConsistentCasingInFileNames: true,
|
||||||
declaration: true,
|
declaration: true,
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
|
downlevelIteration: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let service: LanguageService;
|
let service: LanguageService;
|
||||||
@ -114,7 +115,7 @@ register(next => {
|
|||||||
const result = outputs["/src.js"];
|
const result = outputs["/src.js"];
|
||||||
const declaration = outputs["/src.d.ts"];
|
const declaration = outputs["/src.d.ts"];
|
||||||
|
|
||||||
const compiled = next("ts-internal://" + filename, result, SourceMap.chain(prevMap, map));
|
const compiled = next("ts-internal://" + filename, result, SourceMap.chain(map, prevMap));
|
||||||
registerSource(filename, code);
|
registerSource(filename, code);
|
||||||
|
|
||||||
return function (this: any) {
|
return function (this: any) {
|
||||||
@ -123,4 +124,4 @@ register(next => {
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
});
|
}
|
Loading…
Reference in New Issue
Block a user