feat: improve transpiler infrastructure

This commit is contained in:
TopchetoEU 2024-12-28 13:18:56 +02:00
parent 74f08b7483
commit 6c8c329992
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
9 changed files with 100 additions and 11 deletions

View File

@ -31,7 +31,7 @@ task compileEnv(type: NpmTask) {
}
task compileTypescript(type: NpmTask) {
inputs.files('rollup.config.js');
inputs.dir('src/lib/ts');
inputs.dir('src/lib/transpiler');
outputs.files("build/js/ts.js");
// nom nom tasty ram
environment.put("NODE_OPTIONS", "--max-old-space-size=4096");

View File

@ -1,10 +1,17 @@
{
"scripts": {
"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": {
"@babel/core": "^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"
},
"devDependencies": {

View File

@ -4,6 +4,7 @@ const typescript = require("@rollup/plugin-typescript");
const babel = require("@rollup/plugin-babel");
const commonjs = require("@rollup/plugin-commonjs");
const nodeResolve = require("@rollup/plugin-node-resolve");
const json = require("@rollup/plugin-json");
const { resolve } = require("path");
const shouldMinify = () => false;
@ -21,6 +22,7 @@ const construct = (input, output) => defineConfig({
},
commonjs(),
nodeResolve(),
json(),
babel({
extensions: [],
exclude: ["node_modules/**"],
@ -107,6 +109,14 @@ const construct = (input, output) => defineConfig({
path: "null",
os: "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({
// allowAllFormats: true,

View File

@ -0,0 +1,4 @@
import coffeescript from "./coffeescript.ts";
import babel from "./babel.ts";
register(v => coffeescript(babel(v)));

View 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;
};
}

View 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;
};
}

View File

@ -123,13 +123,16 @@ export class VLQSourceMap {
public static parseVLQ(compiled: string, filenames: string[], raw: string): VLQSourceMap {
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 originalCol = 0;
let originalFile = 0;
const lastCols = new Set<number>();
for (let compiledRow = 0; compiledRow < mapping.length; compiledRow++) {
const line = file[compiledRow] ??= [];
let compiledCol = 0;
for (const rawSeg of mapping[compiledRow]) {
@ -138,12 +141,13 @@ export class VLQSourceMap {
originalRow += rawSeg.length > 2 ? rawSeg[2] : 0;
originalCol += rawSeg.length > 3 ? rawSeg[3] : 0;
let file = res.get(compiled);
if (file == null) res.set(compiled, file = []);
const line = file[compiledRow] ??= [];
if (!lastCols.has(compiledCol)) {
line[line.length] = [compiledCol, [filenames[originalFile], originalRow, originalCol]];
}
lastCols.add(compiledCol);
}
line.sort((a, b) => a[0] - b[0]);
}
return new VLQSourceMap(res);

View 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;
}

View File

@ -17,7 +17,7 @@ function resource(name: string) {
else return resources[name] = getResource(name);
}
register(next => {
export default function typescript(next: Compiler): Compiler {
const files: Record<string, IScriptSnapshot> = {};
const versions: Record<string, number> = {};
let declI = 0;
@ -34,6 +34,7 @@ register(next => {
forceConsistentCasingInFileNames: true,
declaration: true,
sourceMap: true,
downlevelIteration: true,
};
let service: LanguageService;
@ -114,7 +115,7 @@ register(next => {
const result = outputs["/src.js"];
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);
return function (this: any) {
@ -123,4 +124,4 @@ register(next => {
return res;
};
};
});
}