From 7b1902183c7daab81f39861ef1908adada30977b Mon Sep 17 00:00:00 2001 From: Timothy Jones Date: Wed, 20 Oct 2010 03:53:38 +1300 Subject: [PATCH] Just catch alls for inner scoping now. --- lib/browser.js | 14 ++++---------- lib/command.js | 4 ++-- lib/nodes.js | 11 +++++++---- src/nodes.coffee | 13 +++++++++---- test/test_comprehensions.coffee | 11 +++++++++++ 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/lib/browser.js b/lib/browser.js index 37eb8b97..c35d5feb 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -29,16 +29,10 @@ for (_i = 0, _len = (_ref = document.getElementsByTagName('script')).length; _i < _len; _i++) { (function() { var script = _ref[_i]; - if (script.type === 'text/coffeescript') { - if (script.src) { - CoffeeScript.load(script.src); - } else { - setTimeout(function() { - return CoffeeScript.run(script.innerHTML); - }); - } - } - return (_j = script); + _j = script; + return script.type === 'text/coffeescript' ? (script.src ? CoffeeScript.load(script.src) : setTimeout(function() { + return CoffeeScript.run(script.innerHTML); + })) : undefined; })(); script = _j; } diff --git a/lib/command.js b/lib/command.js index 40b058da..17b3116e 100644 --- a/lib/command.js +++ b/lib/command.js @@ -54,7 +54,8 @@ (function() { var base, compile; var source = _ref2[_i]; - _result.push((function() { + _j = source; + return _result.push((function() { base = source; compile = function(source, topLevel) { return path.exists(source, function(exists) { @@ -83,7 +84,6 @@ }; return compile(source, true); })()); - return (_j = source); })(); source = _j; } diff --git a/lib/nodes.js b/lib/nodes.js index f38d5d49..99a925fb 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -1168,7 +1168,7 @@ } return _result; })(); - if (!empty) { + if (!(empty || this.noReturn)) { this.body.makeReturn(); } for (_j = 0, _len2 = params.length; _j < _len2; _j++) { @@ -1657,7 +1657,7 @@ return ''; }; For.prototype.compileNode = function(o) { - var body, codeInBody, forPart, guardPart, idt1, index, ivar, lvar, name, namePart, nvar, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars; + var body, codeInBody, forPart, guardPart, idt1, index, ivar, lastLine, lvar, name, namePart, nvar, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars; topLevel = del(o, 'top') && !this.returns; range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; source = range ? this.source.base : this.source; @@ -1734,13 +1734,15 @@ if (index) { body.unshift(new Literal("var " + index + " = " + ivar)); } + lastLine = body.expressions.pop(); if (index) { body.push(new Assign(new Literal(ivar), new Literal(index))); } if (nvar) { body.push(new Assign(new Literal(nvar), new Literal(name))); } - body = Closure.wrap(body, true); + body.push(lastLine); + body = Closure.wrap(body, true, true); if (index) { body.push(new Assign(new Literal(index), new Literal(ivar))); } @@ -1932,7 +1934,7 @@ } }; Closure = { - wrap: function(expressions, statement) { + wrap: function(expressions, statement, noReturn) { var args, call, func, mentionsArgs, meth; if (expressions.containsPureStatement()) { return expressions; @@ -1946,6 +1948,7 @@ args.push(new Literal('arguments')); } func = new Value(func, [new Accessor(meth)]); + func.noReturn = noReturn; } call = new Call(func, args); return statement ? Expressions.wrap([call]) : call; diff --git a/src/nodes.coffee b/src/nodes.coffee index f4e19d15..7edb8013 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -994,7 +994,7 @@ exports.Code = class Code extends Base params.push param o.scope.startLevel() params = (param.compile(o) for param in params) - @body.makeReturn() unless empty + @body.makeReturn() unless empty or @noReturn (o.scope.parameter(param)) for param in params comm = if @comment then @comment.compile(o) + '\n' else '' o.indent = @idt 2 if @className @@ -1456,16 +1456,20 @@ exports.For = class For extends Base body.unshift new Literal "var #{name} = #{ivar}" if range body.unshift new Literal "var #{namePart}" if namePart body.unshift new Literal "var #{index} = #{ivar}" if index + lastLine = body.expressions.pop() body.push new Assign new Literal(ivar), new Literal index if index body.push new Assign new Literal(nvar), new Literal name if nvar - body = Closure.wrap(body, true) + body.push lastLine + # o.indent = @idt 1 + # comp = new Literal body.compile o + body = Closure.wrap(body, yes, yes) body.push new Assign new Literal(index), new Literal ivar if index body.push new Assign new Literal(name), new Literal nvar or ivar if name else varPart = "#{idt1}#{namePart};\n" if namePart if @object forPart = "#{ivar} in #{sourcePart}" - guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" unless @raw + guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" unless @raw body = body.compile merge o, indent: idt1, top: true vars = if range then name else "#{name}, #{ivar}" """ @@ -1624,7 +1628,7 @@ Closure = # Wrap the expressions body, unless it contains a pure statement, # in which case, no dice. If the body mentions `this` or `arguments`, # then make sure that the closure wrapper preserves the original values. - wrap: (expressions, statement) -> + wrap: (expressions, statement, noReturn) -> return expressions if expressions.containsPureStatement() func = new Parens new Code [], Expressions.wrap [expressions] args = [] @@ -1634,6 +1638,7 @@ Closure = args = [new Literal 'this'] args.push new Literal 'arguments' if mentionsArgs func = new Value func, [new Accessor meth] + func.noReturn = noReturn call = new Call func, args if statement then Expressions.wrap [call] else call diff --git a/test/test_comprehensions.coffee b/test/test_comprehensions.coffee index 787147c6..d122256f 100644 --- a/test/test_comprehensions.coffee +++ b/test/test_comprehensions.coffee @@ -78,6 +78,17 @@ funcs = for i in [1..3] ok (func() for func in funcs).join(' ') is '-1 -2 -3' +# Ensure that closing over local variables doesn't break scoping laws. +ok i is 3 + +for i in [0] + count = 0 + i = 50 + -> +ok count is 0 +ok i is 50 + + # Even when referenced in the filter. list = ['one', 'two', 'three']