mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 20:28:58 +00:00
# Oxc Module Lexer This is not a lexer. The name "lexer" is used for easier recognition. ## [es-module-lexer](https://github.com/guybedford/es-module-lexer) Outputs the list of exports and locations of import specifiers, including dynamic import and import meta handling. Does not have any [limitations](https://github.com/guybedford/es-module-lexer?tab=readme-ov-file#limitations) mentioned in `es-module-lexer`. I'll also work on the following cases to make this feature complete. - [ ] get imported variables https://github.com/guybedford/es-module-lexer/issues/163 - [ ] track star exports as imports as well https://github.com/guybedford/es-module-lexer/issues/76 - [ ] TypeScript specific syntax - [ ] TypeScript `type` import / export keyword ## [cjs-module-lexer](https://github.com/nodejs/cjs-module-lexer) - [ ] TODO ## Benchmark This is 2 times slower than `es-module-lexer`, but will be significantly faster when TypeScript is processed. The difference is around 10ms vs 20ms on a large file (700k).
103 lines
2.5 KiB
JavaScript
103 lines
2.5 KiB
JavaScript
/*
|
|
* Test and bench against `es-module-lexer`
|
|
*/
|
|
import fs from "fs";
|
|
import assert from "assert";
|
|
|
|
import oxc from "./index.js";
|
|
import * as esModuleLexer from "es-module-lexer";
|
|
|
|
const root = "/Users/boshen/github/es-module-lexer/test/samples";
|
|
|
|
main();
|
|
|
|
async function main() {
|
|
await esModuleLexer.init;
|
|
|
|
const files = fs
|
|
.readdirSync(root)
|
|
.filter((x) => x.endsWith(".js"))
|
|
.map((file) => {
|
|
const source = fs.readFileSync(`${root}/${file}`);
|
|
return {
|
|
file,
|
|
code: source.toString(),
|
|
size: source.byteLength,
|
|
};
|
|
});
|
|
|
|
function test(source) {
|
|
const [imports, exports, facade, hasModuleSyntax] =
|
|
esModuleLexer.parse(source);
|
|
const moduleLexer = oxc.moduleLexerSync(source);
|
|
assert(moduleLexer.imports.length == imports.length);
|
|
assert(moduleLexer.exports.length == exports.length);
|
|
assert(moduleLexer.facade == facade);
|
|
assert(moduleLexer.hasModuleSyntax == hasModuleSyntax);
|
|
}
|
|
|
|
function testAll(files) {
|
|
for (const file of files) {
|
|
test(file.code);
|
|
}
|
|
}
|
|
|
|
testAll(files);
|
|
|
|
const n = 25;
|
|
|
|
bench("es-module-lexer", esModuleLexer.parse);
|
|
bench("oxc", oxc.moduleLexerSync);
|
|
|
|
function bench(name, fn) {
|
|
console.log("-----------");
|
|
console.log(name);
|
|
|
|
doRun();
|
|
|
|
function timeRun(code) {
|
|
const start = process.hrtime.bigint();
|
|
fn(code);
|
|
const end = process.hrtime.bigint();
|
|
return Math.round(Number(end - start) / 1e6);
|
|
}
|
|
|
|
function doRun() {
|
|
console.log("Cold Run, All Samples");
|
|
let totalSize = 0;
|
|
{
|
|
let total = 0;
|
|
files.forEach(({ code, size }) => {
|
|
totalSize += size;
|
|
total += timeRun(code);
|
|
});
|
|
console.log(`test/samples/*.js (${Math.round(totalSize / 1e3)} KiB)`);
|
|
console.log(`> ${total + "ms"}`);
|
|
}
|
|
|
|
console.log(`\nWarm Runs (average of ${n} runs)`);
|
|
files.forEach(({ file, code, size }) => {
|
|
console.log(`${file} (${Math.round(size / 1e3)} KiB)`);
|
|
|
|
let total = 0;
|
|
for (let i = 0; i < n; i++) {
|
|
total += timeRun(code);
|
|
}
|
|
|
|
console.log(`> ${total / n + "ms"}`);
|
|
});
|
|
|
|
console.log(`\nWarm Runs, All Samples (average of ${n} runs)`);
|
|
{
|
|
let total = 0;
|
|
for (let i = 0; i < n; i++) {
|
|
files.forEach(({ code }) => {
|
|
total += timeRun(code);
|
|
});
|
|
}
|
|
console.log(`test/samples/*.js (${Math.round(totalSize / 1e3)} KiB)`);
|
|
console.log(`> ${total / n + "ms"}`);
|
|
}
|
|
}
|
|
}
|
|
}
|