Class ConcretizeStaticInheritanceForInlining

java.lang.Object
com.google.javascript.jscomp.ConcretizeStaticInheritanceForInlining
All Implemented Interfaces:
CompilerPass

public final class ConcretizeStaticInheritanceForInlining extends Object implements CompilerPass
Rewrites static inheritance to explicitly copy inherited properties from superclass to subclass so that the optimizer knows the subclass has those properties.

For example, the main transpilation passes will convert this ES6 code:

   class Foo { static f() {} }
   class Bar extends Foo {}
 
to this ES3 code:
   function Foo() {}
   Foo.f = function() {};
   function Bar() {}
   $jscomp.inherits(Bar, Foo);
 
and then this class will convert that to
   function Foo() {}
   Foo.f = function() {};
   function Bar() {}
   $jscomp.inherits(Bar, Foo);
   Bar.f = Foo.f;
 
Additionally, there are getter and setter fields which are transpiled from:
   class Foo { static get prop() { return 1; } }
   class Bar extends Foo {}
 
to:
   var Foo = function() {};
   Foo.prop; // stub declaration so that the optimizer knows about prop
   Object.defineProperties(Foo, {prop:{get:function() { return 1; }}});

   var Bar = function() {};
   $jscomp.inherits(Bar, Foo);
 
The stub declaration of Foo.prop needs to be duplicated for Bar so that the optimizer knows that Bar also has this property. (ES5 classes don't have class-side inheritance).
   var Bar = function() {};
   Bar.prop;
   $jscomp.inherits(Bar, Foo);
 

In order to gather the stub declarations, this pass gathers all GETPROPs on a class. In order to determine which of these are the stub declarations it filters them based on names discovered in Object.defineProperties. Unfortunately, we cannot simply gather the defined properties because they don't have the JSDoc, which may include optimization-relevant annotations like @nocollapse.

TODO(tdeegan): In the future the JSDoc for getter/setter properties could be stored in the defineProperties functions. It would reduce the complexity of this pass significantly.

NOTE: currently this pass only exists to prevent property collapsing from breaking some simple class-side inheritance cases when transpiling.

  • Constructor Details

    • ConcretizeStaticInheritanceForInlining

      public ConcretizeStaticInheritanceForInlining(AbstractCompiler compiler)
  • Method Details

    • process

      public void process(Node externs, Node root)
      Description copied from interface: CompilerPass
      Process the JS with root node root. Can modify the contents of each Node tree
      Specified by:
      process in interface CompilerPass
      Parameters:
      externs - Top of external JS tree
      root - Top of JS tree