mirror of
https://github.com/MercuryWorkshop/scramjet.git
synced 2025-05-13 14:30:02 -04:00
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
import { ScramjetClient } from "../client";
|
|
|
|
let sourcemaps: {
|
|
source: string;
|
|
map: [string, number, number][];
|
|
}[] = [];
|
|
|
|
export const enabled = self.$scramjet.config.flags.sourcemaps;
|
|
|
|
export default function (client: ScramjetClient, self: Self) {
|
|
// every script will push a sourcemap
|
|
Object.defineProperty(self, "$scramjet$pushsourcemap", {
|
|
value: (map, source) => {
|
|
sourcemaps.push({ map, source });
|
|
},
|
|
enumerable: false,
|
|
writable: false,
|
|
configurable: false,
|
|
});
|
|
|
|
// when we rewrite javascript it will make function.toString leak internals
|
|
// this can lead to double rewrites which is bad
|
|
client.Proxy("Function.prototype.toString", {
|
|
apply(ctx) {
|
|
const stringified = ctx.fn.call(ctx.this);
|
|
let newString = "";
|
|
|
|
// find the sourcemap, brute force, just check every file until the body of the function shows up
|
|
// it doesnt matter if there's multiple with the same content because it will be the same function
|
|
const sourcemap = sourcemaps.find(({ source }) =>
|
|
source.includes(stringified)
|
|
);
|
|
|
|
// i don't know what cases this would happen under, but it does
|
|
if (!sourcemap) return ctx.return(stringified);
|
|
const { source, map } = sourcemap;
|
|
|
|
// first we need to find the character # where the function starts relative to the *transformed* source
|
|
let starting = source.indexOf(stringified);
|
|
|
|
const beforeFunctionRewrites = map.filter(
|
|
([str, start, end]) => start < starting
|
|
);
|
|
|
|
// map the offsets of the original source to the transformed source
|
|
for (const [str, start, end] of beforeFunctionRewrites) {
|
|
starting -= end - start - str.length;
|
|
}
|
|
|
|
const relevantRewrites = map.filter(
|
|
([str, start, end]) =>
|
|
start >= starting && end <= starting + stringified.length
|
|
);
|
|
|
|
let i = 0;
|
|
let offset = 0;
|
|
for (const [str, start, end] of relevantRewrites) {
|
|
// ooh i should really document this before i forget how it works
|
|
newString += stringified.slice(i, start - starting + offset);
|
|
newString += str;
|
|
offset += end - start - str.length;
|
|
i = start - starting + offset + str.length;
|
|
}
|
|
return ctx.return(newString + stringified.slice(i));
|
|
},
|
|
});
|
|
}
|