google / google/closure-compiler

Weird order-dependency when transpiling `Foo.Bar = class extends Foo`

Open
#2,708 2 comments 1 reaction 1 assignee Claimed by @MatrixFrog View on GitHub
ES6 P3
Dominant language
JavaScript
Stars
7.7k
Forks
1.2k
Avg merge
2d 12h
Merged PRs (30d)
6

Description

[repro]

The following code should work, but causes a type error:
```js
class Foo {}
Foo.Bar = class extends Foo {};
Foo.Baz = class {};
```
```
input0:3: WARNING - Expected constructor name but found Foo.Baz.
Foo.Baz = class {};
^^^^^^^^
```
This seems to have to do with how ES6 classes are transpiled to explicitly add static fields from superclasses onto subclasses (omitting most jsdoc):
```js
var Foo = function() {};
Foo.Bar = function(var_args) { Foo.apply(this, arguments); };
$jscomp.inherits(Foo.Bar, Foo);
/** @struct @constructor @suppress {visibility} */
Foo.Bar.Baz = Foo.Baz;
Foo.Bar.Bar = Foo.Bar;
Foo.Baz = function() {};
```

I'm assuming that the error is actually coming from the line `Foo.Bar.Baz = Foo.Baz` since the latter has not yet been defined but is being assigned to an `@constructor`.

Interestingly, if `Foo.Baz` is [not a class but rather a simple primitive][not a class] then there is no error (presumably since there's no `@constructor` annotation), but the output is still broken:

```js
Foo.Bar = function(var_args) { /* ... */ };
$jscomp.inherits(Foo.Bar, Foo);
/** @suppress {visibility} */
Foo.Bar.baz = Foo.baz;
Foo.Bar.Bar = Foo.Bar;
Foo.baz = 42;
```

I think the way to fix this is that we need to add the declaration *after* the later of the two classes.

[repro]: https://closure-compiler-debugger.appspot.com/#input0%3Dclass%2520Foo%2520%257B%257D%250AFoo.Bar%2520%253D%2520class%2520extends%2520Foo%2520%257B%257D%253B%250AFoo.Baz%2520%253D%2520class%2520%257B%257D%253B%26input1%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CHECK_TYPES%3Dtrue%26CHECK_TYPES_NEW_INFERENCE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue

[not a class]: https://closure-compiler-debugger.appspot.com/#input0%3Dclass%2520Foo%2520%257B%257D%250AFoo.Bar%2520%253D%2520class%2520extends%2520Foo%2520%257B%257D%253B%250AFoo.baz%2520%253D%252042%253B%26input1%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CHECK_TYPES%3Dtrue%26CHECK_TYPES_NEW_INFERENCE%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue

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.