From a352f2878536486be8b9dd753faadbb294184e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Mon, 29 Jan 2024 11:13:48 +0100 Subject: [PATCH] Fix transform of unary expression in Babel plugin All of our static evaluation & dead-code elimination transforms need to happen in post-order, transforming inner nodes first. This is so that in complex nested cases all transforms see the simplified version of their inner nodes. For example: async getNimbusExperimentData() { if (!PDFJSDev.test("GECKOVIEW")) { return null; } // other code } -> [evaluation of PDFJSDev.*] async getNimbusExperimentData() { if (!false) { return null; } // other code } -> [!false -> true] async getNimbusExperimentData() { if (true) { return null; } // other code } -> [if (true) -> replace with the if branch] async getNimbusExperimentData() { return null; // other code } -> [early return -> remove dead code] async getNimbusExperimentData() { return null; // other code } This was done correctly in all cases except for our `UnaryExpression` transform, which was happening in pre-order. --- .../babel-plugin-pdfjs-preprocessor.mjs | 27 +++++++++++-------- .../fixtures_esprima/evals-expected.js | 2 ++ external/builder/fixtures_esprima/evals.js | 2 ++ web/firefoxcom.js | 2 +- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/external/builder/babel-plugin-pdfjs-preprocessor.mjs b/external/builder/babel-plugin-pdfjs-preprocessor.mjs index 175ba050d..83f7fa1c8 100644 --- a/external/builder/babel-plugin-pdfjs-preprocessor.mjs +++ b/external/builder/babel-plugin-pdfjs-preprocessor.mjs @@ -92,17 +92,22 @@ function babelPluginPDFJSPreprocessor(babel, ctx) { } }, }, - UnaryExpression(path) { - const { node } = path; - if (node.operator === "typeof" && isPDFJSPreprocessor(node.argument)) { - // typeof PDFJSDev => 'object' - path.replaceWith(t.stringLiteral("object")); - return; - } - if (node.operator === "!" && t.isBooleanLiteral(node.argument)) { - // !true => false, !false => true - path.replaceWith(t.booleanLiteral(!node.argument.value)); - } + UnaryExpression: { + exit(path) { + const { node } = path; + if ( + node.operator === "typeof" && + isPDFJSPreprocessor(node.argument) + ) { + // typeof PDFJSDev => 'object' + path.replaceWith(t.stringLiteral("object")); + return; + } + if (node.operator === "!" && t.isBooleanLiteral(node.argument)) { + // !true => false, !false => true + path.replaceWith(t.booleanLiteral(!node.argument.value)); + } + }, }, LogicalExpression: { exit(path) { diff --git a/external/builder/fixtures_esprima/evals-expected.js b/external/builder/fixtures_esprima/evals-expected.js index 8bd569759..510e62f1b 100644 --- a/external/builder/fixtures_esprima/evals-expected.js +++ b/external/builder/fixtures_esprima/evals-expected.js @@ -17,3 +17,5 @@ var i = '0'; var j = { i: 1 }; +var k = false; +var l = true; diff --git a/external/builder/fixtures_esprima/evals.js b/external/builder/fixtures_esprima/evals.js index c0649ae83..db03ab047 100644 --- a/external/builder/fixtures_esprima/evals.js +++ b/external/builder/fixtures_esprima/evals.js @@ -8,3 +8,5 @@ var g = PDFJSDev.eval('OBJ'); var h = PDFJSDev.json('$ROOT/external/builder/fixtures_esprima/evals.json'); var i = typeof PDFJSDev === 'undefined' ? PDFJSDev.eval('FALSE') : '0'; var j = typeof PDFJSDev !== 'undefined' ? PDFJSDev.eval('OBJ.obj') : '0'; +var k = !PDFJSDev.test('TRUE'); +var l = !PDFJSDev.test('FALSE'); diff --git a/web/firefoxcom.js b/web/firefoxcom.js index e8265df72..b788f2f29 100644 --- a/web/firefoxcom.js +++ b/web/firefoxcom.js @@ -400,7 +400,7 @@ class ExternalServices extends BaseExternalServices { } async getNimbusExperimentData() { - if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("GECKOVIEW")) { + if (!PDFJSDev.test("GECKOVIEW")) { return null; } const nimbusData = await FirefoxCom.requestAsync(