diff --git a/javascript/ql/lib/change-notes/2025-04-29-combined-es6-func.md b/javascript/ql/lib/change-notes/2025-04-29-combined-es6-func.md
new file mode 100644
index 000000000000..2303d3d8c629
--- /dev/null
+++ b/javascript/ql/lib/change-notes/2025-04-29-combined-es6-func.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Improved analysis for `ES6 classes` mixed with `function prototypes`, leading to more accurate call graph resolution.
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 974fdd7c0cbf..af1676086628 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -1236,7 +1236,7 @@ module API {
       exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) |
         ref = cls.getAReceiverNode()
         or
-        ref = cls.(DataFlow::ClassNode::FunctionStyleClass).getAPrototypeReference()
+        ref = cls.(DataFlow::ClassNode).getAPrototypeReference()
       )
       or
       nd = MkUse(ref)
diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll
index 2e2313835227..f0d31df2a8f3 100644
--- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll
+++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll
@@ -861,21 +861,61 @@ module MemberKind {
  *
  * Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`.
  */
-class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
+class ClassNode extends DataFlow::ValueNode, DataFlow::SourceNode {
+  override AST::ValueNode astNode;
+  AbstractCallable function;
+
+  ClassNode() {
+    // ES6 class case
+    astNode instanceof ClassDefinition and
+    function.(AbstractClass).getClass() = astNode
+    or
+    // Function-style class case
+    astNode instanceof Function and
+    not astNode = any(ClassDefinition cls).getConstructor().getBody() and
+    function.getFunction() = astNode and
+    (
+      exists(getAFunctionValueWithPrototype(function))
+      or
+      function = any(NewNode new).getCalleeNode().analyze().getAValue()
+      or
+      exists(string name | this = AccessPath::getAnAssignmentTo(name) |
+        exists(getAPrototypeReferenceInFile(name, this.getFile()))
+        or
+        exists(getAnInstantiationInFile(name, this.getFile()))
+      )
+    )
+  }
+
   /**
    * Gets the unqualified name of the class, if it has one or one can be determined from the context.
    */
-  string getName() { result = super.getName() }
+  string getName() {
+    astNode instanceof ClassDefinition and result = astNode.(ClassDefinition).getName()
+    or
+    astNode instanceof Function and result = astNode.(Function).getName()
+  }
 
   /**
    * Gets a description of the class.
    */
-  string describe() { result = super.describe() }
+  string describe() {
+    astNode instanceof ClassDefinition and result = astNode.(ClassDefinition).describe()
+    or
+    astNode instanceof Function and result = astNode.(Function).describe()
+  }
 
   /**
    * Gets the constructor function of this class.
    */
-  FunctionNode getConstructor() { result = super.getConstructor() }
+  FunctionNode getConstructor() {
+    // For ES6 classes
+    astNode instanceof ClassDefinition and
+    result = astNode.(ClassDefinition).getConstructor().getBody().flow()
+    or
+    // For function-style classes
+    astNode instanceof Function and result = this
+  }
 
   /**
    * Gets an instance method declared in this class, with the given name, if any.
@@ -883,7 +923,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
    * Does not include methods from superclasses.
    */
   FunctionNode getInstanceMethod(string name) {
-    result = super.getInstanceMember(name, MemberKind::method())
+    result = this.getInstanceMember(name, MemberKind::method())
   }
 
   /**
@@ -893,7 +933,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
    *
    * Does not include methods from superclasses.
    */
-  FunctionNode getAnInstanceMethod() { result = super.getAnInstanceMember(MemberKind::method()) }
+  FunctionNode getAnInstanceMethod() { result = this.getAnInstanceMember(MemberKind::method()) }
 
   /**
    * Gets the instance method, getter, or setter with the given name and kind.
@@ -901,7 +941,29 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
    * Does not include members from superclasses.
    */
   FunctionNode getInstanceMember(string name, MemberKind kind) {
-    result = super.getInstanceMember(name, kind)
+    // ES6 class methods
+    exists(MethodDeclaration method |
+      astNode instanceof ClassDefinition and
+      method = astNode.(ClassDefinition).getMethod(name) and
+      not method.isStatic() and
+      kind = MemberKind::of(method) and
+      result = method.getBody().flow()
+    )
+    or
+    // Function-style class accessors
+    astNode instanceof Function and
+    exists(PropertyAccessor accessor |
+      accessor = this.getAnAccessor(kind) and
+      accessor.getName() = name and
+      result = accessor.getInit().flow()
+    )
+    or
+    kind = MemberKind::method() and
+    result =
+      [
+        this.getConstructor().getReceiver().getAPropertySource(name),
+        this.getAPrototypeReference().getAPropertySource(name)
+      ]
   }
 
   /**
@@ -909,20 +971,52 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
    *
    * Does not include members from superclasses.
    */
-  FunctionNode getAnInstanceMember(MemberKind kind) { result = super.getAnInstanceMember(kind) }
+  FunctionNode getAnInstanceMember(MemberKind kind) {
+    // ES6 class methods
+    exists(MethodDeclaration method |
+      astNode instanceof ClassDefinition and
+      method = astNode.(ClassDefinition).getAMethod() and
+      not method.isStatic() and
+      kind = MemberKind::of(method) and
+      result = method.getBody().flow()
+    )
+    or
+    // Function-style class accessors
+    astNode instanceof Function and
+    exists(PropertyAccessor accessor |
+      accessor = this.getAnAccessor(kind) and
+      result = accessor.getInit().flow()
+    )
+    or
+    kind = MemberKind::method() and
+    result =
+      [
+        this.getConstructor().getReceiver().getAPropertySource(),
+        this.getAPrototypeReference().getAPropertySource()
+      ]
+  }
 
   /**
    * Gets an instance method, getter, or setter declared in this class.
    *
    * Does not include members from superclasses.
    */
-  FunctionNode getAnInstanceMember() { result = super.getAnInstanceMember(_) }
+  FunctionNode getAnInstanceMember() { result = this.getAnInstanceMember(_) }
 
   /**
    * Gets the static method, getter, or setter declared in this class with the given name and kind.
    */
   FunctionNode getStaticMember(string name, MemberKind kind) {
-    result = super.getStaticMember(name, kind)
+    exists(MethodDeclaration method |
+      astNode instanceof ClassDefinition and
+      method = astNode.(ClassDefinition).getMethod(name) and
+      method.isStatic() and
+      kind = MemberKind::of(method) and
+      result = method.getBody().flow()
+    )
+    or
+    kind.isMethod() and
+    result = this.getAPropertySource(name)
   }
 
   /**
@@ -935,7 +1029,18 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
   /**
    * Gets a static method, getter, or setter declared in this class with the given kind.
    */
-  FunctionNode getAStaticMember(MemberKind kind) { result = super.getAStaticMember(kind) }
+  FunctionNode getAStaticMember(MemberKind kind) {
+    exists(MethodDeclaration method |
+      astNode instanceof ClassDefinition and
+      method = astNode.(ClassDefinition).getAMethod() and
+      method.isStatic() and
+      kind = MemberKind::of(method) and
+      result = method.getBody().flow()
+    )
+    or
+    kind.isMethod() and
+    result = this.getAPropertySource()
+  }
 
   /**
    * Gets a static method declared in this class.
@@ -944,10 +1049,79 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
    */
   FunctionNode getAStaticMethod() { result = this.getAStaticMember(MemberKind::method()) }
 
+  /**
+   * Gets a reference to the prototype of this class.
+   * Only applies to function-style classes.
+   */
+  DataFlow::SourceNode getAPrototypeReference() {
+    exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) |
+      result = base.getAPropertyRead("prototype")
+      or
+      result = base.getAPropertySource("prototype")
+    )
+    or
+    exists(string name |
+      this = AccessPath::getAnAssignmentTo(name) and
+      result = getAPrototypeReferenceInFile(name, this.getFile())
+    )
+    or
+    exists(string name, DataFlow::SourceNode root |
+      result = AccessPath::getAReferenceOrAssignmentTo(root, name + ".prototype").getALocalSource() and
+      this = AccessPath::getAnAssignmentTo(root, name)
+    )
+    or
+    exists(ExtendCall call |
+      call.getDestinationOperand() = this.getAPrototypeReference() and
+      result = call.getASourceOperand()
+    )
+  }
+
+  private PropertyAccessor getAnAccessor(MemberKind kind) {
+    // Only applies to function-style classes
+    astNode instanceof Function and
+    result.getObjectExpr() = this.getAPrototypeReference().asExpr() and
+    (
+      kind = MemberKind::getter() and
+      result instanceof PropertyGetter
+      or
+      kind = MemberKind::setter() and
+      result instanceof PropertySetter
+    )
+  }
+
   /**
    * Gets a dataflow node that refers to the superclass of this class.
    */
-  DataFlow::Node getASuperClassNode() { result = super.getASuperClassNode() }
+  DataFlow::Node getASuperClassNode() {
+    // ES6 class superclass
+    astNode instanceof ClassDefinition and
+    result = astNode.(ClassDefinition).getSuperClass().flow()
+    or
+    (
+      // C.prototype = Object.create(D.prototype)
+      exists(DataFlow::InvokeNode objectCreate, DataFlow::PropRead superProto |
+        this.getAPropertySource("prototype") = objectCreate and
+        objectCreate = DataFlow::globalVarRef("Object").getAMemberCall("create") and
+        superProto.flowsTo(objectCreate.getArgument(0)) and
+        superProto.getPropertyName() = "prototype" and
+        result = superProto.getBase()
+      )
+      or
+      // C.prototype = new D()
+      exists(DataFlow::NewNode newCall |
+        this.getAPropertySource("prototype") = newCall and
+        result = newCall.getCalleeNode()
+      )
+      or
+      // util.inherits(C, D);
+      exists(DataFlow::CallNode inheritsCall |
+        inheritsCall = DataFlow::moduleMember("util", "inherits").getACall()
+      |
+        this = inheritsCall.getArgument(0).getALocalSource() and
+        result = inheritsCall.getArgument(1)
+      )
+    )
+  }
 
   /**
    * Gets a direct super class of this class.
@@ -1136,13 +1310,47 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
    * Gets the type annotation for the field `fieldName`, if any.
    */
   TypeAnnotation getFieldTypeAnnotation(string fieldName) {
-    result = super.getFieldTypeAnnotation(fieldName)
+    exists(FieldDeclaration field |
+      field.getDeclaringClass() = astNode and
+      fieldName = field.getName() and
+      result = field.getTypeAnnotation()
+    )
   }
 
   /**
    * Gets a decorator applied to this class.
    */
-  DataFlow::Node getADecorator() { result = super.getADecorator() }
+  DataFlow::Node getADecorator() {
+    astNode instanceof ClassDefinition and
+    result = astNode.(ClassDefinition).getADecorator().getExpression().flow()
+  }
+}
+
+/**
+ * Helper predicate to get a prototype reference in a file.
+ */
+private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) {
+  result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and
+  result.getPropertyName() = "prototype" and
+  result.getFile() = f
+}
+
+/**
+ * Helper predicate to get an instantiation in a file.
+ */
+private DataFlow::NewNode getAnInstantiationInFile(string name, File f) {
+  result = AccessPath::getAReferenceTo(name).(DataFlow::LocalSourceNode).getAnInstantiation() and
+  result.getFile() = f
+}
+
+/**
+ * Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference.
+ */
+pragma[noinline]
+private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) {
+  exists(result.getAPropertyReference("prototype")) and
+  result.analyze().getAValue() = pragma[only_bind_into](func) and
+  func instanceof AbstractCallable // the join-order goes bad if `func` has type `AbstractFunction`.
 }
 
 module ClassNode {
@@ -1214,225 +1422,7 @@ module ClassNode {
     DataFlow::Node getADecorator() { none() }
   }
 
-  /**
-   * An ES6 class as a `ClassNode` instance.
-   */
-  private class ES6Class extends Range, DataFlow::ValueNode {
-    override ClassDefinition astNode;
-
-    override string getName() { result = astNode.getName() }
-
-    override string describe() { result = astNode.describe() }
-
-    override FunctionNode getConstructor() { result = astNode.getConstructor().getBody().flow() }
-
-    override FunctionNode getInstanceMember(string name, MemberKind kind) {
-      exists(MethodDeclaration method |
-        method = astNode.getMethod(name) and
-        not method.isStatic() and
-        kind = MemberKind::of(method) and
-        result = method.getBody().flow()
-      )
-      or
-      kind = MemberKind::method() and
-      result = this.getConstructor().getReceiver().getAPropertySource(name)
-    }
-
-    override FunctionNode getAnInstanceMember(MemberKind kind) {
-      exists(MethodDeclaration method |
-        method = astNode.getAMethod() and
-        not method.isStatic() and
-        kind = MemberKind::of(method) and
-        result = method.getBody().flow()
-      )
-      or
-      kind = MemberKind::method() and
-      result = this.getConstructor().getReceiver().getAPropertySource()
-    }
-
-    override FunctionNode getStaticMember(string name, MemberKind kind) {
-      exists(MethodDeclaration method |
-        method = astNode.getMethod(name) and
-        method.isStatic() and
-        kind = MemberKind::of(method) and
-        result = method.getBody().flow()
-      )
-      or
-      kind.isMethod() and
-      result = this.getAPropertySource(name)
-    }
-
-    override FunctionNode getAStaticMember(MemberKind kind) {
-      exists(MethodDeclaration method |
-        method = astNode.getAMethod() and
-        method.isStatic() and
-        kind = MemberKind::of(method) and
-        result = method.getBody().flow()
-      )
-      or
-      kind.isMethod() and
-      result = this.getAPropertySource()
-    }
-
-    override DataFlow::Node getASuperClassNode() { result = astNode.getSuperClass().flow() }
-
-    override TypeAnnotation getFieldTypeAnnotation(string fieldName) {
-      exists(FieldDeclaration field |
-        field.getDeclaringClass() = astNode and
-        fieldName = field.getName() and
-        result = field.getTypeAnnotation()
-      )
-    }
-
-    override DataFlow::Node getADecorator() {
-      result = astNode.getADecorator().getExpression().flow()
-    }
-  }
-
-  private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) {
-    result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and
-    result.getPropertyName() = "prototype" and
-    result.getFile() = f
-  }
-
-  pragma[nomagic]
-  private DataFlow::NewNode getAnInstantiationInFile(string name, File f) {
-    result = AccessPath::getAReferenceTo(name).(DataFlow::LocalSourceNode).getAnInstantiation() and
-    result.getFile() = f
-  }
-
-  /**
-   * Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference.
-   */
-  pragma[noinline]
-  private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) {
-    exists(result.getAPropertyReference("prototype")) and
-    result.analyze().getAValue() = pragma[only_bind_into](func) and
-    func instanceof AbstractFunction // the join-order goes bad if `func` has type `AbstractFunction`.
-  }
-
-  /**
-   * A function definition, targeted by a `new`-call or with prototype manipulation, seen as a `ClassNode` instance.
-   */
-  class FunctionStyleClass extends Range, DataFlow::ValueNode {
-    override Function astNode;
-    AbstractFunction function;
-
-    FunctionStyleClass() {
-      function.getFunction() = astNode and
-      (
-        exists(getAFunctionValueWithPrototype(function))
-        or
-        function = any(NewNode new).getCalleeNode().analyze().getAValue()
-        or
-        exists(string name | this = AccessPath::getAnAssignmentTo(name) |
-          exists(getAPrototypeReferenceInFile(name, this.getFile()))
-          or
-          exists(getAnInstantiationInFile(name, this.getFile()))
-        )
-      )
-    }
-
-    override string getName() { result = astNode.getName() }
-
-    override string describe() { result = astNode.describe() }
-
-    override FunctionNode getConstructor() { result = this }
-
-    private PropertyAccessor getAnAccessor(MemberKind kind) {
-      result.getObjectExpr() = this.getAPrototypeReference().asExpr() and
-      (
-        kind = MemberKind::getter() and
-        result instanceof PropertyGetter
-        or
-        kind = MemberKind::setter() and
-        result instanceof PropertySetter
-      )
-    }
-
-    override FunctionNode getInstanceMember(string name, MemberKind kind) {
-      kind = MemberKind::method() and
-      result = this.getAPrototypeReference().getAPropertySource(name)
-      or
-      kind = MemberKind::method() and
-      result = this.getConstructor().getReceiver().getAPropertySource(name)
-      or
-      exists(PropertyAccessor accessor |
-        accessor = this.getAnAccessor(kind) and
-        accessor.getName() = name and
-        result = accessor.getInit().flow()
-      )
-    }
-
-    override FunctionNode getAnInstanceMember(MemberKind kind) {
-      kind = MemberKind::method() and
-      result = this.getAPrototypeReference().getAPropertySource()
-      or
-      kind = MemberKind::method() and
-      result = this.getConstructor().getReceiver().getAPropertySource()
-      or
-      exists(PropertyAccessor accessor |
-        accessor = this.getAnAccessor(kind) and
-        result = accessor.getInit().flow()
-      )
-    }
-
-    override FunctionNode getStaticMember(string name, MemberKind kind) {
-      kind.isMethod() and
-      result = this.getAPropertySource(name)
-    }
-
-    override FunctionNode getAStaticMember(MemberKind kind) {
-      kind.isMethod() and
-      result = this.getAPropertySource()
-    }
-
-    /**
-     * Gets a reference to the prototype of this class.
-     */
-    DataFlow::SourceNode getAPrototypeReference() {
-      exists(DataFlow::SourceNode base | base = getAFunctionValueWithPrototype(function) |
-        result = base.getAPropertyRead("prototype")
-        or
-        result = base.getAPropertySource("prototype")
-      )
-      or
-      exists(string name |
-        this = AccessPath::getAnAssignmentTo(name) and
-        result = getAPrototypeReferenceInFile(name, this.getFile())
-      )
-      or
-      exists(ExtendCall call |
-        call.getDestinationOperand() = this.getAPrototypeReference() and
-        result = call.getASourceOperand()
-      )
-    }
-
-    override DataFlow::Node getASuperClassNode() {
-      // C.prototype = Object.create(D.prototype)
-      exists(DataFlow::InvokeNode objectCreate, DataFlow::PropRead superProto |
-        this.getAPropertySource("prototype") = objectCreate and
-        objectCreate = DataFlow::globalVarRef("Object").getAMemberCall("create") and
-        superProto.flowsTo(objectCreate.getArgument(0)) and
-        superProto.getPropertyName() = "prototype" and
-        result = superProto.getBase()
-      )
-      or
-      // C.prototype = new D()
-      exists(DataFlow::NewNode newCall |
-        this.getAPropertySource("prototype") = newCall and
-        result = newCall.getCalleeNode()
-      )
-      or
-      // util.inherits(C, D);
-      exists(DataFlow::CallNode inheritsCall |
-        inheritsCall = DataFlow::moduleMember("util", "inherits").getACall()
-      |
-        this = inheritsCall.getArgument(0).getALocalSource() and
-        result = inheritsCall.getArgument(1)
-      )
-    }
-  }
+  deprecated class FunctionStyleClass = ClassNode;
 }
 
 /**
diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll
index 541e3a6f3e90..cc4c883381ea 100644
--- a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll
@@ -254,7 +254,7 @@ module CallGraph {
     not exists(DataFlow::ClassNode cls |
       node = cls.getConstructor().getReceiver()
       or
-      node = cls.(DataFlow::ClassNode::FunctionStyleClass).getAPrototypeReference()
+      node = cls.(DataFlow::ClassNode).getAPrototypeReference()
     )
   }
 
diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql
index 4388a2d388d1..82533ba74c4a 100644
--- a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql
+++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/Test.ql
@@ -31,7 +31,7 @@ class AnnotatedCall extends DataFlow::Node {
 
   AnnotatedCall() {
     this instanceof DataFlow::InvokeNode and
-    calls = getAnnotation(this.asExpr(), kind) and
+    calls = getAnnotation(this.getEnclosingExpr(), kind) and
     kind = "calls"
     or
     this instanceof DataFlow::PropRef and
@@ -79,12 +79,14 @@ query predicate spuriousCallee(AnnotatedCall call, Function target, int boundArg
 }
 
 query predicate missingCallee(
-  AnnotatedCall call, AnnotatedFunction target, int boundArgs, string kind
+  InvokeExpr invoke, AnnotatedFunction target, int boundArgs, string kind
 ) {
-  not callEdge(call, target, boundArgs) and
-  kind = call.getKind() and
-  target = call.getAnExpectedCallee(kind) and
-  boundArgs = call.getBoundArgsOrMinusOne()
+  forex(AnnotatedCall call | call.getEnclosingExpr() = invoke |
+    not callEdge(call, target, boundArgs) and
+    kind = call.getKind() and
+    target = call.getAnExpectedCallee(kind) and
+    boundArgs = call.getBoundArgsOrMinusOne()
+  )
 }
 
 query predicate badAnnotation(string name) {
diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/prototypes.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/prototypes.js
new file mode 100644
index 000000000000..815a9e7f1e77
--- /dev/null
+++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/prototypes.js
@@ -0,0 +1,142 @@
+import 'dummy'
+
+class Baz {
+  baz() {
+    console.log("Baz baz");
+    /** calls:Baz.greet calls:Derived.greet1 calls:BazExtented.greet2 */
+    this.greet();
+  }
+  /** name:Baz.greet */
+  greet() { console.log("Baz greet"); }
+}
+
+/** name:Baz.shout */
+Baz.prototype.shout = function() { console.log("Baz shout"); };
+/** name:Baz.staticShout */
+Baz.staticShout = function() { console.log("Baz staticShout"); };
+
+function foo(baz){
+  /** calls:Baz.greet */
+  baz.greet();
+  /** calls:Baz.shout */
+  baz.shout();
+  /** calls:Baz.staticShout */
+  Baz.staticShout();
+}
+
+const baz = new Baz();
+foo(baz);
+
+class Derived extends Baz {
+  /** name:Derived.greet1 */
+  greet() {
+    console.log("Derived greet");
+    super.greet();
+  }
+
+  /** name:Derived.shout1 */
+  shout() {
+    console.log("Derived shout");
+    super.shout();
+  }
+}
+
+function bar(derived){
+  /** calls:Derived.greet1 */
+  derived.greet();
+  /** calls:Derived.shout1 */
+  derived.shout();
+}
+
+bar(new Derived());
+
+class BazExtented {
+  constructor() {
+    console.log("BazExtented construct");
+  }
+
+  /** name:BazExtented.greet2 */
+  greet() { 
+    console.log("BazExtented greet");
+    /** calls:Baz.greet */
+    Baz.prototype.greet.call(this); 
+  };
+}
+
+BazExtented.prototype = Object.create(Baz.prototype);
+BazExtented.prototype.constructor = BazExtented;
+BazExtented.staticShout = Baz.staticShout;
+
+/** name:BazExtented.talk */
+BazExtented.prototype.talk = function() { console.log("BazExtented talk"); };
+
+/** name:BazExtented.shout2 */
+BazExtented.prototype.shout = function() { 
+  console.log("BazExtented shout");
+  /** calls:Baz.shout */
+  Baz.prototype.shout.call(this); 
+};
+
+function barbar(bazExtented){
+  /** calls:BazExtented.talk */
+  bazExtented.talk();
+  /** calls:BazExtented.shout2 */
+  bazExtented.shout();
+  /** calls:BazExtented.greet2 */
+  bazExtented.greet();
+  /** calls:Baz.staticShout */
+  BazExtented.staticShout();
+}
+
+barbar(new BazExtented());
+
+class Base {
+  constructor() {
+    /** calls:Base.read calls:Derived1.read calls:Derived2.read */
+    this.read();
+  }
+  /** name:Base.read */
+  read() { }
+}
+
+class Derived1 extends Base {}
+/** name:Derived1.read */
+Derived1.prototype.read = function() {};
+
+class Derived2 {}
+Derived2.prototype = Object.create(Base.prototype);
+/** name:Derived2.read */
+Derived2.prototype.read = function() {};
+
+
+/** name:BanClass.tmpClass */
+function tmpClass() {}
+
+function callerClass() {
+    /** calls:BanClass.tmpClass */
+    this.tmpClass();
+}
+class BanClass {
+    constructor() {
+      this.tmpClass = tmpClass;
+      this.callerClass = callerClass;
+    }
+}
+
+/** name:BanProtytpe.tmpPrototype */
+function tmpPrototype() {}
+
+function callerPrototype() {
+    /** calls:BanProtytpe.tmpPrototype */
+    this.tmpPrototype();
+}
+
+function BanProtytpe() {
+    this.tmpPrototype = tmpPrototype;
+    this.callerPrototype = callerPrototype;
+}
+
+function banInstantiation(){
+  const instance = new BanProtytpe();
+  instance.callerPrototype();
+}