UglifyJs - 缩小的损坏变量在运行时恢复其原始名称

UglifyJs - minified mangled variable recovers at runtime its original name

在我的代码库中,我有与 fabric.js:

交互的自定义​​代码
export function cropToCircle(object) {
    let minDim = Math.min(object.width, object.height);
    window.lastMinDim = minDim;
    return object.set('clipTo', ctx => {
        if (typeof minDim === 'undefined') minDim = window.lastMinDim || 1000;
        ctx.arc(0, 0, minDim / 2, 0, Math.PI * 2, true);
    });
}

它被 uglify.js 缩小到这个字符串中,我在这里展示它是美化的:

function s(e) {
    var t = Math.min(e.width, e.height);
    return window.lastMinDim = t, e.set('clipTo', function (e) {
        'undefined' === typeof t && (t = window.lastMinDim || 1e3), e.arc(0, 0, t / 2, 0, 2 * Math.PI, !0);
    });
}

在 运行 时,这个缩小的代码在大多数调用中都运行良好。但是有一次,由 Fabric 的 canvas.renderAll() 触发,我在其中收到错误 "Reference Error: e is not defined"。 在执行 e.set('clipTo').

的回调期间出现错误

令人惊奇的是,如果我检查调试器,我会看到回调被 运行 作为一个片段,其中输入参数被称为 ctx 而不是 e .这是屏幕截图:

显然如果输入参数被解释器重命名为ctx,那么body里面的e就没有定义;但它就像浏览器 "knows" 最初调用 e ctx,这对我来说没有任何意义,除非 Fabric(到处使用 ctx)以某种方式影响了这段代码的执行。

这在 Chrome 65 和 Firefox 59 中都得到验证。

我已经尽我所能地尝试更改源代码中的某些内容,以避免出现 ctx:

但还是不开心

谁能解释为什么浏览器要重命名此回调的输入变量?

这是一个非常值得纪念的事故。从未见过这样的事情,而且显然没有其他人对此有任何看法。

我找到的解决方案是保护参数名称 ctx 在缩小过程中不被破坏。

相关的 UglifyJS 配置是:

  mangle: {
    except: ['ctx'],
  },

创建以下 minified/prettified 代码:

function s(e) {
    var t = Math.min(e.width, e.height);
    return window.lastMinDim = t, e.set('clipTo', function (ctx) {
        'undefined' === typeof t && (t = window.lastMinDim || 1e3), ctx.arc(0, 0, t / 2, 0, 2 * Math.PI, !0);
    });
}

这样浏览器仍然会用 ctx 覆盖输入参数名称,但在这种情况下,函数体在执行期间仍然有意义。