Skip to content

Commit

Permalink
Correctly handle "this" inside switch exprs
Browse files Browse the repository at this point in the history
  • Loading branch information
niloc132 committed Apr 26, 2024
1 parent 3f05b8f commit 679fee3
Showing 1 changed file with 12 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1632,19 +1632,24 @@ public boolean visit(JsInvocation x, JsContext ctx) {
public JsNode transformSwitchExpression(JSwitchExpression x) {
SourceInfo info = x.getSourceInfo();
// Any remaining switch expression that couldn't be rewritten to a switch statement must be
// wrapped in a JsFunction, with yields replaced by returns:
// wrapped in a JsFunction, with yields replaced by returns. The function is invoked with
// Function.prototype.call, so that "this" is correctly applied to the contents of the
// function, and to avoid making the function appear in the local scope (avoiding the need
// for a name for the function, and thus allowing more than one switch, or nested switches,
// etc). That is,
//
// foo(switch(bar) {
// case 123 -> "abc"
// });
//
// would be written as
//
// foo((function() {
// switch(bar) {
// case 123:
// return "abc";
// }
// })());
// }).call(this));
//

// We need a scope for the wrapper - we're just going to use the enclosing method for that,
Expand All @@ -1653,19 +1658,18 @@ public JsNode transformSwitchExpression(JSwitchExpression x) {
// potentially lets the compiler reuse locals.
JsScope scope = getJsFunctionFor(currentMethod).getScope();

// TODO we must bind(this) or .apply(this), or use an arrow expression instead
JsFunction wrapper = new JsFunction(info, scope);
JsFunction fnWrapper = new JsFunction(info, scope);

// Write out the switch expression as if it was a statement - every case must have returns
// already built in
JsStatement switchStatement = transformSwitchStatement(new JSwitchStatement(x));

wrapper.setBody(new JsBlock(info));
wrapper.getBody().getStatements().add(switchStatement);
fnWrapper.setBody(new JsBlock(info));
fnWrapper.getBody().getStatements().add(switchStatement);

wrapper.setName(scope.declareName("switch_" + info.getStartLine() + "_" + info.getStartPos()));
JsNameRef call = new JsNameRef(info, "call", fnWrapper);

return JsUtils.createCommaExpression(wrapper, new JsInvocation(info, wrapper));
return new JsInvocation(info, call, new JsThisRef(info));
}

@Override
Expand Down

0 comments on commit 679fee3

Please sign in to comment.