google / google/closure-compiler

Class decorator causes static method to be removed when compiled in advanced mode

Open
#3,062 8 comments 0 reactions 0 assignees View on GitHub
internal-issue-created triage-done
Dominant language
JavaScript
Stars
7.7k
Forks
1.2k
Avg merge
2d 12h
Merged PRs (30d)
6

Description

This Typescript source:

```
function decorate(target: any) { }

@decorate
class StaticTest {
private static testMethod() {
console.log('I am missing');
}

private invokesTest = () => StaticTest.testMethod();

constructor() {
this.invokesTest();
}
}
```

Gets transpiled (ES2017 target) into:

```
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var StaticTest_1;
"use strict";
function decorate(target) { }
let StaticTest = StaticTest_1 = class StaticTest {
constructor() {
this.invokesTest = () => StaticTest_1.testMethod();
this.invokesTest();
}
static testMethod() {
console.log('I am missing');
}
};
StaticTest = StaticTest_1 = __decorate([
decorate
], StaticTest);
```

Which gets CCed (with `ADVANCED_MODE`) into:

```
var l = this && this.c || function(h, b, d, e) {
var f = arguments.length, a = 3 > f ? b : null === e ? e = Object.getOwnPropertyDescriptor(b, d) : e, g;
if ("object" === typeof Reflect && "function" === typeof Reflect.a) {
a = Reflect.a(h, b, d, e);
} else {
for (var k = h.length - 1; 0 <= k; k--) {
if (g = h[k]) {
a = (3 > f ? g(a) : 3 < f ? g(b, d, a) : g(b, d)) || a;
}
}
}
return 3 < f && a && Object.defineProperty(b, d, a), a;
}, m;
"use strict";
var n = m = function() {
this.b = function() {
m.f();
};
this.b();
};
n = m = l([function() {
}], n);
```

The static method that prints "I am missing" is gone.

Same thing happens when the decorator is called as a function (i.e., `decorate(StaticTest)`.

`@nocollapse` prevents that from happening but it's easy to forget to add it =>
runtime errors.

Hey and thanks so much for all the work you guys do on Closure Compiler!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.