Compare commits

..

4 Commits

Author SHA1 Message Date
Jonas Jenwald
6a1368ad81
Merge pull request #21339 from nicolo-ribaudo/remove-unused-variables
Remove unused variables with the Babel plugin
2026-05-26 18:59:32 +02:00
Nicolò Ribaudo
2691868904 Remove unused variables with the Babel plugin
- functions were already removed
- variables can be removed when their initializer does not have side effects
- classes can be removed when they have no static blocks

Fixes #21337
2026-05-26 16:35:57 +02:00
calixteman
03eda70d7e
Merge pull request #21340 from Snuffleupagus/test-modified-external-builder
Run unit-tests and integration-tests when the `external/builder/` folder is changed
2026-05-26 16:14:36 +02:00
Jonas Jenwald
927da8c78e Run unit-tests and integration-tests when the external/builder/ folder is changed
Given that changes to either the Babel plugin or the "old" builder could accidentally cause issues in the built files, it seems like a good idea to run all test-suites when the `external/builder/` folder is changed.
2026-05-26 15:12:22 +02:00
13 changed files with 86 additions and 25 deletions

View File

@ -3,6 +3,7 @@ on:
push: push:
paths: paths:
- 'gulpfile.mjs' - 'gulpfile.mjs'
- 'external/builder/**'
- 'src/**' - 'src/**'
- 'test/test.mjs' - 'test/test.mjs'
- 'test/integration/**' - 'test/integration/**'
@ -13,6 +14,7 @@ on:
pull_request: pull_request:
paths: paths:
- 'gulpfile.mjs' - 'gulpfile.mjs'
- 'external/builder/**'
- 'src/**' - 'src/**'
- 'test/test.mjs' - 'test/test.mjs'
- 'test/integration/**' - 'test/integration/**'

View File

@ -3,6 +3,7 @@ on:
push: push:
paths: paths:
- 'gulpfile.mjs' - 'gulpfile.mjs'
- 'external/builder/**'
- 'src/**' - 'src/**'
- 'test/test.mjs' - 'test/test.mjs'
- 'test/unit/**' - 'test/unit/**'
@ -13,6 +14,7 @@ on:
pull_request: pull_request:
paths: paths:
- 'gulpfile.mjs' - 'gulpfile.mjs'
- 'external/builder/**'
- 'src/**' - 'src/**'
- 'test/test.mjs' - 'test/test.mjs'
- 'test/unit/**' - 'test/unit/**'

View File

