facebookarchive / prepack

A JavaScript bundle optimizer.
http://prepack.io
Other
14.22k stars 426 forks source link

Leaking bindings stops tracking their values #2011

Open NTillmann opened 6 years ago

NTillmann commented 6 years ago

Prepacking this...

(function () {
    function f(g) {
        let x = 23;
        function f() { return x; }
        g(f); // <- this leaks x
        x = 1;
        x = 2;
        x = 3;
        x = 4;
        x = 5;
        return x;
    }
    global.__optimize && __optimize(f);
    global.inspect = function() { return f(g => g()); }
})();

results in the following (at least after #2010 lands):

(function () {
  var _$2 = this;

  var _1 = function (g) {
    var __scope_0 = new Array(1);

    var __scope_1 = function (__selector) {
      var __captured;

      switch (__selector) {
        case 0:
          __captured = [void 0];
          break;

        default:
          throw new Error("Unknown scope selector");
      }

      __scope_0[__selector] = __captured;
      return __captured;
    };

    var _A = function () {
      var __captured__scope_2 = __scope_0[0] || __scope_1(0);

      return __captured__scope_2[0];
    };

    (__scope_0[0] || __scope_1(0))[0] = 23;

    var _$0 = g(_A);

    (__scope_0[0] || __scope_1(0))[0] = 1;
    (__scope_0[0] || __scope_1(0))[0] = 2;
    (__scope_0[0] || __scope_1(0))[0] = 3;
    (__scope_0[0] || __scope_1(0))[0] = 4;
    (__scope_0[0] || __scope_1(0))[0] = 5;

    var _$1 = (__scope_0[0] || __scope_1(0))[0];

    return _$1;
  };

  var _0 = function () {
    return _1(g => g());
  };

  _$2.inspect = _0;
}).call(this);

Ignoring the whole (__scope_0[0] || __scope_1(0))[0] verbosity, this is not great because, because after havocing...

NTillmann commented 6 years ago

2031 made the situation a bit better for bindings, as at least for final objects the leaked final descriptor is kept around and used.