Skip to content

Commit ccbb2d8

Browse files
committed
Validate that all IDL types are defined somewhere
1 parent 8abb850 commit ccbb2d8

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

packages/idl/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@ for (const [shortname, ast] of Object.entries(parsedFiles)) {
3232

3333
The following guarantees are provided by this package:
3434
- All IDL files can be parsed by the version of [webidl2.js](https://github.com/w3c/webidl2.js/) used in `peerDependencies` in `package.json`.
35+
- All types except `void` are defined by some specification.
3536
- No duplicate top-level definitions or members.
3637
- No missing or mismatched types in inheritance chains.
3738
- No conflicts when applying mixins and partials.
3839

3940
The following guarantees are *not* provided:
4041
- `WebIDL2.validate` rules are not guaranteed to pass.
4142
- Extended attributes are not validated at all.
42-
- Some types referenced may not be defined.
43+
4344
- Generally no other guarantees except the ones enforced by tests.

test/idl/consistency.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,79 @@ describe('Web IDL consistency', () => {
186186
}
187187
});
188188

189+
// Validate that there are no unknown types.
190+
it('all used types are defined', () => {
191+
// There are types in lots of places in the AST (interface members,
192+
// arguments, return types) and rather than trying to cover them all, walk
193+
// the whole AST looking for "idlType".
194+
const usedTypes = new Set();
195+
196+
// Serialize and reparse the ast to not have to worry about own properties
197+
// vs enumerable properties on the prototypes, etc.
198+
const pending = [JSON.parse(JSON.stringify([...dfns, ...partials]))];
199+
while (pending.length) {
200+
const node = pending.pop();
201+
for (const [key, value] of Object.entries(node)) {
202+
if (key === 'idlType' && typeof value === 'string') {
203+
usedTypes.add(value);
204+
} else if (typeof value === 'object' && value !== null) {
205+
pending.push(value);
206+
}
207+
}
208+
}
209+
210+
const knownTypes = new Set([
211+
// Types defined by Web IDL itself:
212+
'any', // https://heycam.github.io/webidl/#idl-any
213+
'ArrayBuffer', // https://heycam.github.io/webidl/#idl-ArrayBuffer
214+
'boolean', // https://heycam.github.io/webidl/#idl-boolean
215+
'byte', // https://heycam.github.io/webidl/#idl-byte
216+
'ByteString', // https://heycam.github.io/webidl/#idl-ByteString
217+
'DataView', // https://heycam.github.io/webidl/#idl-DataView
218+
'DOMString', // https://heycam.github.io/webidl/#idl-DOMString
219+
'double', // https://heycam.github.io/webidl/#idl-double
220+
'float', // https://heycam.github.io/webidl/#idl-float
221+
'Float32Array', // https://heycam.github.io/webidl/#idl-Float32Array
222+
'Float64Array', // https://heycam.github.io/webidl/#idl-Float64Array
223+
'Int16Array', // https://heycam.github.io/webidl/#idl-Int16Array
224+
'Int32Array', // https://heycam.github.io/webidl/#idl-Int32Array
225+
'Int8Array', // https://heycam.github.io/webidl/#idl-Int8Array
226+
'long long', // https://heycam.github.io/webidl/#idl-long-long
227+
'long', // https://heycam.github.io/webidl/#idl-long
228+
'object', // https://heycam.github.io/webidl/#idl-object
229+
'octet', // https://heycam.github.io/webidl/#idl-octet
230+
'short', // https://heycam.github.io/webidl/#idl-short
231+
'symbol', // https://heycam.github.io/webidl/#idl-symbol
232+
'Uint16Array', // https://heycam.github.io/webidl/#idl-Uint16Array
233+
'Uint32Array', // https://heycam.github.io/webidl/#idl-Uint32Array
234+
'Uint8Array', // https://heycam.github.io/webidl/#idl-Uint8Array
235+
'Uint8ClampedArray', // https://heycam.github.io/webidl/#idl-Uint8ClampedArray
236+
'unrestricted double', // https://heycam.github.io/webidl/#idl-unrestricted-double
237+
'unrestricted float', // https://heycam.github.io/webidl/#idl-unrestricted-float
238+
'unsigned long long', // https://heycam.github.io/webidl/#idl-unsigned-long-long
239+
'unsigned long', // https://heycam.github.io/webidl/#idl-unsigned-long
240+
'unsigned short', // https://heycam.github.io/webidl/#idl-unsigned-short
241+
'USVString', // https://heycam.github.io/webidl/#idl-USVString
242+
'undefined', // https://heycam.github.io/webidl/#idl-undefined
243+
244+
// TODO: drop void when it has been removed from all specs
245+
'void',
246+
247+
// Types defined by other specs:
248+
'CSSOMString', // https://drafts.csswg.org/cssom/#cssomstring-type
249+
'WindowProxy' // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy
250+
]);
251+
252+
// Add any types defined by the parsed IDL.
253+
for (const dfn of dfns) {
254+
knownTypes.add(dfn.name);
255+
}
256+
257+
for (const usedType of usedTypes) {
258+
assert(knownTypes.has(usedType), `type ${usedType} is used but never defined`);
259+
}
260+
});
261+
189262
// This test should remain the last one as it slightly modifies objects in dfns in place.
190263
it('merging in partials/mixins', () => {
191264
const merged = merge(dfns, partials, includes);

0 commit comments

Comments
 (0)