Skip to content

Commit eff160e

Browse files
authored
Merge pull request #4640 from GeoffreyBooth/generated-variables-in-function-parameters
[CS2] Fix #4413: Generated variables in function parameters
2 parents ae7f97b + 911c21f commit eff160e

File tree

3 files changed

+48
-19
lines changed

3 files changed

+48
-19
lines changed

lib/coffeescript/nodes.js

Lines changed: 23 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nodes.coffee

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ exports.Base = class Base
107107
@compileCommentFragments o, node, fragments
108108
fragments
109109

110+
compileToFragmentsWithoutComments: (o, lvl) ->
111+
@compileWithoutComments o, lvl, 'compileToFragments'
112+
110113
# Statements converted into expressions via closure-wrapping share a scope
111114
# object with their parent closure, to preserve the expected lexical scope.
112115
compileClosure: (o) ->
@@ -2626,11 +2629,7 @@ exports.Code = class Code extends Base
26262629
# compilation, so that they get output the “real” time this param
26272630
# is compiled.
26282631
paramToAddToScope = if param.value? then param else ref
2629-
if paramToAddToScope.name?.comments
2630-
salvagedComments = paramToAddToScope.name.comments
2631-
delete paramToAddToScope.name.comments
2632-
o.scope.parameter fragmentsToText paramToAddToScope.compileToFragments o
2633-
paramToAddToScope.name.comments = salvagedComments if salvagedComments
2632+
o.scope.parameter fragmentsToText paramToAddToScope.compileToFragmentsWithoutComments o
26342633
params.push ref
26352634
else
26362635
paramsAfterSplat.push param
@@ -2675,7 +2674,14 @@ exports.Code = class Code extends Base
26752674
for param, i in params
26762675
signature.push @makeCode ', ' if i isnt 0
26772676
signature.push @makeCode '...' if haveSplatParam and i is params.length - 1
2677+
# Compile this parameter, but if any generated variables get created
2678+
# (e.g. `ref`), shift those into the parent scope since we can’t put a
2679+
# `var` line inside a function parameter list.
2680+
scopeVariablesCount = o.scope.variables.length
26782681
signature.push param.compileToFragments(o)...
2682+
if scopeVariablesCount isnt o.scope.variables.length
2683+
generatedVariables = o.scope.variables.splice scopeVariablesCount
2684+
o.scope.parent.variables.push generatedVariables...
26792685
signature.push @makeCode ')'
26802686
# Block comments between `)` and `->`/`=>` get output between `)` and `{`.
26812687
if @funcGlyph?.comments?
@@ -2774,6 +2780,9 @@ exports.Param = class Param extends Base
27742780
compileToFragments: (o) ->
27752781
@name.compileToFragments o, LEVEL_LIST
27762782

2783+
compileToFragmentsWithoutComments: (o) ->
2784+
@name.compileToFragmentsWithoutComments o, LEVEL_LIST
2785+
27772786
asReference: (o) ->
27782787
return @reference if @reference
27792788
node = @name

test/functions.coffee

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,14 @@ test "#3845/#3446: chain after function glyph", ->
471471
doThing()
472472
.then (@result) =>
473473
.catch handleError
474+
475+
test "#4413: expressions in function parameters that create generated variables have those variables declared correctly", ->
476+
'use strict'
477+
# We’re in strict mode because we want an error to be thrown if the generated
478+
# variable (`ref`) is assigned before being declared.
479+
foo = -> null
480+
bar = -> 33
481+
f = (a = foo() ? bar()) -> a
482+
g = (a = foo() ? bar()) -> a + 1
483+
eq f(), 33
484+
eq g(), 34

0 commit comments

Comments
 (0)