1import WebIDL
2
3def WebIDLTest(parser, harness):
4    def checkArgument(argument, QName, name, type, optional, variadic):
5        harness.ok(isinstance(argument, WebIDL.IDLArgument),
6                   "Should be an IDLArgument")
7        harness.check(argument.identifier.QName(), QName, "Argument has the right QName")
8        harness.check(argument.identifier.name, name, "Argument has the right name")
9        harness.check(str(argument.type), type, "Argument has the right return type")
10        harness.check(argument.optional, optional, "Argument has the right optional value")
11        harness.check(argument.variadic, variadic, "Argument has the right variadic value")
12
13    def checkMethod(method, QName, name, signatures,
14                    static=True, getter=False, setter=False, deleter=False,
15                    legacycaller=False, stringifier=False, chromeOnly=False,
16                    htmlConstructor=False, secureContext=False, pref=None, func=None):
17        harness.ok(isinstance(method, WebIDL.IDLMethod),
18                   "Should be an IDLMethod")
19        harness.ok(method.isMethod(), "Method is a method")
20        harness.ok(not method.isAttr(), "Method is not an attr")
21        harness.ok(not method.isConst(), "Method is not a const")
22        harness.check(method.identifier.QName(), QName, "Method has the right QName")
23        harness.check(method.identifier.name, name, "Method has the right name")
24        harness.check(method.isStatic(), static, "Method has the correct static value")
25        harness.check(method.isGetter(), getter, "Method has the correct getter value")
26        harness.check(method.isSetter(), setter, "Method has the correct setter value")
27        harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
28        harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
29        harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
30        harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
31        harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
32        harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
33        harness.check(method.getExtendedAttribute("Pref"), pref, "Method has the correct pref value")
34        harness.check(method.getExtendedAttribute("Func"), func, "Method has the correct func value")
35        harness.check(method.getExtendedAttribute("SecureContext") is not None, secureContext, "Method has the correct SecureContext value")
36
37        sigpairs = zip(method.signatures(), signatures)
38        for (gotSignature, expectedSignature) in sigpairs:
39            (gotRetType, gotArgs) = gotSignature
40            (expectedRetType, expectedArgs) = expectedSignature
41
42            harness.check(str(gotRetType), expectedRetType,
43                          "Method has the expected return type.")
44
45            for i in range(0, len(gotArgs)):
46                (QName, name, type, optional, variadic) = expectedArgs[i]
47                checkArgument(gotArgs[i], QName, name, type, optional, variadic)
48
49    def checkResults(results):
50        harness.check(len(results), 3, "Should be three productions")
51        harness.ok(isinstance(results[0], WebIDL.IDLInterface),
52                   "Should be an IDLInterface")
53        harness.ok(isinstance(results[1], WebIDL.IDLInterface),
54                   "Should be an IDLInterface")
55        harness.ok(isinstance(results[2], WebIDL.IDLInterface),
56                   "Should be an IDLInterface")
57
58        checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor",
59                    "constructor", [("TestConstructorNoArgs (Wrapper)", [])])
60        harness.check(len(results[0].members), 0,
61                      "TestConstructorNoArgs should not have members")
62        checkMethod(results[1].ctor(), "::TestConstructorWithArgs::constructor",
63                    "constructor",
64                    [("TestConstructorWithArgs (Wrapper)",
65                      [("::TestConstructorWithArgs::constructor::name", "name", "String", False, False)])])
66        harness.check(len(results[1].members), 0,
67                      "TestConstructorWithArgs should not have members")
68        checkMethod(results[2].ctor(), "::TestConstructorOverloads::constructor",
69                    "constructor",
70                    [("TestConstructorOverloads (Wrapper)",
71                      [("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]),
72                     ("TestConstructorOverloads (Wrapper)",
73                      [("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])])
74        harness.check(len(results[2].members), 0,
75                      "TestConstructorOverloads should not have members")
76
77    parser.parse("""
78        interface TestConstructorNoArgs {
79          constructor();
80        };
81
82        interface TestConstructorWithArgs {
83          constructor(DOMString name);
84        };
85
86        interface TestConstructorOverloads {
87          constructor(object foo);
88          constructor(boolean bar);
89        };
90    """)
91    results = parser.finish()
92    checkResults(results)
93
94    parser = parser.reset()
95    parser.parse("""
96        interface TestPrefConstructor {
97            [Pref="dom.webidl.test1"] constructor();
98        };
99    """)
100    results = parser.finish()
101    harness.check(len(results), 1, "Should be one production")
102    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
103               "Should be an IDLInterface")
104
105    checkMethod(results[0].ctor(), "::TestPrefConstructor::constructor",
106                "constructor", [("TestPrefConstructor (Wrapper)", [])],
107                pref=["dom.webidl.test1"])
108
109    parser = parser.reset()
110    parser.parse("""
111        interface TestChromeOnlyConstructor {
112          [ChromeOnly] constructor();
113        };
114    """)
115    results = parser.finish()
116    harness.check(len(results), 1, "Should be one production")
117    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
118               "Should be an IDLInterface")
119
120    checkMethod(results[0].ctor(), "::TestChromeOnlyConstructor::constructor",
121                "constructor", [("TestChromeOnlyConstructor (Wrapper)", [])],
122                chromeOnly=True)
123
124    parser = parser.reset()
125    parser.parse("""
126        interface TestSCConstructor {
127            [SecureContext] constructor();
128        };
129    """)
130    results = parser.finish()
131    harness.check(len(results), 1, "Should be one production")
132    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
133               "Should be an IDLInterface")
134
135    checkMethod(results[0].ctor(), "::TestSCConstructor::constructor",
136                "constructor", [("TestSCConstructor (Wrapper)", [])],
137                secureContext=True)
138
139    parser = parser.reset()
140    parser.parse("""
141        interface TestFuncConstructor {
142            [Func="Document::IsWebAnimationsEnabled"] constructor();
143        };
144    """)
145    results = parser.finish()
146    harness.check(len(results), 1, "Should be one production")
147    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
148               "Should be an IDLInterface")
149
150    checkMethod(results[0].ctor(), "::TestFuncConstructor::constructor",
151                "constructor", [("TestFuncConstructor (Wrapper)", [])],
152                func=["Document::IsWebAnimationsEnabled"])
153
154    parser = parser.reset()
155    parser.parse("""
156        interface TestPrefChromeOnlySCFuncConstructor {
157            [ChromeOnly, Pref="dom.webidl.test1", SecureContext, Func="Document::IsWebAnimationsEnabled"]
158            constructor();
159        };
160    """)
161    results = parser.finish()
162    harness.check(len(results), 1, "Should be one production")
163    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
164               "Should be an IDLInterface")
165
166    checkMethod(results[0].ctor(), "::TestPrefChromeOnlySCFuncConstructor::constructor",
167                "constructor", [("TestPrefChromeOnlySCFuncConstructor (Wrapper)", [])],
168                func=["Document::IsWebAnimationsEnabled"], pref=["dom.webidl.test1"],
169                chromeOnly=True, secureContext=True)
170
171    parser = parser.reset()
172    parser.parse("""
173        interface TestHTMLConstructor {
174          [HTMLConstructor] constructor();
175        };
176    """)
177    results = parser.finish()
178    harness.check(len(results), 1, "Should be one production")
179    harness.ok(isinstance(results[0], WebIDL.IDLInterface),
180               "Should be an IDLInterface")
181
182    checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor",
183                "constructor", [("TestHTMLConstructor (Wrapper)", [])],
184                htmlConstructor=True)
185
186    parser = parser.reset()
187    threw = False
188    try:
189        parser.parse("""
190        interface TestChromeOnlyConstructor {
191          constructor()
192          [ChromeOnly] constructor(DOMString a);
193        };
194        """)
195        results = parser.finish()
196    except:
197        threw = True
198
199    harness.ok(threw, "Can't have both a constructor and a ChromeOnly constructor")
200
201    # Test HTMLConstructor with argument
202    parser = parser.reset()
203    threw = False
204    try:
205        parser.parse("""
206            interface TestHTMLConstructorWithArgs {
207              [HTMLConstructor] constructor(DOMString a);
208            };
209        """)
210        results = parser.finish()
211    except:
212        threw = True
213
214    harness.ok(threw, "HTMLConstructor should take no argument")
215
216    # Test HTMLConstructor on a callback interface
217    parser = parser.reset()
218    threw = False
219    try:
220        parser.parse("""
221            callback interface TestHTMLConstructorOnCallbackInterface {
222              [HTMLConstructor] constructor();
223            };
224        """)
225        results = parser.finish()
226    except:
227        threw = True
228
229    harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
230
231    # Test HTMLConstructor and constructor operation
232    parser = parser.reset()
233    threw = False
234    try:
235        parser.parse("""
236            interface TestHTMLConstructorAndConstructor {
237              constructor();
238              [HTMLConstructor] constructor();
239            };
240        """)
241        results = parser.finish()
242    except:
243        threw = True
244
245    harness.ok(threw, "Can't have both a constructor and a HTMLConstructor")
246
247    parser = parser.reset()
248    threw = False
249    try:
250        parser.parse("""
251            interface TestHTMLConstructorAndConstructor {
252              [Throws]
253              constructor();
254              [HTMLConstructor] constructor();
255            };
256        """)
257        results = parser.finish()
258    except:
259        threw = True
260
261    harness.ok(threw,
262               "Can't have both a throwing constructor and a HTMLConstructor")
263
264    parser = parser.reset()
265    threw = False
266    try:
267        parser.parse("""
268            interface TestHTMLConstructorAndConstructor {
269              constructor(DOMString a);
270              [HTMLConstructor] constructor();
271            };
272        """)
273        results = parser.finish()
274    except:
275        threw = True
276
277    harness.ok(threw,
278               "Can't have both a HTMLConstructor and a constructor operation")
279
280    parser = parser.reset()
281    threw = False
282    try:
283        parser.parse("""
284            interface TestHTMLConstructorAndConstructor {
285              [Throws]
286              constructor(DOMString a);
287              [HTMLConstructor] constructor();
288            };
289        """)
290        results = parser.finish()
291    except:
292        threw = True
293
294    harness.ok(threw,
295               "Can't have both a HTMLConstructor and a throwing constructor "
296               "operation")
297
298    # Test HTMLConstructor and [ChromeOnly] constructor operation
299    parser = parser.reset()
300    threw = False
301    try:
302        parser.parse("""
303            interface TestHTMLConstructorAndConstructor {
304              [ChromeOnly]
305              constructor();
306              [HTMLConstructor] constructor();
307            };
308        """)
309        results = parser.finish()
310    except:
311        threw = True
312
313    harness.ok(threw,
314               "Can't have both a ChromeOnly constructor and a HTMLConstructor")
315
316    parser = parser.reset()
317    threw = False
318    try:
319        parser.parse("""
320            interface TestHTMLConstructorAndConstructor {
321              [Throws, ChromeOnly]
322              constructor();
323              [HTMLConstructor] constructor();
324            };
325        """)
326        results = parser.finish()
327    except:
328        threw = True
329
330    harness.ok(threw,
331               "Can't have both a throwing chromeonly constructor and a "
332               "HTMLConstructor")
333
334    parser = parser.reset()
335    threw = False
336    try:
337        parser.parse("""
338            interface TestHTMLConstructorAndConstructor {
339              [ChromeOnly]
340              constructor(DOMString a);
341              [HTMLConstructor] constructor();
342            };
343        """)
344        results = parser.finish()
345    except:
346        threw = True
347
348    harness.ok(threw,
349               "Can't have both a HTMLConstructor and a chromeonly constructor "
350               "operation")
351
352    parser = parser.reset()
353    threw = False
354    try:
355        parser.parse("""
356            interface TestHTMLConstructorAndConstructor {
357              [Throws, ChromeOnly]
358              constructor(DOMString a);
359              [HTMLConstructor] constructor();
360            };
361        """)
362        results = parser.finish()
363    except:
364        threw = True
365
366    harness.ok(threw,
367               "Can't have both a HTMLConstructor and a throwing chromeonly "
368               "constructor operation")
369
370    parser = parser.reset()
371    threw = False
372    try:
373        parser.parse("""
374            [NoInterfaceObject]
375            interface InterfaceWithoutInterfaceObject {
376              constructor();
377            };
378        """)
379        results = parser.finish()
380    except:
381        threw = True
382
383    harness.ok(threw,
384               "Can't have a constructor operation on a [NoInterfaceObject] "
385               "interface")
386
387    parser = parser.reset()
388    threw = False
389    try:
390        parser.parse("""
391            interface InterfaceWithPartial {
392            };
393
394            partial interface InterfaceWithPartial {
395              constructor();
396            };
397        """)
398        results = parser.finish()
399    except:
400        threw = True
401
402    harness.ok(threw,
403               "Can't have a constructor operation on a partial interface")
404
405    parser = parser.reset()
406    threw = False
407    try:
408        parser.parse("""
409            interface InterfaceWithMixin {
410            };
411
412            interface mixin Mixin {
413              constructor();
414            };
415
416            InterfaceWithMixin includes Mixin
417        """)
418        results = parser.finish()
419    except:
420        threw = True
421
422    harness.ok(threw,
423               "Can't have a constructor operation on a mixin")
424
425