chrome-devtools-frontend 1.0.1013367 → 1.0.1014853

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,345 @@
1
+ // Copyright 2022 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
+
5
+ /**
6
+ * All the specs relevant for generating the DOM pinned properties dataset.
7
+ * These strings represent file names. A list of all file names can be found at
8
+ * https://github.com/w3c/webref/tree/main/tr/idl or via the @webref/idl API.
9
+ *
10
+ * These spec names are included in the generated dataset. To keep it small,
11
+ * the values are bitwise or'd.
12
+ */
13
+ export const SPECS = {
14
+ 'html': 1,
15
+ 'dom': 2,
16
+ 'uievents': 4,
17
+ 'pointerevents': 8,
18
+ 'cssom': 16,
19
+ 'wai-aria': 32
20
+ };
21
+
22
+ /**
23
+ * All the "global" attributes as defined in the DOM specification.
24
+ * Used to annotate the extracted properties from the WebIDL types.
25
+ */
26
+ export const GLOBAL_ATTRIBUTES = new Set([
27
+ // https://html.spec.whatwg.org/multipage/dom.html#global-attributes
28
+ 'accesskey', 'autocapitalize', 'autofocus', 'contenteditable', 'dir', 'draggable', 'enterkeyhint',
29
+ 'hidden', 'inputmode', 'is', 'itemid', 'itemprop', 'itemref', 'itemscope',
30
+ 'itemtype', 'lang', 'nonce', 'spellcheck', 'style', 'tabindex', 'title',
31
+ 'translate',
32
+ ]);
33
+
34
+ /**
35
+ * The "applicable" members for certain "states" that WebIDL types can be in.
36
+ * In other words, some members are "valid" only valid in certain situations:
37
+ * for example, with the HTML input element, the set of valid members are
38
+ * determined by the "type" property.
39
+ */
40
+ export const APPLICABLE_MEMBERS = {
41
+ // https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary
42
+ HTMLInputElement: [
43
+ {
44
+ rule: {when: 'type', is: 'hidden'},
45
+ members: new Set([
46
+ 'autocomplete',
47
+ 'value',
48
+ ])
49
+ },
50
+ {
51
+ rule: {when: 'type', is: 'text'},
52
+ members: new Set([
53
+ 'autocomplete',
54
+ 'dirname',
55
+ 'list',
56
+ 'maxlength',
57
+ 'minlength',
58
+ 'pattern',
59
+ 'placeholder',
60
+ 'readonly',
61
+ 'required',
62
+ 'size',
63
+ 'value',
64
+ 'list',
65
+ 'selectionstart',
66
+ 'selectionend',
67
+ 'selectiondirection',
68
+ ])
69
+ },
70
+ {
71
+ rule: {when: 'type', is: 'search'},
72
+ members: new Set([
73
+ 'autocomplete',
74
+ 'dirname',
75
+ 'list',
76
+ 'maxlength',
77
+ 'minlength',
78
+ 'pattern',
79
+ 'placeholder',
80
+ 'readonly',
81
+ 'required',
82
+ 'size',
83
+ 'value',
84
+ 'list',
85
+ 'selectionstart',
86
+ 'selectionend',
87
+ 'selectiondirection',
88
+ ])
89
+ },
90
+ {
91
+ rule: {when: 'type', is: 'url'},
92
+ members: new Set([
93
+ 'autocomplete',
94
+ 'list',
95
+ 'maxlength',
96
+ 'minlength',
97
+ 'pattern',
98
+ 'placeholder',
99
+ 'readonly',
100
+ 'required',
101
+ 'size',
102
+ 'value',
103
+ 'list',
104
+ 'selectionstart',
105
+ 'selectionend',
106
+ 'selectiondirection',
107
+ ])
108
+ },
109
+ {
110
+ rule: {when: 'type', is: 'tel'},
111
+ members: new Set([
112
+ 'autocomplete',
113
+ 'list',
114
+ 'maxlength',
115
+ 'minlength',
116
+ 'pattern',
117
+ 'placeholder',
118
+ 'readonly',
119
+ 'required',
120
+ 'size',
121
+ 'value',
122
+ 'list',
123
+ 'selectionstart',
124
+ 'selectionend',
125
+ 'selectiondirection',
126
+ ])
127
+ },
128
+ {
129
+ rule: {when: 'type', is: 'email'},
130
+ members: new Set([
131
+ 'autocomplete',
132
+ 'list',
133
+ 'maxlength',
134
+ 'minlength',
135
+ 'multiple',
136
+ 'pattern',
137
+ 'placeholder',
138
+ 'readonly',
139
+ 'required',
140
+ 'size',
141
+ 'value',
142
+ 'list',
143
+ ])
144
+ },
145
+ {
146
+ rule: {when: 'type', is: 'password'},
147
+ members: new Set([
148
+ 'autocomplete',
149
+ 'maxlength',
150
+ 'minlength',
151
+ 'pattern',
152
+ 'placeholder',
153
+ 'readonly',
154
+ 'required',
155
+ 'size',
156
+ 'value',
157
+ 'selectionstart',
158
+ 'selectionend',
159
+ 'selectiondirection',
160
+ ])
161
+ },
162
+ {
163
+ rule: {when: 'type', is: 'date'},
164
+ members: new Set([
165
+ 'autocomplete',
166
+ 'list',
167
+ 'max',
168
+ 'min',
169
+ 'readonly',
170
+ 'required',
171
+ 'step',
172
+ 'value',
173
+ 'valueasdate',
174
+ 'valueasnumber',
175
+ 'list',
176
+ ])
177
+ },
178
+ {
179
+ rule: {when: 'type', is: 'month'},
180
+ members: new Set([
181
+ 'autocomplete',
182
+ 'list',
183
+ 'max',
184
+ 'min',
185
+ 'readonly',
186
+ 'required',
187
+ 'step',
188
+ 'value',
189
+ 'valueasdate',
190
+ 'valueasnumber',
191
+ 'list',
192
+ ])
193
+ },
194
+ {
195
+ rule: {when: 'type', is: 'week'},
196
+ members: new Set([
197
+ 'autocomplete',
198
+ 'list',
199
+ 'max',
200
+ 'min',
201
+ 'readonly',
202
+ 'required',
203
+ 'step',
204
+ 'value',
205
+ 'valueasdate',
206
+ 'valueasnumber',
207
+ 'list',
208
+ ])
209
+ },
210
+ {
211
+ rule: {when: 'type', is: 'time'},
212
+ members: new Set([
213
+ 'autocomplete',
214
+ 'list',
215
+ 'max',
216
+ 'min',
217
+ 'readonly',
218
+ 'required',
219
+ 'step',
220
+ 'value',
221
+ 'valueasdate',
222
+ 'valueasnumber',
223
+ 'list',
224
+ ])
225
+ },
226
+ {
227
+ rule: {when: 'type', is: 'datetime-local'},
228
+ members: new Set([
229
+ 'autocomplete',
230
+ 'list',
231
+ 'max',
232
+ 'min',
233
+ 'readonly',
234
+ 'required',
235
+ 'step',
236
+ 'value',
237
+ 'valueasnumber',
238
+ 'list',
239
+ ])
240
+ },
241
+ {
242
+ rule: {when: 'type', is: 'number'},
243
+ members: new Set([
244
+ 'autocomplete',
245
+ 'list',
246
+ 'max',
247
+ 'min',
248
+ 'placeholder',
249
+ 'readonly',
250
+ 'required',
251
+ 'step',
252
+ 'value',
253
+ 'valueasnumber',
254
+ 'list',
255
+ ])
256
+ },
257
+ {
258
+ rule: {when: 'type', is: 'range'},
259
+ members: new Set([
260
+ 'autocomplete',
261
+ 'list',
262
+ 'max',
263
+ 'min',
264
+ 'step',
265
+ 'value',
266
+ 'valueasnumber',
267
+ 'list',
268
+ ])
269
+ },
270
+ {
271
+ rule: {when: 'type', is: 'color'},
272
+ members: new Set([
273
+ 'autocomplete',
274
+ 'list',
275
+ 'value',
276
+ ])
277
+ },
278
+ {
279
+ rule: {when: 'type', is: 'checkbox'},
280
+ members: new Set([
281
+ 'checked',
282
+ 'required',
283
+ 'checked',
284
+ 'value',
285
+ ])
286
+ },
287
+ {
288
+ rule: {when: 'type', is: 'radio'},
289
+ members: new Set([
290
+ 'checked',
291
+ 'required',
292
+ 'checked',
293
+ 'value',
294
+ ])
295
+ },
296
+ {
297
+ rule: {when: 'type', is: 'file'},
298
+ members: new Set([
299
+ 'accept',
300
+ 'multiple',
301
+ 'required',
302
+ 'files',
303
+ 'value',
304
+ ])
305
+ },
306
+ {
307
+ rule: {when: 'type', is: 'submit'},
308
+ members: new Set([
309
+ 'formaction',
310
+ 'formenctype',
311
+ 'formmethod',
312
+ 'formnovalidate',
313
+ 'formtarget',
314
+ 'value',
315
+ ])
316
+ },
317
+ {
318
+ rule: {when: 'type', is: 'image'},
319
+ members: new Set([
320
+ 'alt',
321
+ 'formaction',
322
+ 'formenctype',
323
+ 'formmethod',
324
+ 'formnovalidate',
325
+ 'formtarget',
326
+ 'height',
327
+ 'src',
328
+ 'width',
329
+ 'value',
330
+ ])
331
+ },
332
+ {
333
+ rule: {when: 'type', is: 'reset'},
334
+ members: new Set([
335
+ 'value',
336
+ ])
337
+ },
338
+ {
339
+ rule: {when: 'type', is: 'button'},
340
+ members: new Set([
341
+ 'value',
342
+ ])
343
+ },
344
+ ],
345
+ };
@@ -0,0 +1,150 @@
1
+ // Copyright 2022 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
+
5
+ import {APPLICABLE_MEMBERS, GLOBAL_ATTRIBUTES, SPECS} from './config.js';
6
+ import {merge} from './util.js';
7
+
8
+ /**
9
+ * All the members relevant for generating the DOM pinned properties dataset
10
+ * from WebIDL interfaces, mixins and dictionaries.
11
+ */
12
+ const ACCEPTED_MEMBER_TYPES = new Set(['attribute', 'field']);
13
+
14
+ /**
15
+ * Generates the DOM pinned properties dataset.
16
+ *
17
+ * @param {array} specs A list of specs. Each spec specifies its name and
18
+ * all the idl definitions it contains.
19
+ * @returns {object} output An object with WebIDL type names as keys and their
20
+ * WebIDL properties and inheritance/include chains as values.
21
+ */
22
+ export function getIDLProps(specs, output = {}) {
23
+ for (const spec of specs) {
24
+ transform(spec, output);
25
+ }
26
+ return output;
27
+ }
28
+
29
+ function transform({name, idls}, output = {}) {
30
+ const makeEntry = () => ({
31
+ inheritance: null,
32
+ includes: [],
33
+ props: {},
34
+ });
35
+
36
+ for (const idl of idls) {
37
+ switch (idl.type) {
38
+ case 'interface':
39
+ case 'interface mixin':
40
+ case 'dictionary': {
41
+ output[idl.name] = output[idl.name] ?? makeEntry();
42
+ let props = idl.members?.filter(member => ACCEPTED_MEMBER_TYPES.has(member.type));
43
+ props = props?.map(member => [member.name, {specs: [name]}]);
44
+ merge(output[idl.name], {
45
+ inheritance: idl.inheritance,
46
+ props: Object.fromEntries(props),
47
+ });
48
+ break;
49
+ }
50
+ case 'includes': {
51
+ output[idl.target] = output[idl.target] ?? makeEntry();
52
+ merge(output[idl.target], {
53
+ includes: [idl.includes],
54
+ });
55
+ break;
56
+ }
57
+ case 'callback':
58
+ case 'callback interface':
59
+ case 'enum':
60
+ case 'typedef':
61
+ case 'namespace': {
62
+ break;
63
+ }
64
+ default: {
65
+ console.warn('Skipping unknown WebIDL type', idl.type);
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Adds additional metadata to the DOM pinned properties dataset.
73
+ *
74
+ * Currently:
75
+ * - Adds a field specifying whether a member is a global attribute or not.
76
+ * - Adds information about which properties are "applicable" members for
77
+ * certain "states" their parent WebIDL type can be in, such as for the
78
+ * HTMLInputElement where the set of valid members are determined by the "type"
79
+ * property. See `APPLICABLE_MEMBERS`.
80
+ *
81
+ * @param {*} output
82
+ */
83
+ export function addMetadata(output) {
84
+ for (const [key, value] of Object.entries(output)) {
85
+ for (const [name, prop] of Object.entries(value.props)) {
86
+ prop.global = GLOBAL_ATTRIBUTES.has(name);
87
+
88
+ const rules = APPLICABLE_MEMBERS[key];
89
+ if (!rules) {
90
+ continue;
91
+ }
92
+
93
+ for (const {rule, members} of rules) {
94
+ if (members.has(name.toLowerCase())) {
95
+ merge(prop, {rules: [rule]});
96
+ }
97
+ }
98
+
99
+ value.rules = rules.map(({rule}) => rule);
100
+ }
101
+ }
102
+ return output;
103
+ }
104
+
105
+ /**
106
+ * Minimizes the DOM pinned properties dataset to remove the bits of data that
107
+ * don't contain information. For example, empty inheritance/includes chains.
108
+ *
109
+ * This should be done right at the end, before writing into the output file, to
110
+ * allow for certain diagnostics (such as finding "missing types").
111
+ *
112
+ * @param {*} output
113
+ * @returns {object}
114
+ */
115
+ export function minimize(output) {
116
+ for (const [key, value] of Object.entries(output)) {
117
+ if (!value.inheritance) {
118
+ // Remove empty inheritance chains.
119
+ delete value.inheritance;
120
+ }
121
+ if (!value.includes.length) {
122
+ // Remove empty include chains.
123
+ delete value.includes;
124
+ }
125
+ const props = Object.entries(value.props);
126
+ if (!props.length) {
127
+ // Remove empty 'prop' lists.
128
+ delete value.props;
129
+ } else {
130
+ for (const [, value] of props) {
131
+ if (!value.global) {
132
+ // Remove the 'global' flag if it's false.
133
+ delete value.global;
134
+ }
135
+ if (value.specs.length === 1 && value.specs[0] === 'html') {
136
+ // Remove the 'specs' list if it's just "html".
137
+ delete value.specs;
138
+ } else {
139
+ // Combine multiple spec names into a single value.
140
+ value.specs = value.specs.reduce((acc, name) => acc | SPECS[name], 0);
141
+ }
142
+ }
143
+ }
144
+ // Remove the entire entry if there's nothing left after the cleanup above.
145
+ if (!Object.entries(value).length) {
146
+ delete output[key];
147
+ }
148
+ }
149
+ return output;
150
+ }
@@ -0,0 +1,90 @@
1
+ // 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
+
5
+ // eslint-disable-next-line rulesdir/es_modules_import
6
+ import idl from '@webref/idl';
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as url from 'url';
10
+
11
+ import {SPECS} from './config.js';
12
+ import {addMetadata, getIDLProps, minimize} from './get-props.js';
13
+ import {getMissingTypes} from './util.js';
14
+
15
+ if (process.argv.length !== 3) {
16
+ throw new Error('Please provide the path to devtools-frontend');
17
+ }
18
+
19
+ const files = await idl.listAll();
20
+ const names = Object.keys(SPECS);
21
+ const specs = await Promise.all(names.map(name => files[name].parse().then(idls => ({name, idls}))));
22
+
23
+ const output = addMetadata(getIDLProps(specs));
24
+
25
+ const missing = getMissingTypes(output);
26
+ for (const type of missing) {
27
+ console.warn('Found missing type:', type);
28
+ }
29
+
30
+ const frontendPath = path.resolve(process.argv[2]);
31
+ const jsMetadataPath = path.join(frontendPath, 'front_end/models/javascript_metadata/');
32
+ const outPath = path.join(jsMetadataPath, 'DOMPinnedProperties.ts');
33
+ const thisPath = path.relative(frontendPath, url.fileURLToPath(import.meta.url));
34
+
35
+ const stringify = object => JSON.stringify(object, null, 2);
36
+
37
+ fs.writeFileSync(outPath, `
38
+ // Copyright 2022 The Chromium Authors. All rights reserved.
39
+ // Use of this source code is governed by a BSD-style license that can be
40
+ // found in the LICENSE file.
41
+ // Generated from ${thisPath}
42
+
43
+ /**
44
+ * All the specs used when generating the DOM pinned properties dataset.
45
+ */
46
+ export const SPECS = ${stringify(SPECS)};
47
+
48
+ export interface DOMPinnedWebIDLProp {
49
+ // A flag specifying whether it's a "global" attribute.
50
+ global?: boolean;
51
+ // A bitfield of the specs in which the property is found.
52
+ // If missing, it implies the default spec: "html".
53
+ specs?: number;
54
+ // The "states" in which this property is "applicable".
55
+ rules?: Array<DOMPinnedWebIDLRule>;
56
+ }
57
+
58
+ export interface DOMPinnedWebIDLType {
59
+ // An inherited Type.
60
+ inheritance?: string;
61
+ // A set of Types to also include properties from.
62
+ includes?: Array<string>;
63
+ // The properties defined on this Type.
64
+ props?: {
65
+ // A property name such as "checked".
66
+ [PropName: string]: DOMPinnedWebIDLProp,
67
+ };
68
+ // The "states" in which only certain properties are "applicable".
69
+ rules?: Array<DOMPinnedWebIDLRule>;
70
+ }
71
+
72
+ export interface DOMPinnedWebIDLRule {
73
+ when: string;
74
+ is: string;
75
+ }
76
+
77
+ export interface DOMPinnedPropertiesDataset {
78
+ [TypeName: string]: DOMPinnedWebIDLType;
79
+ }
80
+
81
+ /**
82
+ * The DOM pinned properties dataset. Generated from WebIDL data parsed from
83
+ * the SPECS above.
84
+ *
85
+ * This is an object with WebIDL type names as keys and their WebIDL properties
86
+ * and inheritance/include chains as values.
87
+ */
88
+ export const DOMPinnedProperties: DOMPinnedPropertiesDataset = ${stringify(minimize(output))};
89
+
90
+ `);
@@ -0,0 +1,9 @@
1
+ {
2
+ "private": true,
3
+ "main": "index.js",
4
+ "type": "module",
5
+ "scripts": {
6
+ "start": "node index.js",
7
+ "test": "mocha tests.js"
8
+ }
9
+ }