Forward mixin interface methods to their includers

This ensures that we have argument hints for things such as
`window.clearTimeout` where `clearTimeout` is defined in a mixin
`WindowOrWorkerGlobalScope` and `Window` includes the mixin.

Bug: 1255619
Change-Id: I8fe2434f0b88bc39454feed3900639f5edc05305
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3660423
Reviewed-by: Simon Zünd <szuend@chromium.org>
Commit-Queue: Johan Bay <jobay@chromium.org>
diff --git a/scripts/javascript_natives/helpers.js b/scripts/javascript_natives/helpers.js
index 19c49ac..26b0fb5 100644
--- a/scripts/javascript_natives/helpers.js
+++ b/scripts/javascript_natives/helpers.js
@@ -10,9 +10,12 @@
 
 /** @type {Map<string, Map<string, string[][]>>} */
 const methods = new Map();
+/** @type {Map<string, string[]>} */
+const includes = new Map();
 
 export function clearState() {
   methods.clear();
+  includes.clear();
 }
 
 export function parseTSFunction(func, node) {
@@ -47,10 +50,23 @@
     case 'namespace':
       walkMembers(thing);
       break;
+    case 'includes':
+      walkIncludes(thing);
+      break;
   }
 }
 
 /**
+ * @param {WebIDL2.IncludesType} thing
+ * */
+function walkIncludes(thing) {
+  if (includes.has(thing.includes)) {
+    includes.get(thing.includes).push(thing.target);
+  } else {
+    includes.set(thing.includes, [thing.target]);
+  }
+}
+/**
  * @param {WebIDL2.InterfaceType} thing
  * */
 function walkInterface(thing) {
@@ -177,12 +193,16 @@
     } else {
       const receiversMap = new Map();
       for (const [parent, signatures] of method) {
-        const receivers = receiversMap.get(JSON.stringify(signatures)) || [];
-        receivers.push(parent);
+        const receivers = receiversMap.get(JSON.stringify(signatures)) || new Set();
+        if (includes.has(parent)) {
+          includes.get(parent).forEach(receiver => receivers.add(receiver));
+        } else {
+          receivers.add(parent);
+        }
         receiversMap.set(JSON.stringify(signatures), receivers);
       }
       for (const [signatures, receivers] of receiversMap) {
-        functions.push({name, signatures: JSON.parse(signatures), receivers});
+        functions.push({name, signatures: JSON.parse(signatures), receivers: Array.from(receivers)});
       }
     }
   }
diff --git a/scripts/javascript_natives/index.js b/scripts/javascript_natives/index.js
index f1f4895..f3798e6 100644
--- a/scripts/javascript_natives/index.js
+++ b/scripts/javascript_natives/index.js
@@ -32,7 +32,6 @@
     if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
       parseTSFunction(node, {name: {text: 'Window'}});
     }
-
   });
 }