blob: 65f4821e1fbef406a0b7e21c1ea25e1a02f6513c [file] [log] [blame]
Joel Einbinder3f23eb22018-05-14 23:27:51 +00001const WebIDL2 = require('webidl2');
2const fs = require('fs');
3const path = require('path');
4const ts = require('typescript');
5const glob = require('glob');
6const methods = {
7 __proto__: null
8};
Tim van der Lippee6a98682020-01-15 14:23:08 +00009const program = ts.createProgram(
10 [
11 path.join(__dirname, 'node_modules', 'typescript', 'lib', 'lib.esnext.d.ts'),
12 ],
13 {noLib: true});
Joel Einbinder3f23eb22018-05-14 23:27:51 +000014for (const file of program.getSourceFiles()) {
15 ts.forEachChild(file, node => {
16 if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
17 for (const member of node.members) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000018 if (member.kind === ts.SyntaxKind.MethodSignature) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000019 parseTSFunction(member, node);
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000020 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000021 }
22 }
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000023 if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000024 parseTSFunction(node, {name: {text: 'Window'}});
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000025 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000026
27 });
28}
29
30function parseTSFunction(func, node) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000031 if (!func.name.escapedText) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000032 return;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000033 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000034
35 const args = func.parameters
36 .map(p => {
37 let text = p.name.escapedText;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000038 if (p.questionToken) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000039 text = '?' + text;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000040 }
41 if (p.dotDotDotToken) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000042 text = '...' + text;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000043 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000044 return text;
45 })
46 .filter(x => x !== 'this');
47 storeMethod(node.name.text, func.name.escapedText, args);
48}
49
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000050glob('../../../../blink/renderer/+(core|modules)/**/*.idl', {cwd: process.env.PWD}, function(er, files) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000051 for (const file of files) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000052 if (file.includes('testing')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000053 continue;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000054 }
Tim van der Lippee6a98682020-01-15 14:23:08 +000055 const data = fs.readFileSync(path.join(process.env.PWD, file), 'utf8');
Joel Einbinder3f23eb22018-05-14 23:27:51 +000056 const lines = data.split('\n');
57 const newLines = [];
58 for (line of lines) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000059 if (!line.includes(' attribute ')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000060 newLines.push(line);
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000061 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000062 }
63
64 try {
65 WebIDL2.parse(newLines.join('\n')).forEach(walk);
66 } catch (e) {
67 // console.error(file);
68 }
69 }
70 WebIDL2
71 .parse(`
72 namespace console {
73 void assert(optional boolean condition = false, any... data);
74 void clear();
75 void count(optional DOMString label = "default");
76 void debug(any... data);
77 void dir(any item, optional object? options);
78 void dirxml(any... data);
79 void error(any... data);
80 void group(any... data);
81 void groupCollapsed(any... data);
82 void groupEnd();
83 void info(any... data);
84 void log(any... data);
85 void profile(optional DOMString title);
86 void profileEnd(optional DOMString title);
87 void table(any... tabularData);
88 void time(optional DOMString label);
89 void timeEnd(optional DOMString label);
90 void timeStamp(optional DOMString name);
91 void trace(any... data);
92 void warn(any... data);
93 };
94`).forEach(walk);
95 postProcess();
96});
97
98function walk(thing, parent) {
99 if (thing.type === 'interface') {
100 const constructor = thing.extAttrs.find(extAttr => extAttr.name === 'Constructor');
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000101 if (constructor && constructor.arguments && thing.extAttrs.find(extAttr => extAttr.name === 'Exposed')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000102 storeMethod('Window', thing.name, constructor.arguments.map(argName));
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000103 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000104
105 const namedConstructor = thing.extAttrs.find(extAttr => extAttr.name === 'NamedConstructor');
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000106 if (namedConstructor && namedConstructor.arguments) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000107 storeMethod('Window', namedConstructor.rhs.value, namedConstructor.arguments.map(argName));
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000108 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000109 }
110 if (thing.type.includes('operation')) {
111 storeMethod(thing.static ? (parent.name + 'Constructor') : parent.name, thing.name, thing.arguments.map(argName));
112 return;
113 }
114 if (thing.members) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000115 for (const member of thing.members) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000116 walk(member, thing);
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000117 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000118 }
119}
120
121function argName(a) {
122 let name = a.name;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000123 if (a.optional) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000124 name = '?' + name;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000125 }
126 if (a.variadic) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000127 name = '...' + name;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000128 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000129 return name;
130}
131
132function storeMethod(parent, name, args) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000133 if (!methods[name]) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000134 methods[name] = {__proto__: null};
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000135 }
136 if (!methods[name][parent]) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000137 methods[name][parent] = [];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000138 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000139 methods[name][parent].push(args);
140}
141
142function postProcess() {
143 for (const name in methods) {
144 const jsonParents = new Set();
145 for (const parent in methods[name]) {
146 const signatures = methods[name][parent];
147 signatures.sort((a, b) => a.length - b.length);
148 const filteredSignatures = [];
149 for (const signature of signatures) {
150 const smallerIndex = filteredSignatures.findIndex(smaller => startsThesame(smaller, signature));
151 if (smallerIndex !== -1) {
152 filteredSignatures[smallerIndex] = (signature.map((arg, index) => {
Joel Einbinder705daf02018-05-16 23:57:41 +0000153 const otherArg = filteredSignatures[smallerIndex][index];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000154 if (otherArg) {
Joel Einbinder705daf02018-05-16 23:57:41 +0000155 return otherArg.length > arg.length ? otherArg : arg;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000156 }
157 if (arg.startsWith('?') || arg.startsWith('...')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000158 return arg;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000159 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000160 return '?' + arg;
161 }));
162 } else {
163 filteredSignatures.push(signature);
164 }
165 }
166
167 function startsThesame(smaller, bigger) {
168 for (let i = 0; i < smaller.length; i++) {
Joel Einbinder705daf02018-05-16 23:57:41 +0000169 const withoutQuestion = str => /[\?]?(.*)/.exec(str)[1];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000170 if (withoutQuestion(smaller[i]) !== withoutQuestion(bigger[i])) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000171 return false;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000172 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000173 }
174 return true;
175 }
176
177 methods[name][parent] = filteredSignatures;
178 jsonParents.add(JSON.stringify(filteredSignatures));
179 }
180 if (jsonParents.size === 1) {
181 methods[name] = {'*': JSON.parse(jsonParents.values().next().value)};
182 }
183 for (const parent in methods[name]) {
184 const signatures = methods[name][parent];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000185 if (signatures.length === 1 && !signatures[0].length) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000186 delete methods[name][parent];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000187 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000188 }
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000189 if (!Object.keys(methods[name]).length) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000190 delete methods[name];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000191 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000192 }
193 const functions = [];
194 for (const name in methods) {
195 if (methods[name]['*']) {
196 functions.push({name, signatures: methods[name]['*']});
197 } else {
198 for (const parent in methods[name]) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000199 if (parent.endsWith('Constructor')) {
200 functions.push({
201 name,
202 signatures: methods[name][parent],
203 static: true,
204 receiver: parent.substring(0, parent.length - 'Constructor'.length)
205 });
206 } else {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000207 functions.push({name, signatures: methods[name][parent], receiver: parent});
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000208 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000209 }
210 }
211 }
212
213 fs.writeFileSync(
214 path.join(__dirname, '..', '..', 'front_end', 'javascript_metadata', 'NativeFunctions.js'),
Brandon Goddard53faba12020-01-24 16:55:04 +0000215 `// Copyright 2020 The Chromium Authors. All rights reserved.
216// Use of this source code is governed by a BSD-style license that can be
217// found in the LICENSE file.
218// Generated from ${path.relative(path.join(__dirname, '..', '..'), __filename)}
Paul Lewisea12f142019-11-26 17:00:09 +0000219export const NativeFunctions = ${JSON.stringify(functions)};
Paul Lewisea12f142019-11-26 17:00:09 +0000220`);
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000221}