blob: 3c87be48dc57cdcae2f8548b3689d31fb131962a [file] [log] [blame]
Tim van der Lippec2cb4302020-03-11 17:22:14 +00001// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Joel Einbinder3f23eb22018-05-14 23:27:51 +00005const WebIDL2 = require('webidl2');
6const fs = require('fs');
7const path = require('path');
8const ts = require('typescript');
9const glob = require('glob');
10const methods = {
11 __proto__: null
12};
Tim van der Lippee6a98682020-01-15 14:23:08 +000013const program = ts.createProgram(
14 [
15 path.join(__dirname, 'node_modules', 'typescript', 'lib', 'lib.esnext.d.ts'),
16 ],
17 {noLib: true});
Joel Einbinder3f23eb22018-05-14 23:27:51 +000018for (const file of program.getSourceFiles()) {
19 ts.forEachChild(file, node => {
20 if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
21 for (const member of node.members) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000022 if (member.kind === ts.SyntaxKind.MethodSignature) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000023 parseTSFunction(member, node);
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000024 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000025 }
26 }
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000027 if (node.kind === ts.SyntaxKind.FunctionDeclaration) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000028 parseTSFunction(node, {name: {text: 'Window'}});
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000029 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000030
31 });
32}
33
34function parseTSFunction(func, node) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000035 if (!func.name.escapedText) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000036 return;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000037 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000038
39 const args = func.parameters
40 .map(p => {
41 let text = p.name.escapedText;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000042 if (p.questionToken) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000043 text = '?' + text;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000044 }
45 if (p.dotDotDotToken) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000046 text = '...' + text;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000047 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000048 return text;
49 })
50 .filter(x => x !== 'this');
51 storeMethod(node.name.text, func.name.escapedText, args);
52}
53
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000054glob('../../../../blink/renderer/+(core|modules)/**/*.idl', {cwd: process.env.PWD}, function(er, files) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000055 for (const file of files) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000056 if (file.includes('testing')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000057 continue;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000058 }
Tim van der Lippee6a98682020-01-15 14:23:08 +000059 const data = fs.readFileSync(path.join(process.env.PWD, file), 'utf8');
Joel Einbinder3f23eb22018-05-14 23:27:51 +000060 const lines = data.split('\n');
61 const newLines = [];
62 for (line of lines) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000063 if (!line.includes(' attribute ')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +000064 newLines.push(line);
Tim van der Lippeba26b2b2020-03-11 14:40:00 +000065 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +000066 }
67
68 try {
69 WebIDL2.parse(newLines.join('\n')).forEach(walk);
70 } catch (e) {
71 // console.error(file);
72 }
73 }
74 WebIDL2
75 .parse(`
76 namespace console {
77 void assert(optional boolean condition = false, any... data);
78 void clear();
79 void count(optional DOMString label = "default");
80 void debug(any... data);
81 void dir(any item, optional object? options);
82 void dirxml(any... data);
83 void error(any... data);
84 void group(any... data);
85 void groupCollapsed(any... data);
86 void groupEnd();
87 void info(any... data);
88 void log(any... data);
89 void profile(optional DOMString title);
90 void profileEnd(optional DOMString title);
91 void table(any... tabularData);
92 void time(optional DOMString label);
93 void timeEnd(optional DOMString label);
94 void timeStamp(optional DOMString name);
95 void trace(any... data);
96 void warn(any... data);
97 };
98`).forEach(walk);
99 postProcess();
100});
101
102function walk(thing, parent) {
103 if (thing.type === 'interface') {
104 const constructor = thing.extAttrs.find(extAttr => extAttr.name === 'Constructor');
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000105 if (constructor && constructor.arguments && thing.extAttrs.find(extAttr => extAttr.name === 'Exposed')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000106 storeMethod('Window', thing.name, constructor.arguments.map(argName));
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000107 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000108
109 const namedConstructor = thing.extAttrs.find(extAttr => extAttr.name === 'NamedConstructor');
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000110 if (namedConstructor && namedConstructor.arguments) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000111 storeMethod('Window', namedConstructor.rhs.value, namedConstructor.arguments.map(argName));
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000112 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000113 }
114 if (thing.type.includes('operation')) {
115 storeMethod(thing.static ? (parent.name + 'Constructor') : parent.name, thing.name, thing.arguments.map(argName));
116 return;
117 }
118 if (thing.members) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000119 for (const member of thing.members) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000120 walk(member, thing);
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000121 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000122 }
123}
124
125function argName(a) {
126 let name = a.name;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000127 if (a.optional) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000128 name = '?' + name;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000129 }
130 if (a.variadic) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000131 name = '...' + name;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000132 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000133 return name;
134}
135
136function storeMethod(parent, name, args) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000137 if (!methods[name]) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000138 methods[name] = {__proto__: null};
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000139 }
140 if (!methods[name][parent]) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000141 methods[name][parent] = [];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000142 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000143 methods[name][parent].push(args);
144}
145
146function postProcess() {
147 for (const name in methods) {
148 const jsonParents = new Set();
149 for (const parent in methods[name]) {
150 const signatures = methods[name][parent];
151 signatures.sort((a, b) => a.length - b.length);
152 const filteredSignatures = [];
153 for (const signature of signatures) {
154 const smallerIndex = filteredSignatures.findIndex(smaller => startsThesame(smaller, signature));
155 if (smallerIndex !== -1) {
156 filteredSignatures[smallerIndex] = (signature.map((arg, index) => {
Joel Einbinder705daf02018-05-16 23:57:41 +0000157 const otherArg = filteredSignatures[smallerIndex][index];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000158 if (otherArg) {
Joel Einbinder705daf02018-05-16 23:57:41 +0000159 return otherArg.length > arg.length ? otherArg : arg;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000160 }
161 if (arg.startsWith('?') || arg.startsWith('...')) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000162 return arg;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000163 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000164 return '?' + arg;
165 }));
166 } else {
167 filteredSignatures.push(signature);
168 }
169 }
170
171 function startsThesame(smaller, bigger) {
172 for (let i = 0; i < smaller.length; i++) {
Joel Einbinder705daf02018-05-16 23:57:41 +0000173 const withoutQuestion = str => /[\?]?(.*)/.exec(str)[1];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000174 if (withoutQuestion(smaller[i]) !== withoutQuestion(bigger[i])) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000175 return false;
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000176 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000177 }
178 return true;
179 }
180
181 methods[name][parent] = filteredSignatures;
182 jsonParents.add(JSON.stringify(filteredSignatures));
183 }
184 if (jsonParents.size === 1) {
185 methods[name] = {'*': JSON.parse(jsonParents.values().next().value)};
186 }
187 for (const parent in methods[name]) {
188 const signatures = methods[name][parent];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000189 if (signatures.length === 1 && !signatures[0].length) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000190 delete methods[name][parent];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000191 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000192 }
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000193 if (!Object.keys(methods[name]).length) {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000194 delete methods[name];
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000195 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000196 }
197 const functions = [];
198 for (const name in methods) {
199 if (methods[name]['*']) {
200 functions.push({name, signatures: methods[name]['*']});
201 } else {
202 for (const parent in methods[name]) {
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000203 if (parent.endsWith('Constructor')) {
204 functions.push({
205 name,
206 signatures: methods[name][parent],
207 static: true,
208 receiver: parent.substring(0, parent.length - 'Constructor'.length)
209 });
210 } else {
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000211 functions.push({name, signatures: methods[name][parent], receiver: parent});
Tim van der Lippeba26b2b2020-03-11 14:40:00 +0000212 }
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000213 }
214 }
215 }
216
217 fs.writeFileSync(
218 path.join(__dirname, '..', '..', 'front_end', 'javascript_metadata', 'NativeFunctions.js'),
Brandon Goddard53faba12020-01-24 16:55:04 +0000219 `// Copyright 2020 The Chromium Authors. All rights reserved.
220// Use of this source code is governed by a BSD-style license that can be
221// found in the LICENSE file.
222// Generated from ${path.relative(path.join(__dirname, '..', '..'), __filename)}
Paul Lewisea12f142019-11-26 17:00:09 +0000223export const NativeFunctions = ${JSON.stringify(functions)};
Paul Lewisea12f142019-11-26 17:00:09 +0000224`);
Joel Einbinder3f23eb22018-05-14 23:27:51 +0000225}