mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-10-28 17:22:51 +08:00
116 lines
4.7 KiB
JavaScript
116 lines
4.7 KiB
JavaScript
/* Gate: prove jsmin's output is the SAME PROGRAM as the source.
|
|
*
|
|
* `luci.mk` minifies every LuCI package's JS with jsmin, whose hand-written scanner decides REGEX
|
|
* vs DIVISION from exactly one preceding character against a fixed allow-list — `n`, the last
|
|
* letter of `return`, is not on it, nor is `>` from `=>`. So `return /re/` makes jsmin read the
|
|
* regex's `//` as a line comment and swallow the rest of the file, exiting 0 while doing it
|
|
* (openwrt/luci#8299, #8020, #8021, #8256).
|
|
*
|
|
* A zero exit code therefore proves nothing. The only proof jsmin did not eat our code is
|
|
* comparing the TOKEN STREAM of source and output — same tokens, same order, or the build is
|
|
* wrong. acorn is already an eslint transitive dependency.
|
|
*
|
|
* `allowReturnOutsideFunction`: a LuCI resource file is evaluated inside a function wrapper and
|
|
* legitimately ends in a top-level `return baseclass.extend()`. */
|
|
import { readFileSync, existsSync } from 'node:fs';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { join } from 'node:path';
|
|
import * as acorn from 'acorn';
|
|
|
|
const JSMIN = process.env.JSMIN || '/tmp/jsmin';
|
|
const OPTS = { ecmaVersion: 2022, allowReturnOutsideFunction: true, allowAwaitOutsideFunction: true };
|
|
|
|
if (!existsSync(JSMIN)) {
|
|
console.error(`jsmin not found at ${JSMIN}. Build it from luci-base/src/jsmin.c and set $JSMIN.`);
|
|
process.exit(2);
|
|
}
|
|
|
|
const tokens = (src) => [...acorn.tokenizer(src, OPTS)].map(t => `${t.type.label} |