From 94313029e4ec5d1030423b38aafa9bc291cdeeab Mon Sep 17 00:00:00 2001 From: Joe Moon Date: Thu, 4 Dec 2025 16:29:39 -0800 Subject: [PATCH 1/3] add some failing fixture tests --- .../input.js | 11 ++++++++ .../output.js | 23 +++++++++++++++++ .../conditional-exports-or-false/input.js | 13 ++++++++++ .../conditional-exports-or-false/output.js | 25 +++++++++++++++++++ .../form/conditional-exports-or-null/input.js | 10 ++++++++ .../conditional-exports-or-null/output.js | 22 ++++++++++++++++ .../form/conditional-exports-or-true/input.js | 10 ++++++++ .../conditional-exports-or-true/output.js | 22 ++++++++++++++++ .../input.js | 10 ++++++++ .../output.js | 22 ++++++++++++++++ 10 files changed, 168 insertions(+) create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/input.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/output.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-false/input.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-false/output.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-null/input.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-null/output.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-true/input.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/input.js create mode 100644 packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/output.js diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/input.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/input.js new file mode 100644 index 000000000..1b2e503af --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/input.js @@ -0,0 +1,11 @@ +var condition1 = typeof global !== 'undefined' && global.env && global.env.USE_FEATURE_A; +var condition2 = typeof global !== 'undefined' && global.env && global.env.USE_FEATURE_B; + +function featureHandler() { return 'feature'; } +function defaultHandler() { return 'default'; } + +if (condition1 || condition2) { + exports.handler = featureHandler; +} else { + exports.handler = defaultHandler; +} diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/output.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/output.js new file mode 100644 index 000000000..d7ac94de8 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-conditional/output.js @@ -0,0 +1,23 @@ +import * as commonjsHelpers from "_commonjsHelpers.js"; +import { __exports as input } from "\u0000fixtures/form/conditional-exports-or-conditional/input.js?commonjs-exports"; + +var hasRequiredInput; + +function requireInput () { + if (hasRequiredInput) return input; + hasRequiredInput = 1; + var condition1 = typeof commonjsHelpers.commonjsGlobal !== 'undefined' && commonjsHelpers.commonjsGlobal.env && commonjsHelpers.commonjsGlobal.env.USE_FEATURE_A; + var condition2 = typeof commonjsHelpers.commonjsGlobal !== 'undefined' && commonjsHelpers.commonjsGlobal.env && commonjsHelpers.commonjsGlobal.env.USE_FEATURE_B; + + function featureHandler() { return 'feature'; } + function defaultHandler() { return 'default'; } + + if (condition1 || condition2) { + input.handler = featureHandler; + } else { + input.handler = defaultHandler; + } + return input; +} + +export { requireInput as __require }; diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-false/input.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-false/input.js new file mode 100644 index 000000000..273bc249f --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-false/input.js @@ -0,0 +1,13 @@ +var crypto = (typeof global !== 'undefined' && global.crypto) || null; + +function randomFill() { return 'randomFill'; } +function randomFillSync() { return 'randomFillSync'; } +function oldBrowser() { throw new Error('not supported'); } + +if ((crypto && crypto.getRandomValues) || false) { + exports.randomFill = randomFill; + exports.randomFillSync = randomFillSync; +} else { + exports.randomFill = oldBrowser; + exports.randomFillSync = oldBrowser; +} diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-false/output.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-false/output.js new file mode 100644 index 000000000..38bac02bb --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-false/output.js @@ -0,0 +1,25 @@ +import * as commonjsHelpers from "_commonjsHelpers.js"; +import { __exports as input } from "\u0000fixtures/form/conditional-exports-or-false/input.js?commonjs-exports"; + +var hasRequiredInput; + +function requireInput () { + if (hasRequiredInput) return input; + hasRequiredInput = 1; + var crypto = (typeof commonjsHelpers.commonjsGlobal !== 'undefined' && commonjsHelpers.commonjsGlobal.crypto) || null; + + function randomFill() { return 'randomFill'; } + function randomFillSync() { return 'randomFillSync'; } + function oldBrowser() { throw new Error('not supported'); } + + if ((crypto && crypto.getRandomValues) || false) { + input.randomFill = randomFill; + input.randomFillSync = randomFillSync; + } else { + input.randomFill = oldBrowser; + input.randomFillSync = oldBrowser; + } + return input; +} + +export { requireInput as __require }; diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-null/input.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-null/input.js new file mode 100644 index 000000000..fe30f0332 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-null/input.js @@ -0,0 +1,10 @@ +var crypto = (typeof global !== 'undefined' && global.crypto) || null; + +function secureHandler() { return 'secure'; } +function fallbackHandler() { return 'fallback'; } + +if ((crypto && crypto.getRandomValues) || null) { + exports.handler = secureHandler; +} else { + exports.handler = fallbackHandler; +} diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-null/output.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-null/output.js new file mode 100644 index 000000000..d71869fb5 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-null/output.js @@ -0,0 +1,22 @@ +import * as commonjsHelpers from "_commonjsHelpers.js"; +import { __exports as input } from "\u0000fixtures/form/conditional-exports-or-null/input.js?commonjs-exports"; + +var hasRequiredInput; + +function requireInput () { + if (hasRequiredInput) return input; + hasRequiredInput = 1; + var crypto = (typeof commonjsHelpers.commonjsGlobal !== 'undefined' && commonjsHelpers.commonjsGlobal.crypto) || null; + + function secureHandler() { return 'secure'; } + function fallbackHandler() { return 'fallback'; } + + if ((crypto && crypto.getRandomValues) || null) { + input.handler = secureHandler; + } else { + input.handler = fallbackHandler; + } + return input; +} + +export { requireInput as __require }; diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-true/input.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-true/input.js new file mode 100644 index 000000000..dfe4c5ca8 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-true/input.js @@ -0,0 +1,10 @@ +var condition = typeof global !== 'undefined' && global.env && global.env.NODE_ENV; + +function prodHandler() { return 'production'; } +function defaultHandler() { return 'default'; } + +if (condition || true) { + exports.handler = prodHandler; +} else { + exports.handler = defaultHandler; +} diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js new file mode 100644 index 000000000..8110e5fb8 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js @@ -0,0 +1,22 @@ +import * as commonjsHelpers from "_commonjsHelpers.js"; +import { __exports as input } from "\u0000fixtures/form/conditional-exports-or-true/input.js?commonjs-exports"; + +var hasRequiredInput; + +function requireInput () { + if (hasRequiredInput) return input; + hasRequiredInput = 1; + var condition = typeof commonjsHelpers.commonjsGlobal !== 'undefined' && commonjsHelpers.commonjsGlobal.env && commonjsHelpers.commonjsGlobal.env.NODE_ENV; + + function prodHandler() { return 'production'; } + function defaultHandler() { return 'default'; } + + if (condition || true) { + input.handler = prodHandler; + } else { + input.handler = defaultHandler; + } + return input; +} + +export { requireInput as __require }; diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/input.js b/packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/input.js new file mode 100644 index 000000000..9355bba01 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/input.js @@ -0,0 +1,10 @@ +var condition = typeof global !== 'undefined' && global.env && global.env.DEBUG; + +function enabledHandler() { return 'enabled'; } +function disabledHandler() { return 'disabled'; } + +if (true || condition) { + exports.handler = enabledHandler; +} else { + exports.handler = disabledHandler; +} diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/output.js b/packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/output.js new file mode 100644 index 000000000..9a9c6ddb5 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/conditional-exports-true-or-conditional/output.js @@ -0,0 +1,22 @@ +import * as commonjsHelpers from "_commonjsHelpers.js"; +import { __exports as input } from "\u0000fixtures/form/conditional-exports-true-or-conditional/input.js?commonjs-exports"; + +var hasRequiredInput; + +function requireInput () { + if (hasRequiredInput) return input; + hasRequiredInput = 1; + var condition = typeof commonjsHelpers.commonjsGlobal !== 'undefined' && commonjsHelpers.commonjsGlobal.env && commonjsHelpers.commonjsGlobal.env.DEBUG; + + function enabledHandler() { return 'enabled'; } + function disabledHandler() { return 'disabled'; } + + if (true || condition) { + input.handler = enabledHandler; + } else { + exports.handler = disabledHandler; + } + return input; +} + +export { requireInput as __require }; From c674007cf941cf1c79b6242f99cfadab1545348a Mon Sep 17 00:00:00 2001 From: Joe Moon Date: Thu, 4 Dec 2025 16:31:49 -0800 Subject: [PATCH 2/3] fix conditional check bug --- packages/commonjs/src/ast-utils.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/commonjs/src/ast-utils.js b/packages/commonjs/src/ast-utils.js index 042ef8f2e..2e0bbb288 100644 --- a/packages/commonjs/src/ast-utils.js +++ b/packages/commonjs/src/ast-utils.js @@ -13,7 +13,18 @@ const operators = { '&&': (x) => isTruthy(x.left) && isTruthy(x.right), - '||': (x) => isTruthy(x.left) || isTruthy(x.right) + '||': (x) => { + const leftTruthy = isTruthy(x.left); + const rightTruthy = isTruthy(x.right); + // If left is definitely truthy, the whole expression is truthy + if (leftTruthy === true) return true; + // If both are definitely falsy, the whole expression is falsy + if (leftTruthy === false && rightTruthy === false) return false; + // If left is falsy but right is truthy, the whole expression is truthy + if (leftTruthy === false && rightTruthy === true) return true; + // Otherwise it's conditional + return null; + } }; function not(value) { From 537a334b714828b28ace5b82b86af05b92236fa8 Mon Sep 17 00:00:00 2001 From: Joe Moon Date: Mon, 16 Feb 2026 12:18:24 -0800 Subject: [PATCH 3/3] fix regression of (condition || true) case --- packages/commonjs/src/ast-utils.js | 32 +++++++++++-------- .../conditional-exports-or-true/output.js | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/commonjs/src/ast-utils.js b/packages/commonjs/src/ast-utils.js index 2e0bbb288..adbbaedd0 100644 --- a/packages/commonjs/src/ast-utils.js +++ b/packages/commonjs/src/ast-utils.js @@ -1,5 +1,19 @@ export { default as isReference } from 'is-reference'; +function triStateAnd(a, b) { + if (a === false) return false; + if (b === false) return false; + if (a === true && b === true) return true; + return null; +} + +function triStateOr(a, b) { + if (a === true) return true; + if (b === true) return true; + if (a === false && b === false) return false; + return null; +} + const operators = { '==': (x) => equals(x.left, x.right, false), @@ -11,20 +25,9 @@ const operators = { '!': (x) => isFalsy(x.argument), - '&&': (x) => isTruthy(x.left) && isTruthy(x.right), - - '||': (x) => { - const leftTruthy = isTruthy(x.left); - const rightTruthy = isTruthy(x.right); - // If left is definitely truthy, the whole expression is truthy - if (leftTruthy === true) return true; - // If both are definitely falsy, the whole expression is falsy - if (leftTruthy === false && rightTruthy === false) return false; - // If left is falsy but right is truthy, the whole expression is truthy - if (leftTruthy === false && rightTruthy === true) return true; - // Otherwise it's conditional - return null; - } + '&&': (x) => triStateAnd(isTruthy(x.left), isTruthy(x.right)), + + '||': (x) => triStateOr(isTruthy(x.left), isTruthy(x.right)) }; function not(value) { @@ -137,3 +140,4 @@ export function hasDefineEsmProperty(node) { return false; }); } + diff --git a/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js b/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js index 8110e5fb8..00e85b0a3 100644 --- a/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js +++ b/packages/commonjs/test/fixtures/form/conditional-exports-or-true/output.js @@ -14,7 +14,7 @@ function requireInput () { if (condition || true) { input.handler = prodHandler; } else { - input.handler = defaultHandler; + exports.handler = defaultHandler; } return input; }