Fixes #3143 -- Potential memory leaks caused by use of fat arrow next to other (non-fat-arrow-using) long-lived closures.

This commit is contained in:
Jeremy Ashkenas
2013-10-20 12:53:18 -03:00
parent 928f949761
commit 392767a04e
2 changed files with 67 additions and 56 deletions

View File

@@ -779,33 +779,34 @@
};
Value.prototype.unfoldSoak = function(o) {
var _this = this;
return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (function() {
var fst, i, ifn, prop, ref, snd, _i, _len, _ref4, _ref5;
if (ifn = _this.base.unfoldSoak(o)) {
(_ref4 = ifn.body.properties).push.apply(_ref4, _this.properties);
return ifn;
}
_ref5 = _this.properties;
for (i = _i = 0, _len = _ref5.length; _i < _len; i = ++_i) {
prop = _ref5[i];
if (!prop.soak) {
continue;
return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (function(_this) {
return function() {
var fst, i, ifn, prop, ref, snd, _i, _len, _ref4, _ref5;
if (ifn = _this.base.unfoldSoak(o)) {
(_ref4 = ifn.body.properties).push.apply(_ref4, _this.properties);
return ifn;
}
prop.soak = false;
fst = new Value(_this.base, _this.properties.slice(0, i));
snd = new Value(_this.base, _this.properties.slice(i));
if (fst.isComplex()) {
ref = new Literal(o.scope.freeVariable('ref'));
fst = new Parens(new Assign(ref, fst));
snd.base = ref;
_ref5 = _this.properties;
for (i = _i = 0, _len = _ref5.length; _i < _len; i = ++_i) {
prop = _ref5[i];
if (!prop.soak) {
continue;
}
prop.soak = false;
fst = new Value(_this.base, _this.properties.slice(0, i));
snd = new Value(_this.base, _this.properties.slice(i));
if (fst.isComplex()) {
ref = new Literal(o.scope.freeVariable('ref'));
fst = new Parens(new Assign(ref, fst));
snd.base = ref;
}
return new If(new Existence(fst), snd, {
soak: true
});
}
return new If(new Existence(fst), snd, {
soak: true
});
}
return false;
})();
return false;
};
})(this)();
};
return Value;
@@ -1437,26 +1438,27 @@
};
Class.prototype.walkBody = function(name, o) {
var _this = this;
return this.traverseChildren(false, function(child) {
var cont, exps, i, node, _i, _len, _ref4;
cont = true;
if (child instanceof Class) {
return false;
}
if (child instanceof Block) {
_ref4 = exps = child.expressions;
for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) {
node = _ref4[i];
if (node instanceof Value && node.isObject(true)) {
cont = false;
exps[i] = _this.addProperties(node, name, o);
}
return this.traverseChildren(false, (function(_this) {
return function(child) {
var cont, exps, i, node, _i, _len, _ref4;
cont = true;
if (child instanceof Class) {
return false;
}
child.expressions = exps = flatten(exps);
}
return cont && !(child instanceof Class);
});
if (child instanceof Block) {
_ref4 = exps = child.expressions;
for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) {
node = _ref4[i];
if (node instanceof Value && node.isObject(true)) {
cont = false;
exps[i] = _this.addProperties(node, name, o);
}
}
child.expressions = exps = flatten(exps);
}
return cont && !(child instanceof Class);
};
})(this));
};
Class.prototype.hoistDirectivePrologue = function() {
@@ -1778,7 +1780,14 @@
Code.prototype.jumps = NO;
Code.prototype.compileNode = function(o) {
var answer, code, exprs, i, idt, lit, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref4, _ref5, _ref6, _ref7, _ref8;
var answer, boundfunc, code, exprs, i, idt, lit, p, param, params, ref, splats, uniqs, val, wasEmpty, wrapper, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref4, _ref5, _ref6, _ref7, _ref8;
if (this.bound && !this.wrapped && !this["static"]) {
this.wrapped = true;
wrapper = new Code([new Param(new Literal('_this'))], new Block([this]));
boundfunc = new Call(wrapper, [new Literal('this')]);
boundfunc.updateLocationDataIfMissing(this.locationData);
return boundfunc.compileNode(o);
}
o.scope = new Scope(o.scope, this.body, this);
o.scope.shared = del(o, 'sharedScope');
o.indent += TAB;
@@ -1864,12 +1873,8 @@
if (!(wasEmpty || this.noReturn)) {
this.body.makeReturn();
}
if (this.bound) {
if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) {
this.bound = this.context = o.scope.parent.method.context;
} else if (!this["static"]) {
o.scope.parent.assign('_this', 'this');
}
if (this.bound && ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0)) {
this.bound = this.context = o.scope.parent.method.context;
}
idt = o.indent;
code = 'function';