Change JavaScriptMetadata to contain list of receivers

Bug: 1255619, 1327573
Change-Id: I8fbe5a041b1ef5aef519d1b0b76f1bded237bd6f
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3580497
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 ac0b71e..19c49ac 100644
--- a/scripts/javascript_natives/helpers.js
+++ b/scripts/javascript_natives/helpers.js
@@ -84,9 +84,7 @@
  * @param {WebIDL2.OperationMemberType} member
  * */
 function handleOperation(member) {
-  storeMethod(
-      member.special === 'static' ? (parent.name + 'Constructor') : member.parent.name, member.name,
-      member.arguments.map(argName));
+  storeMethod(member.parent.name, member.name, member.arguments.map(argName));
 }
 
 /**
@@ -177,13 +175,14 @@
       // All parents had the same signature so we emit an entry without receiver.
       functions.push({name, signatures: method.get('*')});
     } else {
+      const receiversMap = new Map();
       for (const [parent, signatures] of method) {
-        if (parent.endsWith('Constructor')) {
-          functions.push(
-              {name, signatures, static: true, receiver: parent.substring(0, parent.length - 'Constructor'.length)});
-        } else {
-          functions.push({name, signatures, receiver: parent});
-        }
+        const receivers = receiversMap.get(JSON.stringify(signatures)) || [];
+        receivers.push(parent);
+        receiversMap.set(JSON.stringify(signatures), receivers);
+      }
+      for (const [signatures, receivers] of receiversMap) {
+        functions.push({name, signatures: JSON.parse(signatures), receivers});
       }
     }
   }
diff --git a/scripts/javascript_natives/index.js b/scripts/javascript_natives/index.js
index bc75452..f1f4895 100644
--- a/scripts/javascript_natives/index.js
+++ b/scripts/javascript_natives/index.js
@@ -14,9 +14,11 @@
 }
 
 const chromiumSource = process.argv[2];
-const typescriptSource = process.argv[3] + 'node_modules/typescript/lib/lib.esnext.d.ts';
+const REL_TS_LIB_PATH = '/node_modules/typescript/lib/';
+const typescriptSources =
+    fs.readdirSync(process.argv[3] + REL_TS_LIB_PATH).map(name => process.argv[3] + REL_TS_LIB_PATH + name);
 
-const program = ts.createProgram([typescriptSource], {noLib: false, types: []});
+const program = ts.createProgram({rootNames: typescriptSources, options: {noResolve: true, types: []}});
 
 for (const file of program.getSourceFiles()) {
   ts.forEachChild(file, node => {
diff --git a/scripts/javascript_natives/tests.js b/scripts/javascript_natives/tests.js
index 84e3499..97f0bc7 100644
--- a/scripts/javascript_natives/tests.js
+++ b/scripts/javascript_natives/tests.js
@@ -182,12 +182,12 @@
   {
     name: "diffSig",
     signatures: [["oneSig"]],
-    receiver: "Array"
+    receivers: ["Array"]
   },
   {
     name: "diffSig",
     signatures: [["twoSig"]],
-    receiver: "ReadonlyArray"
+    receivers: ["ReadonlyArray"]
   }
 ];`;
     assert.equal(output, expected);