google / google/closure-compiler

Error devirtualizing prototype methods of classes that share an interface's method

Open
#794 3 comments 0 reactions 0 assignees View on GitHub
enhancement P3
Dominant language
JavaScript
Stars
7.7k
Forks
1.2k
Avg merge
2d 12h
Merged PRs (30d)
6

Description

The below code won't get devirtualized correctly:

``` javascript
/**
* @interface
*/
var Interface = function ()
{
};
Interface.prototype = {
doIt: function ()
{
}
};

/**
* @constructor
* @implements {Interface}
*/
var ClassA = goog.defineClass(null, {
constructor: function ()
{
},

/**
* @this {ClassA}
*
* @return {ClassA}
*/
doIt: function ()
{
console.log("do A");
return this;
}
});

/**
* @constructor
* @implements {Interface}
*/
var ClassB = goog.defineClass(null, {
constructor: function ()
{
},

/**
* @this {ClassB}
*
* @return {ClassB}
*/
doIt: function ()
{
console.log("do B");
return this;
}
});

/**
* @type {ClassA}
*/
var a = new ClassA();
a.doIt();

/**
* @type {ClassB}
*/
var b = new ClassB();
b.doIt().doIt().doIt().doIt();
```

Through advanced closure compiler, we would receive:

``` javascript
function d()
{
}

d.prototype.a = function ()
{
console.log("do A");
return this
};
function e()
{
}

e.prototype.a = function ()
{
console.log("do B");
return this
};
(new d).a();
(new e).a().a().a().a();
```

As we can see the "ClassA.doIt" and "ClassB.doIt" methods is not correctly devirtualize even though they are unrelated and returns the correct object type. And "Interface.doIt" is not even referenced.

Deleting the definition of "Interface.doIt", and devirtualization is executed correctly.

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.