@ -47,18 +47,31 @@ function handlePreprocessorAction(ctx, actionName, args, path) {
} }
function babelPluginPDFJSPreprocessor(babel, ctx) { function babelPluginPDFJSPreprocessor(babel, ctx) {
function removeUnusedFunctions(path) { function removeUnusedFunctionsAndVariables(path) {
const { scope } = path;
let removed; let removed;
do { do {
removed = false; removed = false;
path.scope.crawl(); scope.crawl();
for (const name in path.scope.bindings) { for (const name in scope.bindings) {
const binding = path.scope.bindings[name]; const binding = scope.bindings[name];
if (!binding.referenced) { if (!binding.referenced) {
const { path: bindingPath } = binding; const { path: bindingPath } = binding;
if (bindingPath.isFunctionDeclaration()) { if (bindingPath.isFunctionDeclaration()) {
bindingPath.remove(); bindingPath.remove();
removed = true; removed = true;
} else if (
bindingPath.isClassDeclaration() &&
!bindingPath.node.body.body.some(m => m.type === "StaticBlock")
) {
bindingPath.remove();
removed = true;
} else if (
bindingPath.isVariableDeclarator() &&
scope.isPure(bindingPath.node.init, false)
) {
bindingPath.remove();
removed = true;
} }
} }
} }
@ -113,7 +126,15 @@ function babelPluginPDFJSPreprocessor(babel, ctx) {
LogicalExpression: { LogicalExpression: {
exit(path) { exit(path) {
const { node } = path; const { node } = path;
if (!t.isBooleanLiteral(node.left)) { let leftIsTruthy = false;
switch (node.left.type) {
case "BooleanLiteral":
case "NumericLiteral":
case "StringLiteral":
case "NullLiteral":
leftIsTruthy = Boolean(node.left.value);
break;
default:
return; return;
} }
@ -121,16 +142,12 @@ function babelPluginPDFJSPreprocessor(babel, ctx) {
case "&&": case "&&":
// true && expr => expr // true && expr => expr
// false && expr => false // false && expr => false
path.replaceWith( path.replaceWith(leftIsTruthy ? node.right : node.left);
node.left.value === true ? node.right : node.left
);
break; break;
case "||": case "||":
// true || expr => true // true || expr => true
// false || expr => expr // false || expr => expr
path.replaceWith( path.replaceWith(leftIsTruthy ? node.left : node.right);
node.left.value === true ? node.left : node.right
);
break; break;
} }
}, },
@ -258,7 +275,7 @@ function babelPluginPDFJSPreprocessor(babel, ctx) {
body.pop(); body.pop();
} }
removeUnusedFunctions(path); removeUnusedFunctionsAndVariables(path);
}, },
}, },
ClassMethod: { ClassMethod: {
@ -284,7 +301,7 @@ function babelPluginPDFJSPreprocessor(babel, ctx) {
Program: { Program: {
exit(path) { exit(path) {
if (path.node.sourceType === "module") { if (path.node.sourceType === "module") {
removeUnusedFunctions(path); removeUnusedFunctionsAndVariables(path);
} }
}, },
}, },

View File

@ -13,3 +13,6 @@ var l = true;
var m = false; var m = false;
var n = false; var n = false;
var o = true; var o = true;
var p = null;
var q = 1;
use(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);

View File

@ -13,3 +13,7 @@ var l = 'test' !== 'test2';
var m = '1' === true; var m = '1' === true;
var n = !true; var n = !true;
var o = !false; var o = !false;
var p = null && 1;
var q = null || 1;
use(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);

View File

@ -18,6 +18,8 @@ class E extends A {
class F { class F {
constructor() { constructor() {
var a = 0; var a = 0;
use(a);
} }
} }
class G {} class G {}
use(B, C, D, E, F, G);

View File

@ -24,6 +24,7 @@ class F {
constructor() { constructor() {
if (PDFJSDev.test('TRUE')) { if (PDFJSDev.test('TRUE')) {
var a = 0; var a = 0;
use(a);
} }
} }
} }
@ -32,6 +33,9 @@ class G {
constructor() { constructor() {
if (PDFJSDev.test('FALSE')) { if (PDFJSDev.test('FALSE')) {
var a = 0; var a = 0;
use(a);
} }
} }
} }
use(B, C, D, E, F, G);

View File

@ -5,12 +5,12 @@ function f2() {
} }
f2(); f2();
function f3() { function f3() {
var i = 0; before();
throw "test"; throw "test";
} }
f3(); f3();
function f4() { function f4() {
var i = 0; before();
} }
f4(); f4();
var obj = { var obj = {
@ -23,3 +23,4 @@ class C {
} }
var arrow1 = () => {}; var arrow1 = () => {};
var arrow2 = () => {}; var arrow2 = () => {};
use(obj, C, arrow1, arrow2);

View File

@ -1,41 +1,43 @@
function f1() { function f1() {
return; return;
var i = 0; after();
} }
f1(); f1();
function f2() { function f2() {
return 1; return 1;
var i = 0; after();
} }
f2(); f2();
function f3() { function f3() {
var i = 0; before();
throw "test"; throw "test";
var j = 0; after();
} }
f3(); f3();
function f4() { function f4() {
var i = 0; before();
if (true) { if (true) {
return; return;
} }
throw "test"; throw "test";
var j = 0; after();
} }
f4(); f4();
var obj = { var obj = {
method1() { return; var i = 0; }, method1() { return; after(); },
method2() { return; }, method2() { return; },
}; };
class C { class C {
method1() { return; var i = 0; } method1() { return; after(); }
method2() { return; } method2() { return; }
} }
var arrow1 = () => { return; var i = 0; }; var arrow1 = () => { return; after(); };
var arrow2 = () => { return; }; var arrow2 = () => { return; };
use(obj, C, arrow1, arrow2);

View File

@ -16,3 +16,4 @@ var j = {
}; };
var k = false; var k = false;
var l = true; var l = true;
use(a, b, c, d, e, f, g, i, j, k, l);

View File

@ -9,3 +9,5 @@ var i = typeof PDFJSDev === 'undefined' ? PDFJSDev.eval('FALSE') : '0';
var j = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('OBJ.obj') : '0'; var j = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('OBJ.obj') : '0';
var k = !PDFJSDev.test('TRUE'); var k = !PDFJSDev.test('TRUE');
var l = !PDFJSDev.test('FALSE'); var l = !PDFJSDev.test('FALSE');
use(a, b, c, d, e, f, g, i, j, k, l);

View File

@ -0,0 +1,7 @@
let c = 4;
let e = sideEffect();
let f = 5;
use(c);
{
use(f);
}

View File

@ -0,0 +1,14 @@
let a = 1;
let b = a, c = 4;
let d = null && sideEffect();
let e = null || sideEffect();
let f = 5;
let g = 6;
use(c);
if (PDFJSDev.test('TRUE')) {
use(f);
} else {
use(g);
}