Skip to content

Commit

Permalink
Update async await transpilation to avoid captures of super when us…
Browse files Browse the repository at this point in the history
…ing ES2015 output.

MS Edge 17 does not properly capture references to `super` in an arrow function.
Closes google#3101
  • Loading branch information
ChadKillingsworth committed Oct 12, 2018
1 parent 826b0fc commit ef49982
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 2 deletions.
27 changes: 25 additions & 2 deletions src/com/google/javascript/jscomp/RewriteAsyncFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,33 @@ private void convertAsyncFunction(NodeTraversal t, LexicalContext functionContex
newBody.addChildToBack(IR.constNode(IR.name(ASYNC_ARGUMENTS), IR.name("arguments")));
NodeUtil.addFeatureToScript(t.getCurrentFile(), Feature.CONST_DECLARATIONS);
}
boolean needsSuperTranspilation = compiler.getOptions().needsTranspilationFrom(FeatureSet.ES6);
for (String replacedMethodName : functionContext.replacedSuperProperties) {
// MS Edge 17 cannot properly capture references to "super" in an arrow function.
// If we are not transpiling classes, switch to using Object.getPrototypeOf(this.constructor)
// as a replacement for super.
// If we are transpiling classes, the super reference will be handled elsewhere.
Node superReference;
if (needsSuperTranspilation) {
superReference = IR.superNode();
} else {
// instance super: Object.getPrototypeOf(this.constructor).prototype
// static super: Object.getPrototypeOf(this.constructor)
superReference =
IR.call(
IR.getprop(IR.name("Object"), IR.string("getPrototypeOf")),
IR.getprop(IR.thisNode(), IR.string("constructor")));
if (!originalFunction.getParent().isStaticMember()) {
superReference = IR.getprop(superReference, IR.string("prototype"));
}
}

// const super$get$x = () => super.x;
Node arrowFunction = IR.arrowFunction(
IR.name(""), IR.paramList(), IR.getprop(IR.superNode(), IR.string(replacedMethodName)));
Node arrowFunction =
IR.arrowFunction(
IR.name(""),
IR.paramList(),
IR.getprop(superReference, IR.string(replacedMethodName)));
compiler.reportChangeToChangeScope(arrowFunction);
NodeUtil.addFeatureToScript(t.getCurrentFile(), Feature.ARROW_FUNCTIONS);

Expand Down
68 changes: 68 additions & 0 deletions test/com/google/javascript/jscomp/RewriteAsyncFunctionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,74 @@ public void testInnerSuperReference() {
"}"));
}

@Test
public void testInnerSuperCallEs2015Out() {
setLanguageOut(LanguageMode.ECMASCRIPT_2015);
test(
lines(
"class A {",
" m() {",
" return this;",
" }",
"}",
"class X extends A {",
" async m() {",
" return super.m();",
" }",
"}"),
lines(
"class A {",
" m() {",
" return this;",
" }",
"}",
"class X extends A {",
" m() {",
" const $jscomp$async$this = this;",
" const $jscomp$async$super$get$m =",
" () => Object.getPrototypeOf(this.constructor).prototype.m;",
" return $jscomp.asyncExecutePromiseGeneratorFunction(",
" function* () {",
" return $jscomp$async$super$get$m().call($jscomp$async$this);",
" });",
" }",
"}"));
}

@Test
public void testInnerSuperCallStaticEs2015Out() {
setLanguageOut(LanguageMode.ECMASCRIPT_2015);
test(
lines(
"class A {",
" static m() {",
" return this;",
" }",
"}",
"class X extends A {",
" static async m() {",
" return super.m();",
" }",
"}"),
lines(
"class A {",
" static m() {",
" return this;",
" }",
"}",
"class X extends A {",
" static m() {",
" const $jscomp$async$this = this;",
" const $jscomp$async$super$get$m =",
" () => Object.getPrototypeOf(this.constructor).m;",
" return $jscomp.asyncExecutePromiseGeneratorFunction(",
" function* () {",
" return $jscomp$async$super$get$m().call($jscomp$async$this);",
" });",
" }",
"}"));
}

@Test
public void testNestedArrowFunctionUsingThis() {
test(
Expand Down

0 comments on commit ef49982

Please sign in to comment.